drivers/i2c/da7219: Add driver for generating device in SSDT
Add a device driver to generate the device and required properties
into the SSDT.
This driver uses the ACPI Device Property interface to generate the
required parameters into the _DSD table format expected by the kernel.
This was tested on the reef mainboard to ensure that the SSDT contained
the equivalent parameters that are provided by the current DSDT object.
Change-Id: Ia809e953932a7e127352a7ef193974d95e511565
Signed-off-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-on: https://review.coreboot.org/15538
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
diff --git a/src/drivers/i2c/da7219/Kconfig b/src/drivers/i2c/da7219/Kconfig
new file mode 100644
index 0000000..5539af1
--- /dev/null
+++ b/src/drivers/i2c/da7219/Kconfig
@@ -0,0 +1,2 @@
+config DRIVERS_I2C_DA7219
+ bool
diff --git a/src/drivers/i2c/da7219/Makefile.inc b/src/drivers/i2c/da7219/Makefile.inc
new file mode 100644
index 0000000..354a330
--- /dev/null
+++ b/src/drivers/i2c/da7219/Makefile.inc
@@ -0,0 +1 @@
+ramstage-$(CONFIG_DRIVERS_I2C_DA7219) += da7219.c
diff --git a/src/drivers/i2c/da7219/chip.h b/src/drivers/i2c/da7219/chip.h
new file mode 100644
index 0000000..823b940
--- /dev/null
+++ b/src/drivers/i2c/da7219/chip.h
@@ -0,0 +1,106 @@
+#include <arch/acpi_device.h>
+
+/*
+ * Dialog Semiconductor DA7219 Audio Codec devicetree bindings
+ * linux/Documentation/devicetree/bindings/sound/da7219.txt
+ */
+struct drivers_i2c_da7219_config {
+ /* Interrupt configuration */
+ struct acpi_irq irq;
+
+ /* I2C Bus Frequency in Hertz (default 400kHz) */
+ unsigned bus_speed;
+
+ /*
+ * micbias-lvl : Voltage (mV) for Mic Bias
+ * [<1600>, <1800>, <2000>, <2200>, <2400>, <2600>]
+ */
+ unsigned micbias_lvl;
+
+ /*
+ * mic-amp-in-sel : Mic input source type
+ * ["diff", "se_p", "se_n"]
+ */
+ const char *mic_amp_in_sel;
+
+ /*
+ * Properties for da7219_aad child node
+ */
+
+ /*
+ * micbias-pulse-lvl : Mic bias higher voltage pulse level (mV)
+ * [<2800>, <2900>]
+ */
+ unsigned micbias_pulse_lvl;
+
+ /*
+ * micbias-pulse-time : Mic bias higher voltage pulse duration (ms)
+ */
+ unsigned micbias_pulse_time;
+
+ /*
+ * btn-cfg : Periodic button press measurements for 4-pole jack (ms)
+ * [<2>, <5>, <10>, <50>, <100>, <200>, <500>]
+ */
+ unsigned btn_cfg;
+
+ /*
+ * mic-det-thr : Impedance threshold for mic detection measurement (Ohms)
+ * [<200>, <500>, <750>, <1000>]
+ */
+ unsigned mic_det_thr;
+
+ /*
+ * jack-ins-deb : Debounce time for jack insertion (ms)
+ * [<5>, <10>, <20>, <50>, <100>, <200>, <500>, <1000>]
+ */
+ unsigned jack_ins_deb;
+
+ /*
+ * jack-det-rate : Jack type detection latency (3/4 pole)
+ * ["32ms_64ms", "64ms_128ms", "128ms_256ms", "256ms_512ms"]
+ */
+ const char *jack_det_rate;
+
+ /*
+ * jack-rem-deb : Debounce time for jack removal (ms)
+ * [<1>, <5>, <10>, <20>]
+ */
+ unsigned jack_rem_deb;
+
+ /*
+ * a-d-btn-thr : Impedance threshold between buttons A and D
+ * [0x0 - 0xFF]
+ */
+ unsigned a_d_btn_thr;
+
+ /*
+ * d-b-btn-thr : Impedance threshold between buttons D and B
+ * [0x0 - 0xFF]
+ */
+ unsigned d_b_btn_thr;
+
+ /*
+ * b-c-btn-thr : Impedance threshold between buttons B and C
+ * [0x0 - 0xFF]
+ */
+ unsigned b_c_btn_thr;
+
+ /*
+ * c-mic-btn-thr : Impedance threshold between button C and Mic
+ * [0x0 - 0xFF]
+ */
+ unsigned c_mic_btn_thr;
+
+ /*
+ * btn-avg : Number of 8-bit readings for averaged button measurement
+ * [<1>, <2>, <4>, <8>]
+ */
+ unsigned btn_avg;
+
+ /*
+ * adc-1bit-rpt : Repeat count for 1-bit button measurement
+ * [<1>, <2>, <4>, <8>]
+ */
+ unsigned adc_1bit_rpt;
+};
diff --git a/src/drivers/i2c/da7219/da7219.c b/src/drivers/i2c/da7219/da7219.c
new file mode 100644
index 0000000..b29a4a1
--- /dev/null
+++ b/src/drivers/i2c/da7219/da7219.c
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/acpi.h>
+#include <arch/acpi_device.h>
+#include <arch/acpigen.h>
+#include <console/console.h>
+#include <device/i2c.h>
+#include <device/device.h>
+#include <device/path.h>
+#include <stdint.h>
+#include <string.h>
+#include "chip.h"
+
+#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
+
+#define DA7219_ACPI_NAME "DLG7"
+#define DA7219_ACPI_HID "DLGS7219"
+
+static void da7219_fill_ssdt(struct device *dev)
+{
+ struct drivers_i2c_da7219_config *config = dev->chip_info;
+ const char *scope = acpi_device_scope(dev);
+ struct acpi_i2c i2c = {
+ .address = dev->path.i2c.device,
+ .mode_10bit = dev->path.i2c.mode_10bit,
+ .speed = config->bus_speed ? : I2C_SPEED_FAST,
+ .resource = scope,
+ };
+ struct acpi_dp *dsd, *aad;
+
+ if (!dev->enabled || !scope)
+ return;
+
+ /* Device */
+ acpigen_write_scope(scope);
+ acpigen_write_device(acpi_device_name(dev));
+ acpigen_write_name_string("_HID", DA7219_ACPI_HID);
+ acpigen_write_name_integer("_UID", 1);
+ acpigen_write_name_string("_DDN", dev->chip_ops->name);
+ acpigen_write_name_integer("_S0W", 4);
+ acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
+
+ /* Resources */
+ acpigen_write_name("_CRS");
+ acpigen_write_resourcetemplate_header();
+ acpi_device_write_i2c(&i2c);
+ acpi_device_write_interrupt(&config->irq);
+ acpigen_write_resourcetemplate_footer();
+
+ /* AAD Child Device Properties */
+ aad = acpi_dp_new_table("DAAD");
+ acpi_dp_add_integer(aad, "dlg,btn-cfg", config->btn_cfg);
+ acpi_dp_add_integer(aad, "dlg,mic-det-thr", config->mic_det_thr);
+ acpi_dp_add_integer(aad, "dlg,jack-ins-deb", config->jack_ins_deb);
+ acpi_dp_add_string(aad, "dlg,jack-det-rate", config->jack_det_rate);
+ acpi_dp_add_integer(aad, "dlg,jack-rem-deb", config->jack_rem_deb);
+ acpi_dp_add_integer(aad, "dlg,a-d-btn-thr", config->a_d_btn_thr);
+ acpi_dp_add_integer(aad, "dlg,d-b-btn-thr", config->d_b_btn_thr);
+ acpi_dp_add_integer(aad, "dlg,b-c-btn-thr", config->b_c_btn_thr);
+ acpi_dp_add_integer(aad, "dlg,c-mic-btn-thr", config->c_mic_btn_thr);
+ acpi_dp_add_integer(aad, "dlg,btn-avg", config->btn_avg);
+ acpi_dp_add_integer(aad, "dlg,adc-1bit-rpt", config->adc_1bit_rpt);
+ acpi_dp_add_integer(aad, "dlg,micbias-pulse-lvl",
+ config->micbias_pulse_lvl);
+ acpi_dp_add_integer(aad, "dlg,micbias-pulse-time",
+ config->micbias_pulse_time);
+
+ /* DA7219 Properties */
+ dsd = acpi_dp_new_table("_DSD");
+ acpi_dp_add_integer(dsd, "dlg,micbias-lvl", config->micbias_lvl);
+ acpi_dp_add_string(dsd, "dlg,mic-amp-in-sel", config->mic_amp_in_sel);
+ acpi_dp_add_child(dsd, "da7219_aad", aad);
+
+ /* Write Device Property Hierarchy */
+ acpi_dp_write(dsd);
+
+ acpigen_pop_len(); /* Device */
+ acpigen_pop_len(); /* Scope */
+
+ printk(BIOS_INFO, "%s: %s address 0%xh irq %d\n",
+ acpi_device_path(dev), dev->chip_ops->name,
+ dev->path.i2c.device, config->irq.pin);
+}
+
+static const char *da7219_acpi_name(struct device *dev)
+{
+ return DA7219_ACPI_NAME;
+}
+#endif
+
+static struct device_operations da7219_ops = {
+ .read_resources = DEVICE_NOOP,
+ .set_resources = DEVICE_NOOP,
+ .enable_resources = DEVICE_NOOP,
+#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
+ .acpi_name = &da7219_acpi_name,
+ .acpi_fill_ssdt_generator = &da7219_fill_ssdt,
+#endif
+};
+
+static void da7219_enable(struct device *dev)
+{
+ dev->ops = &da7219_ops;
+}
+
+struct chip_operations drivers_i2c_da7219_ops = {
+ CHIP_NAME("Dialog Semiconductor DA7219 Audio Codec")
+ .enable_dev = &da7219_enable
+};