xref: /linux/drivers/soundwire/dmi-quirks.c (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2 // Copyright(c) 2021 Intel Corporation.
3 
4 /*
5  * Soundwire DMI quirks
6  */
7 
8 #include <linux/device.h>
9 #include <linux/dmi.h>
10 #include <linux/soundwire/sdw.h>
11 #include "bus.h"
12 
13 struct adr_remap {
14 	u64 adr;
15 	u64 remapped_adr;
16 };
17 
18 static const struct adr_remap global_ghost_adr[] = {
19 	{
20 		0x000000D010010500ull,
21 		0x0000000000000000ull
22 	},
23 	{}
24 };
25 
26 /*
27  * Some TigerLake devices based on an initial Intel BIOS do not expose
28  * the correct _ADR in the DSDT.
29  * Remap the bad _ADR values to the ones reported by hardware
30  */
31 static const struct adr_remap intel_tgl_bios[] = {
32 	{
33 		0x000010025D070100ull,
34 		0x000020025D071100ull
35 	},
36 	{
37 		0x000110025d070100ull,
38 		0x000120025D130800ull
39 	},
40 	{}
41 };
42 
43 /*
44  * The initial version of the Dell SKU 0A3E did not expose the devices
45  * on the correct links.
46  */
47 static const struct adr_remap dell_sku_0A3E[] = {
48 	/* rt715 on link0 */
49 	{
50 		0x00020025d071100ull,
51 		0x00021025d071500ull
52 	},
53 	/* rt711 on link1 */
54 	{
55 		0x000120025d130800ull,
56 		0x000120025d071100ull,
57 	},
58 	/* rt1308 on link2 */
59 	{
60 		0x000220025d071500ull,
61 		0x000220025d130800ull
62 	},
63 	{}
64 };
65 
66 /*
67  * The HP Omen 16-k0005TX does not expose the correct version of RT711 on link0
68  * and does not expose a RT1316 on link3
69  */
70 static const struct adr_remap hp_omen_16[] = {
71 	/* rt711-sdca on link0 */
72 	{
73 		0x000020025d071100ull,
74 		0x000030025d071101ull
75 	},
76 	/* rt1316-sdca on link3 */
77 	{
78 		0x000120025d071100ull,
79 		0x000330025d131601ull
80 	},
81 	{}
82 };
83 
84 /*
85  * Intel NUC M15 LAPRC510 and LAPRC710
86  */
87 static const struct adr_remap intel_rooks_county[] = {
88 	/* rt711-sdca on link0 */
89 	{
90 		0x000020025d071100ull,
91 		0x000030025d071101ull
92 	},
93 	/* rt1316-sdca on link2 */
94 	{
95 		0x000120025d071100ull,
96 		0x000230025d131601ull
97 	},
98 	{}
99 };
100 
101 /*
102  * Many platforms have ghost realtek devices in the ACPI that don't physically
103  * exist, remove those devices.
104  */
105 static const struct adr_remap ghost_realtek[] = {
106 	/* rt722 on link3 */
107 	{
108 		0x000330025d072201ull,
109 		0x0000000000000000ull
110 	},
111 	{}
112 };
113 
114 static const struct dmi_system_id adr_remap_quirk_table[] = {
115 	/* TGL devices */
116 	{
117 		.matches = {
118 			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
119 			DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Conv"),
120 		},
121 		.driver_data = (void *)intel_tgl_bios,
122 	},
123 	{
124 		.matches = {
125 			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
126 			DMI_MATCH(DMI_BOARD_NAME, "8709"),
127 		},
128 		.driver_data = (void *)intel_tgl_bios,
129 	},
130 	{
131 		/* quirk used for NUC15 'Bishop County' LAPBC510 and LAPBC710 skews */
132 		.matches = {
133 			DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
134 			DMI_MATCH(DMI_PRODUCT_NAME, "LAPBC"),
135 		},
136 		.driver_data = (void *)intel_tgl_bios,
137 	},
138 	{
139 		/* quirk used for NUC15 LAPBC710 skew */
140 		.matches = {
141 			DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
142 			DMI_MATCH(DMI_BOARD_NAME, "LAPBC710"),
143 		},
144 		.driver_data = (void *)intel_tgl_bios,
145 	},
146 	{
147 		/*
148 		 * quirk used for Avell B.ON (OEM rebrand of NUC15 'Bishop County'
149 		 * LAPBC510 and LAPBC710)
150 		 */
151 		.matches = {
152 			DMI_MATCH(DMI_SYS_VENDOR, "Avell High Performance"),
153 			DMI_MATCH(DMI_PRODUCT_NAME, "B.ON"),
154 		},
155 		.driver_data = (void *)intel_tgl_bios,
156 	},
157 	{
158 		/* quirk used for NUC15 'Rooks County' LAPRC510 and LAPRC710 skews */
159 		.matches = {
160 			DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
161 			DMI_MATCH(DMI_PRODUCT_NAME, "LAPRC"),
162 		},
163 		.driver_data = (void *)intel_rooks_county,
164 	},
165 	{
166 		/* quirk used for NUC15 LAPRC710 skew */
167 		.matches = {
168 			DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
169 			DMI_MATCH(DMI_BOARD_NAME, "LAPRC710"),
170 		},
171 		.driver_data = (void *)intel_rooks_county,
172 	},
173 	{
174 		.matches = {
175 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
176 			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E")
177 		},
178 		.driver_data = (void *)dell_sku_0A3E,
179 	},
180 	/* ADL devices */
181 	{
182 		.matches = {
183 			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
184 			DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16"),
185 		},
186 		.driver_data = (void *)hp_omen_16,
187 	},
188 	/* PTL devices */
189 	{
190 		.matches = {
191 			DMI_MATCH(DMI_SYS_VENDOR, "ASUS"),
192 			DMI_MATCH(DMI_BOARD_NAME, "B9406CAA"),
193 		},
194 		.driver_data = (void *)ghost_realtek,
195 	},
196 	{
197 		.matches = {
198 			DMI_MATCH(DMI_SYS_VENDOR, "ASUS"),
199 			DMI_MATCH(DMI_BOARD_NAME, "GX651AR"),
200 		},
201 		.driver_data = (void *)ghost_realtek,
202 	},
203 	{
204 		.matches = {
205 			DMI_MATCH(DMI_SYS_VENDOR, "ASUS"),
206 			DMI_MATCH(DMI_BOARD_NAME, "UX5406AA"),
207 		},
208 		.driver_data = (void *)ghost_realtek,
209 	},
210 	{
211 		.matches = {
212 			DMI_MATCH(DMI_SYS_VENDOR, "ASUS"),
213 			DMI_MATCH(DMI_BOARD_NAME, "UX8407AA"),
214 		},
215 		.driver_data = (void *)ghost_realtek,
216 	},
217 	{
218 		.matches = {
219 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
220 			DMI_MATCH(DMI_PRODUCT_NAME, "83QK"),
221 		},
222 		.driver_data = (void *)ghost_realtek,
223 	},
224 	{
225 		.matches = {
226 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
227 			DMI_MATCH(DMI_PRODUCT_NAME, "83SF"),
228 		},
229 		.driver_data = (void *)ghost_realtek,
230 	},
231 	{}
232 };
233 
234 u64 sdw_dmi_override_adr(struct sdw_bus *bus, u64 addr)
235 {
236 	const struct dmi_system_id *dmi_id;
237 	int i;
238 
239 	/* check if any address remap quirk applies */
240 	dmi_id = dmi_first_match(adr_remap_quirk_table);
241 	if (dmi_id) {
242 		struct adr_remap *map;
243 
244 		for (map = dmi_id->driver_data; map->adr; map++) {
245 			if (map->adr == addr) {
246 				dev_dbg(bus->dev, "remapped _ADR 0x%llx as 0x%llx\n",
247 					addr, map->remapped_adr);
248 				addr = map->remapped_adr;
249 				goto out;
250 			}
251 		}
252 	}
253 
254 	/* remap the ghost ADRs */
255 	for (i = 0; i < ARRAY_SIZE(global_ghost_adr); i++) {
256 		if (global_ghost_adr[i].adr == addr) {
257 			dev_dbg(bus->dev, "remapped _ADR 0x%llx as 0x%llx\n",
258 				addr, global_ghost_adr[i].remapped_adr);
259 			addr = global_ghost_adr[i].remapped_adr;
260 			break;
261 		}
262 	}
263 out:
264 	return addr;
265 }
266