1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (c) 2014 MediaTek Inc. |
4 | * Author: Jie Qiu <jie.qiu@mediatek.com> |
5 | */ |
6 | |
7 | #include <linux/arm-smccc.h> |
8 | #include <linux/clk.h> |
9 | #include <linux/delay.h> |
10 | #include <linux/hdmi.h> |
11 | #include <linux/i2c.h> |
12 | #include <linux/io.h> |
13 | #include <linux/kernel.h> |
14 | #include <linux/mfd/syscon.h> |
15 | #include <linux/module.h> |
16 | #include <linux/mutex.h> |
17 | #include <linux/of_platform.h> |
18 | #include <linux/of.h> |
19 | #include <linux/of_graph.h> |
20 | #include <linux/phy/phy.h> |
21 | #include <linux/platform_device.h> |
22 | #include <linux/regmap.h> |
23 | |
24 | #include <sound/hdmi-codec.h> |
25 | |
26 | #include <drm/drm_atomic_helper.h> |
27 | #include <drm/drm_bridge.h> |
28 | #include <drm/drm_crtc.h> |
29 | #include <drm/drm_edid.h> |
30 | #include <drm/drm_print.h> |
31 | #include <drm/drm_probe_helper.h> |
32 | |
33 | #include "mtk_cec.h" |
34 | #include "mtk_hdmi.h" |
35 | #include "mtk_hdmi_regs.h" |
36 | |
37 | #define NCTS_BYTES 7 |
38 | |
39 | enum mtk_hdmi_clk_id { |
40 | MTK_HDMI_CLK_HDMI_PIXEL, |
41 | MTK_HDMI_CLK_HDMI_PLL, |
42 | MTK_HDMI_CLK_AUD_BCLK, |
43 | MTK_HDMI_CLK_AUD_SPDIF, |
44 | MTK_HDMI_CLK_COUNT |
45 | }; |
46 | |
47 | enum hdmi_aud_input_type { |
48 | HDMI_AUD_INPUT_I2S = 0, |
49 | HDMI_AUD_INPUT_SPDIF, |
50 | }; |
51 | |
52 | enum hdmi_aud_i2s_fmt { |
53 | HDMI_I2S_MODE_RJT_24BIT = 0, |
54 | HDMI_I2S_MODE_RJT_16BIT, |
55 | HDMI_I2S_MODE_LJT_24BIT, |
56 | HDMI_I2S_MODE_LJT_16BIT, |
57 | HDMI_I2S_MODE_I2S_24BIT, |
58 | HDMI_I2S_MODE_I2S_16BIT |
59 | }; |
60 | |
61 | enum hdmi_aud_mclk { |
62 | HDMI_AUD_MCLK_128FS, |
63 | HDMI_AUD_MCLK_192FS, |
64 | HDMI_AUD_MCLK_256FS, |
65 | HDMI_AUD_MCLK_384FS, |
66 | HDMI_AUD_MCLK_512FS, |
67 | HDMI_AUD_MCLK_768FS, |
68 | HDMI_AUD_MCLK_1152FS, |
69 | }; |
70 | |
71 | enum hdmi_aud_channel_type { |
72 | HDMI_AUD_CHAN_TYPE_1_0 = 0, |
73 | HDMI_AUD_CHAN_TYPE_1_1, |
74 | HDMI_AUD_CHAN_TYPE_2_0, |
75 | HDMI_AUD_CHAN_TYPE_2_1, |
76 | HDMI_AUD_CHAN_TYPE_3_0, |
77 | HDMI_AUD_CHAN_TYPE_3_1, |
78 | HDMI_AUD_CHAN_TYPE_4_0, |
79 | HDMI_AUD_CHAN_TYPE_4_1, |
80 | HDMI_AUD_CHAN_TYPE_5_0, |
81 | HDMI_AUD_CHAN_TYPE_5_1, |
82 | HDMI_AUD_CHAN_TYPE_6_0, |
83 | HDMI_AUD_CHAN_TYPE_6_1, |
84 | HDMI_AUD_CHAN_TYPE_7_0, |
85 | HDMI_AUD_CHAN_TYPE_7_1, |
86 | HDMI_AUD_CHAN_TYPE_3_0_LRS, |
87 | HDMI_AUD_CHAN_TYPE_3_1_LRS, |
88 | HDMI_AUD_CHAN_TYPE_4_0_CLRS, |
89 | HDMI_AUD_CHAN_TYPE_4_1_CLRS, |
90 | HDMI_AUD_CHAN_TYPE_6_1_CS, |
91 | HDMI_AUD_CHAN_TYPE_6_1_CH, |
92 | HDMI_AUD_CHAN_TYPE_6_1_OH, |
93 | HDMI_AUD_CHAN_TYPE_6_1_CHR, |
94 | HDMI_AUD_CHAN_TYPE_7_1_LH_RH, |
95 | HDMI_AUD_CHAN_TYPE_7_1_LSR_RSR, |
96 | HDMI_AUD_CHAN_TYPE_7_1_LC_RC, |
97 | HDMI_AUD_CHAN_TYPE_7_1_LW_RW, |
98 | HDMI_AUD_CHAN_TYPE_7_1_LSD_RSD, |
99 | , |
100 | HDMI_AUD_CHAN_TYPE_7_1_LHS_RHS, |
101 | HDMI_AUD_CHAN_TYPE_7_1_CS_CH, |
102 | HDMI_AUD_CHAN_TYPE_7_1_CS_OH, |
103 | HDMI_AUD_CHAN_TYPE_7_1_CS_CHR, |
104 | HDMI_AUD_CHAN_TYPE_7_1_CH_OH, |
105 | HDMI_AUD_CHAN_TYPE_7_1_CH_CHR, |
106 | HDMI_AUD_CHAN_TYPE_7_1_OH_CHR, |
107 | , |
108 | HDMI_AUD_CHAN_TYPE_6_0_CS, |
109 | HDMI_AUD_CHAN_TYPE_6_0_CH, |
110 | HDMI_AUD_CHAN_TYPE_6_0_OH, |
111 | HDMI_AUD_CHAN_TYPE_6_0_CHR, |
112 | HDMI_AUD_CHAN_TYPE_7_0_LH_RH, |
113 | HDMI_AUD_CHAN_TYPE_7_0_LSR_RSR, |
114 | HDMI_AUD_CHAN_TYPE_7_0_LC_RC, |
115 | HDMI_AUD_CHAN_TYPE_7_0_LW_RW, |
116 | HDMI_AUD_CHAN_TYPE_7_0_LSD_RSD, |
117 | , |
118 | HDMI_AUD_CHAN_TYPE_7_0_LHS_RHS, |
119 | HDMI_AUD_CHAN_TYPE_7_0_CS_CH, |
120 | HDMI_AUD_CHAN_TYPE_7_0_CS_OH, |
121 | HDMI_AUD_CHAN_TYPE_7_0_CS_CHR, |
122 | HDMI_AUD_CHAN_TYPE_7_0_CH_OH, |
123 | HDMI_AUD_CHAN_TYPE_7_0_CH_CHR, |
124 | HDMI_AUD_CHAN_TYPE_7_0_OH_CHR, |
125 | , |
126 | HDMI_AUD_CHAN_TYPE_8_0_LH_RH_CS, |
127 | HDMI_AUD_CHAN_TYPE_UNKNOWN = 0xFF |
128 | }; |
129 | |
130 | enum hdmi_aud_channel_swap_type { |
131 | HDMI_AUD_SWAP_LR, |
132 | HDMI_AUD_SWAP_LFE_CC, |
133 | HDMI_AUD_SWAP_LSRS, |
134 | HDMI_AUD_SWAP_RLS_RRS, |
135 | HDMI_AUD_SWAP_LR_STATUS, |
136 | }; |
137 | |
138 | struct hdmi_audio_param { |
139 | enum hdmi_audio_coding_type aud_codec; |
140 | enum hdmi_audio_sample_size aud_sampe_size; |
141 | enum hdmi_aud_input_type aud_input_type; |
142 | enum hdmi_aud_i2s_fmt aud_i2s_fmt; |
143 | enum hdmi_aud_mclk aud_mclk; |
144 | enum hdmi_aud_channel_type aud_input_chan_type; |
145 | struct hdmi_codec_params codec_params; |
146 | }; |
147 | |
148 | struct mtk_hdmi_conf { |
149 | bool tz_disabled; |
150 | bool cea_modes_only; |
151 | unsigned long max_mode_clock; |
152 | }; |
153 | |
154 | struct mtk_hdmi { |
155 | struct drm_bridge bridge; |
156 | struct drm_bridge *next_bridge; |
157 | struct drm_connector *curr_conn;/* current connector (only valid when 'enabled') */ |
158 | struct device *dev; |
159 | const struct mtk_hdmi_conf *conf; |
160 | struct phy *phy; |
161 | struct device *cec_dev; |
162 | struct i2c_adapter *ddc_adpt; |
163 | struct clk *clk[MTK_HDMI_CLK_COUNT]; |
164 | struct drm_display_mode mode; |
165 | bool dvi_mode; |
166 | u32 min_clock; |
167 | u32 max_clock; |
168 | u32 max_hdisplay; |
169 | u32 max_vdisplay; |
170 | u32 ibias; |
171 | u32 ibias_up; |
172 | struct regmap *sys_regmap; |
173 | unsigned int sys_offset; |
174 | void __iomem *regs; |
175 | enum hdmi_colorspace csp; |
176 | struct hdmi_audio_param aud_param; |
177 | bool audio_enable; |
178 | bool powered; |
179 | bool enabled; |
180 | hdmi_codec_plugged_cb plugged_cb; |
181 | struct device *codec_dev; |
182 | struct mutex update_plugged_status_lock; |
183 | }; |
184 | |
185 | static inline struct mtk_hdmi *hdmi_ctx_from_bridge(struct drm_bridge *b) |
186 | { |
187 | return container_of(b, struct mtk_hdmi, bridge); |
188 | } |
189 | |
190 | static u32 mtk_hdmi_read(struct mtk_hdmi *hdmi, u32 offset) |
191 | { |
192 | return readl(addr: hdmi->regs + offset); |
193 | } |
194 | |
195 | static void mtk_hdmi_write(struct mtk_hdmi *hdmi, u32 offset, u32 val) |
196 | { |
197 | writel(val, addr: hdmi->regs + offset); |
198 | } |
199 | |
200 | static void mtk_hdmi_clear_bits(struct mtk_hdmi *hdmi, u32 offset, u32 bits) |
201 | { |
202 | void __iomem *reg = hdmi->regs + offset; |
203 | u32 tmp; |
204 | |
205 | tmp = readl(addr: reg); |
206 | tmp &= ~bits; |
207 | writel(val: tmp, addr: reg); |
208 | } |
209 | |
210 | static void mtk_hdmi_set_bits(struct mtk_hdmi *hdmi, u32 offset, u32 bits) |
211 | { |
212 | void __iomem *reg = hdmi->regs + offset; |
213 | u32 tmp; |
214 | |
215 | tmp = readl(addr: reg); |
216 | tmp |= bits; |
217 | writel(val: tmp, addr: reg); |
218 | } |
219 | |
220 | static void mtk_hdmi_mask(struct mtk_hdmi *hdmi, u32 offset, u32 val, u32 mask) |
221 | { |
222 | void __iomem *reg = hdmi->regs + offset; |
223 | u32 tmp; |
224 | |
225 | tmp = readl(addr: reg); |
226 | tmp = (tmp & ~mask) | (val & mask); |
227 | writel(val: tmp, addr: reg); |
228 | } |
229 | |
230 | static void mtk_hdmi_hw_vid_black(struct mtk_hdmi *hdmi, bool black) |
231 | { |
232 | mtk_hdmi_mask(hdmi, VIDEO_CFG_4, val: black ? GEN_RGB : NORMAL_PATH, |
233 | VIDEO_SOURCE_SEL); |
234 | } |
235 | |
236 | static void mtk_hdmi_hw_make_reg_writable(struct mtk_hdmi *hdmi, bool enable) |
237 | { |
238 | struct arm_smccc_res res; |
239 | |
240 | /* |
241 | * MT8173 HDMI hardware has an output control bit to enable/disable HDMI |
242 | * output. This bit can only be controlled in ARM supervisor mode. |
243 | * The ARM trusted firmware provides an API for the HDMI driver to set |
244 | * this control bit to enable HDMI output in supervisor mode. |
245 | */ |
246 | if (hdmi->conf && hdmi->conf->tz_disabled) |
247 | regmap_update_bits(map: hdmi->sys_regmap, |
248 | reg: hdmi->sys_offset + HDMI_SYS_CFG20, |
249 | mask: 0x80008005, val: enable ? 0x80000005 : 0x8000); |
250 | else |
251 | arm_smccc_smc(MTK_SIP_SET_AUTHORIZED_SECURE_REG, 0x14000904, |
252 | 0x80000000, 0, 0, 0, 0, 0, &res); |
253 | |
254 | regmap_update_bits(map: hdmi->sys_regmap, reg: hdmi->sys_offset + HDMI_SYS_CFG20, |
255 | HDMI_PCLK_FREE_RUN, val: enable ? HDMI_PCLK_FREE_RUN : 0); |
256 | regmap_update_bits(map: hdmi->sys_regmap, reg: hdmi->sys_offset + HDMI_SYS_CFG1C, |
257 | HDMI_ON | ANLG_ON, val: enable ? (HDMI_ON | ANLG_ON) : 0); |
258 | } |
259 | |
260 | static void mtk_hdmi_hw_1p4_version_enable(struct mtk_hdmi *hdmi, bool enable) |
261 | { |
262 | regmap_update_bits(map: hdmi->sys_regmap, reg: hdmi->sys_offset + HDMI_SYS_CFG20, |
263 | HDMI2P0_EN, val: enable ? 0 : HDMI2P0_EN); |
264 | } |
265 | |
266 | static void mtk_hdmi_hw_aud_mute(struct mtk_hdmi *hdmi) |
267 | { |
268 | mtk_hdmi_set_bits(hdmi, GRL_AUDIO_CFG, AUDIO_ZERO); |
269 | } |
270 | |
271 | static void mtk_hdmi_hw_aud_unmute(struct mtk_hdmi *hdmi) |
272 | { |
273 | mtk_hdmi_clear_bits(hdmi, GRL_AUDIO_CFG, AUDIO_ZERO); |
274 | } |
275 | |
276 | static void mtk_hdmi_hw_reset(struct mtk_hdmi *hdmi) |
277 | { |
278 | regmap_update_bits(map: hdmi->sys_regmap, reg: hdmi->sys_offset + HDMI_SYS_CFG1C, |
279 | HDMI_RST, HDMI_RST); |
280 | regmap_update_bits(map: hdmi->sys_regmap, reg: hdmi->sys_offset + HDMI_SYS_CFG1C, |
281 | HDMI_RST, val: 0); |
282 | mtk_hdmi_clear_bits(hdmi, GRL_CFG3, CFG3_CONTROL_PACKET_DELAY); |
283 | regmap_update_bits(map: hdmi->sys_regmap, reg: hdmi->sys_offset + HDMI_SYS_CFG1C, |
284 | ANLG_ON, ANLG_ON); |
285 | } |
286 | |
287 | static void mtk_hdmi_hw_enable_notice(struct mtk_hdmi *hdmi, bool enable_notice) |
288 | { |
289 | mtk_hdmi_mask(hdmi, GRL_CFG2, val: enable_notice ? CFG2_NOTICE_EN : 0, |
290 | CFG2_NOTICE_EN); |
291 | } |
292 | |
293 | static void mtk_hdmi_hw_write_int_mask(struct mtk_hdmi *hdmi, u32 int_mask) |
294 | { |
295 | mtk_hdmi_write(hdmi, GRL_INT_MASK, val: int_mask); |
296 | } |
297 | |
298 | static void mtk_hdmi_hw_enable_dvi_mode(struct mtk_hdmi *hdmi, bool enable) |
299 | { |
300 | mtk_hdmi_mask(hdmi, GRL_CFG1, val: enable ? CFG1_DVI : 0, CFG1_DVI); |
301 | } |
302 | |
303 | static void mtk_hdmi_hw_send_info_frame(struct mtk_hdmi *hdmi, u8 *buffer, |
304 | u8 len) |
305 | { |
306 | u32 ctrl_reg = GRL_CTRL; |
307 | int i; |
308 | u8 *frame_data; |
309 | enum hdmi_infoframe_type frame_type; |
310 | u8 frame_ver; |
311 | u8 frame_len; |
312 | u8 checksum; |
313 | int ctrl_frame_en = 0; |
314 | |
315 | frame_type = *buffer++; |
316 | frame_ver = *buffer++; |
317 | frame_len = *buffer++; |
318 | checksum = *buffer++; |
319 | frame_data = buffer; |
320 | |
321 | dev_dbg(hdmi->dev, |
322 | "frame_type:0x%x,frame_ver:0x%x,frame_len:0x%x,checksum:0x%x\n" , |
323 | frame_type, frame_ver, frame_len, checksum); |
324 | |
325 | switch (frame_type) { |
326 | case HDMI_INFOFRAME_TYPE_AVI: |
327 | ctrl_frame_en = CTRL_AVI_EN; |
328 | ctrl_reg = GRL_CTRL; |
329 | break; |
330 | case HDMI_INFOFRAME_TYPE_SPD: |
331 | ctrl_frame_en = CTRL_SPD_EN; |
332 | ctrl_reg = GRL_CTRL; |
333 | break; |
334 | case HDMI_INFOFRAME_TYPE_AUDIO: |
335 | ctrl_frame_en = CTRL_AUDIO_EN; |
336 | ctrl_reg = GRL_CTRL; |
337 | break; |
338 | case HDMI_INFOFRAME_TYPE_VENDOR: |
339 | ctrl_frame_en = VS_EN; |
340 | ctrl_reg = GRL_ACP_ISRC_CTRL; |
341 | break; |
342 | default: |
343 | dev_err(hdmi->dev, "Unknown infoframe type %d\n" , frame_type); |
344 | return; |
345 | } |
346 | mtk_hdmi_clear_bits(hdmi, offset: ctrl_reg, bits: ctrl_frame_en); |
347 | mtk_hdmi_write(hdmi, GRL_INFOFRM_TYPE, val: frame_type); |
348 | mtk_hdmi_write(hdmi, GRL_INFOFRM_VER, val: frame_ver); |
349 | mtk_hdmi_write(hdmi, GRL_INFOFRM_LNG, val: frame_len); |
350 | |
351 | mtk_hdmi_write(hdmi, GRL_IFM_PORT, val: checksum); |
352 | for (i = 0; i < frame_len; i++) |
353 | mtk_hdmi_write(hdmi, GRL_IFM_PORT, val: frame_data[i]); |
354 | |
355 | mtk_hdmi_set_bits(hdmi, offset: ctrl_reg, bits: ctrl_frame_en); |
356 | } |
357 | |
358 | static void mtk_hdmi_hw_send_aud_packet(struct mtk_hdmi *hdmi, bool enable) |
359 | { |
360 | mtk_hdmi_mask(hdmi, GRL_SHIFT_R2, val: enable ? 0 : AUDIO_PACKET_OFF, |
361 | AUDIO_PACKET_OFF); |
362 | } |
363 | |
364 | static void mtk_hdmi_hw_config_sys(struct mtk_hdmi *hdmi) |
365 | { |
366 | regmap_update_bits(map: hdmi->sys_regmap, reg: hdmi->sys_offset + HDMI_SYS_CFG20, |
367 | HDMI_OUT_FIFO_EN | MHL_MODE_ON, val: 0); |
368 | usleep_range(min: 2000, max: 4000); |
369 | regmap_update_bits(map: hdmi->sys_regmap, reg: hdmi->sys_offset + HDMI_SYS_CFG20, |
370 | HDMI_OUT_FIFO_EN | MHL_MODE_ON, HDMI_OUT_FIFO_EN); |
371 | } |
372 | |
373 | static void mtk_hdmi_hw_set_deep_color_mode(struct mtk_hdmi *hdmi) |
374 | { |
375 | regmap_update_bits(map: hdmi->sys_regmap, reg: hdmi->sys_offset + HDMI_SYS_CFG20, |
376 | DEEP_COLOR_MODE_MASK | DEEP_COLOR_EN, |
377 | COLOR_8BIT_MODE); |
378 | } |
379 | |
380 | static void mtk_hdmi_hw_send_av_mute(struct mtk_hdmi *hdmi) |
381 | { |
382 | mtk_hdmi_clear_bits(hdmi, GRL_CFG4, CTRL_AVMUTE); |
383 | usleep_range(min: 2000, max: 4000); |
384 | mtk_hdmi_set_bits(hdmi, GRL_CFG4, CTRL_AVMUTE); |
385 | } |
386 | |
387 | static void mtk_hdmi_hw_send_av_unmute(struct mtk_hdmi *hdmi) |
388 | { |
389 | mtk_hdmi_mask(hdmi, GRL_CFG4, CFG4_AV_UNMUTE_EN, |
390 | CFG4_AV_UNMUTE_EN | CFG4_AV_UNMUTE_SET); |
391 | usleep_range(min: 2000, max: 4000); |
392 | mtk_hdmi_mask(hdmi, GRL_CFG4, CFG4_AV_UNMUTE_SET, |
393 | CFG4_AV_UNMUTE_EN | CFG4_AV_UNMUTE_SET); |
394 | } |
395 | |
396 | static void mtk_hdmi_hw_ncts_enable(struct mtk_hdmi *hdmi, bool on) |
397 | { |
398 | mtk_hdmi_mask(hdmi, GRL_CTS_CTRL, val: on ? 0 : CTS_CTRL_SOFT, |
399 | CTS_CTRL_SOFT); |
400 | } |
401 | |
402 | static void mtk_hdmi_hw_ncts_auto_write_enable(struct mtk_hdmi *hdmi, |
403 | bool enable) |
404 | { |
405 | mtk_hdmi_mask(hdmi, GRL_CTS_CTRL, val: enable ? NCTS_WRI_ANYTIME : 0, |
406 | NCTS_WRI_ANYTIME); |
407 | } |
408 | |
409 | static void mtk_hdmi_hw_msic_setting(struct mtk_hdmi *hdmi, |
410 | struct drm_display_mode *mode) |
411 | { |
412 | mtk_hdmi_clear_bits(hdmi, GRL_CFG4, CFG4_MHL_MODE); |
413 | |
414 | if (mode->flags & DRM_MODE_FLAG_INTERLACE && |
415 | mode->clock == 74250 && |
416 | mode->vdisplay == 1080) |
417 | mtk_hdmi_clear_bits(hdmi, GRL_CFG2, CFG2_MHL_DE_SEL); |
418 | else |
419 | mtk_hdmi_set_bits(hdmi, GRL_CFG2, CFG2_MHL_DE_SEL); |
420 | } |
421 | |
422 | static void mtk_hdmi_hw_aud_set_channel_swap(struct mtk_hdmi *hdmi, |
423 | enum hdmi_aud_channel_swap_type swap) |
424 | { |
425 | u8 swap_bit; |
426 | |
427 | switch (swap) { |
428 | case HDMI_AUD_SWAP_LR: |
429 | swap_bit = LR_SWAP; |
430 | break; |
431 | case HDMI_AUD_SWAP_LFE_CC: |
432 | swap_bit = LFE_CC_SWAP; |
433 | break; |
434 | case HDMI_AUD_SWAP_LSRS: |
435 | swap_bit = LSRS_SWAP; |
436 | break; |
437 | case HDMI_AUD_SWAP_RLS_RRS: |
438 | swap_bit = RLS_RRS_SWAP; |
439 | break; |
440 | case HDMI_AUD_SWAP_LR_STATUS: |
441 | swap_bit = LR_STATUS_SWAP; |
442 | break; |
443 | default: |
444 | swap_bit = LFE_CC_SWAP; |
445 | break; |
446 | } |
447 | mtk_hdmi_mask(hdmi, GRL_CH_SWAP, val: swap_bit, mask: 0xff); |
448 | } |
449 | |
450 | static void mtk_hdmi_hw_aud_set_bit_num(struct mtk_hdmi *hdmi, |
451 | enum hdmi_audio_sample_size bit_num) |
452 | { |
453 | u32 val; |
454 | |
455 | switch (bit_num) { |
456 | case HDMI_AUDIO_SAMPLE_SIZE_16: |
457 | val = AOUT_16BIT; |
458 | break; |
459 | case HDMI_AUDIO_SAMPLE_SIZE_20: |
460 | val = AOUT_20BIT; |
461 | break; |
462 | case HDMI_AUDIO_SAMPLE_SIZE_24: |
463 | case HDMI_AUDIO_SAMPLE_SIZE_STREAM: |
464 | val = AOUT_24BIT; |
465 | break; |
466 | } |
467 | |
468 | mtk_hdmi_mask(hdmi, GRL_AOUT_CFG, val, AOUT_BNUM_SEL_MASK); |
469 | } |
470 | |
471 | static void mtk_hdmi_hw_aud_set_i2s_fmt(struct mtk_hdmi *hdmi, |
472 | enum hdmi_aud_i2s_fmt i2s_fmt) |
473 | { |
474 | u32 val; |
475 | |
476 | val = mtk_hdmi_read(hdmi, GRL_CFG0); |
477 | val &= ~(CFG0_W_LENGTH_MASK | CFG0_I2S_MODE_MASK); |
478 | |
479 | switch (i2s_fmt) { |
480 | case HDMI_I2S_MODE_RJT_24BIT: |
481 | val |= CFG0_I2S_MODE_RTJ | CFG0_W_LENGTH_24BIT; |
482 | break; |
483 | case HDMI_I2S_MODE_RJT_16BIT: |
484 | val |= CFG0_I2S_MODE_RTJ | CFG0_W_LENGTH_16BIT; |
485 | break; |
486 | case HDMI_I2S_MODE_LJT_24BIT: |
487 | default: |
488 | val |= CFG0_I2S_MODE_LTJ | CFG0_W_LENGTH_24BIT; |
489 | break; |
490 | case HDMI_I2S_MODE_LJT_16BIT: |
491 | val |= CFG0_I2S_MODE_LTJ | CFG0_W_LENGTH_16BIT; |
492 | break; |
493 | case HDMI_I2S_MODE_I2S_24BIT: |
494 | val |= CFG0_I2S_MODE_I2S | CFG0_W_LENGTH_24BIT; |
495 | break; |
496 | case HDMI_I2S_MODE_I2S_16BIT: |
497 | val |= CFG0_I2S_MODE_I2S | CFG0_W_LENGTH_16BIT; |
498 | break; |
499 | } |
500 | mtk_hdmi_write(hdmi, GRL_CFG0, val); |
501 | } |
502 | |
503 | static void mtk_hdmi_hw_audio_config(struct mtk_hdmi *hdmi, bool dst) |
504 | { |
505 | const u8 mask = HIGH_BIT_RATE | DST_NORMAL_DOUBLE | SACD_DST | DSD_SEL; |
506 | u8 val; |
507 | |
508 | /* Disable high bitrate, set DST packet normal/double */ |
509 | mtk_hdmi_clear_bits(hdmi, GRL_AOUT_CFG, HIGH_BIT_RATE_PACKET_ALIGN); |
510 | |
511 | if (dst) |
512 | val = DST_NORMAL_DOUBLE | SACD_DST; |
513 | else |
514 | val = 0; |
515 | |
516 | mtk_hdmi_mask(hdmi, GRL_AUDIO_CFG, val, mask); |
517 | } |
518 | |
519 | static void mtk_hdmi_hw_aud_set_i2s_chan_num(struct mtk_hdmi *hdmi, |
520 | enum hdmi_aud_channel_type channel_type, |
521 | u8 channel_count) |
522 | { |
523 | unsigned int ch_switch; |
524 | u8 i2s_uv; |
525 | |
526 | ch_switch = CH_SWITCH(7, 7) | CH_SWITCH(6, 6) | |
527 | CH_SWITCH(5, 5) | CH_SWITCH(4, 4) | |
528 | CH_SWITCH(3, 3) | CH_SWITCH(1, 2) | |
529 | CH_SWITCH(2, 1) | CH_SWITCH(0, 0); |
530 | |
531 | if (channel_count == 2) { |
532 | i2s_uv = I2S_UV_CH_EN(0); |
533 | } else if (channel_count == 3 || channel_count == 4) { |
534 | if (channel_count == 4 && |
535 | (channel_type == HDMI_AUD_CHAN_TYPE_3_0_LRS || |
536 | channel_type == HDMI_AUD_CHAN_TYPE_4_0)) |
537 | i2s_uv = I2S_UV_CH_EN(2) | I2S_UV_CH_EN(0); |
538 | else |
539 | i2s_uv = I2S_UV_CH_EN(3) | I2S_UV_CH_EN(2); |
540 | } else if (channel_count == 6 || channel_count == 5) { |
541 | if (channel_count == 6 && |
542 | channel_type != HDMI_AUD_CHAN_TYPE_5_1 && |
543 | channel_type != HDMI_AUD_CHAN_TYPE_4_1_CLRS) { |
544 | i2s_uv = I2S_UV_CH_EN(3) | I2S_UV_CH_EN(2) | |
545 | I2S_UV_CH_EN(1) | I2S_UV_CH_EN(0); |
546 | } else { |
547 | i2s_uv = I2S_UV_CH_EN(2) | I2S_UV_CH_EN(1) | |
548 | I2S_UV_CH_EN(0); |
549 | } |
550 | } else if (channel_count == 8 || channel_count == 7) { |
551 | i2s_uv = I2S_UV_CH_EN(3) | I2S_UV_CH_EN(2) | |
552 | I2S_UV_CH_EN(1) | I2S_UV_CH_EN(0); |
553 | } else { |
554 | i2s_uv = I2S_UV_CH_EN(0); |
555 | } |
556 | |
557 | mtk_hdmi_write(hdmi, GRL_CH_SW0, val: ch_switch & 0xff); |
558 | mtk_hdmi_write(hdmi, GRL_CH_SW1, val: (ch_switch >> 8) & 0xff); |
559 | mtk_hdmi_write(hdmi, GRL_CH_SW2, val: (ch_switch >> 16) & 0xff); |
560 | mtk_hdmi_write(hdmi, GRL_I2S_UV, val: i2s_uv); |
561 | } |
562 | |
563 | static void mtk_hdmi_hw_aud_set_input_type(struct mtk_hdmi *hdmi, |
564 | enum hdmi_aud_input_type input_type) |
565 | { |
566 | u32 val; |
567 | |
568 | val = mtk_hdmi_read(hdmi, GRL_CFG1); |
569 | if (input_type == HDMI_AUD_INPUT_I2S && |
570 | (val & CFG1_SPDIF) == CFG1_SPDIF) { |
571 | val &= ~CFG1_SPDIF; |
572 | } else if (input_type == HDMI_AUD_INPUT_SPDIF && |
573 | (val & CFG1_SPDIF) == 0) { |
574 | val |= CFG1_SPDIF; |
575 | } |
576 | mtk_hdmi_write(hdmi, GRL_CFG1, val); |
577 | } |
578 | |
579 | static void mtk_hdmi_hw_aud_set_channel_status(struct mtk_hdmi *hdmi, |
580 | u8 *channel_status) |
581 | { |
582 | int i; |
583 | |
584 | for (i = 0; i < 5; i++) { |
585 | mtk_hdmi_write(hdmi, GRL_I2S_C_STA0 + i * 4, val: channel_status[i]); |
586 | mtk_hdmi_write(hdmi, GRL_L_STATUS_0 + i * 4, val: channel_status[i]); |
587 | mtk_hdmi_write(hdmi, GRL_R_STATUS_0 + i * 4, val: channel_status[i]); |
588 | } |
589 | for (; i < 24; i++) { |
590 | mtk_hdmi_write(hdmi, GRL_L_STATUS_0 + i * 4, val: 0); |
591 | mtk_hdmi_write(hdmi, GRL_R_STATUS_0 + i * 4, val: 0); |
592 | } |
593 | } |
594 | |
595 | static void mtk_hdmi_hw_aud_src_reenable(struct mtk_hdmi *hdmi) |
596 | { |
597 | u32 val; |
598 | |
599 | val = mtk_hdmi_read(hdmi, GRL_MIX_CTRL); |
600 | if (val & MIX_CTRL_SRC_EN) { |
601 | val &= ~MIX_CTRL_SRC_EN; |
602 | mtk_hdmi_write(hdmi, GRL_MIX_CTRL, val); |
603 | usleep_range(min: 255, max: 512); |
604 | val |= MIX_CTRL_SRC_EN; |
605 | mtk_hdmi_write(hdmi, GRL_MIX_CTRL, val); |
606 | } |
607 | } |
608 | |
609 | static void mtk_hdmi_hw_aud_src_disable(struct mtk_hdmi *hdmi) |
610 | { |
611 | u32 val; |
612 | |
613 | val = mtk_hdmi_read(hdmi, GRL_MIX_CTRL); |
614 | val &= ~MIX_CTRL_SRC_EN; |
615 | mtk_hdmi_write(hdmi, GRL_MIX_CTRL, val); |
616 | mtk_hdmi_write(hdmi, GRL_SHIFT_L1, val: 0x00); |
617 | } |
618 | |
619 | static void mtk_hdmi_hw_aud_set_mclk(struct mtk_hdmi *hdmi, |
620 | enum hdmi_aud_mclk mclk) |
621 | { |
622 | u32 val; |
623 | |
624 | val = mtk_hdmi_read(hdmi, GRL_CFG5); |
625 | val &= CFG5_CD_RATIO_MASK; |
626 | |
627 | switch (mclk) { |
628 | case HDMI_AUD_MCLK_128FS: |
629 | val |= CFG5_FS128; |
630 | break; |
631 | case HDMI_AUD_MCLK_256FS: |
632 | val |= CFG5_FS256; |
633 | break; |
634 | case HDMI_AUD_MCLK_384FS: |
635 | val |= CFG5_FS384; |
636 | break; |
637 | case HDMI_AUD_MCLK_512FS: |
638 | val |= CFG5_FS512; |
639 | break; |
640 | case HDMI_AUD_MCLK_768FS: |
641 | val |= CFG5_FS768; |
642 | break; |
643 | default: |
644 | val |= CFG5_FS256; |
645 | break; |
646 | } |
647 | mtk_hdmi_write(hdmi, GRL_CFG5, val); |
648 | } |
649 | |
650 | struct hdmi_acr_n { |
651 | unsigned int clock; |
652 | unsigned int n[3]; |
653 | }; |
654 | |
655 | /* Recommended N values from HDMI specification, tables 7-1 to 7-3 */ |
656 | static const struct hdmi_acr_n hdmi_rec_n_table[] = { |
657 | /* Clock, N: 32kHz 44.1kHz 48kHz */ |
658 | { 25175, { 4576, 7007, 6864 } }, |
659 | { 74176, { 11648, 17836, 11648 } }, |
660 | { 148352, { 11648, 8918, 5824 } }, |
661 | { 296703, { 5824, 4459, 5824 } }, |
662 | { 297000, { 3072, 4704, 5120 } }, |
663 | { 0, { 4096, 6272, 6144 } }, /* all other TMDS clocks */ |
664 | }; |
665 | |
666 | /** |
667 | * hdmi_recommended_n() - Return N value recommended by HDMI specification |
668 | * @freq: audio sample rate in Hz |
669 | * @clock: rounded TMDS clock in kHz |
670 | */ |
671 | static unsigned int hdmi_recommended_n(unsigned int freq, unsigned int clock) |
672 | { |
673 | const struct hdmi_acr_n *recommended; |
674 | unsigned int i; |
675 | |
676 | for (i = 0; i < ARRAY_SIZE(hdmi_rec_n_table) - 1; i++) { |
677 | if (clock == hdmi_rec_n_table[i].clock) |
678 | break; |
679 | } |
680 | recommended = hdmi_rec_n_table + i; |
681 | |
682 | switch (freq) { |
683 | case 32000: |
684 | return recommended->n[0]; |
685 | case 44100: |
686 | return recommended->n[1]; |
687 | case 48000: |
688 | return recommended->n[2]; |
689 | case 88200: |
690 | return recommended->n[1] * 2; |
691 | case 96000: |
692 | return recommended->n[2] * 2; |
693 | case 176400: |
694 | return recommended->n[1] * 4; |
695 | case 192000: |
696 | return recommended->n[2] * 4; |
697 | default: |
698 | return (128 * freq) / 1000; |
699 | } |
700 | } |
701 | |
702 | static unsigned int hdmi_mode_clock_to_hz(unsigned int clock) |
703 | { |
704 | switch (clock) { |
705 | case 25175: |
706 | return 25174825; /* 25.2/1.001 MHz */ |
707 | case 74176: |
708 | return 74175824; /* 74.25/1.001 MHz */ |
709 | case 148352: |
710 | return 148351648; /* 148.5/1.001 MHz */ |
711 | case 296703: |
712 | return 296703297; /* 297/1.001 MHz */ |
713 | default: |
714 | return clock * 1000; |
715 | } |
716 | } |
717 | |
718 | static unsigned int hdmi_expected_cts(unsigned int audio_sample_rate, |
719 | unsigned int tmds_clock, unsigned int n) |
720 | { |
721 | return DIV_ROUND_CLOSEST_ULL((u64)hdmi_mode_clock_to_hz(tmds_clock) * n, |
722 | 128 * audio_sample_rate); |
723 | } |
724 | |
725 | static void do_hdmi_hw_aud_set_ncts(struct mtk_hdmi *hdmi, unsigned int n, |
726 | unsigned int cts) |
727 | { |
728 | unsigned char val[NCTS_BYTES]; |
729 | int i; |
730 | |
731 | mtk_hdmi_write(hdmi, GRL_NCTS, val: 0); |
732 | mtk_hdmi_write(hdmi, GRL_NCTS, val: 0); |
733 | mtk_hdmi_write(hdmi, GRL_NCTS, val: 0); |
734 | memset(val, 0, sizeof(val)); |
735 | |
736 | val[0] = (cts >> 24) & 0xff; |
737 | val[1] = (cts >> 16) & 0xff; |
738 | val[2] = (cts >> 8) & 0xff; |
739 | val[3] = cts & 0xff; |
740 | |
741 | val[4] = (n >> 16) & 0xff; |
742 | val[5] = (n >> 8) & 0xff; |
743 | val[6] = n & 0xff; |
744 | |
745 | for (i = 0; i < NCTS_BYTES; i++) |
746 | mtk_hdmi_write(hdmi, GRL_NCTS, val: val[i]); |
747 | } |
748 | |
749 | static void mtk_hdmi_hw_aud_set_ncts(struct mtk_hdmi *hdmi, |
750 | unsigned int sample_rate, |
751 | unsigned int clock) |
752 | { |
753 | unsigned int n, cts; |
754 | |
755 | n = hdmi_recommended_n(freq: sample_rate, clock); |
756 | cts = hdmi_expected_cts(audio_sample_rate: sample_rate, tmds_clock: clock, n); |
757 | |
758 | dev_dbg(hdmi->dev, "%s: sample_rate=%u, clock=%d, cts=%u, n=%u\n" , |
759 | __func__, sample_rate, clock, n, cts); |
760 | |
761 | mtk_hdmi_mask(hdmi, DUMMY_304, AUDIO_I2S_NCTS_SEL_64, |
762 | AUDIO_I2S_NCTS_SEL); |
763 | do_hdmi_hw_aud_set_ncts(hdmi, n, cts); |
764 | } |
765 | |
766 | static u8 mtk_hdmi_aud_get_chnl_count(enum hdmi_aud_channel_type channel_type) |
767 | { |
768 | switch (channel_type) { |
769 | case HDMI_AUD_CHAN_TYPE_1_0: |
770 | case HDMI_AUD_CHAN_TYPE_1_1: |
771 | case HDMI_AUD_CHAN_TYPE_2_0: |
772 | return 2; |
773 | case HDMI_AUD_CHAN_TYPE_2_1: |
774 | case HDMI_AUD_CHAN_TYPE_3_0: |
775 | return 3; |
776 | case HDMI_AUD_CHAN_TYPE_3_1: |
777 | case HDMI_AUD_CHAN_TYPE_4_0: |
778 | case HDMI_AUD_CHAN_TYPE_3_0_LRS: |
779 | return 4; |
780 | case HDMI_AUD_CHAN_TYPE_4_1: |
781 | case HDMI_AUD_CHAN_TYPE_5_0: |
782 | case HDMI_AUD_CHAN_TYPE_3_1_LRS: |
783 | case HDMI_AUD_CHAN_TYPE_4_0_CLRS: |
784 | return 5; |
785 | case HDMI_AUD_CHAN_TYPE_5_1: |
786 | case HDMI_AUD_CHAN_TYPE_6_0: |
787 | case HDMI_AUD_CHAN_TYPE_4_1_CLRS: |
788 | case HDMI_AUD_CHAN_TYPE_6_0_CS: |
789 | case HDMI_AUD_CHAN_TYPE_6_0_CH: |
790 | case HDMI_AUD_CHAN_TYPE_6_0_OH: |
791 | case HDMI_AUD_CHAN_TYPE_6_0_CHR: |
792 | return 6; |
793 | case HDMI_AUD_CHAN_TYPE_6_1: |
794 | case HDMI_AUD_CHAN_TYPE_6_1_CS: |
795 | case HDMI_AUD_CHAN_TYPE_6_1_CH: |
796 | case HDMI_AUD_CHAN_TYPE_6_1_OH: |
797 | case HDMI_AUD_CHAN_TYPE_6_1_CHR: |
798 | case HDMI_AUD_CHAN_TYPE_7_0: |
799 | case HDMI_AUD_CHAN_TYPE_7_0_LH_RH: |
800 | case HDMI_AUD_CHAN_TYPE_7_0_LSR_RSR: |
801 | case HDMI_AUD_CHAN_TYPE_7_0_LC_RC: |
802 | case HDMI_AUD_CHAN_TYPE_7_0_LW_RW: |
803 | case HDMI_AUD_CHAN_TYPE_7_0_LSD_RSD: |
804 | case HDMI_AUD_CHAN_TYPE_7_0_LSS_RSS: |
805 | case HDMI_AUD_CHAN_TYPE_7_0_LHS_RHS: |
806 | case HDMI_AUD_CHAN_TYPE_7_0_CS_CH: |
807 | case HDMI_AUD_CHAN_TYPE_7_0_CS_OH: |
808 | case HDMI_AUD_CHAN_TYPE_7_0_CS_CHR: |
809 | case HDMI_AUD_CHAN_TYPE_7_0_CH_OH: |
810 | case HDMI_AUD_CHAN_TYPE_7_0_CH_CHR: |
811 | case HDMI_AUD_CHAN_TYPE_7_0_OH_CHR: |
812 | case HDMI_AUD_CHAN_TYPE_7_0_LSS_RSS_LSR_RSR: |
813 | case HDMI_AUD_CHAN_TYPE_8_0_LH_RH_CS: |
814 | return 7; |
815 | case HDMI_AUD_CHAN_TYPE_7_1: |
816 | case HDMI_AUD_CHAN_TYPE_7_1_LH_RH: |
817 | case HDMI_AUD_CHAN_TYPE_7_1_LSR_RSR: |
818 | case HDMI_AUD_CHAN_TYPE_7_1_LC_RC: |
819 | case HDMI_AUD_CHAN_TYPE_7_1_LW_RW: |
820 | case HDMI_AUD_CHAN_TYPE_7_1_LSD_RSD: |
821 | case HDMI_AUD_CHAN_TYPE_7_1_LSS_RSS: |
822 | case HDMI_AUD_CHAN_TYPE_7_1_LHS_RHS: |
823 | case HDMI_AUD_CHAN_TYPE_7_1_CS_CH: |
824 | case HDMI_AUD_CHAN_TYPE_7_1_CS_OH: |
825 | case HDMI_AUD_CHAN_TYPE_7_1_CS_CHR: |
826 | case HDMI_AUD_CHAN_TYPE_7_1_CH_OH: |
827 | case HDMI_AUD_CHAN_TYPE_7_1_CH_CHR: |
828 | case HDMI_AUD_CHAN_TYPE_7_1_OH_CHR: |
829 | case HDMI_AUD_CHAN_TYPE_7_1_LSS_RSS_LSR_RSR: |
830 | return 8; |
831 | default: |
832 | return 2; |
833 | } |
834 | } |
835 | |
836 | static int mtk_hdmi_video_change_vpll(struct mtk_hdmi *hdmi, u32 clock) |
837 | { |
838 | unsigned long rate; |
839 | int ret; |
840 | |
841 | /* The DPI driver already should have set TVDPLL to the correct rate */ |
842 | ret = clk_set_rate(clk: hdmi->clk[MTK_HDMI_CLK_HDMI_PLL], rate: clock); |
843 | if (ret) { |
844 | dev_err(hdmi->dev, "Failed to set PLL to %u Hz: %d\n" , clock, |
845 | ret); |
846 | return ret; |
847 | } |
848 | |
849 | rate = clk_get_rate(clk: hdmi->clk[MTK_HDMI_CLK_HDMI_PLL]); |
850 | |
851 | if (DIV_ROUND_CLOSEST(rate, 1000) != DIV_ROUND_CLOSEST(clock, 1000)) |
852 | dev_warn(hdmi->dev, "Want PLL %u Hz, got %lu Hz\n" , clock, |
853 | rate); |
854 | else |
855 | dev_dbg(hdmi->dev, "Want PLL %u Hz, got %lu Hz\n" , clock, rate); |
856 | |
857 | mtk_hdmi_hw_config_sys(hdmi); |
858 | mtk_hdmi_hw_set_deep_color_mode(hdmi); |
859 | return 0; |
860 | } |
861 | |
862 | static void mtk_hdmi_video_set_display_mode(struct mtk_hdmi *hdmi, |
863 | struct drm_display_mode *mode) |
864 | { |
865 | mtk_hdmi_hw_reset(hdmi); |
866 | mtk_hdmi_hw_enable_notice(hdmi, enable_notice: true); |
867 | mtk_hdmi_hw_write_int_mask(hdmi, int_mask: 0xff); |
868 | mtk_hdmi_hw_enable_dvi_mode(hdmi, enable: hdmi->dvi_mode); |
869 | mtk_hdmi_hw_ncts_auto_write_enable(hdmi, enable: true); |
870 | |
871 | mtk_hdmi_hw_msic_setting(hdmi, mode); |
872 | } |
873 | |
874 | |
875 | static void mtk_hdmi_aud_set_input(struct mtk_hdmi *hdmi) |
876 | { |
877 | enum hdmi_aud_channel_type chan_type; |
878 | u8 chan_count; |
879 | bool dst; |
880 | |
881 | mtk_hdmi_hw_aud_set_channel_swap(hdmi, swap: HDMI_AUD_SWAP_LFE_CC); |
882 | mtk_hdmi_set_bits(hdmi, GRL_MIX_CTRL, MIX_CTRL_FLAT); |
883 | |
884 | if (hdmi->aud_param.aud_input_type == HDMI_AUD_INPUT_SPDIF && |
885 | hdmi->aud_param.aud_codec == HDMI_AUDIO_CODING_TYPE_DST) { |
886 | mtk_hdmi_hw_aud_set_bit_num(hdmi, bit_num: HDMI_AUDIO_SAMPLE_SIZE_24); |
887 | } else if (hdmi->aud_param.aud_i2s_fmt == HDMI_I2S_MODE_LJT_24BIT) { |
888 | hdmi->aud_param.aud_i2s_fmt = HDMI_I2S_MODE_LJT_16BIT; |
889 | } |
890 | |
891 | mtk_hdmi_hw_aud_set_i2s_fmt(hdmi, i2s_fmt: hdmi->aud_param.aud_i2s_fmt); |
892 | mtk_hdmi_hw_aud_set_bit_num(hdmi, bit_num: HDMI_AUDIO_SAMPLE_SIZE_24); |
893 | |
894 | dst = ((hdmi->aud_param.aud_input_type == HDMI_AUD_INPUT_SPDIF) && |
895 | (hdmi->aud_param.aud_codec == HDMI_AUDIO_CODING_TYPE_DST)); |
896 | mtk_hdmi_hw_audio_config(hdmi, dst); |
897 | |
898 | if (hdmi->aud_param.aud_input_type == HDMI_AUD_INPUT_SPDIF) |
899 | chan_type = HDMI_AUD_CHAN_TYPE_2_0; |
900 | else |
901 | chan_type = hdmi->aud_param.aud_input_chan_type; |
902 | chan_count = mtk_hdmi_aud_get_chnl_count(channel_type: chan_type); |
903 | mtk_hdmi_hw_aud_set_i2s_chan_num(hdmi, channel_type: chan_type, channel_count: chan_count); |
904 | mtk_hdmi_hw_aud_set_input_type(hdmi, input_type: hdmi->aud_param.aud_input_type); |
905 | } |
906 | |
907 | static int mtk_hdmi_aud_set_src(struct mtk_hdmi *hdmi, |
908 | struct drm_display_mode *display_mode) |
909 | { |
910 | unsigned int sample_rate = hdmi->aud_param.codec_params.sample_rate; |
911 | |
912 | mtk_hdmi_hw_ncts_enable(hdmi, on: false); |
913 | mtk_hdmi_hw_aud_src_disable(hdmi); |
914 | mtk_hdmi_clear_bits(hdmi, GRL_CFG2, CFG2_ACLK_INV); |
915 | |
916 | if (hdmi->aud_param.aud_input_type == HDMI_AUD_INPUT_I2S) { |
917 | switch (sample_rate) { |
918 | case 32000: |
919 | case 44100: |
920 | case 48000: |
921 | case 88200: |
922 | case 96000: |
923 | break; |
924 | default: |
925 | return -EINVAL; |
926 | } |
927 | mtk_hdmi_hw_aud_set_mclk(hdmi, mclk: hdmi->aud_param.aud_mclk); |
928 | } else { |
929 | switch (sample_rate) { |
930 | case 32000: |
931 | case 44100: |
932 | case 48000: |
933 | break; |
934 | default: |
935 | return -EINVAL; |
936 | } |
937 | mtk_hdmi_hw_aud_set_mclk(hdmi, mclk: HDMI_AUD_MCLK_128FS); |
938 | } |
939 | |
940 | mtk_hdmi_hw_aud_set_ncts(hdmi, sample_rate, clock: display_mode->clock); |
941 | |
942 | mtk_hdmi_hw_aud_src_reenable(hdmi); |
943 | return 0; |
944 | } |
945 | |
946 | static int mtk_hdmi_aud_output_config(struct mtk_hdmi *hdmi, |
947 | struct drm_display_mode *display_mode) |
948 | { |
949 | mtk_hdmi_hw_aud_mute(hdmi); |
950 | mtk_hdmi_hw_send_aud_packet(hdmi, enable: false); |
951 | |
952 | mtk_hdmi_aud_set_input(hdmi); |
953 | mtk_hdmi_aud_set_src(hdmi, display_mode); |
954 | mtk_hdmi_hw_aud_set_channel_status(hdmi, |
955 | channel_status: hdmi->aud_param.codec_params.iec.status); |
956 | |
957 | usleep_range(min: 50, max: 100); |
958 | |
959 | mtk_hdmi_hw_ncts_enable(hdmi, on: true); |
960 | mtk_hdmi_hw_send_aud_packet(hdmi, enable: true); |
961 | mtk_hdmi_hw_aud_unmute(hdmi); |
962 | return 0; |
963 | } |
964 | |
965 | static int mtk_hdmi_setup_avi_infoframe(struct mtk_hdmi *hdmi, |
966 | struct drm_display_mode *mode) |
967 | { |
968 | struct hdmi_avi_infoframe frame; |
969 | u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; |
970 | ssize_t err; |
971 | |
972 | err = drm_hdmi_avi_infoframe_from_display_mode(frame: &frame, |
973 | connector: hdmi->curr_conn, mode); |
974 | if (err < 0) { |
975 | dev_err(hdmi->dev, |
976 | "Failed to get AVI infoframe from mode: %zd\n" , err); |
977 | return err; |
978 | } |
979 | |
980 | err = hdmi_avi_infoframe_pack(frame: &frame, buffer, size: sizeof(buffer)); |
981 | if (err < 0) { |
982 | dev_err(hdmi->dev, "Failed to pack AVI infoframe: %zd\n" , err); |
983 | return err; |
984 | } |
985 | |
986 | mtk_hdmi_hw_send_info_frame(hdmi, buffer, len: sizeof(buffer)); |
987 | return 0; |
988 | } |
989 | |
990 | static int mtk_hdmi_setup_spd_infoframe(struct mtk_hdmi *hdmi, |
991 | const char *vendor, |
992 | const char *product) |
993 | { |
994 | struct hdmi_spd_infoframe frame; |
995 | u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_SPD_INFOFRAME_SIZE]; |
996 | ssize_t err; |
997 | |
998 | err = hdmi_spd_infoframe_init(frame: &frame, vendor, product); |
999 | if (err < 0) { |
1000 | dev_err(hdmi->dev, "Failed to initialize SPD infoframe: %zd\n" , |
1001 | err); |
1002 | return err; |
1003 | } |
1004 | |
1005 | err = hdmi_spd_infoframe_pack(frame: &frame, buffer, size: sizeof(buffer)); |
1006 | if (err < 0) { |
1007 | dev_err(hdmi->dev, "Failed to pack SDP infoframe: %zd\n" , err); |
1008 | return err; |
1009 | } |
1010 | |
1011 | mtk_hdmi_hw_send_info_frame(hdmi, buffer, len: sizeof(buffer)); |
1012 | return 0; |
1013 | } |
1014 | |
1015 | static int mtk_hdmi_setup_audio_infoframe(struct mtk_hdmi *hdmi) |
1016 | { |
1017 | struct hdmi_audio_infoframe frame; |
1018 | u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE]; |
1019 | ssize_t err; |
1020 | |
1021 | err = hdmi_audio_infoframe_init(frame: &frame); |
1022 | if (err < 0) { |
1023 | dev_err(hdmi->dev, "Failed to setup audio infoframe: %zd\n" , |
1024 | err); |
1025 | return err; |
1026 | } |
1027 | |
1028 | frame.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM; |
1029 | frame.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM; |
1030 | frame.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM; |
1031 | frame.channels = mtk_hdmi_aud_get_chnl_count( |
1032 | channel_type: hdmi->aud_param.aud_input_chan_type); |
1033 | |
1034 | err = hdmi_audio_infoframe_pack(frame: &frame, buffer, size: sizeof(buffer)); |
1035 | if (err < 0) { |
1036 | dev_err(hdmi->dev, "Failed to pack audio infoframe: %zd\n" , |
1037 | err); |
1038 | return err; |
1039 | } |
1040 | |
1041 | mtk_hdmi_hw_send_info_frame(hdmi, buffer, len: sizeof(buffer)); |
1042 | return 0; |
1043 | } |
1044 | |
1045 | static int mtk_hdmi_setup_vendor_specific_infoframe(struct mtk_hdmi *hdmi, |
1046 | struct drm_display_mode *mode) |
1047 | { |
1048 | struct hdmi_vendor_infoframe frame; |
1049 | u8 buffer[10]; |
1050 | ssize_t err; |
1051 | |
1052 | err = drm_hdmi_vendor_infoframe_from_display_mode(frame: &frame, |
1053 | connector: hdmi->curr_conn, mode); |
1054 | if (err) { |
1055 | dev_err(hdmi->dev, |
1056 | "Failed to get vendor infoframe from mode: %zd\n" , err); |
1057 | return err; |
1058 | } |
1059 | |
1060 | err = hdmi_vendor_infoframe_pack(frame: &frame, buffer, size: sizeof(buffer)); |
1061 | if (err < 0) { |
1062 | dev_err(hdmi->dev, "Failed to pack vendor infoframe: %zd\n" , |
1063 | err); |
1064 | return err; |
1065 | } |
1066 | |
1067 | mtk_hdmi_hw_send_info_frame(hdmi, buffer, len: sizeof(buffer)); |
1068 | return 0; |
1069 | } |
1070 | |
1071 | static int mtk_hdmi_output_init(struct mtk_hdmi *hdmi) |
1072 | { |
1073 | struct hdmi_audio_param *aud_param = &hdmi->aud_param; |
1074 | |
1075 | hdmi->csp = HDMI_COLORSPACE_RGB; |
1076 | aud_param->aud_codec = HDMI_AUDIO_CODING_TYPE_PCM; |
1077 | aud_param->aud_sampe_size = HDMI_AUDIO_SAMPLE_SIZE_16; |
1078 | aud_param->aud_input_type = HDMI_AUD_INPUT_I2S; |
1079 | aud_param->aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT; |
1080 | aud_param->aud_mclk = HDMI_AUD_MCLK_128FS; |
1081 | aud_param->aud_input_chan_type = HDMI_AUD_CHAN_TYPE_2_0; |
1082 | |
1083 | return 0; |
1084 | } |
1085 | |
1086 | static void mtk_hdmi_audio_enable(struct mtk_hdmi *hdmi) |
1087 | { |
1088 | mtk_hdmi_hw_send_aud_packet(hdmi, enable: true); |
1089 | hdmi->audio_enable = true; |
1090 | } |
1091 | |
1092 | static void mtk_hdmi_audio_disable(struct mtk_hdmi *hdmi) |
1093 | { |
1094 | mtk_hdmi_hw_send_aud_packet(hdmi, enable: false); |
1095 | hdmi->audio_enable = false; |
1096 | } |
1097 | |
1098 | static int mtk_hdmi_audio_set_param(struct mtk_hdmi *hdmi, |
1099 | struct hdmi_audio_param *param) |
1100 | { |
1101 | if (!hdmi->audio_enable) { |
1102 | dev_err(hdmi->dev, "hdmi audio is in disable state!\n" ); |
1103 | return -EINVAL; |
1104 | } |
1105 | dev_dbg(hdmi->dev, "codec:%d, input:%d, channel:%d, fs:%d\n" , |
1106 | param->aud_codec, param->aud_input_type, |
1107 | param->aud_input_chan_type, param->codec_params.sample_rate); |
1108 | memcpy(&hdmi->aud_param, param, sizeof(*param)); |
1109 | return mtk_hdmi_aud_output_config(hdmi, display_mode: &hdmi->mode); |
1110 | } |
1111 | |
1112 | static int mtk_hdmi_output_set_display_mode(struct mtk_hdmi *hdmi, |
1113 | struct drm_display_mode *mode) |
1114 | { |
1115 | int ret; |
1116 | |
1117 | mtk_hdmi_hw_vid_black(hdmi, black: true); |
1118 | mtk_hdmi_hw_aud_mute(hdmi); |
1119 | mtk_hdmi_hw_send_av_mute(hdmi); |
1120 | phy_power_off(phy: hdmi->phy); |
1121 | |
1122 | ret = mtk_hdmi_video_change_vpll(hdmi, |
1123 | clock: mode->clock * 1000); |
1124 | if (ret) { |
1125 | dev_err(hdmi->dev, "Failed to set vpll: %d\n" , ret); |
1126 | return ret; |
1127 | } |
1128 | mtk_hdmi_video_set_display_mode(hdmi, mode); |
1129 | |
1130 | phy_power_on(phy: hdmi->phy); |
1131 | mtk_hdmi_aud_output_config(hdmi, display_mode: mode); |
1132 | |
1133 | mtk_hdmi_hw_vid_black(hdmi, black: false); |
1134 | mtk_hdmi_hw_aud_unmute(hdmi); |
1135 | mtk_hdmi_hw_send_av_unmute(hdmi); |
1136 | |
1137 | return 0; |
1138 | } |
1139 | |
1140 | static const char * const mtk_hdmi_clk_names[MTK_HDMI_CLK_COUNT] = { |
1141 | [MTK_HDMI_CLK_HDMI_PIXEL] = "pixel" , |
1142 | [MTK_HDMI_CLK_HDMI_PLL] = "pll" , |
1143 | [MTK_HDMI_CLK_AUD_BCLK] = "bclk" , |
1144 | [MTK_HDMI_CLK_AUD_SPDIF] = "spdif" , |
1145 | }; |
1146 | |
1147 | static int mtk_hdmi_get_all_clk(struct mtk_hdmi *hdmi, |
1148 | struct device_node *np) |
1149 | { |
1150 | int i; |
1151 | |
1152 | for (i = 0; i < ARRAY_SIZE(mtk_hdmi_clk_names); i++) { |
1153 | hdmi->clk[i] = of_clk_get_by_name(np, |
1154 | name: mtk_hdmi_clk_names[i]); |
1155 | if (IS_ERR(ptr: hdmi->clk[i])) |
1156 | return PTR_ERR(ptr: hdmi->clk[i]); |
1157 | } |
1158 | return 0; |
1159 | } |
1160 | |
1161 | static int mtk_hdmi_clk_enable_audio(struct mtk_hdmi *hdmi) |
1162 | { |
1163 | int ret; |
1164 | |
1165 | ret = clk_prepare_enable(clk: hdmi->clk[MTK_HDMI_CLK_AUD_BCLK]); |
1166 | if (ret) |
1167 | return ret; |
1168 | |
1169 | ret = clk_prepare_enable(clk: hdmi->clk[MTK_HDMI_CLK_AUD_SPDIF]); |
1170 | if (ret) |
1171 | goto err; |
1172 | |
1173 | return 0; |
1174 | err: |
1175 | clk_disable_unprepare(clk: hdmi->clk[MTK_HDMI_CLK_AUD_BCLK]); |
1176 | return ret; |
1177 | } |
1178 | |
1179 | static void mtk_hdmi_clk_disable_audio(struct mtk_hdmi *hdmi) |
1180 | { |
1181 | clk_disable_unprepare(clk: hdmi->clk[MTK_HDMI_CLK_AUD_BCLK]); |
1182 | clk_disable_unprepare(clk: hdmi->clk[MTK_HDMI_CLK_AUD_SPDIF]); |
1183 | } |
1184 | |
1185 | static enum drm_connector_status |
1186 | mtk_hdmi_update_plugged_status(struct mtk_hdmi *hdmi) |
1187 | { |
1188 | bool connected; |
1189 | |
1190 | mutex_lock(&hdmi->update_plugged_status_lock); |
1191 | connected = mtk_cec_hpd_high(dev: hdmi->cec_dev); |
1192 | if (hdmi->plugged_cb && hdmi->codec_dev) |
1193 | hdmi->plugged_cb(hdmi->codec_dev, connected); |
1194 | mutex_unlock(lock: &hdmi->update_plugged_status_lock); |
1195 | |
1196 | return connected ? |
1197 | connector_status_connected : connector_status_disconnected; |
1198 | } |
1199 | |
1200 | static enum drm_connector_status mtk_hdmi_detect(struct mtk_hdmi *hdmi) |
1201 | { |
1202 | return mtk_hdmi_update_plugged_status(hdmi); |
1203 | } |
1204 | |
1205 | static enum drm_mode_status |
1206 | mtk_hdmi_bridge_mode_valid(struct drm_bridge *bridge, |
1207 | const struct drm_display_info *info, |
1208 | const struct drm_display_mode *mode) |
1209 | { |
1210 | struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(b: bridge); |
1211 | struct drm_bridge *next_bridge; |
1212 | |
1213 | dev_dbg(hdmi->dev, "xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n" , |
1214 | mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode), |
1215 | !!(mode->flags & DRM_MODE_FLAG_INTERLACE), mode->clock * 1000); |
1216 | |
1217 | next_bridge = drm_bridge_get_next_bridge(bridge: &hdmi->bridge); |
1218 | if (next_bridge) { |
1219 | struct drm_display_mode adjusted_mode; |
1220 | |
1221 | drm_mode_init(dst: &adjusted_mode, src: mode); |
1222 | if (!drm_bridge_chain_mode_fixup(bridge: next_bridge, mode, |
1223 | adjusted_mode: &adjusted_mode)) |
1224 | return MODE_BAD; |
1225 | } |
1226 | |
1227 | if (hdmi->conf) { |
1228 | if (hdmi->conf->cea_modes_only && !drm_match_cea_mode(to_match: mode)) |
1229 | return MODE_BAD; |
1230 | |
1231 | if (hdmi->conf->max_mode_clock && |
1232 | mode->clock > hdmi->conf->max_mode_clock) |
1233 | return MODE_CLOCK_HIGH; |
1234 | } |
1235 | |
1236 | if (mode->clock < 27000) |
1237 | return MODE_CLOCK_LOW; |
1238 | if (mode->clock > 297000) |
1239 | return MODE_CLOCK_HIGH; |
1240 | |
1241 | return drm_mode_validate_size(mode, maxX: 0x1fff, maxY: 0x1fff); |
1242 | } |
1243 | |
1244 | static void mtk_hdmi_hpd_event(bool hpd, struct device *dev) |
1245 | { |
1246 | struct mtk_hdmi *hdmi = dev_get_drvdata(dev); |
1247 | |
1248 | if (hdmi && hdmi->bridge.encoder && hdmi->bridge.encoder->dev) { |
1249 | static enum drm_connector_status status; |
1250 | |
1251 | status = mtk_hdmi_detect(hdmi); |
1252 | drm_helper_hpd_irq_event(dev: hdmi->bridge.encoder->dev); |
1253 | drm_bridge_hpd_notify(bridge: &hdmi->bridge, status); |
1254 | } |
1255 | } |
1256 | |
1257 | /* |
1258 | * Bridge callbacks |
1259 | */ |
1260 | |
1261 | static enum drm_connector_status mtk_hdmi_bridge_detect(struct drm_bridge *bridge) |
1262 | { |
1263 | struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(b: bridge); |
1264 | |
1265 | return mtk_hdmi_detect(hdmi); |
1266 | } |
1267 | |
1268 | static const struct drm_edid *mtk_hdmi_bridge_edid_read(struct drm_bridge *bridge, |
1269 | struct drm_connector *connector) |
1270 | { |
1271 | struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(b: bridge); |
1272 | const struct drm_edid *drm_edid; |
1273 | |
1274 | if (!hdmi->ddc_adpt) |
1275 | return NULL; |
1276 | drm_edid = drm_edid_read_ddc(connector, adapter: hdmi->ddc_adpt); |
1277 | if (drm_edid) { |
1278 | /* |
1279 | * FIXME: This should use !connector->display_info.has_audio (or |
1280 | * !connector->display_info.is_hdmi) from a path that has read |
1281 | * the EDID and called drm_edid_connector_update(). |
1282 | */ |
1283 | const struct edid *edid = drm_edid_raw(drm_edid); |
1284 | |
1285 | hdmi->dvi_mode = !drm_detect_monitor_audio(edid); |
1286 | } |
1287 | |
1288 | return drm_edid; |
1289 | } |
1290 | |
1291 | static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge, |
1292 | enum drm_bridge_attach_flags flags) |
1293 | { |
1294 | struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(b: bridge); |
1295 | int ret; |
1296 | |
1297 | if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { |
1298 | DRM_ERROR("%s: The flag DRM_BRIDGE_ATTACH_NO_CONNECTOR must be supplied\n" , |
1299 | __func__); |
1300 | return -EINVAL; |
1301 | } |
1302 | |
1303 | if (hdmi->next_bridge) { |
1304 | ret = drm_bridge_attach(encoder: bridge->encoder, bridge: hdmi->next_bridge, |
1305 | previous: bridge, flags); |
1306 | if (ret) |
1307 | return ret; |
1308 | } |
1309 | |
1310 | mtk_cec_set_hpd_event(dev: hdmi->cec_dev, hotplug_event: mtk_hdmi_hpd_event, hdmi_dev: hdmi->dev); |
1311 | |
1312 | return 0; |
1313 | } |
1314 | |
1315 | static bool mtk_hdmi_bridge_mode_fixup(struct drm_bridge *bridge, |
1316 | const struct drm_display_mode *mode, |
1317 | struct drm_display_mode *adjusted_mode) |
1318 | { |
1319 | return true; |
1320 | } |
1321 | |
1322 | static void mtk_hdmi_bridge_atomic_disable(struct drm_bridge *bridge, |
1323 | struct drm_bridge_state *old_bridge_state) |
1324 | { |
1325 | struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(b: bridge); |
1326 | |
1327 | if (!hdmi->enabled) |
1328 | return; |
1329 | |
1330 | phy_power_off(phy: hdmi->phy); |
1331 | clk_disable_unprepare(clk: hdmi->clk[MTK_HDMI_CLK_HDMI_PIXEL]); |
1332 | clk_disable_unprepare(clk: hdmi->clk[MTK_HDMI_CLK_HDMI_PLL]); |
1333 | |
1334 | hdmi->curr_conn = NULL; |
1335 | |
1336 | hdmi->enabled = false; |
1337 | } |
1338 | |
1339 | static void mtk_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge, |
1340 | struct drm_bridge_state *old_state) |
1341 | { |
1342 | struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(b: bridge); |
1343 | |
1344 | if (!hdmi->powered) |
1345 | return; |
1346 | |
1347 | mtk_hdmi_hw_1p4_version_enable(hdmi, enable: true); |
1348 | mtk_hdmi_hw_make_reg_writable(hdmi, enable: false); |
1349 | |
1350 | hdmi->powered = false; |
1351 | } |
1352 | |
1353 | static void mtk_hdmi_bridge_mode_set(struct drm_bridge *bridge, |
1354 | const struct drm_display_mode *mode, |
1355 | const struct drm_display_mode *adjusted_mode) |
1356 | { |
1357 | struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(b: bridge); |
1358 | |
1359 | dev_dbg(hdmi->dev, "cur info: name:%s, hdisplay:%d\n" , |
1360 | adjusted_mode->name, adjusted_mode->hdisplay); |
1361 | dev_dbg(hdmi->dev, "hsync_start:%d,hsync_end:%d, htotal:%d" , |
1362 | adjusted_mode->hsync_start, adjusted_mode->hsync_end, |
1363 | adjusted_mode->htotal); |
1364 | dev_dbg(hdmi->dev, "hskew:%d, vdisplay:%d\n" , |
1365 | adjusted_mode->hskew, adjusted_mode->vdisplay); |
1366 | dev_dbg(hdmi->dev, "vsync_start:%d, vsync_end:%d, vtotal:%d" , |
1367 | adjusted_mode->vsync_start, adjusted_mode->vsync_end, |
1368 | adjusted_mode->vtotal); |
1369 | dev_dbg(hdmi->dev, "vscan:%d, flag:%d\n" , |
1370 | adjusted_mode->vscan, adjusted_mode->flags); |
1371 | |
1372 | drm_mode_copy(dst: &hdmi->mode, src: adjusted_mode); |
1373 | } |
1374 | |
1375 | static void mtk_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge, |
1376 | struct drm_bridge_state *old_state) |
1377 | { |
1378 | struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(b: bridge); |
1379 | |
1380 | mtk_hdmi_hw_make_reg_writable(hdmi, enable: true); |
1381 | mtk_hdmi_hw_1p4_version_enable(hdmi, enable: true); |
1382 | |
1383 | hdmi->powered = true; |
1384 | } |
1385 | |
1386 | static void mtk_hdmi_send_infoframe(struct mtk_hdmi *hdmi, |
1387 | struct drm_display_mode *mode) |
1388 | { |
1389 | mtk_hdmi_setup_audio_infoframe(hdmi); |
1390 | mtk_hdmi_setup_avi_infoframe(hdmi, mode); |
1391 | mtk_hdmi_setup_spd_infoframe(hdmi, vendor: "mediatek" , product: "On-chip HDMI" ); |
1392 | if (mode->flags & DRM_MODE_FLAG_3D_MASK) |
1393 | mtk_hdmi_setup_vendor_specific_infoframe(hdmi, mode); |
1394 | } |
1395 | |
1396 | static void mtk_hdmi_bridge_atomic_enable(struct drm_bridge *bridge, |
1397 | struct drm_bridge_state *old_state) |
1398 | { |
1399 | struct drm_atomic_state *state = old_state->base.state; |
1400 | struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(b: bridge); |
1401 | |
1402 | /* Retrieve the connector through the atomic state. */ |
1403 | hdmi->curr_conn = drm_atomic_get_new_connector_for_encoder(state, |
1404 | encoder: bridge->encoder); |
1405 | |
1406 | mtk_hdmi_output_set_display_mode(hdmi, mode: &hdmi->mode); |
1407 | clk_prepare_enable(clk: hdmi->clk[MTK_HDMI_CLK_HDMI_PLL]); |
1408 | clk_prepare_enable(clk: hdmi->clk[MTK_HDMI_CLK_HDMI_PIXEL]); |
1409 | phy_power_on(phy: hdmi->phy); |
1410 | mtk_hdmi_send_infoframe(hdmi, mode: &hdmi->mode); |
1411 | |
1412 | hdmi->enabled = true; |
1413 | } |
1414 | |
1415 | static const struct drm_bridge_funcs mtk_hdmi_bridge_funcs = { |
1416 | .mode_valid = mtk_hdmi_bridge_mode_valid, |
1417 | .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, |
1418 | .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, |
1419 | .atomic_reset = drm_atomic_helper_bridge_reset, |
1420 | .attach = mtk_hdmi_bridge_attach, |
1421 | .mode_fixup = mtk_hdmi_bridge_mode_fixup, |
1422 | .atomic_disable = mtk_hdmi_bridge_atomic_disable, |
1423 | .atomic_post_disable = mtk_hdmi_bridge_atomic_post_disable, |
1424 | .mode_set = mtk_hdmi_bridge_mode_set, |
1425 | .atomic_pre_enable = mtk_hdmi_bridge_atomic_pre_enable, |
1426 | .atomic_enable = mtk_hdmi_bridge_atomic_enable, |
1427 | .detect = mtk_hdmi_bridge_detect, |
1428 | .edid_read = mtk_hdmi_bridge_edid_read, |
1429 | }; |
1430 | |
1431 | static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, |
1432 | struct platform_device *pdev) |
1433 | { |
1434 | struct device *dev = &pdev->dev; |
1435 | struct device_node *np = dev->of_node; |
1436 | struct device_node *cec_np, *remote, *i2c_np; |
1437 | struct platform_device *cec_pdev; |
1438 | struct regmap *regmap; |
1439 | struct resource *mem; |
1440 | int ret; |
1441 | |
1442 | ret = mtk_hdmi_get_all_clk(hdmi, np); |
1443 | if (ret) { |
1444 | if (ret != -EPROBE_DEFER) |
1445 | dev_err(dev, "Failed to get clocks: %d\n" , ret); |
1446 | |
1447 | return ret; |
1448 | } |
1449 | |
1450 | /* The CEC module handles HDMI hotplug detection */ |
1451 | cec_np = of_get_compatible_child(parent: np->parent, compatible: "mediatek,mt8173-cec" ); |
1452 | if (!cec_np) { |
1453 | dev_err(dev, "Failed to find CEC node\n" ); |
1454 | return -EINVAL; |
1455 | } |
1456 | |
1457 | cec_pdev = of_find_device_by_node(np: cec_np); |
1458 | if (!cec_pdev) { |
1459 | dev_err(hdmi->dev, "Waiting for CEC device %pOF\n" , |
1460 | cec_np); |
1461 | of_node_put(node: cec_np); |
1462 | return -EPROBE_DEFER; |
1463 | } |
1464 | of_node_put(node: cec_np); |
1465 | hdmi->cec_dev = &cec_pdev->dev; |
1466 | |
1467 | /* |
1468 | * The mediatek,syscon-hdmi property contains a phandle link to the |
1469 | * MMSYS_CONFIG device and the register offset of the HDMI_SYS_CFG |
1470 | * registers it contains. |
1471 | */ |
1472 | regmap = syscon_regmap_lookup_by_phandle(np, property: "mediatek,syscon-hdmi" ); |
1473 | ret = of_property_read_u32_index(np, propname: "mediatek,syscon-hdmi" , index: 1, |
1474 | out_value: &hdmi->sys_offset); |
1475 | if (IS_ERR(ptr: regmap)) |
1476 | ret = PTR_ERR(ptr: regmap); |
1477 | if (ret) { |
1478 | dev_err(dev, |
1479 | "Failed to get system configuration registers: %d\n" , |
1480 | ret); |
1481 | goto put_device; |
1482 | } |
1483 | hdmi->sys_regmap = regmap; |
1484 | |
1485 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1486 | hdmi->regs = devm_ioremap_resource(dev, res: mem); |
1487 | if (IS_ERR(ptr: hdmi->regs)) { |
1488 | ret = PTR_ERR(ptr: hdmi->regs); |
1489 | goto put_device; |
1490 | } |
1491 | |
1492 | remote = of_graph_get_remote_node(node: np, port: 1, endpoint: 0); |
1493 | if (!remote) { |
1494 | ret = -EINVAL; |
1495 | goto put_device; |
1496 | } |
1497 | |
1498 | if (!of_device_is_compatible(device: remote, "hdmi-connector" )) { |
1499 | hdmi->next_bridge = of_drm_find_bridge(np: remote); |
1500 | if (!hdmi->next_bridge) { |
1501 | dev_err(dev, "Waiting for external bridge\n" ); |
1502 | of_node_put(node: remote); |
1503 | ret = -EPROBE_DEFER; |
1504 | goto put_device; |
1505 | } |
1506 | } |
1507 | |
1508 | i2c_np = of_parse_phandle(np: remote, phandle_name: "ddc-i2c-bus" , index: 0); |
1509 | if (!i2c_np) { |
1510 | dev_err(dev, "Failed to find ddc-i2c-bus node in %pOF\n" , |
1511 | remote); |
1512 | of_node_put(node: remote); |
1513 | ret = -EINVAL; |
1514 | goto put_device; |
1515 | } |
1516 | of_node_put(node: remote); |
1517 | |
1518 | hdmi->ddc_adpt = of_find_i2c_adapter_by_node(node: i2c_np); |
1519 | of_node_put(node: i2c_np); |
1520 | if (!hdmi->ddc_adpt) { |
1521 | dev_err(dev, "Failed to get ddc i2c adapter by node\n" ); |
1522 | ret = -EINVAL; |
1523 | goto put_device; |
1524 | } |
1525 | |
1526 | return 0; |
1527 | put_device: |
1528 | put_device(dev: hdmi->cec_dev); |
1529 | return ret; |
1530 | } |
1531 | |
1532 | /* |
1533 | * HDMI audio codec callbacks |
1534 | */ |
1535 | |
1536 | static int mtk_hdmi_audio_hw_params(struct device *dev, void *data, |
1537 | struct hdmi_codec_daifmt *daifmt, |
1538 | struct hdmi_codec_params *params) |
1539 | { |
1540 | struct mtk_hdmi *hdmi = dev_get_drvdata(dev); |
1541 | struct hdmi_audio_param hdmi_params; |
1542 | unsigned int chan = params->cea.channels; |
1543 | |
1544 | dev_dbg(hdmi->dev, "%s: %u Hz, %d bit, %d channels\n" , __func__, |
1545 | params->sample_rate, params->sample_width, chan); |
1546 | |
1547 | if (!hdmi->bridge.encoder) |
1548 | return -ENODEV; |
1549 | |
1550 | switch (chan) { |
1551 | case 2: |
1552 | hdmi_params.aud_input_chan_type = HDMI_AUD_CHAN_TYPE_2_0; |
1553 | break; |
1554 | case 4: |
1555 | hdmi_params.aud_input_chan_type = HDMI_AUD_CHAN_TYPE_4_0; |
1556 | break; |
1557 | case 6: |
1558 | hdmi_params.aud_input_chan_type = HDMI_AUD_CHAN_TYPE_5_1; |
1559 | break; |
1560 | case 8: |
1561 | hdmi_params.aud_input_chan_type = HDMI_AUD_CHAN_TYPE_7_1; |
1562 | break; |
1563 | default: |
1564 | dev_err(hdmi->dev, "channel[%d] not supported!\n" , chan); |
1565 | return -EINVAL; |
1566 | } |
1567 | |
1568 | switch (params->sample_rate) { |
1569 | case 32000: |
1570 | case 44100: |
1571 | case 48000: |
1572 | case 88200: |
1573 | case 96000: |
1574 | case 176400: |
1575 | case 192000: |
1576 | break; |
1577 | default: |
1578 | dev_err(hdmi->dev, "rate[%d] not supported!\n" , |
1579 | params->sample_rate); |
1580 | return -EINVAL; |
1581 | } |
1582 | |
1583 | switch (daifmt->fmt) { |
1584 | case HDMI_I2S: |
1585 | hdmi_params.aud_codec = HDMI_AUDIO_CODING_TYPE_PCM; |
1586 | hdmi_params.aud_sampe_size = HDMI_AUDIO_SAMPLE_SIZE_16; |
1587 | hdmi_params.aud_input_type = HDMI_AUD_INPUT_I2S; |
1588 | hdmi_params.aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT; |
1589 | hdmi_params.aud_mclk = HDMI_AUD_MCLK_128FS; |
1590 | break; |
1591 | case HDMI_SPDIF: |
1592 | hdmi_params.aud_codec = HDMI_AUDIO_CODING_TYPE_PCM; |
1593 | hdmi_params.aud_sampe_size = HDMI_AUDIO_SAMPLE_SIZE_16; |
1594 | hdmi_params.aud_input_type = HDMI_AUD_INPUT_SPDIF; |
1595 | break; |
1596 | default: |
1597 | dev_err(hdmi->dev, "%s: Invalid DAI format %d\n" , __func__, |
1598 | daifmt->fmt); |
1599 | return -EINVAL; |
1600 | } |
1601 | |
1602 | memcpy(&hdmi_params.codec_params, params, |
1603 | sizeof(hdmi_params.codec_params)); |
1604 | |
1605 | mtk_hdmi_audio_set_param(hdmi, param: &hdmi_params); |
1606 | |
1607 | return 0; |
1608 | } |
1609 | |
1610 | static int mtk_hdmi_audio_startup(struct device *dev, void *data) |
1611 | { |
1612 | struct mtk_hdmi *hdmi = dev_get_drvdata(dev); |
1613 | |
1614 | mtk_hdmi_audio_enable(hdmi); |
1615 | |
1616 | return 0; |
1617 | } |
1618 | |
1619 | static void mtk_hdmi_audio_shutdown(struct device *dev, void *data) |
1620 | { |
1621 | struct mtk_hdmi *hdmi = dev_get_drvdata(dev); |
1622 | |
1623 | mtk_hdmi_audio_disable(hdmi); |
1624 | } |
1625 | |
1626 | static int |
1627 | mtk_hdmi_audio_mute(struct device *dev, void *data, |
1628 | bool enable, int direction) |
1629 | { |
1630 | struct mtk_hdmi *hdmi = dev_get_drvdata(dev); |
1631 | |
1632 | if (enable) |
1633 | mtk_hdmi_hw_aud_mute(hdmi); |
1634 | else |
1635 | mtk_hdmi_hw_aud_unmute(hdmi); |
1636 | |
1637 | return 0; |
1638 | } |
1639 | |
1640 | static int mtk_hdmi_audio_get_eld(struct device *dev, void *data, uint8_t *buf, size_t len) |
1641 | { |
1642 | struct mtk_hdmi *hdmi = dev_get_drvdata(dev); |
1643 | |
1644 | if (hdmi->enabled) |
1645 | memcpy(buf, hdmi->curr_conn->eld, min(sizeof(hdmi->curr_conn->eld), len)); |
1646 | else |
1647 | memset(buf, 0, len); |
1648 | return 0; |
1649 | } |
1650 | |
1651 | static int mtk_hdmi_audio_hook_plugged_cb(struct device *dev, void *data, |
1652 | hdmi_codec_plugged_cb fn, |
1653 | struct device *codec_dev) |
1654 | { |
1655 | struct mtk_hdmi *hdmi = data; |
1656 | |
1657 | mutex_lock(&hdmi->update_plugged_status_lock); |
1658 | hdmi->plugged_cb = fn; |
1659 | hdmi->codec_dev = codec_dev; |
1660 | mutex_unlock(lock: &hdmi->update_plugged_status_lock); |
1661 | |
1662 | mtk_hdmi_update_plugged_status(hdmi); |
1663 | |
1664 | return 0; |
1665 | } |
1666 | |
1667 | static const struct hdmi_codec_ops mtk_hdmi_audio_codec_ops = { |
1668 | .hw_params = mtk_hdmi_audio_hw_params, |
1669 | .audio_startup = mtk_hdmi_audio_startup, |
1670 | .audio_shutdown = mtk_hdmi_audio_shutdown, |
1671 | .mute_stream = mtk_hdmi_audio_mute, |
1672 | .get_eld = mtk_hdmi_audio_get_eld, |
1673 | .hook_plugged_cb = mtk_hdmi_audio_hook_plugged_cb, |
1674 | .no_capture_mute = 1, |
1675 | }; |
1676 | |
1677 | static int mtk_hdmi_register_audio_driver(struct device *dev) |
1678 | { |
1679 | struct mtk_hdmi *hdmi = dev_get_drvdata(dev); |
1680 | struct hdmi_codec_pdata codec_data = { |
1681 | .ops = &mtk_hdmi_audio_codec_ops, |
1682 | .max_i2s_channels = 2, |
1683 | .i2s = 1, |
1684 | .data = hdmi, |
1685 | }; |
1686 | struct platform_device *pdev; |
1687 | |
1688 | pdev = platform_device_register_data(parent: dev, HDMI_CODEC_DRV_NAME, |
1689 | PLATFORM_DEVID_AUTO, data: &codec_data, |
1690 | size: sizeof(codec_data)); |
1691 | if (IS_ERR(ptr: pdev)) |
1692 | return PTR_ERR(ptr: pdev); |
1693 | |
1694 | DRM_INFO("%s driver bound to HDMI\n" , HDMI_CODEC_DRV_NAME); |
1695 | return 0; |
1696 | } |
1697 | |
1698 | static int mtk_drm_hdmi_probe(struct platform_device *pdev) |
1699 | { |
1700 | struct mtk_hdmi *hdmi; |
1701 | struct device *dev = &pdev->dev; |
1702 | int ret; |
1703 | |
1704 | hdmi = devm_kzalloc(dev, size: sizeof(*hdmi), GFP_KERNEL); |
1705 | if (!hdmi) |
1706 | return -ENOMEM; |
1707 | |
1708 | hdmi->dev = dev; |
1709 | hdmi->conf = of_device_get_match_data(dev); |
1710 | |
1711 | ret = mtk_hdmi_dt_parse_pdata(hdmi, pdev); |
1712 | if (ret) |
1713 | return ret; |
1714 | |
1715 | hdmi->phy = devm_phy_get(dev, string: "hdmi" ); |
1716 | if (IS_ERR(ptr: hdmi->phy)) { |
1717 | ret = PTR_ERR(ptr: hdmi->phy); |
1718 | dev_err(dev, "Failed to get HDMI PHY: %d\n" , ret); |
1719 | return ret; |
1720 | } |
1721 | |
1722 | mutex_init(&hdmi->update_plugged_status_lock); |
1723 | platform_set_drvdata(pdev, data: hdmi); |
1724 | |
1725 | ret = mtk_hdmi_output_init(hdmi); |
1726 | if (ret) { |
1727 | dev_err(dev, "Failed to initialize hdmi output\n" ); |
1728 | return ret; |
1729 | } |
1730 | |
1731 | ret = mtk_hdmi_register_audio_driver(dev); |
1732 | if (ret) { |
1733 | dev_err(dev, "Failed to register audio driver: %d\n" , ret); |
1734 | return ret; |
1735 | } |
1736 | |
1737 | hdmi->bridge.funcs = &mtk_hdmi_bridge_funcs; |
1738 | hdmi->bridge.of_node = pdev->dev.of_node; |
1739 | hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |
1740 | | DRM_BRIDGE_OP_HPD; |
1741 | hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA; |
1742 | drm_bridge_add(bridge: &hdmi->bridge); |
1743 | |
1744 | ret = mtk_hdmi_clk_enable_audio(hdmi); |
1745 | if (ret) { |
1746 | dev_err(dev, "Failed to enable audio clocks: %d\n" , ret); |
1747 | goto err_bridge_remove; |
1748 | } |
1749 | |
1750 | return 0; |
1751 | |
1752 | err_bridge_remove: |
1753 | drm_bridge_remove(bridge: &hdmi->bridge); |
1754 | return ret; |
1755 | } |
1756 | |
1757 | static void mtk_drm_hdmi_remove(struct platform_device *pdev) |
1758 | { |
1759 | struct mtk_hdmi *hdmi = platform_get_drvdata(pdev); |
1760 | |
1761 | drm_bridge_remove(bridge: &hdmi->bridge); |
1762 | mtk_hdmi_clk_disable_audio(hdmi); |
1763 | } |
1764 | |
1765 | #ifdef CONFIG_PM_SLEEP |
1766 | static int mtk_hdmi_suspend(struct device *dev) |
1767 | { |
1768 | struct mtk_hdmi *hdmi = dev_get_drvdata(dev); |
1769 | |
1770 | mtk_hdmi_clk_disable_audio(hdmi); |
1771 | |
1772 | return 0; |
1773 | } |
1774 | |
1775 | static int mtk_hdmi_resume(struct device *dev) |
1776 | { |
1777 | struct mtk_hdmi *hdmi = dev_get_drvdata(dev); |
1778 | int ret = 0; |
1779 | |
1780 | ret = mtk_hdmi_clk_enable_audio(hdmi); |
1781 | if (ret) { |
1782 | dev_err(dev, "hdmi resume failed!\n" ); |
1783 | return ret; |
1784 | } |
1785 | |
1786 | return 0; |
1787 | } |
1788 | #endif |
1789 | static SIMPLE_DEV_PM_OPS(mtk_hdmi_pm_ops, |
1790 | mtk_hdmi_suspend, mtk_hdmi_resume); |
1791 | |
1792 | static const struct mtk_hdmi_conf mtk_hdmi_conf_mt2701 = { |
1793 | .tz_disabled = true, |
1794 | }; |
1795 | |
1796 | static const struct mtk_hdmi_conf mtk_hdmi_conf_mt8167 = { |
1797 | .max_mode_clock = 148500, |
1798 | .cea_modes_only = true, |
1799 | }; |
1800 | |
1801 | static const struct of_device_id mtk_drm_hdmi_of_ids[] = { |
1802 | { .compatible = "mediatek,mt2701-hdmi" , |
1803 | .data = &mtk_hdmi_conf_mt2701, |
1804 | }, |
1805 | { .compatible = "mediatek,mt8167-hdmi" , |
1806 | .data = &mtk_hdmi_conf_mt8167, |
1807 | }, |
1808 | { .compatible = "mediatek,mt8173-hdmi" , |
1809 | }, |
1810 | {} |
1811 | }; |
1812 | MODULE_DEVICE_TABLE(of, mtk_drm_hdmi_of_ids); |
1813 | |
1814 | static struct platform_driver mtk_hdmi_driver = { |
1815 | .probe = mtk_drm_hdmi_probe, |
1816 | .remove_new = mtk_drm_hdmi_remove, |
1817 | .driver = { |
1818 | .name = "mediatek-drm-hdmi" , |
1819 | .of_match_table = mtk_drm_hdmi_of_ids, |
1820 | .pm = &mtk_hdmi_pm_ops, |
1821 | }, |
1822 | }; |
1823 | |
1824 | static struct platform_driver * const mtk_hdmi_drivers[] = { |
1825 | &mtk_hdmi_ddc_driver, |
1826 | &mtk_cec_driver, |
1827 | &mtk_hdmi_driver, |
1828 | }; |
1829 | |
1830 | static int __init mtk_hdmitx_init(void) |
1831 | { |
1832 | return platform_register_drivers(mtk_hdmi_drivers, |
1833 | ARRAY_SIZE(mtk_hdmi_drivers)); |
1834 | } |
1835 | |
1836 | static void __exit mtk_hdmitx_exit(void) |
1837 | { |
1838 | platform_unregister_drivers(drivers: mtk_hdmi_drivers, |
1839 | ARRAY_SIZE(mtk_hdmi_drivers)); |
1840 | } |
1841 | |
1842 | module_init(mtk_hdmitx_init); |
1843 | module_exit(mtk_hdmitx_exit); |
1844 | |
1845 | MODULE_AUTHOR("Jie Qiu <jie.qiu@mediatek.com>" ); |
1846 | MODULE_DESCRIPTION("MediaTek HDMI Driver" ); |
1847 | MODULE_LICENSE("GPL v2" ); |
1848 | |