1 | // SPDX-License-Identifier: GPL-2.0-only |
---|---|
2 | /* |
3 | * Copyright (C) 2020 BayLibre, SAS |
4 | * Author: Phong LE <ple@baylibre.com> |
5 | * Copyright (C) 2018-2019, Artem Mygaiev |
6 | * Copyright (C) 2017, Fresco Logic, Incorporated. |
7 | * |
8 | */ |
9 | |
10 | #include <linux/media-bus-format.h> |
11 | #include <linux/module.h> |
12 | #include <linux/device.h> |
13 | #include <linux/interrupt.h> |
14 | #include <linux/i2c.h> |
15 | #include <linux/bitfield.h> |
16 | #include <linux/property.h> |
17 | #include <linux/regmap.h> |
18 | #include <linux/of_graph.h> |
19 | #include <linux/gpio/consumer.h> |
20 | #include <linux/pinctrl/consumer.h> |
21 | #include <linux/regulator/consumer.h> |
22 | |
23 | #include <drm/drm_atomic_helper.h> |
24 | #include <drm/drm_bridge.h> |
25 | #include <drm/drm_edid.h> |
26 | #include <drm/drm_modes.h> |
27 | #include <drm/drm_print.h> |
28 | #include <drm/drm_probe_helper.h> |
29 | |
30 | #include <sound/hdmi-codec.h> |
31 | |
32 | #define IT66121_VENDOR_ID0_REG 0x00 |
33 | #define IT66121_VENDOR_ID1_REG 0x01 |
34 | #define IT66121_DEVICE_ID0_REG 0x02 |
35 | #define IT66121_DEVICE_ID1_REG 0x03 |
36 | |
37 | #define IT66121_REVISION_MASK GENMASK(7, 4) |
38 | #define IT66121_DEVICE_ID1_MASK GENMASK(3, 0) |
39 | |
40 | #define IT66121_MASTER_SEL_REG 0x10 |
41 | #define IT66121_MASTER_SEL_HOST BIT(0) |
42 | |
43 | #define IT66121_AFE_DRV_REG 0x61 |
44 | #define IT66121_AFE_DRV_RST BIT(4) |
45 | #define IT66121_AFE_DRV_PWD BIT(5) |
46 | |
47 | #define IT66121_INPUT_MODE_REG 0x70 |
48 | #define IT66121_INPUT_MODE_RGB (0 << 6) |
49 | #define IT66121_INPUT_MODE_YUV422 BIT(6) |
50 | #define IT66121_INPUT_MODE_YUV444 (2 << 6) |
51 | #define IT66121_INPUT_MODE_CCIR656 BIT(4) |
52 | #define IT66121_INPUT_MODE_SYNCEMB BIT(3) |
53 | #define IT66121_INPUT_MODE_DDR BIT(2) |
54 | |
55 | #define IT66121_INPUT_CSC_REG 0x72 |
56 | #define IT66121_INPUT_CSC_ENDITHER BIT(7) |
57 | #define IT66121_INPUT_CSC_ENUDFILTER BIT(6) |
58 | #define IT66121_INPUT_CSC_DNFREE_GO BIT(5) |
59 | #define IT66121_INPUT_CSC_RGB_TO_YUV 0x02 |
60 | #define IT66121_INPUT_CSC_YUV_TO_RGB 0x03 |
61 | #define IT66121_INPUT_CSC_NO_CONV 0x00 |
62 | |
63 | #define IT66121_AFE_XP_REG 0x62 |
64 | #define IT66121_AFE_XP_GAINBIT BIT(7) |
65 | #define IT66121_AFE_XP_PWDPLL BIT(6) |
66 | #define IT66121_AFE_XP_ENI BIT(5) |
67 | #define IT66121_AFE_XP_ENO BIT(4) |
68 | #define IT66121_AFE_XP_RESETB BIT(3) |
69 | #define IT66121_AFE_XP_PWDI BIT(2) |
70 | #define IT6610_AFE_XP_BYPASS BIT(0) |
71 | |
72 | #define IT66121_AFE_IP_REG 0x64 |
73 | #define IT66121_AFE_IP_GAINBIT BIT(7) |
74 | #define IT66121_AFE_IP_PWDPLL BIT(6) |
75 | #define IT66121_AFE_IP_CKSEL_05 (0 << 4) |
76 | #define IT66121_AFE_IP_CKSEL_1 BIT(4) |
77 | #define IT66121_AFE_IP_CKSEL_2 (2 << 4) |
78 | #define IT66121_AFE_IP_CKSEL_2OR4 (3 << 4) |
79 | #define IT66121_AFE_IP_ER0 BIT(3) |
80 | #define IT66121_AFE_IP_RESETB BIT(2) |
81 | #define IT66121_AFE_IP_ENC BIT(1) |
82 | #define IT66121_AFE_IP_EC1 BIT(0) |
83 | |
84 | #define IT66121_AFE_XP_EC1_REG 0x68 |
85 | #define IT66121_AFE_XP_EC1_LOWCLK BIT(4) |
86 | |
87 | #define IT66121_SW_RST_REG 0x04 |
88 | #define IT66121_SW_RST_REF BIT(5) |
89 | #define IT66121_SW_RST_AREF BIT(4) |
90 | #define IT66121_SW_RST_VID BIT(3) |
91 | #define IT66121_SW_RST_AUD BIT(2) |
92 | #define IT66121_SW_RST_HDCP BIT(0) |
93 | |
94 | #define IT66121_DDC_COMMAND_REG 0x15 |
95 | #define IT66121_DDC_COMMAND_BURST_READ 0x0 |
96 | #define IT66121_DDC_COMMAND_EDID_READ 0x3 |
97 | #define IT66121_DDC_COMMAND_FIFO_CLR 0x9 |
98 | #define IT66121_DDC_COMMAND_SCL_PULSE 0xA |
99 | #define IT66121_DDC_COMMAND_ABORT 0xF |
100 | |
101 | #define IT66121_HDCP_REG 0x20 |
102 | #define IT66121_HDCP_CPDESIRED BIT(0) |
103 | #define IT66121_HDCP_EN1P1FEAT BIT(1) |
104 | |
105 | #define IT66121_INT_STATUS1_REG 0x06 |
106 | #define IT66121_INT_STATUS1_AUD_OVF BIT(7) |
107 | #define IT66121_INT_STATUS1_DDC_NOACK BIT(5) |
108 | #define IT66121_INT_STATUS1_DDC_FIFOERR BIT(4) |
109 | #define IT66121_INT_STATUS1_DDC_BUSHANG BIT(2) |
110 | #define IT66121_INT_STATUS1_RX_SENS_STATUS BIT(1) |
111 | #define IT66121_INT_STATUS1_HPD_STATUS BIT(0) |
112 | |
113 | #define IT66121_DDC_HEADER_REG 0x11 |
114 | #define IT66121_DDC_HEADER_HDCP 0x74 |
115 | #define IT66121_DDC_HEADER_EDID 0xA0 |
116 | |
117 | #define IT66121_DDC_OFFSET_REG 0x12 |
118 | #define IT66121_DDC_BYTE_REG 0x13 |
119 | #define IT66121_DDC_SEGMENT_REG 0x14 |
120 | #define IT66121_DDC_RD_FIFO_REG 0x17 |
121 | |
122 | #define IT66121_CLK_BANK_REG 0x0F |
123 | #define IT66121_CLK_BANK_PWROFF_RCLK BIT(6) |
124 | #define IT66121_CLK_BANK_PWROFF_ACLK BIT(5) |
125 | #define IT66121_CLK_BANK_PWROFF_TXCLK BIT(4) |
126 | #define IT66121_CLK_BANK_PWROFF_CRCLK BIT(3) |
127 | #define IT66121_CLK_BANK_0 0 |
128 | #define IT66121_CLK_BANK_1 1 |
129 | |
130 | #define IT66121_INT_REG 0x05 |
131 | #define IT66121_INT_ACTIVE_HIGH BIT(7) |
132 | #define IT66121_INT_OPEN_DRAIN BIT(6) |
133 | #define IT66121_INT_TX_CLK_OFF BIT(0) |
134 | |
135 | #define IT66121_INT_MASK1_REG 0x09 |
136 | #define IT66121_INT_MASK1_AUD_OVF BIT(7) |
137 | #define IT66121_INT_MASK1_DDC_NOACK BIT(5) |
138 | #define IT66121_INT_MASK1_DDC_FIFOERR BIT(4) |
139 | #define IT66121_INT_MASK1_DDC_BUSHANG BIT(2) |
140 | #define IT66121_INT_MASK1_RX_SENS BIT(1) |
141 | #define IT66121_INT_MASK1_HPD BIT(0) |
142 | |
143 | #define IT66121_INT_CLR1_REG 0x0C |
144 | #define IT66121_INT_CLR1_PKTACP BIT(7) |
145 | #define IT66121_INT_CLR1_PKTNULL BIT(6) |
146 | #define IT66121_INT_CLR1_PKTGEN BIT(5) |
147 | #define IT66121_INT_CLR1_KSVLISTCHK BIT(4) |
148 | #define IT66121_INT_CLR1_AUTHDONE BIT(3) |
149 | #define IT66121_INT_CLR1_AUTHFAIL BIT(2) |
150 | #define IT66121_INT_CLR1_RX_SENS BIT(1) |
151 | #define IT66121_INT_CLR1_HPD BIT(0) |
152 | |
153 | #define IT66121_AV_MUTE_REG 0xC1 |
154 | #define IT66121_AV_MUTE_ON BIT(0) |
155 | #define IT66121_AV_MUTE_BLUESCR BIT(1) |
156 | |
157 | #define IT66121_PKT_CTS_CTRL_REG 0xC5 |
158 | #define IT66121_PKT_CTS_CTRL_SEL BIT(1) |
159 | |
160 | #define IT66121_PKT_GEN_CTRL_REG 0xC6 |
161 | #define IT66121_PKT_GEN_CTRL_ON BIT(0) |
162 | #define IT66121_PKT_GEN_CTRL_RPT BIT(1) |
163 | |
164 | #define IT66121_AVIINFO_DB1_REG 0x158 |
165 | #define IT66121_AVIINFO_DB2_REG 0x159 |
166 | #define IT66121_AVIINFO_DB3_REG 0x15A |
167 | #define IT66121_AVIINFO_DB4_REG 0x15B |
168 | #define IT66121_AVIINFO_DB5_REG 0x15C |
169 | #define IT66121_AVIINFO_CSUM_REG 0x15D |
170 | #define IT66121_AVIINFO_DB6_REG 0x15E |
171 | #define IT66121_AVIINFO_DB7_REG 0x15F |
172 | #define IT66121_AVIINFO_DB8_REG 0x160 |
173 | #define IT66121_AVIINFO_DB9_REG 0x161 |
174 | #define IT66121_AVIINFO_DB10_REG 0x162 |
175 | #define IT66121_AVIINFO_DB11_REG 0x163 |
176 | #define IT66121_AVIINFO_DB12_REG 0x164 |
177 | #define IT66121_AVIINFO_DB13_REG 0x165 |
178 | |
179 | #define IT66121_AVI_INFO_PKT_REG 0xCD |
180 | #define IT66121_AVI_INFO_PKT_ON BIT(0) |
181 | #define IT66121_AVI_INFO_PKT_RPT BIT(1) |
182 | |
183 | #define IT66121_HDMI_MODE_REG 0xC0 |
184 | #define IT66121_HDMI_MODE_HDMI BIT(0) |
185 | |
186 | #define IT66121_SYS_STATUS_REG 0x0E |
187 | #define IT66121_SYS_STATUS_ACTIVE_IRQ BIT(7) |
188 | #define IT66121_SYS_STATUS_HPDETECT BIT(6) |
189 | #define IT66121_SYS_STATUS_SENDECTECT BIT(5) |
190 | #define IT66121_SYS_STATUS_VID_STABLE BIT(4) |
191 | #define IT66121_SYS_STATUS_AUD_CTS_CLR BIT(1) |
192 | #define IT66121_SYS_STATUS_CLEAR_IRQ BIT(0) |
193 | |
194 | #define IT66121_DDC_STATUS_REG 0x16 |
195 | #define IT66121_DDC_STATUS_TX_DONE BIT(7) |
196 | #define IT66121_DDC_STATUS_ACTIVE BIT(6) |
197 | #define IT66121_DDC_STATUS_NOACK BIT(5) |
198 | #define IT66121_DDC_STATUS_WAIT_BUS BIT(4) |
199 | #define IT66121_DDC_STATUS_ARBI_LOSE BIT(3) |
200 | #define IT66121_DDC_STATUS_FIFO_FULL BIT(2) |
201 | #define IT66121_DDC_STATUS_FIFO_EMPTY BIT(1) |
202 | #define IT66121_DDC_STATUS_FIFO_VALID BIT(0) |
203 | |
204 | #define IT66121_EDID_SLEEP_US 20000 |
205 | #define IT66121_EDID_TIMEOUT_US 200000 |
206 | #define IT66121_EDID_FIFO_SIZE 32 |
207 | |
208 | #define IT66121_CLK_CTRL0_REG 0x58 |
209 | #define IT66121_CLK_CTRL0_AUTO_OVER_SAMPLING BIT(4) |
210 | #define IT66121_CLK_CTRL0_EXT_MCLK_MASK GENMASK(3, 2) |
211 | #define IT66121_CLK_CTRL0_EXT_MCLK_128FS (0 << 2) |
212 | #define IT66121_CLK_CTRL0_EXT_MCLK_256FS BIT(2) |
213 | #define IT66121_CLK_CTRL0_EXT_MCLK_512FS (2 << 2) |
214 | #define IT66121_CLK_CTRL0_EXT_MCLK_1024FS (3 << 2) |
215 | #define IT66121_CLK_CTRL0_AUTO_IPCLK BIT(0) |
216 | #define IT66121_CLK_STATUS1_REG 0x5E |
217 | #define IT66121_CLK_STATUS2_REG 0x5F |
218 | |
219 | #define IT66121_AUD_CTRL0_REG 0xE0 |
220 | #define IT66121_AUD_SWL (3 << 6) |
221 | #define IT66121_AUD_16BIT (0 << 6) |
222 | #define IT66121_AUD_18BIT BIT(6) |
223 | #define IT66121_AUD_20BIT (2 << 6) |
224 | #define IT66121_AUD_24BIT (3 << 6) |
225 | #define IT66121_AUD_SPDIFTC BIT(5) |
226 | #define IT66121_AUD_SPDIF BIT(4) |
227 | #define IT66121_AUD_I2S (0 << 4) |
228 | #define IT66121_AUD_EN_I2S3 BIT(3) |
229 | #define IT66121_AUD_EN_I2S2 BIT(2) |
230 | #define IT66121_AUD_EN_I2S1 BIT(1) |
231 | #define IT66121_AUD_EN_I2S0 BIT(0) |
232 | #define IT66121_AUD_CTRL0_AUD_SEL BIT(4) |
233 | |
234 | #define IT66121_AUD_CTRL1_REG 0xE1 |
235 | #define IT66121_AUD_FIFOMAP_REG 0xE2 |
236 | #define IT66121_AUD_CTRL3_REG 0xE3 |
237 | #define IT66121_AUD_SRCVALID_FLAT_REG 0xE4 |
238 | #define IT66121_AUD_FLAT_SRC0 BIT(4) |
239 | #define IT66121_AUD_FLAT_SRC1 BIT(5) |
240 | #define IT66121_AUD_FLAT_SRC2 BIT(6) |
241 | #define IT66121_AUD_FLAT_SRC3 BIT(7) |
242 | #define IT66121_AUD_HDAUDIO_REG 0xE5 |
243 | |
244 | #define IT66121_AUD_PKT_CTS0_REG 0x130 |
245 | #define IT66121_AUD_PKT_CTS1_REG 0x131 |
246 | #define IT66121_AUD_PKT_CTS2_REG 0x132 |
247 | #define IT66121_AUD_PKT_N0_REG 0x133 |
248 | #define IT66121_AUD_PKT_N1_REG 0x134 |
249 | #define IT66121_AUD_PKT_N2_REG 0x135 |
250 | |
251 | #define IT66121_AUD_CHST_MODE_REG 0x191 |
252 | #define IT66121_AUD_CHST_CAT_REG 0x192 |
253 | #define IT66121_AUD_CHST_SRCNUM_REG 0x193 |
254 | #define IT66121_AUD_CHST_CHTNUM_REG 0x194 |
255 | #define IT66121_AUD_CHST_CA_FS_REG 0x198 |
256 | #define IT66121_AUD_CHST_OFS_WL_REG 0x199 |
257 | |
258 | #define IT66121_AUD_PKT_CTS_CNT0_REG 0x1A0 |
259 | #define IT66121_AUD_PKT_CTS_CNT1_REG 0x1A1 |
260 | #define IT66121_AUD_PKT_CTS_CNT2_REG 0x1A2 |
261 | |
262 | #define IT66121_AUD_FS_22P05K 0x4 |
263 | #define IT66121_AUD_FS_44P1K 0x0 |
264 | #define IT66121_AUD_FS_88P2K 0x8 |
265 | #define IT66121_AUD_FS_176P4K 0xC |
266 | #define IT66121_AUD_FS_24K 0x6 |
267 | #define IT66121_AUD_FS_48K 0x2 |
268 | #define IT66121_AUD_FS_96K 0xA |
269 | #define IT66121_AUD_FS_192K 0xE |
270 | #define IT66121_AUD_FS_768K 0x9 |
271 | #define IT66121_AUD_FS_32K 0x3 |
272 | #define IT66121_AUD_FS_OTHER 0x1 |
273 | |
274 | #define IT66121_AUD_SWL_21BIT 0xD |
275 | #define IT66121_AUD_SWL_24BIT 0xB |
276 | #define IT66121_AUD_SWL_23BIT 0x9 |
277 | #define IT66121_AUD_SWL_22BIT 0x5 |
278 | #define IT66121_AUD_SWL_20BIT 0x3 |
279 | #define IT66121_AUD_SWL_17BIT 0xC |
280 | #define IT66121_AUD_SWL_19BIT 0x8 |
281 | #define IT66121_AUD_SWL_18BIT 0x4 |
282 | #define IT66121_AUD_SWL_16BIT 0x2 |
283 | #define IT66121_AUD_SWL_NOT_INDICATED 0x0 |
284 | |
285 | #define IT66121_AFE_CLK_HIGH 80000 /* Khz */ |
286 | |
287 | enum chip_id { |
288 | ID_IT6610, |
289 | ID_IT66121, |
290 | }; |
291 | |
292 | struct it66121_chip_info { |
293 | enum chip_id id; |
294 | u16 vid, pid; |
295 | }; |
296 | |
297 | struct it66121_ctx { |
298 | struct regmap *regmap; |
299 | struct drm_bridge bridge; |
300 | struct drm_bridge *next_bridge; |
301 | struct drm_connector *connector; |
302 | struct device *dev; |
303 | struct gpio_desc *gpio_reset; |
304 | struct i2c_client *client; |
305 | u32 bus_width; |
306 | struct mutex lock; /* Protects fields below and device registers */ |
307 | struct hdmi_avi_infoframe hdmi_avi_infoframe; |
308 | struct { |
309 | struct platform_device *pdev; |
310 | u8 ch_enable; |
311 | u8 fs; |
312 | u8 swl; |
313 | bool auto_cts; |
314 | } audio; |
315 | const struct it66121_chip_info *info; |
316 | }; |
317 | |
318 | static const struct regmap_range_cfg it66121_regmap_banks[] = { |
319 | { |
320 | .name = "it66121", |
321 | .range_min = 0x00, |
322 | .range_max = 0x1FF, |
323 | .selector_reg = IT66121_CLK_BANK_REG, |
324 | .selector_mask = 0x1, |
325 | .selector_shift = 0, |
326 | .window_start = 0x00, |
327 | .window_len = 0x100, |
328 | }, |
329 | }; |
330 | |
331 | static const struct regmap_config it66121_regmap_config = { |
332 | .val_bits = 8, |
333 | .reg_bits = 8, |
334 | .max_register = 0x1FF, |
335 | .ranges = it66121_regmap_banks, |
336 | .num_ranges = ARRAY_SIZE(it66121_regmap_banks), |
337 | }; |
338 | |
339 | static void it66121_hw_reset(struct it66121_ctx *ctx) |
340 | { |
341 | gpiod_set_value(desc: ctx->gpio_reset, value: 1); |
342 | msleep(msecs: 20); |
343 | gpiod_set_value(desc: ctx->gpio_reset, value: 0); |
344 | } |
345 | |
346 | static inline int it66121_preamble_ddc(struct it66121_ctx *ctx) |
347 | { |
348 | return regmap_write(map: ctx->regmap, IT66121_MASTER_SEL_REG, IT66121_MASTER_SEL_HOST); |
349 | } |
350 | |
351 | static inline int it66121_fire_afe(struct it66121_ctx *ctx) |
352 | { |
353 | return regmap_write(map: ctx->regmap, IT66121_AFE_DRV_REG, val: 0); |
354 | } |
355 | |
356 | /* TOFIX: Handle YCbCr Input & Output */ |
357 | static int it66121_configure_input(struct it66121_ctx *ctx) |
358 | { |
359 | int ret; |
360 | u8 mode = IT66121_INPUT_MODE_RGB; |
361 | |
362 | if (ctx->bus_width == 12) |
363 | mode |= IT66121_INPUT_MODE_DDR; |
364 | |
365 | ret = regmap_write(map: ctx->regmap, IT66121_INPUT_MODE_REG, val: mode); |
366 | if (ret) |
367 | return ret; |
368 | |
369 | return regmap_write(map: ctx->regmap, IT66121_INPUT_CSC_REG, IT66121_INPUT_CSC_NO_CONV); |
370 | } |
371 | |
372 | /** |
373 | * it66121_configure_afe() - Configure the analog front end |
374 | * @ctx: it66121_ctx object |
375 | * @mode: mode to configure |
376 | * |
377 | * RETURNS: |
378 | * zero if success, a negative error code otherwise. |
379 | */ |
380 | static int it66121_configure_afe(struct it66121_ctx *ctx, |
381 | const struct drm_display_mode *mode) |
382 | { |
383 | int ret; |
384 | |
385 | ret = regmap_write(map: ctx->regmap, IT66121_AFE_DRV_REG, |
386 | IT66121_AFE_DRV_RST); |
387 | if (ret) |
388 | return ret; |
389 | |
390 | if (mode->clock > IT66121_AFE_CLK_HIGH) { |
391 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AFE_XP_REG, |
392 | IT66121_AFE_XP_GAINBIT | |
393 | IT66121_AFE_XP_ENO, |
394 | IT66121_AFE_XP_GAINBIT); |
395 | if (ret) |
396 | return ret; |
397 | |
398 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AFE_IP_REG, |
399 | IT66121_AFE_IP_GAINBIT | |
400 | IT66121_AFE_IP_ER0, |
401 | IT66121_AFE_IP_GAINBIT); |
402 | if (ret) |
403 | return ret; |
404 | |
405 | if (ctx->info->id == ID_IT66121) { |
406 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AFE_IP_REG, |
407 | IT66121_AFE_IP_EC1, val: 0); |
408 | if (ret) |
409 | return ret; |
410 | |
411 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AFE_XP_EC1_REG, |
412 | IT66121_AFE_XP_EC1_LOWCLK, val: 0x80); |
413 | if (ret) |
414 | return ret; |
415 | } |
416 | } else { |
417 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AFE_XP_REG, |
418 | IT66121_AFE_XP_GAINBIT | |
419 | IT66121_AFE_XP_ENO, |
420 | IT66121_AFE_XP_ENO); |
421 | if (ret) |
422 | return ret; |
423 | |
424 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AFE_IP_REG, |
425 | IT66121_AFE_IP_GAINBIT | |
426 | IT66121_AFE_IP_ER0, |
427 | IT66121_AFE_IP_ER0); |
428 | if (ret) |
429 | return ret; |
430 | |
431 | if (ctx->info->id == ID_IT66121) { |
432 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AFE_IP_REG, |
433 | IT66121_AFE_IP_EC1, |
434 | IT66121_AFE_IP_EC1); |
435 | if (ret) |
436 | return ret; |
437 | |
438 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AFE_XP_EC1_REG, |
439 | IT66121_AFE_XP_EC1_LOWCLK, |
440 | IT66121_AFE_XP_EC1_LOWCLK); |
441 | if (ret) |
442 | return ret; |
443 | } |
444 | } |
445 | |
446 | /* Clear reset flags */ |
447 | ret = regmap_write_bits(map: ctx->regmap, IT66121_SW_RST_REG, |
448 | IT66121_SW_RST_REF | IT66121_SW_RST_VID, val: 0); |
449 | if (ret) |
450 | return ret; |
451 | |
452 | if (ctx->info->id == ID_IT6610) { |
453 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AFE_XP_REG, |
454 | IT6610_AFE_XP_BYPASS, |
455 | IT6610_AFE_XP_BYPASS); |
456 | if (ret) |
457 | return ret; |
458 | } |
459 | |
460 | return it66121_fire_afe(ctx); |
461 | } |
462 | |
463 | static inline int it66121_wait_ddc_ready(struct it66121_ctx *ctx) |
464 | { |
465 | int ret, val; |
466 | u32 error = IT66121_DDC_STATUS_NOACK | IT66121_DDC_STATUS_WAIT_BUS | |
467 | IT66121_DDC_STATUS_ARBI_LOSE; |
468 | u32 done = IT66121_DDC_STATUS_TX_DONE; |
469 | |
470 | ret = regmap_read_poll_timeout(ctx->regmap, IT66121_DDC_STATUS_REG, val, |
471 | val & (error | done), IT66121_EDID_SLEEP_US, |
472 | IT66121_EDID_TIMEOUT_US); |
473 | if (ret) |
474 | return ret; |
475 | |
476 | if (val & error) |
477 | return -EAGAIN; |
478 | |
479 | return 0; |
480 | } |
481 | |
482 | static int it66121_abort_ddc_ops(struct it66121_ctx *ctx) |
483 | { |
484 | int ret; |
485 | unsigned int swreset, cpdesire; |
486 | |
487 | ret = regmap_read(map: ctx->regmap, IT66121_SW_RST_REG, val: &swreset); |
488 | if (ret) |
489 | return ret; |
490 | |
491 | ret = regmap_read(map: ctx->regmap, IT66121_HDCP_REG, val: &cpdesire); |
492 | if (ret) |
493 | return ret; |
494 | |
495 | ret = regmap_write(map: ctx->regmap, IT66121_HDCP_REG, |
496 | val: cpdesire & (~IT66121_HDCP_CPDESIRED & 0xFF)); |
497 | if (ret) |
498 | return ret; |
499 | |
500 | ret = regmap_write(map: ctx->regmap, IT66121_SW_RST_REG, |
501 | val: (swreset | IT66121_SW_RST_HDCP)); |
502 | if (ret) |
503 | return ret; |
504 | |
505 | ret = it66121_preamble_ddc(ctx); |
506 | if (ret) |
507 | return ret; |
508 | |
509 | ret = regmap_write(map: ctx->regmap, IT66121_DDC_COMMAND_REG, |
510 | IT66121_DDC_COMMAND_ABORT); |
511 | if (ret) |
512 | return ret; |
513 | |
514 | return it66121_wait_ddc_ready(ctx); |
515 | } |
516 | |
517 | static int it66121_get_edid_block(void *context, u8 *buf, |
518 | unsigned int block, size_t len) |
519 | { |
520 | struct it66121_ctx *ctx = context; |
521 | int remain = len; |
522 | int offset = 0; |
523 | int ret, cnt; |
524 | |
525 | offset = (block % 2) * len; |
526 | block = block / 2; |
527 | |
528 | while (remain > 0) { |
529 | cnt = (remain > IT66121_EDID_FIFO_SIZE) ? |
530 | IT66121_EDID_FIFO_SIZE : remain; |
531 | |
532 | ret = regmap_write(map: ctx->regmap, IT66121_DDC_COMMAND_REG, |
533 | IT66121_DDC_COMMAND_FIFO_CLR); |
534 | if (ret) |
535 | return ret; |
536 | |
537 | ret = it66121_wait_ddc_ready(ctx); |
538 | if (ret) |
539 | return ret; |
540 | |
541 | ret = regmap_write(map: ctx->regmap, IT66121_DDC_OFFSET_REG, val: offset); |
542 | if (ret) |
543 | return ret; |
544 | |
545 | ret = regmap_write(map: ctx->regmap, IT66121_DDC_BYTE_REG, val: cnt); |
546 | if (ret) |
547 | return ret; |
548 | |
549 | ret = regmap_write(map: ctx->regmap, IT66121_DDC_SEGMENT_REG, val: block); |
550 | if (ret) |
551 | return ret; |
552 | |
553 | ret = regmap_write(map: ctx->regmap, IT66121_DDC_COMMAND_REG, |
554 | IT66121_DDC_COMMAND_EDID_READ); |
555 | if (ret) |
556 | return ret; |
557 | |
558 | offset += cnt; |
559 | remain -= cnt; |
560 | |
561 | ret = it66121_wait_ddc_ready(ctx); |
562 | if (ret) { |
563 | it66121_abort_ddc_ops(ctx); |
564 | return ret; |
565 | } |
566 | |
567 | ret = regmap_noinc_read(map: ctx->regmap, IT66121_DDC_RD_FIFO_REG, |
568 | val: buf, val_len: cnt); |
569 | if (ret) |
570 | return ret; |
571 | |
572 | buf += cnt; |
573 | } |
574 | |
575 | return 0; |
576 | } |
577 | |
578 | static bool it66121_is_hpd_detect(struct it66121_ctx *ctx) |
579 | { |
580 | int val; |
581 | |
582 | if (regmap_read(map: ctx->regmap, IT66121_SYS_STATUS_REG, val: &val)) |
583 | return false; |
584 | |
585 | return val & IT66121_SYS_STATUS_HPDETECT; |
586 | } |
587 | |
588 | static int it66121_bridge_attach(struct drm_bridge *bridge, |
589 | enum drm_bridge_attach_flags flags) |
590 | { |
591 | struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge); |
592 | int ret; |
593 | |
594 | if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) |
595 | return -EINVAL; |
596 | |
597 | ret = drm_bridge_attach(encoder: bridge->encoder, bridge: ctx->next_bridge, previous: bridge, flags); |
598 | if (ret) |
599 | return ret; |
600 | |
601 | if (ctx->info->id == ID_IT66121) { |
602 | ret = regmap_write_bits(map: ctx->regmap, IT66121_CLK_BANK_REG, |
603 | IT66121_CLK_BANK_PWROFF_RCLK, val: 0); |
604 | if (ret) |
605 | return ret; |
606 | } |
607 | |
608 | ret = regmap_write_bits(map: ctx->regmap, IT66121_INT_REG, |
609 | IT66121_INT_TX_CLK_OFF, val: 0); |
610 | if (ret) |
611 | return ret; |
612 | |
613 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AFE_DRV_REG, |
614 | IT66121_AFE_DRV_PWD, val: 0); |
615 | if (ret) |
616 | return ret; |
617 | |
618 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AFE_XP_REG, |
619 | IT66121_AFE_XP_PWDI | IT66121_AFE_XP_PWDPLL, val: 0); |
620 | if (ret) |
621 | return ret; |
622 | |
623 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AFE_IP_REG, |
624 | IT66121_AFE_IP_PWDPLL, val: 0); |
625 | if (ret) |
626 | return ret; |
627 | |
628 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AFE_DRV_REG, |
629 | IT66121_AFE_DRV_RST, val: 0); |
630 | if (ret) |
631 | return ret; |
632 | |
633 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AFE_XP_REG, |
634 | IT66121_AFE_XP_RESETB, IT66121_AFE_XP_RESETB); |
635 | if (ret) |
636 | return ret; |
637 | |
638 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AFE_IP_REG, |
639 | IT66121_AFE_IP_RESETB, IT66121_AFE_IP_RESETB); |
640 | if (ret) |
641 | return ret; |
642 | |
643 | ret = regmap_write_bits(map: ctx->regmap, IT66121_SW_RST_REG, |
644 | IT66121_SW_RST_REF, |
645 | IT66121_SW_RST_REF); |
646 | if (ret) |
647 | return ret; |
648 | |
649 | /* Per programming manual, sleep here for bridge to settle */ |
650 | msleep(msecs: 50); |
651 | |
652 | return 0; |
653 | } |
654 | |
655 | static int it66121_set_mute(struct it66121_ctx *ctx, bool mute) |
656 | { |
657 | int ret; |
658 | unsigned int val = 0; |
659 | |
660 | if (mute) |
661 | val = IT66121_AV_MUTE_ON; |
662 | |
663 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AV_MUTE_REG, IT66121_AV_MUTE_ON, val); |
664 | if (ret) |
665 | return ret; |
666 | |
667 | return regmap_write(map: ctx->regmap, IT66121_PKT_GEN_CTRL_REG, |
668 | IT66121_PKT_GEN_CTRL_ON | IT66121_PKT_GEN_CTRL_RPT); |
669 | } |
670 | |
671 | #define MAX_OUTPUT_SEL_FORMATS 1 |
672 | |
673 | static u32 *it66121_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge, |
674 | struct drm_bridge_state *bridge_state, |
675 | struct drm_crtc_state *crtc_state, |
676 | struct drm_connector_state *conn_state, |
677 | unsigned int *num_output_fmts) |
678 | { |
679 | u32 *output_fmts; |
680 | |
681 | output_fmts = kcalloc(MAX_OUTPUT_SEL_FORMATS, size: sizeof(*output_fmts), |
682 | GFP_KERNEL); |
683 | if (!output_fmts) |
684 | return NULL; |
685 | |
686 | /* TOFIX handle more than MEDIA_BUS_FMT_RGB888_1X24 as output format */ |
687 | output_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24; |
688 | *num_output_fmts = 1; |
689 | |
690 | return output_fmts; |
691 | } |
692 | |
693 | #define MAX_INPUT_SEL_FORMATS 1 |
694 | |
695 | static u32 *it66121_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge, |
696 | struct drm_bridge_state *bridge_state, |
697 | struct drm_crtc_state *crtc_state, |
698 | struct drm_connector_state *conn_state, |
699 | u32 output_fmt, |
700 | unsigned int *num_input_fmts) |
701 | { |
702 | struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge); |
703 | u32 *input_fmts; |
704 | |
705 | *num_input_fmts = 0; |
706 | |
707 | input_fmts = kcalloc(MAX_INPUT_SEL_FORMATS, size: sizeof(*input_fmts), |
708 | GFP_KERNEL); |
709 | if (!input_fmts) |
710 | return NULL; |
711 | |
712 | if (ctx->bus_width == 12) |
713 | /* IT66121FN Datasheet specifies Little-Endian ordering */ |
714 | input_fmts[0] = MEDIA_BUS_FMT_RGB888_2X12_LE; |
715 | else |
716 | /* TOFIX support more input bus formats in 24bit width */ |
717 | input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24; |
718 | *num_input_fmts = 1; |
719 | |
720 | return input_fmts; |
721 | } |
722 | |
723 | static void it66121_bridge_enable(struct drm_bridge *bridge, |
724 | struct drm_bridge_state *bridge_state) |
725 | { |
726 | struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge); |
727 | struct drm_atomic_state *state = bridge_state->base.state; |
728 | |
729 | ctx->connector = drm_atomic_get_new_connector_for_encoder(state, encoder: bridge->encoder); |
730 | |
731 | it66121_set_mute(ctx, mute: false); |
732 | } |
733 | |
734 | static void it66121_bridge_disable(struct drm_bridge *bridge, |
735 | struct drm_bridge_state *bridge_state) |
736 | { |
737 | struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge); |
738 | |
739 | it66121_set_mute(ctx, mute: true); |
740 | |
741 | ctx->connector = NULL; |
742 | } |
743 | |
744 | static int it66121_bridge_check(struct drm_bridge *bridge, |
745 | struct drm_bridge_state *bridge_state, |
746 | struct drm_crtc_state *crtc_state, |
747 | struct drm_connector_state *conn_state) |
748 | { |
749 | struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge); |
750 | |
751 | if (ctx->info->id == ID_IT6610) { |
752 | /* The IT6610 only supports these settings */ |
753 | bridge_state->input_bus_cfg.flags |= DRM_BUS_FLAG_DE_HIGH | |
754 | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE; |
755 | bridge_state->input_bus_cfg.flags &= |
756 | ~DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE; |
757 | } |
758 | |
759 | return 0; |
760 | } |
761 | |
762 | static |
763 | void it66121_bridge_mode_set(struct drm_bridge *bridge, |
764 | const struct drm_display_mode *mode, |
765 | const struct drm_display_mode *adjusted_mode) |
766 | { |
767 | u8 buf[HDMI_INFOFRAME_SIZE(AVI)]; |
768 | struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge); |
769 | int ret; |
770 | |
771 | mutex_lock(&ctx->lock); |
772 | |
773 | hdmi_avi_infoframe_init(frame: &ctx->hdmi_avi_infoframe); |
774 | |
775 | ret = drm_hdmi_avi_infoframe_from_display_mode(frame: &ctx->hdmi_avi_infoframe, connector: ctx->connector, |
776 | mode: adjusted_mode); |
777 | if (ret) { |
778 | DRM_ERROR("Failed to setup AVI infoframe: %d\n", ret); |
779 | goto unlock; |
780 | } |
781 | |
782 | ret = hdmi_avi_infoframe_pack(frame: &ctx->hdmi_avi_infoframe, buffer: buf, size: sizeof(buf)); |
783 | if (ret < 0) { |
784 | DRM_ERROR("Failed to pack infoframe: %d\n", ret); |
785 | goto unlock; |
786 | } |
787 | |
788 | /* Write new AVI infoframe packet */ |
789 | ret = regmap_bulk_write(map: ctx->regmap, IT66121_AVIINFO_DB1_REG, |
790 | val: &buf[HDMI_INFOFRAME_HEADER_SIZE], |
791 | HDMI_AVI_INFOFRAME_SIZE); |
792 | if (ret) |
793 | goto unlock; |
794 | |
795 | if (regmap_write(map: ctx->regmap, IT66121_AVIINFO_CSUM_REG, val: buf[3])) |
796 | goto unlock; |
797 | |
798 | /* Enable AVI infoframe */ |
799 | if (regmap_write(map: ctx->regmap, IT66121_AVI_INFO_PKT_REG, |
800 | IT66121_AVI_INFO_PKT_ON | IT66121_AVI_INFO_PKT_RPT)) |
801 | goto unlock; |
802 | |
803 | /* Set TX mode to HDMI */ |
804 | if (regmap_write(map: ctx->regmap, IT66121_HDMI_MODE_REG, IT66121_HDMI_MODE_HDMI)) |
805 | goto unlock; |
806 | |
807 | if (ctx->info->id == ID_IT66121 && |
808 | regmap_write_bits(map: ctx->regmap, IT66121_CLK_BANK_REG, |
809 | IT66121_CLK_BANK_PWROFF_TXCLK, |
810 | IT66121_CLK_BANK_PWROFF_TXCLK)) { |
811 | goto unlock; |
812 | } |
813 | |
814 | if (it66121_configure_input(ctx)) |
815 | goto unlock; |
816 | |
817 | if (it66121_configure_afe(ctx, mode: adjusted_mode)) |
818 | goto unlock; |
819 | |
820 | if (ctx->info->id == ID_IT66121 && |
821 | regmap_write_bits(map: ctx->regmap, IT66121_CLK_BANK_REG, |
822 | IT66121_CLK_BANK_PWROFF_TXCLK, val: 0)) { |
823 | goto unlock; |
824 | } |
825 | |
826 | unlock: |
827 | mutex_unlock(lock: &ctx->lock); |
828 | } |
829 | |
830 | static enum drm_mode_status it66121_bridge_mode_valid(struct drm_bridge *bridge, |
831 | const struct drm_display_info *info, |
832 | const struct drm_display_mode *mode) |
833 | { |
834 | struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge); |
835 | unsigned long max_clock; |
836 | |
837 | max_clock = (ctx->bus_width == 12) ? 74250 : 148500; |
838 | |
839 | if (mode->clock > max_clock) |
840 | return MODE_CLOCK_HIGH; |
841 | |
842 | if (mode->clock < 25000) |
843 | return MODE_CLOCK_LOW; |
844 | |
845 | return MODE_OK; |
846 | } |
847 | |
848 | static enum drm_connector_status it66121_bridge_detect(struct drm_bridge *bridge) |
849 | { |
850 | struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge); |
851 | |
852 | return it66121_is_hpd_detect(ctx) ? connector_status_connected |
853 | : connector_status_disconnected; |
854 | } |
855 | |
856 | static void it66121_bridge_hpd_enable(struct drm_bridge *bridge) |
857 | { |
858 | struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge); |
859 | int ret; |
860 | |
861 | ret = regmap_write_bits(map: ctx->regmap, IT66121_INT_MASK1_REG, IT66121_INT_MASK1_HPD, val: 0); |
862 | if (ret) |
863 | dev_err(ctx->dev, "failed to enable HPD IRQ\n"); |
864 | } |
865 | |
866 | static void it66121_bridge_hpd_disable(struct drm_bridge *bridge) |
867 | { |
868 | struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge); |
869 | int ret; |
870 | |
871 | ret = regmap_write_bits(map: ctx->regmap, IT66121_INT_MASK1_REG, |
872 | IT66121_INT_MASK1_HPD, IT66121_INT_MASK1_HPD); |
873 | if (ret) |
874 | dev_err(ctx->dev, "failed to disable HPD IRQ\n"); |
875 | } |
876 | |
877 | static const struct drm_edid *it66121_bridge_edid_read(struct drm_bridge *bridge, |
878 | struct drm_connector *connector) |
879 | { |
880 | struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge); |
881 | const struct drm_edid *drm_edid; |
882 | int ret; |
883 | |
884 | mutex_lock(&ctx->lock); |
885 | ret = it66121_preamble_ddc(ctx); |
886 | if (ret) { |
887 | drm_edid = NULL; |
888 | goto out_unlock; |
889 | } |
890 | |
891 | ret = regmap_write(map: ctx->regmap, IT66121_DDC_HEADER_REG, |
892 | IT66121_DDC_HEADER_EDID); |
893 | if (ret) { |
894 | drm_edid = NULL; |
895 | goto out_unlock; |
896 | } |
897 | |
898 | drm_edid = drm_edid_read_custom(connector, read_block: it66121_get_edid_block, context: ctx); |
899 | |
900 | out_unlock: |
901 | mutex_unlock(lock: &ctx->lock); |
902 | |
903 | return drm_edid; |
904 | } |
905 | |
906 | static const struct drm_bridge_funcs it66121_bridge_funcs = { |
907 | .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, |
908 | .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, |
909 | .atomic_reset = drm_atomic_helper_bridge_reset, |
910 | .attach = it66121_bridge_attach, |
911 | .atomic_get_output_bus_fmts = it66121_bridge_atomic_get_output_bus_fmts, |
912 | .atomic_get_input_bus_fmts = it66121_bridge_atomic_get_input_bus_fmts, |
913 | .atomic_enable = it66121_bridge_enable, |
914 | .atomic_disable = it66121_bridge_disable, |
915 | .atomic_check = it66121_bridge_check, |
916 | .mode_set = it66121_bridge_mode_set, |
917 | .mode_valid = it66121_bridge_mode_valid, |
918 | .detect = it66121_bridge_detect, |
919 | .edid_read = it66121_bridge_edid_read, |
920 | .hpd_enable = it66121_bridge_hpd_enable, |
921 | .hpd_disable = it66121_bridge_hpd_disable, |
922 | }; |
923 | |
924 | static irqreturn_t it66121_irq_threaded_handler(int irq, void *dev_id) |
925 | { |
926 | int ret; |
927 | unsigned int val; |
928 | struct it66121_ctx *ctx = dev_id; |
929 | struct device *dev = ctx->dev; |
930 | enum drm_connector_status status; |
931 | bool event = false; |
932 | |
933 | mutex_lock(&ctx->lock); |
934 | |
935 | ret = regmap_read(map: ctx->regmap, IT66121_SYS_STATUS_REG, val: &val); |
936 | if (ret) |
937 | goto unlock; |
938 | |
939 | if (!(val & IT66121_SYS_STATUS_ACTIVE_IRQ)) |
940 | goto unlock; |
941 | |
942 | ret = regmap_read(map: ctx->regmap, IT66121_INT_STATUS1_REG, val: &val); |
943 | if (ret) { |
944 | dev_err(dev, "Cannot read STATUS1_REG %d\n", ret); |
945 | } else if (val & IT66121_INT_STATUS1_HPD_STATUS) { |
946 | regmap_write_bits(map: ctx->regmap, IT66121_INT_CLR1_REG, |
947 | IT66121_INT_CLR1_HPD, IT66121_INT_CLR1_HPD); |
948 | |
949 | status = it66121_is_hpd_detect(ctx) ? connector_status_connected |
950 | : connector_status_disconnected; |
951 | |
952 | event = true; |
953 | } |
954 | |
955 | regmap_write_bits(map: ctx->regmap, IT66121_SYS_STATUS_REG, |
956 | IT66121_SYS_STATUS_CLEAR_IRQ, |
957 | IT66121_SYS_STATUS_CLEAR_IRQ); |
958 | |
959 | unlock: |
960 | mutex_unlock(lock: &ctx->lock); |
961 | |
962 | if (event) |
963 | drm_bridge_hpd_notify(bridge: &ctx->bridge, status); |
964 | |
965 | return IRQ_HANDLED; |
966 | } |
967 | |
968 | static int it661221_set_chstat(struct it66121_ctx *ctx, u8 iec60958_chstat[]) |
969 | { |
970 | int ret; |
971 | |
972 | ret = regmap_write(map: ctx->regmap, IT66121_AUD_CHST_MODE_REG, val: iec60958_chstat[0] & 0x7C); |
973 | if (ret) |
974 | return ret; |
975 | |
976 | ret = regmap_write(map: ctx->regmap, IT66121_AUD_CHST_CAT_REG, val: iec60958_chstat[1]); |
977 | if (ret) |
978 | return ret; |
979 | |
980 | ret = regmap_write(map: ctx->regmap, IT66121_AUD_CHST_SRCNUM_REG, val: iec60958_chstat[2] & 0x0F); |
981 | if (ret) |
982 | return ret; |
983 | |
984 | ret = regmap_write(map: ctx->regmap, IT66121_AUD_CHST_CHTNUM_REG, |
985 | val: (iec60958_chstat[2] >> 4) & 0x0F); |
986 | if (ret) |
987 | return ret; |
988 | |
989 | ret = regmap_write(map: ctx->regmap, IT66121_AUD_CHST_CA_FS_REG, val: iec60958_chstat[3]); |
990 | if (ret) |
991 | return ret; |
992 | |
993 | return regmap_write(map: ctx->regmap, IT66121_AUD_CHST_OFS_WL_REG, val: iec60958_chstat[4]); |
994 | } |
995 | |
996 | static int it661221_set_lpcm_audio(struct it66121_ctx *ctx, u8 audio_src_num, u8 audio_swl) |
997 | { |
998 | int ret; |
999 | unsigned int audio_enable = 0; |
1000 | unsigned int audio_format = 0; |
1001 | |
1002 | switch (audio_swl) { |
1003 | case 16: |
1004 | audio_enable |= IT66121_AUD_16BIT; |
1005 | break; |
1006 | case 18: |
1007 | audio_enable |= IT66121_AUD_18BIT; |
1008 | break; |
1009 | case 20: |
1010 | audio_enable |= IT66121_AUD_20BIT; |
1011 | break; |
1012 | case 24: |
1013 | default: |
1014 | audio_enable |= IT66121_AUD_24BIT; |
1015 | break; |
1016 | } |
1017 | |
1018 | audio_format |= 0x40; |
1019 | switch (audio_src_num) { |
1020 | case 4: |
1021 | audio_enable |= IT66121_AUD_EN_I2S3 | IT66121_AUD_EN_I2S2 | |
1022 | IT66121_AUD_EN_I2S1 | IT66121_AUD_EN_I2S0; |
1023 | break; |
1024 | case 3: |
1025 | audio_enable |= IT66121_AUD_EN_I2S2 | IT66121_AUD_EN_I2S1 | |
1026 | IT66121_AUD_EN_I2S0; |
1027 | break; |
1028 | case 2: |
1029 | audio_enable |= IT66121_AUD_EN_I2S1 | IT66121_AUD_EN_I2S0; |
1030 | break; |
1031 | case 1: |
1032 | default: |
1033 | audio_format &= ~0x40; |
1034 | audio_enable |= IT66121_AUD_EN_I2S0; |
1035 | break; |
1036 | } |
1037 | |
1038 | audio_format |= 0x01; |
1039 | ctx->audio.ch_enable = audio_enable; |
1040 | |
1041 | ret = regmap_write(map: ctx->regmap, IT66121_AUD_CTRL0_REG, val: audio_enable & 0xF0); |
1042 | if (ret) |
1043 | return ret; |
1044 | |
1045 | ret = regmap_write(map: ctx->regmap, IT66121_AUD_CTRL1_REG, val: audio_format); |
1046 | if (ret) |
1047 | return ret; |
1048 | |
1049 | ret = regmap_write(map: ctx->regmap, IT66121_AUD_FIFOMAP_REG, val: 0xE4); |
1050 | if (ret) |
1051 | return ret; |
1052 | |
1053 | ret = regmap_write(map: ctx->regmap, IT66121_AUD_CTRL3_REG, val: 0x00); |
1054 | if (ret) |
1055 | return ret; |
1056 | |
1057 | ret = regmap_write(map: ctx->regmap, IT66121_AUD_SRCVALID_FLAT_REG, val: 0x00); |
1058 | if (ret) |
1059 | return ret; |
1060 | |
1061 | return regmap_write(map: ctx->regmap, IT66121_AUD_HDAUDIO_REG, val: 0x00); |
1062 | } |
1063 | |
1064 | static int it661221_set_ncts(struct it66121_ctx *ctx, u8 fs) |
1065 | { |
1066 | int ret; |
1067 | unsigned int n; |
1068 | |
1069 | switch (fs) { |
1070 | case IT66121_AUD_FS_32K: |
1071 | n = 4096; |
1072 | break; |
1073 | case IT66121_AUD_FS_44P1K: |
1074 | n = 6272; |
1075 | break; |
1076 | case IT66121_AUD_FS_48K: |
1077 | n = 6144; |
1078 | break; |
1079 | case IT66121_AUD_FS_88P2K: |
1080 | n = 12544; |
1081 | break; |
1082 | case IT66121_AUD_FS_96K: |
1083 | n = 12288; |
1084 | break; |
1085 | case IT66121_AUD_FS_176P4K: |
1086 | n = 25088; |
1087 | break; |
1088 | case IT66121_AUD_FS_192K: |
1089 | n = 24576; |
1090 | break; |
1091 | case IT66121_AUD_FS_768K: |
1092 | n = 24576; |
1093 | break; |
1094 | default: |
1095 | n = 6144; |
1096 | break; |
1097 | } |
1098 | |
1099 | ret = regmap_write(map: ctx->regmap, IT66121_AUD_PKT_N0_REG, val: (u8)((n) & 0xFF)); |
1100 | if (ret) |
1101 | return ret; |
1102 | |
1103 | ret = regmap_write(map: ctx->regmap, IT66121_AUD_PKT_N1_REG, val: (u8)((n >> 8) & 0xFF)); |
1104 | if (ret) |
1105 | return ret; |
1106 | |
1107 | ret = regmap_write(map: ctx->regmap, IT66121_AUD_PKT_N2_REG, val: (u8)((n >> 16) & 0xF)); |
1108 | if (ret) |
1109 | return ret; |
1110 | |
1111 | if (ctx->audio.auto_cts) { |
1112 | u8 loop_cnt = 255; |
1113 | u8 cts_stable_cnt = 0; |
1114 | unsigned int sum_cts = 0; |
1115 | unsigned int cts = 0; |
1116 | unsigned int last_cts = 0; |
1117 | unsigned int diff; |
1118 | unsigned int val; |
1119 | |
1120 | while (loop_cnt--) { |
1121 | msleep(msecs: 30); |
1122 | regmap_read(map: ctx->regmap, IT66121_AUD_PKT_CTS_CNT2_REG, val: &val); |
1123 | cts = val << 12; |
1124 | regmap_read(map: ctx->regmap, IT66121_AUD_PKT_CTS_CNT1_REG, val: &val); |
1125 | cts |= val << 4; |
1126 | regmap_read(map: ctx->regmap, IT66121_AUD_PKT_CTS_CNT0_REG, val: &val); |
1127 | cts |= val >> 4; |
1128 | if (cts == 0) { |
1129 | continue; |
1130 | } else { |
1131 | if (last_cts > cts) |
1132 | diff = last_cts - cts; |
1133 | else |
1134 | diff = cts - last_cts; |
1135 | last_cts = cts; |
1136 | if (diff < 5) { |
1137 | cts_stable_cnt++; |
1138 | sum_cts += cts; |
1139 | } else { |
1140 | cts_stable_cnt = 0; |
1141 | sum_cts = 0; |
1142 | continue; |
1143 | } |
1144 | |
1145 | if (cts_stable_cnt >= 32) { |
1146 | last_cts = (sum_cts >> 5); |
1147 | break; |
1148 | } |
1149 | } |
1150 | } |
1151 | |
1152 | regmap_write(map: ctx->regmap, IT66121_AUD_PKT_CTS0_REG, val: (u8)((last_cts) & 0xFF)); |
1153 | regmap_write(map: ctx->regmap, IT66121_AUD_PKT_CTS1_REG, val: (u8)((last_cts >> 8) & 0xFF)); |
1154 | regmap_write(map: ctx->regmap, IT66121_AUD_PKT_CTS2_REG, val: (u8)((last_cts >> 16) & 0x0F)); |
1155 | } |
1156 | |
1157 | ret = regmap_write(map: ctx->regmap, reg: 0xF8, val: 0xC3); |
1158 | if (ret) |
1159 | return ret; |
1160 | |
1161 | ret = regmap_write(map: ctx->regmap, reg: 0xF8, val: 0xA5); |
1162 | if (ret) |
1163 | return ret; |
1164 | |
1165 | if (ctx->audio.auto_cts) { |
1166 | ret = regmap_write_bits(map: ctx->regmap, IT66121_PKT_CTS_CTRL_REG, |
1167 | IT66121_PKT_CTS_CTRL_SEL, |
1168 | val: 1); |
1169 | } else { |
1170 | ret = regmap_write_bits(map: ctx->regmap, IT66121_PKT_CTS_CTRL_REG, |
1171 | IT66121_PKT_CTS_CTRL_SEL, |
1172 | val: 0); |
1173 | } |
1174 | |
1175 | if (ret) |
1176 | return ret; |
1177 | |
1178 | return regmap_write(map: ctx->regmap, reg: 0xF8, val: 0xFF); |
1179 | } |
1180 | |
1181 | static int it661221_audio_output_enable(struct it66121_ctx *ctx, bool enable) |
1182 | { |
1183 | int ret; |
1184 | |
1185 | if (enable) { |
1186 | ret = regmap_write_bits(map: ctx->regmap, IT66121_SW_RST_REG, |
1187 | IT66121_SW_RST_AUD | IT66121_SW_RST_AREF, |
1188 | val: 0); |
1189 | if (ret) |
1190 | return ret; |
1191 | |
1192 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AUD_CTRL0_REG, |
1193 | IT66121_AUD_EN_I2S3 | IT66121_AUD_EN_I2S2 | |
1194 | IT66121_AUD_EN_I2S1 | IT66121_AUD_EN_I2S0, |
1195 | val: ctx->audio.ch_enable); |
1196 | } else { |
1197 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AUD_CTRL0_REG, |
1198 | IT66121_AUD_EN_I2S3 | IT66121_AUD_EN_I2S2 | |
1199 | IT66121_AUD_EN_I2S1 | IT66121_AUD_EN_I2S0, |
1200 | val: ctx->audio.ch_enable & 0xF0); |
1201 | if (ret) |
1202 | return ret; |
1203 | |
1204 | ret = regmap_write_bits(map: ctx->regmap, IT66121_SW_RST_REG, |
1205 | IT66121_SW_RST_AUD | IT66121_SW_RST_AREF, |
1206 | IT66121_SW_RST_AUD | IT66121_SW_RST_AREF); |
1207 | } |
1208 | |
1209 | return ret; |
1210 | } |
1211 | |
1212 | static int it661221_audio_ch_enable(struct it66121_ctx *ctx, bool enable) |
1213 | { |
1214 | int ret; |
1215 | |
1216 | if (enable) { |
1217 | ret = regmap_write(map: ctx->regmap, IT66121_AUD_SRCVALID_FLAT_REG, val: 0); |
1218 | if (ret) |
1219 | return ret; |
1220 | |
1221 | ret = regmap_write(map: ctx->regmap, IT66121_AUD_CTRL0_REG, val: ctx->audio.ch_enable); |
1222 | } else { |
1223 | ret = regmap_write(map: ctx->regmap, IT66121_AUD_CTRL0_REG, val: ctx->audio.ch_enable & 0xF0); |
1224 | } |
1225 | |
1226 | return ret; |
1227 | } |
1228 | |
1229 | static int it66121_audio_hw_params(struct device *dev, void *data, |
1230 | struct hdmi_codec_daifmt *daifmt, |
1231 | struct hdmi_codec_params *params) |
1232 | { |
1233 | u8 fs; |
1234 | u8 swl; |
1235 | int ret; |
1236 | struct it66121_ctx *ctx = dev_get_drvdata(dev); |
1237 | static u8 iec60958_chstat[5]; |
1238 | unsigned int channels = params->channels; |
1239 | unsigned int sample_rate = params->sample_rate; |
1240 | unsigned int sample_width = params->sample_width; |
1241 | |
1242 | mutex_lock(&ctx->lock); |
1243 | dev_dbg(dev, "%s: %u, %u, %u, %u\n", __func__, |
1244 | daifmt->fmt, sample_rate, sample_width, channels); |
1245 | |
1246 | switch (daifmt->fmt) { |
1247 | case HDMI_I2S: |
1248 | dev_dbg(dev, "Using HDMI I2S\n"); |
1249 | break; |
1250 | default: |
1251 | dev_err(dev, "Invalid or unsupported DAI format %d\n", daifmt->fmt); |
1252 | ret = -EINVAL; |
1253 | goto out; |
1254 | } |
1255 | |
1256 | // Set audio clock recovery (N/CTS) |
1257 | ret = regmap_write(map: ctx->regmap, IT66121_CLK_CTRL0_REG, |
1258 | IT66121_CLK_CTRL0_AUTO_OVER_SAMPLING | |
1259 | IT66121_CLK_CTRL0_EXT_MCLK_256FS | |
1260 | IT66121_CLK_CTRL0_AUTO_IPCLK); |
1261 | if (ret) |
1262 | goto out; |
1263 | |
1264 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AUD_CTRL0_REG, |
1265 | IT66121_AUD_CTRL0_AUD_SEL, val: 0); // remove spdif selection |
1266 | if (ret) |
1267 | goto out; |
1268 | |
1269 | switch (sample_rate) { |
1270 | case 44100L: |
1271 | fs = IT66121_AUD_FS_44P1K; |
1272 | break; |
1273 | case 88200L: |
1274 | fs = IT66121_AUD_FS_88P2K; |
1275 | break; |
1276 | case 176400L: |
1277 | fs = IT66121_AUD_FS_176P4K; |
1278 | break; |
1279 | case 32000L: |
1280 | fs = IT66121_AUD_FS_32K; |
1281 | break; |
1282 | case 48000L: |
1283 | fs = IT66121_AUD_FS_48K; |
1284 | break; |
1285 | case 96000L: |
1286 | fs = IT66121_AUD_FS_96K; |
1287 | break; |
1288 | case 192000L: |
1289 | fs = IT66121_AUD_FS_192K; |
1290 | break; |
1291 | case 768000L: |
1292 | fs = IT66121_AUD_FS_768K; |
1293 | break; |
1294 | default: |
1295 | fs = IT66121_AUD_FS_48K; |
1296 | break; |
1297 | } |
1298 | |
1299 | ctx->audio.fs = fs; |
1300 | ret = it661221_set_ncts(ctx, fs); |
1301 | if (ret) { |
1302 | dev_err(dev, "Failed to set N/CTS: %d\n", ret); |
1303 | goto out; |
1304 | } |
1305 | |
1306 | // Set audio format register (except audio channel enable) |
1307 | ret = it661221_set_lpcm_audio(ctx, audio_src_num: (channels + 1) / 2, audio_swl: sample_width); |
1308 | if (ret) { |
1309 | dev_err(dev, "Failed to set LPCM audio: %d\n", ret); |
1310 | goto out; |
1311 | } |
1312 | |
1313 | // Set audio channel status |
1314 | iec60958_chstat[0] = 0; |
1315 | if ((channels + 1) / 2 == 1) |
1316 | iec60958_chstat[0] |= 0x1; |
1317 | iec60958_chstat[0] &= ~(1 << 1); |
1318 | iec60958_chstat[1] = 0; |
1319 | iec60958_chstat[2] = (channels + 1) / 2; |
1320 | iec60958_chstat[2] |= (channels << 4) & 0xF0; |
1321 | iec60958_chstat[3] = fs; |
1322 | |
1323 | switch (sample_width) { |
1324 | case 21L: |
1325 | swl = IT66121_AUD_SWL_21BIT; |
1326 | break; |
1327 | case 24L: |
1328 | swl = IT66121_AUD_SWL_24BIT; |
1329 | break; |
1330 | case 23L: |
1331 | swl = IT66121_AUD_SWL_23BIT; |
1332 | break; |
1333 | case 22L: |
1334 | swl = IT66121_AUD_SWL_22BIT; |
1335 | break; |
1336 | case 20L: |
1337 | swl = IT66121_AUD_SWL_20BIT; |
1338 | break; |
1339 | case 17L: |
1340 | swl = IT66121_AUD_SWL_17BIT; |
1341 | break; |
1342 | case 19L: |
1343 | swl = IT66121_AUD_SWL_19BIT; |
1344 | break; |
1345 | case 18L: |
1346 | swl = IT66121_AUD_SWL_18BIT; |
1347 | break; |
1348 | case 16L: |
1349 | swl = IT66121_AUD_SWL_16BIT; |
1350 | break; |
1351 | default: |
1352 | swl = IT66121_AUD_SWL_NOT_INDICATED; |
1353 | break; |
1354 | } |
1355 | |
1356 | iec60958_chstat[4] = (((~fs) << 4) & 0xF0) | swl; |
1357 | ret = it661221_set_chstat(ctx, iec60958_chstat); |
1358 | if (ret) { |
1359 | dev_err(dev, "Failed to set channel status: %d\n", ret); |
1360 | goto out; |
1361 | } |
1362 | |
1363 | // Enable audio channel enable while input clock stable (if SPDIF). |
1364 | ret = it661221_audio_ch_enable(ctx, enable: true); |
1365 | if (ret) { |
1366 | dev_err(dev, "Failed to enable audio channel: %d\n", ret); |
1367 | goto out; |
1368 | } |
1369 | |
1370 | ret = regmap_write_bits(map: ctx->regmap, IT66121_INT_MASK1_REG, |
1371 | IT66121_INT_MASK1_AUD_OVF, |
1372 | val: 0); |
1373 | if (ret) |
1374 | goto out; |
1375 | |
1376 | dev_dbg(dev, "HDMI audio enabled.\n"); |
1377 | out: |
1378 | mutex_unlock(lock: &ctx->lock); |
1379 | |
1380 | return ret; |
1381 | } |
1382 | |
1383 | static int it66121_audio_startup(struct device *dev, void *data) |
1384 | { |
1385 | int ret; |
1386 | struct it66121_ctx *ctx = dev_get_drvdata(dev); |
1387 | |
1388 | dev_dbg(dev, "%s\n", __func__); |
1389 | |
1390 | mutex_lock(&ctx->lock); |
1391 | ret = it661221_audio_output_enable(ctx, enable: true); |
1392 | if (ret) |
1393 | dev_err(dev, "Failed to enable audio output: %d\n", ret); |
1394 | |
1395 | mutex_unlock(lock: &ctx->lock); |
1396 | |
1397 | return ret; |
1398 | } |
1399 | |
1400 | static void it66121_audio_shutdown(struct device *dev, void *data) |
1401 | { |
1402 | int ret; |
1403 | struct it66121_ctx *ctx = dev_get_drvdata(dev); |
1404 | |
1405 | dev_dbg(dev, "%s\n", __func__); |
1406 | |
1407 | mutex_lock(&ctx->lock); |
1408 | ret = it661221_audio_output_enable(ctx, enable: false); |
1409 | if (ret) |
1410 | dev_err(dev, "Failed to disable audio output: %d\n", ret); |
1411 | |
1412 | mutex_unlock(lock: &ctx->lock); |
1413 | } |
1414 | |
1415 | static int it66121_audio_mute(struct device *dev, void *data, |
1416 | bool enable, int direction) |
1417 | { |
1418 | int ret; |
1419 | struct it66121_ctx *ctx = dev_get_drvdata(dev); |
1420 | |
1421 | dev_dbg(dev, "%s: enable=%s, direction=%d\n", |
1422 | __func__, enable ? "true": "false", direction); |
1423 | |
1424 | mutex_lock(&ctx->lock); |
1425 | |
1426 | if (enable) { |
1427 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AUD_SRCVALID_FLAT_REG, |
1428 | IT66121_AUD_FLAT_SRC0 | IT66121_AUD_FLAT_SRC1 | |
1429 | IT66121_AUD_FLAT_SRC2 | IT66121_AUD_FLAT_SRC3, |
1430 | IT66121_AUD_FLAT_SRC0 | IT66121_AUD_FLAT_SRC1 | |
1431 | IT66121_AUD_FLAT_SRC2 | IT66121_AUD_FLAT_SRC3); |
1432 | } else { |
1433 | ret = regmap_write_bits(map: ctx->regmap, IT66121_AUD_SRCVALID_FLAT_REG, |
1434 | IT66121_AUD_FLAT_SRC0 | IT66121_AUD_FLAT_SRC1 | |
1435 | IT66121_AUD_FLAT_SRC2 | IT66121_AUD_FLAT_SRC3, |
1436 | val: 0); |
1437 | } |
1438 | |
1439 | mutex_unlock(lock: &ctx->lock); |
1440 | |
1441 | return ret; |
1442 | } |
1443 | |
1444 | static int it66121_audio_get_eld(struct device *dev, void *data, |
1445 | u8 *buf, size_t len) |
1446 | { |
1447 | struct it66121_ctx *ctx = dev_get_drvdata(dev); |
1448 | |
1449 | mutex_lock(&ctx->lock); |
1450 | if (!ctx->connector) { |
1451 | /* Pass en empty ELD if connector not available */ |
1452 | dev_dbg(dev, "No connector present, passing empty EDID data"); |
1453 | memset(buf, 0, len); |
1454 | } else { |
1455 | memcpy(buf, ctx->connector->eld, |
1456 | min(sizeof(ctx->connector->eld), len)); |
1457 | } |
1458 | mutex_unlock(lock: &ctx->lock); |
1459 | |
1460 | return 0; |
1461 | } |
1462 | |
1463 | static const struct hdmi_codec_ops it66121_audio_codec_ops = { |
1464 | .hw_params = it66121_audio_hw_params, |
1465 | .audio_startup = it66121_audio_startup, |
1466 | .audio_shutdown = it66121_audio_shutdown, |
1467 | .mute_stream = it66121_audio_mute, |
1468 | .get_eld = it66121_audio_get_eld, |
1469 | .no_capture_mute = 1, |
1470 | }; |
1471 | |
1472 | static int it66121_audio_codec_init(struct it66121_ctx *ctx, struct device *dev) |
1473 | { |
1474 | struct hdmi_codec_pdata codec_data = { |
1475 | .ops = &it66121_audio_codec_ops, |
1476 | .i2s = 1, /* Only i2s support for now */ |
1477 | .spdif = 0, |
1478 | .max_i2s_channels = 8, |
1479 | }; |
1480 | |
1481 | dev_dbg(dev, "%s\n", __func__); |
1482 | |
1483 | if (!of_property_read_bool(np: dev->of_node, propname: "#sound-dai-cells")) { |
1484 | dev_info(dev, "No \"#sound-dai-cells\", no audio\n"); |
1485 | return 0; |
1486 | } |
1487 | |
1488 | ctx->audio.pdev = platform_device_register_data(parent: dev, |
1489 | HDMI_CODEC_DRV_NAME, |
1490 | PLATFORM_DEVID_AUTO, |
1491 | data: &codec_data, |
1492 | size: sizeof(codec_data)); |
1493 | |
1494 | if (IS_ERR(ptr: ctx->audio.pdev)) { |
1495 | dev_err(dev, "Failed to initialize HDMI audio codec: %d\n", |
1496 | PTR_ERR_OR_ZERO(ctx->audio.pdev)); |
1497 | } |
1498 | |
1499 | return PTR_ERR_OR_ZERO(ptr: ctx->audio.pdev); |
1500 | } |
1501 | |
1502 | static const char * const it66121_supplies[] = { |
1503 | "vcn33", "vcn18", "vrf12" |
1504 | }; |
1505 | |
1506 | static int it66121_probe(struct i2c_client *client) |
1507 | { |
1508 | u32 revision_id, vendor_ids[2] = { 0 }, device_ids[2] = { 0 }; |
1509 | struct device_node *ep; |
1510 | int ret; |
1511 | struct it66121_ctx *ctx; |
1512 | struct device *dev = &client->dev; |
1513 | |
1514 | if (!i2c_check_functionality(adap: client->adapter, I2C_FUNC_I2C)) { |
1515 | dev_err(dev, "I2C check functionality failed.\n"); |
1516 | return -ENXIO; |
1517 | } |
1518 | |
1519 | ctx = devm_kzalloc(dev, size: sizeof(*ctx), GFP_KERNEL); |
1520 | if (!ctx) |
1521 | return -ENOMEM; |
1522 | |
1523 | ep = of_graph_get_endpoint_by_regs(parent: dev->of_node, port_reg: 0, reg: 0); |
1524 | if (!ep) |
1525 | return -EINVAL; |
1526 | |
1527 | ctx->dev = dev; |
1528 | ctx->client = client; |
1529 | ctx->info = i2c_get_match_data(client); |
1530 | |
1531 | of_property_read_u32(np: ep, propname: "bus-width", out_value: &ctx->bus_width); |
1532 | of_node_put(node: ep); |
1533 | |
1534 | if (ctx->bus_width != 12 && ctx->bus_width != 24) |
1535 | return -EINVAL; |
1536 | |
1537 | ep = of_graph_get_remote_node(node: dev->of_node, port: 1, endpoint: -1); |
1538 | if (!ep) { |
1539 | dev_err(ctx->dev, "The endpoint is unconnected\n"); |
1540 | return -EINVAL; |
1541 | } |
1542 | |
1543 | if (!of_device_is_available(device: ep)) { |
1544 | of_node_put(node: ep); |
1545 | dev_err(ctx->dev, "The remote device is disabled\n"); |
1546 | return -ENODEV; |
1547 | } |
1548 | |
1549 | ctx->next_bridge = of_drm_find_bridge(np: ep); |
1550 | of_node_put(node: ep); |
1551 | if (!ctx->next_bridge) { |
1552 | dev_dbg(ctx->dev, "Next bridge not found, deferring probe\n"); |
1553 | return -EPROBE_DEFER; |
1554 | } |
1555 | |
1556 | i2c_set_clientdata(client, data: ctx); |
1557 | mutex_init(&ctx->lock); |
1558 | |
1559 | ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(it66121_supplies), |
1560 | id: it66121_supplies); |
1561 | if (ret) { |
1562 | dev_err(dev, "Failed to enable power supplies\n"); |
1563 | return ret; |
1564 | } |
1565 | |
1566 | it66121_hw_reset(ctx); |
1567 | |
1568 | ctx->regmap = devm_regmap_init_i2c(client, &it66121_regmap_config); |
1569 | if (IS_ERR(ptr: ctx->regmap)) |
1570 | return PTR_ERR(ptr: ctx->regmap); |
1571 | |
1572 | regmap_read(map: ctx->regmap, IT66121_VENDOR_ID0_REG, val: &vendor_ids[0]); |
1573 | regmap_read(map: ctx->regmap, IT66121_VENDOR_ID1_REG, val: &vendor_ids[1]); |
1574 | regmap_read(map: ctx->regmap, IT66121_DEVICE_ID0_REG, val: &device_ids[0]); |
1575 | regmap_read(map: ctx->regmap, IT66121_DEVICE_ID1_REG, val: &device_ids[1]); |
1576 | |
1577 | /* Revision is shared with DEVICE_ID1 */ |
1578 | revision_id = FIELD_GET(IT66121_REVISION_MASK, device_ids[1]); |
1579 | device_ids[1] &= IT66121_DEVICE_ID1_MASK; |
1580 | |
1581 | if ((vendor_ids[1] << 8 | vendor_ids[0]) != ctx->info->vid || |
1582 | (device_ids[1] << 8 | device_ids[0]) != ctx->info->pid) { |
1583 | return -ENODEV; |
1584 | } |
1585 | |
1586 | ctx->bridge.funcs = &it66121_bridge_funcs; |
1587 | ctx->bridge.of_node = dev->of_node; |
1588 | ctx->bridge.type = DRM_MODE_CONNECTOR_HDMIA; |
1589 | ctx->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_HPD; |
1590 | |
1591 | ret = devm_request_threaded_irq(dev, irq: client->irq, NULL, thread_fn: it66121_irq_threaded_handler, |
1592 | IRQF_ONESHOT, devname: dev_name(dev), dev_id: ctx); |
1593 | if (ret < 0) { |
1594 | dev_err(dev, "Failed to request irq %d:%d\n", client->irq, ret); |
1595 | return ret; |
1596 | } |
1597 | |
1598 | it66121_audio_codec_init(ctx, dev); |
1599 | |
1600 | drm_bridge_add(bridge: &ctx->bridge); |
1601 | |
1602 | dev_info(ctx->dev, "IT66121 revision %d probed\n", revision_id); |
1603 | |
1604 | return 0; |
1605 | } |
1606 | |
1607 | static void it66121_remove(struct i2c_client *client) |
1608 | { |
1609 | struct it66121_ctx *ctx = i2c_get_clientdata(client); |
1610 | |
1611 | drm_bridge_remove(bridge: &ctx->bridge); |
1612 | mutex_destroy(lock: &ctx->lock); |
1613 | } |
1614 | |
1615 | static const struct it66121_chip_info it66121_chip_info = { |
1616 | .id = ID_IT66121, |
1617 | .vid = 0x4954, |
1618 | .pid = 0x0612, |
1619 | }; |
1620 | |
1621 | static const struct it66121_chip_info it6610_chip_info = { |
1622 | .id = ID_IT6610, |
1623 | .vid = 0xca00, |
1624 | .pid = 0x0611, |
1625 | }; |
1626 | |
1627 | static const struct of_device_id it66121_dt_match[] = { |
1628 | { .compatible = "ite,it66121", &it66121_chip_info }, |
1629 | { .compatible = "ite,it6610", &it6610_chip_info }, |
1630 | { } |
1631 | }; |
1632 | MODULE_DEVICE_TABLE(of, it66121_dt_match); |
1633 | |
1634 | static const struct i2c_device_id it66121_id[] = { |
1635 | { "it66121", (kernel_ulong_t) &it66121_chip_info }, |
1636 | { "it6610", (kernel_ulong_t) &it6610_chip_info }, |
1637 | { } |
1638 | }; |
1639 | MODULE_DEVICE_TABLE(i2c, it66121_id); |
1640 | |
1641 | static struct i2c_driver it66121_driver = { |
1642 | .driver = { |
1643 | .name = "it66121", |
1644 | .of_match_table = it66121_dt_match, |
1645 | }, |
1646 | .probe = it66121_probe, |
1647 | .remove = it66121_remove, |
1648 | .id_table = it66121_id, |
1649 | }; |
1650 | |
1651 | module_i2c_driver(it66121_driver); |
1652 | |
1653 | MODULE_AUTHOR("Phong LE"); |
1654 | MODULE_DESCRIPTION("IT66121 HDMI transmitter driver"); |
1655 | MODULE_LICENSE("GPL v2"); |
1656 |
Definitions
- chip_id
- it66121_chip_info
- it66121_ctx
- it66121_regmap_banks
- it66121_regmap_config
- it66121_hw_reset
- it66121_preamble_ddc
- it66121_fire_afe
- it66121_configure_input
- it66121_configure_afe
- it66121_wait_ddc_ready
- it66121_abort_ddc_ops
- it66121_get_edid_block
- it66121_is_hpd_detect
- it66121_bridge_attach
- it66121_set_mute
- it66121_bridge_atomic_get_output_bus_fmts
- it66121_bridge_atomic_get_input_bus_fmts
- it66121_bridge_enable
- it66121_bridge_disable
- it66121_bridge_check
- it66121_bridge_mode_set
- it66121_bridge_mode_valid
- it66121_bridge_detect
- it66121_bridge_hpd_enable
- it66121_bridge_hpd_disable
- it66121_bridge_edid_read
- it66121_bridge_funcs
- it66121_irq_threaded_handler
- it661221_set_chstat
- it661221_set_lpcm_audio
- it661221_set_ncts
- it661221_audio_output_enable
- it661221_audio_ch_enable
- it66121_audio_hw_params
- it66121_audio_startup
- it66121_audio_shutdown
- it66121_audio_mute
- it66121_audio_get_eld
- it66121_audio_codec_ops
- it66121_audio_codec_init
- it66121_supplies
- it66121_probe
- it66121_remove
- it66121_chip_info
- it6610_chip_info
- it66121_dt_match
- it66121_id
Improve your Profiling and Debugging skills
Find out more