blob: 8d674bcb4fa32788e237a50176b00407ce832d27 [file] [log] [blame]
Simon Glass0324b712020-07-07 21:32:17 -06001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * ACPI driver for DA7219 codec
4 *
5 * Copyright 2019 Google LLC
6 * Parts taken from coreboot
7 */
8
9#include <common.h>
10#include <dm.h>
11#include <i2c.h>
12#include <irq.h>
13#include <log.h>
14#include <acpi/acpigen.h>
15#include <acpi/acpi_device.h>
16#include <acpi/acpi_dp.h>
17#ifdef CONFIG_X86
18#include <asm/acpi_nhlt.h>
19#endif
20#include <asm-generic/gpio.h>
21#include <dt-bindings/sound/nhlt.h>
22#include <dm/acpi.h>
23
24#define DA7219_ACPI_HID "DLGS7219"
25
26static int da7219_acpi_fill_ssdt(const struct udevice *dev,
27 struct acpi_ctx *ctx)
28{
29 char scope[ACPI_PATH_MAX];
30 char name[ACPI_NAME_MAX];
31 struct acpi_dp *dsd, *aad;
32 ofnode node;
33 u32 val;
34 int ret;
35
36 ret = acpi_device_scope(dev, scope, sizeof(scope));
37 if (ret)
38 return log_msg_ret("scope", ret);
39 ret = acpi_get_name(dev, name);
40 if (ret)
41 return log_msg_ret("name", ret);
42
43 /* Device */
44 acpigen_write_scope(ctx, scope);
45 acpigen_write_device(ctx, name);
46 acpigen_write_name_string(ctx, "_HID", DA7219_ACPI_HID);
47 acpigen_write_name_integer(ctx, "_UID", 1);
48 acpigen_write_name_string(ctx, "_DDN",
49 dev_read_string(dev, "acpi,ddn"));
50 acpigen_write_name_integer(ctx, "_S0W", 4);
51 acpigen_write_sta(ctx, acpi_device_status(dev));
52
53 /* Resources */
54 acpigen_write_name(ctx, "_CRS");
55 acpigen_write_resourcetemplate_header(ctx);
56 ret = acpi_device_write_i2c_dev(ctx, dev);
Simon Glassdd30c5b2020-11-04 09:57:29 -070057 if (ret < 0)
Simon Glass0324b712020-07-07 21:32:17 -060058 return log_msg_ret("i2c", ret);
59
60 /* Use either Interrupt() or GpioInt() */
61 ret = acpi_device_write_interrupt_or_gpio(ctx, (struct udevice *)dev,
62 "req-gpios");
Simon Glassdd30c5b2020-11-04 09:57:29 -070063 if (ret < 0)
Simon Glass0324b712020-07-07 21:32:17 -060064 return log_msg_ret("irq_gpio", ret);
65 acpigen_write_resourcetemplate_footer(ctx);
66
67 /* AAD Child Device Properties */
68 aad = acpi_dp_new_table("DAAD");
69 if (!aad)
70 return log_msg_ret("aad", -ENOMEM);
71
72 node = ofnode_find_subnode(dev_ofnode(dev), "da7219_aad");
73 if (!ofnode_valid(node))
74 return log_msg_ret("da7219_aad", -EINVAL);
75 acpi_dp_ofnode_copy_int(node, aad, "dlg,btn-cfg");
76 acpi_dp_ofnode_copy_int(node, aad, "dlg,mic-det-thr");
77 acpi_dp_ofnode_copy_int(node, aad, "dlg,jack-ins-deb");
78 acpi_dp_ofnode_copy_str(node, aad, "dlg,jack-det-rate");
79 acpi_dp_ofnode_copy_int(node, aad, "dlg,jack-rem-deb");
80 acpi_dp_ofnode_copy_int(node, aad, "dlg,a-d-btn-thr");
81 acpi_dp_ofnode_copy_int(node, aad, "dlg,d-b-btn-thr");
82 acpi_dp_ofnode_copy_int(node, aad, "dlg,b-c-btn-thr");
83 acpi_dp_ofnode_copy_int(node, aad, "dlg,c-mic-btn-thr");
84 acpi_dp_ofnode_copy_int(node, aad, "dlg,btn-avg");
85 acpi_dp_ofnode_copy_int(node, aad, "dlg,adc-1bit-rpt");
86 if (!ofnode_read_u32(node, "dlg,micbias-pulse-lvl", &val)) {
87 acpi_dp_ofnode_copy_int(node, aad, "dlg,micbias-pulse-lvl");
88 acpi_dp_ofnode_copy_int(node, aad, "dlg,micbias-pulse-time");
89 }
90
91 /* DA7219 Properties */
92 dsd = acpi_dp_new_table("_DSD");
93 if (!dsd)
94 return log_msg_ret("dsd", -ENOMEM);
95 acpi_dp_dev_copy_int(dev, dsd, "dlg,micbias-lvl");
96 acpi_dp_dev_copy_str(dev, dsd, "dlg,mic-amp-in-sel");
97 acpi_dp_dev_copy_str(dev, dsd, "dlg,mclk-name");
98 acpi_dp_add_child(dsd, "da7219_aad", aad);
99
100 /* Write Device Property Hierarchy */
101 acpi_dp_write(ctx, dsd);
102
103 acpigen_pop_len(ctx); /* Device */
104 acpigen_pop_len(ctx); /* Scope */
105
106 return 0;
107}
108
109/* For now only X86 boards support NHLT */
110#ifdef CONFIG_X86
111static const struct nhlt_format_config da7219_formats[] = {
112 /* 48 KHz 24-bits per sample. */
113 {
114 .num_channels = 2,
115 .sample_freq_khz = 48,
116 .container_bits_per_sample = 32,
117 .valid_bits_per_sample = 24,
118 .settings_file = "dialog-2ch-48khz-24b.dat",
119 },
120};
121
122static const struct nhlt_tdm_config tdm_config = {
123 .virtual_slot = 0,
124 .config_type = NHLT_TDM_BASIC,
125};
126
127static const struct nhlt_endp_descriptor da7219_descriptors[] = {
128 /* Render Endpoint */
129 {
130 .link = NHLT_LINK_SSP,
131 .device = NHLT_SSP_DEV_I2S,
132 .direction = NHLT_DIR_RENDER,
133 .vid = NHLT_VID,
134 .did = NHLT_DID_SSP,
135 .cfg = &tdm_config,
136 .cfg_size = sizeof(tdm_config),
137 .formats = da7219_formats,
138 .num_formats = ARRAY_SIZE(da7219_formats),
139 },
140 /* Capture Endpoint */
141 {
142 .link = NHLT_LINK_SSP,
143 .device = NHLT_SSP_DEV_I2S,
144 .direction = NHLT_DIR_CAPTURE,
145 .vid = NHLT_VID,
146 .did = NHLT_DID_SSP,
147 .cfg = &tdm_config,
148 .cfg_size = sizeof(tdm_config),
149 .formats = da7219_formats,
150 .num_formats = ARRAY_SIZE(da7219_formats),
151 },
152};
153
154static int da7219_acpi_setup_nhlt(const struct udevice *dev,
155 struct acpi_ctx *ctx)
156{
157 u32 hwlink;
158 int ret;
159
160 if (dev_read_u32(dev, "acpi,audio-link", &hwlink))
161 return log_msg_ret("link", -EINVAL);
162
163 /* Virtual bus id of SSP links are the hardware port ids proper. */
164 ret = nhlt_add_ssp_endpoints(ctx->nhlt, hwlink, da7219_descriptors,
165 ARRAY_SIZE(da7219_descriptors));
166 if (ret)
167 return log_msg_ret("add", ret);
168
169 return 0;
170}
171#endif
172
173struct acpi_ops da7219_acpi_ops = {
174 .fill_ssdt = da7219_acpi_fill_ssdt,
175#ifdef CONFIG_X86
176 .setup_nhlt = da7219_acpi_setup_nhlt,
177#endif
178};
179
180static const struct udevice_id da7219_ids[] = {
181 { .compatible = "dlg,da7219" },
182 { }
183};
184
185U_BOOT_DRIVER(da7219) = {
186 .name = "da7219",
187 .id = UCLASS_MISC,
188 .of_match = da7219_ids,
189 ACPI_OPS_PTR(&da7219_acpi_ops)
190};