2 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
3 * Zheng Yang <zhengyang@rock-chips.com>
4 * Yakir Yang <ykk@rock-chips.com>
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <linux/irq.h>
17 #include <linux/clk.h>
18 #include <linux/delay.h>
19 #include <linux/err.h>
20 #include <linux/hdmi.h>
21 #include <linux/mfd/syscon.h>
22 #include <linux/module.h>
23 #include <linux/mutex.h>
24 #include <linux/of_device.h>
26 #include <drm/drm_of.h>
28 #include <drm/drm_atomic_helper.h>
29 #include <drm/drm_crtc_helper.h>
30 #include <drm/drm_edid.h>
32 #include "rockchip_drm_drv.h"
33 #include "rockchip_drm_vop.h"
35 #include "inno_hdmi.h"
37 #define to_inno_hdmi(x) container_of(x, struct inno_hdmi, x)
39 struct hdmi_data_info
{
43 unsigned int enc_in_format
;
44 unsigned int enc_out_format
;
45 unsigned int colorimetry
;
48 struct inno_hdmi_i2c
{
49 struct i2c_adapter adap
;
55 struct completion cmp
;
60 struct drm_device
*drm_dev
;
66 struct drm_connector connector
;
67 struct drm_encoder encoder
;
69 struct inno_hdmi_i2c
*i2c
;
70 struct i2c_adapter
*ddc
;
72 unsigned int tmds_rate
;
74 struct hdmi_data_info hdmi_data
;
75 struct drm_display_mode previous_mode
;
79 CSC_ITU601_16_235_TO_RGB_0_255_8BIT
,
80 CSC_ITU601_0_255_TO_RGB_0_255_8BIT
,
81 CSC_ITU709_16_235_TO_RGB_0_255_8BIT
,
82 CSC_RGB_0_255_TO_ITU601_16_235_8BIT
,
83 CSC_RGB_0_255_TO_ITU709_16_235_8BIT
,
84 CSC_RGB_0_255_TO_RGB_16_235_8BIT
,
87 static const char coeff_csc
[][24] = {
89 * YUV2RGB:601 SD mode(Y[16:235], UV[16:240], RGB[0:255]):
90 * R = 1.164*Y + 1.596*V - 204
91 * G = 1.164*Y - 0.391*U - 0.813*V + 154
92 * B = 1.164*Y + 2.018*U - 258
95 0x04, 0xa7, 0x00, 0x00, 0x06, 0x62, 0x02, 0xcc,
96 0x04, 0xa7, 0x11, 0x90, 0x13, 0x40, 0x00, 0x9a,
97 0x04, 0xa7, 0x08, 0x12, 0x00, 0x00, 0x03, 0x02
100 * YUV2RGB:601 SD mode(YUV[0:255],RGB[0:255]):
101 * R = Y + 1.402*V - 248
102 * G = Y - 0.344*U - 0.714*V + 135
103 * B = Y + 1.772*U - 227
106 0x04, 0x00, 0x00, 0x00, 0x05, 0x9b, 0x02, 0xf8,
107 0x04, 0x00, 0x11, 0x60, 0x12, 0xdb, 0x00, 0x87,
108 0x04, 0x00, 0x07, 0x16, 0x00, 0x00, 0x02, 0xe3
111 * YUV2RGB:709 HD mode(Y[16:235],UV[16:240],RGB[0:255]):
112 * R = 1.164*Y + 1.793*V - 248
113 * G = 1.164*Y - 0.213*U - 0.534*V + 77
114 * B = 1.164*Y + 2.115*U - 289
117 0x04, 0xa7, 0x00, 0x00, 0x07, 0x2c, 0x02, 0xf8,
118 0x04, 0xa7, 0x10, 0xda, 0x12, 0x22, 0x00, 0x4d,
119 0x04, 0xa7, 0x08, 0x74, 0x00, 0x00, 0x03, 0x21
123 * RGB2YUV:601 SD mode:
124 * Cb = -0.291G - 0.148R + 0.439B + 128
125 * Y = 0.504G + 0.257R + 0.098B + 16
126 * Cr = -0.368G + 0.439R - 0.071B + 128
129 0x11, 0x5f, 0x01, 0x82, 0x10, 0x23, 0x00, 0x80,
130 0x02, 0x1c, 0x00, 0xa1, 0x00, 0x36, 0x00, 0x1e,
131 0x11, 0x29, 0x10, 0x59, 0x01, 0x82, 0x00, 0x80
134 * RGB2YUV:709 HD mode:
135 * Cb = - 0.338G - 0.101R + 0.439B + 128
136 * Y = 0.614G + 0.183R + 0.062B + 16
137 * Cr = - 0.399G + 0.439R - 0.040B + 128
140 0x11, 0x98, 0x01, 0xc1, 0x10, 0x28, 0x00, 0x80,
141 0x02, 0x74, 0x00, 0xbb, 0x00, 0x3f, 0x00, 0x10,
142 0x11, 0x5a, 0x10, 0x67, 0x01, 0xc1, 0x00, 0x80
145 * RGB[0:255]2RGB[16:235]:
146 * R' = R x (235-16)/255 + 16;
147 * G' = G x (235-16)/255 + 16;
148 * B' = B x (235-16)/255 + 16;
151 0x00, 0x00, 0x03, 0x6F, 0x00, 0x00, 0x00, 0x10,
152 0x03, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
153 0x00, 0x00, 0x00, 0x00, 0x03, 0x6F, 0x00, 0x10
157 static inline u8
hdmi_readb(struct inno_hdmi
*hdmi
, u16 offset
)
159 return readl_relaxed(hdmi
->regs
+ (offset
) * 0x04);
162 static inline void hdmi_writeb(struct inno_hdmi
*hdmi
, u16 offset
, u32 val
)
164 writel_relaxed(val
, hdmi
->regs
+ (offset
) * 0x04);
167 static inline void hdmi_modb(struct inno_hdmi
*hdmi
, u16 offset
,
170 u8 temp
= hdmi_readb(hdmi
, offset
) & ~msk
;
173 hdmi_writeb(hdmi
, offset
, temp
);
176 static void inno_hdmi_i2c_init(struct inno_hdmi
*hdmi
)
180 ddc_bus_freq
= (hdmi
->tmds_rate
>> 2) / HDMI_SCL_RATE
;
182 hdmi_writeb(hdmi
, DDC_BUS_FREQ_L
, ddc_bus_freq
& 0xFF);
183 hdmi_writeb(hdmi
, DDC_BUS_FREQ_H
, (ddc_bus_freq
>> 8) & 0xFF);
185 /* Clear the EDID interrupt flag and mute the interrupt */
186 hdmi_writeb(hdmi
, HDMI_INTERRUPT_MASK1
, 0);
187 hdmi_writeb(hdmi
, HDMI_INTERRUPT_STATUS1
, m_INT_EDID_READY
);
190 static void inno_hdmi_sys_power(struct inno_hdmi
*hdmi
, bool enable
)
193 hdmi_modb(hdmi
, HDMI_SYS_CTRL
, m_POWER
, v_PWR_ON
);
195 hdmi_modb(hdmi
, HDMI_SYS_CTRL
, m_POWER
, v_PWR_OFF
);
198 static void inno_hdmi_set_pwr_mode(struct inno_hdmi
*hdmi
, int mode
)
202 inno_hdmi_sys_power(hdmi
, false);
204 hdmi_writeb(hdmi
, HDMI_PHY_PRE_EMPHASIS
, 0x6f);
205 hdmi_writeb(hdmi
, HDMI_PHY_DRIVER
, 0xbb);
207 hdmi_writeb(hdmi
, HDMI_PHY_SYS_CTL
, 0x15);
208 hdmi_writeb(hdmi
, HDMI_PHY_SYS_CTL
, 0x14);
209 hdmi_writeb(hdmi
, HDMI_PHY_SYS_CTL
, 0x10);
210 hdmi_writeb(hdmi
, HDMI_PHY_CHG_PWR
, 0x0f);
211 hdmi_writeb(hdmi
, HDMI_PHY_SYNC
, 0x00);
212 hdmi_writeb(hdmi
, HDMI_PHY_SYNC
, 0x01);
214 inno_hdmi_sys_power(hdmi
, true);
218 inno_hdmi_sys_power(hdmi
, false);
219 hdmi_writeb(hdmi
, HDMI_PHY_DRIVER
, 0x00);
220 hdmi_writeb(hdmi
, HDMI_PHY_PRE_EMPHASIS
, 0x00);
221 hdmi_writeb(hdmi
, HDMI_PHY_CHG_PWR
, 0x00);
222 hdmi_writeb(hdmi
, HDMI_PHY_SYS_CTL
, 0x15);
227 DRM_DEV_ERROR(hdmi
->dev
, "Unknown power mode %d\n", mode
);
231 static void inno_hdmi_reset(struct inno_hdmi
*hdmi
)
236 hdmi_modb(hdmi
, HDMI_SYS_CTRL
, m_RST_DIGITAL
, v_NOT_RST_DIGITAL
);
239 hdmi_modb(hdmi
, HDMI_SYS_CTRL
, m_RST_ANALOG
, v_NOT_RST_ANALOG
);
242 msk
= m_REG_CLK_INV
| m_REG_CLK_SOURCE
| m_POWER
| m_INT_POL
;
243 val
= v_REG_CLK_INV
| v_REG_CLK_SOURCE_SYS
| v_PWR_ON
| v_INT_POL_HIGH
;
244 hdmi_modb(hdmi
, HDMI_SYS_CTRL
, msk
, val
);
246 inno_hdmi_set_pwr_mode(hdmi
, NORMAL
);
249 static int inno_hdmi_upload_frame(struct inno_hdmi
*hdmi
, int setup_rc
,
250 union hdmi_infoframe
*frame
, u32 frame_index
,
251 u32 mask
, u32 disable
, u32 enable
)
254 hdmi_modb(hdmi
, HDMI_PACKET_SEND_AUTO
, mask
, disable
);
256 hdmi_writeb(hdmi
, HDMI_CONTROL_PACKET_BUF_INDEX
, frame_index
);
259 u8 packed_frame
[HDMI_MAXIMUM_INFO_FRAME_SIZE
];
262 rc
= hdmi_infoframe_pack(frame
, packed_frame
,
263 sizeof(packed_frame
));
267 for (i
= 0; i
< rc
; i
++)
268 hdmi_writeb(hdmi
, HDMI_CONTROL_PACKET_ADDR
+ i
,
272 hdmi_modb(hdmi
, HDMI_PACKET_SEND_AUTO
, mask
, enable
);
278 static int inno_hdmi_config_video_vsi(struct inno_hdmi
*hdmi
,
279 struct drm_display_mode
*mode
)
281 union hdmi_infoframe frame
;
284 rc
= drm_hdmi_vendor_infoframe_from_display_mode(&frame
.vendor
.hdmi
,
288 return inno_hdmi_upload_frame(hdmi
, rc
, &frame
, INFOFRAME_VSI
,
289 m_PACKET_VSI_EN
, v_PACKET_VSI_EN(0), v_PACKET_VSI_EN(1));
292 static int inno_hdmi_config_video_avi(struct inno_hdmi
*hdmi
,
293 struct drm_display_mode
*mode
)
295 union hdmi_infoframe frame
;
298 rc
= drm_hdmi_avi_infoframe_from_display_mode(&frame
.avi
, mode
, false);
300 if (hdmi
->hdmi_data
.enc_out_format
== HDMI_COLORSPACE_YUV444
)
301 frame
.avi
.colorspace
= HDMI_COLORSPACE_YUV444
;
302 else if (hdmi
->hdmi_data
.enc_out_format
== HDMI_COLORSPACE_YUV422
)
303 frame
.avi
.colorspace
= HDMI_COLORSPACE_YUV422
;
305 frame
.avi
.colorspace
= HDMI_COLORSPACE_RGB
;
307 return inno_hdmi_upload_frame(hdmi
, rc
, &frame
, INFOFRAME_AVI
, 0, 0, 0);
310 static int inno_hdmi_config_video_csc(struct inno_hdmi
*hdmi
)
312 struct hdmi_data_info
*data
= &hdmi
->hdmi_data
;
313 int c0_c2_change
= 0;
320 /* Input video mode is SDR RGB24bit, data enable signal from external */
321 hdmi_writeb(hdmi
, HDMI_VIDEO_CONTRL1
, v_DE_EXTERNAL
|
322 v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444
));
324 /* Input color hardcode to RGB, and output color hardcode to RGB888 */
325 value
= v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS
) |
326 v_VIDEO_OUTPUT_COLOR(0) |
327 v_VIDEO_INPUT_CSP(0);
328 hdmi_writeb(hdmi
, HDMI_VIDEO_CONTRL2
, value
);
330 if (data
->enc_in_format
== data
->enc_out_format
) {
331 if ((data
->enc_in_format
== HDMI_COLORSPACE_RGB
) ||
332 (data
->enc_in_format
>= HDMI_COLORSPACE_YUV444
)) {
333 value
= v_SOF_DISABLE
| v_COLOR_DEPTH_NOT_INDICATED(1);
334 hdmi_writeb(hdmi
, HDMI_VIDEO_CONTRL3
, value
);
336 hdmi_modb(hdmi
, HDMI_VIDEO_CONTRL
,
337 m_VIDEO_AUTO_CSC
| m_VIDEO_C0_C2_SWAP
,
338 v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE
) |
339 v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE
));
344 if (data
->colorimetry
== HDMI_COLORIMETRY_ITU_601
) {
345 if ((data
->enc_in_format
== HDMI_COLORSPACE_RGB
) &&
346 (data
->enc_out_format
== HDMI_COLORSPACE_YUV444
)) {
347 csc_mode
= CSC_RGB_0_255_TO_ITU601_16_235_8BIT
;
348 auto_csc
= AUTO_CSC_DISABLE
;
349 c0_c2_change
= C0_C2_CHANGE_DISABLE
;
350 csc_enable
= v_CSC_ENABLE
;
351 } else if ((data
->enc_in_format
== HDMI_COLORSPACE_YUV444
) &&
352 (data
->enc_out_format
== HDMI_COLORSPACE_RGB
)) {
353 csc_mode
= CSC_ITU601_16_235_TO_RGB_0_255_8BIT
;
354 auto_csc
= AUTO_CSC_ENABLE
;
355 c0_c2_change
= C0_C2_CHANGE_DISABLE
;
356 csc_enable
= v_CSC_DISABLE
;
359 if ((data
->enc_in_format
== HDMI_COLORSPACE_RGB
) &&
360 (data
->enc_out_format
== HDMI_COLORSPACE_YUV444
)) {
361 csc_mode
= CSC_RGB_0_255_TO_ITU709_16_235_8BIT
;
362 auto_csc
= AUTO_CSC_DISABLE
;
363 c0_c2_change
= C0_C2_CHANGE_DISABLE
;
364 csc_enable
= v_CSC_ENABLE
;
365 } else if ((data
->enc_in_format
== HDMI_COLORSPACE_YUV444
) &&
366 (data
->enc_out_format
== HDMI_COLORSPACE_RGB
)) {
367 csc_mode
= CSC_ITU709_16_235_TO_RGB_0_255_8BIT
;
368 auto_csc
= AUTO_CSC_ENABLE
;
369 c0_c2_change
= C0_C2_CHANGE_DISABLE
;
370 csc_enable
= v_CSC_DISABLE
;
374 for (i
= 0; i
< 24; i
++)
375 hdmi_writeb(hdmi
, HDMI_VIDEO_CSC_COEF
+ i
,
376 coeff_csc
[csc_mode
][i
]);
378 value
= v_SOF_DISABLE
| csc_enable
| v_COLOR_DEPTH_NOT_INDICATED(1);
379 hdmi_writeb(hdmi
, HDMI_VIDEO_CONTRL3
, value
);
380 hdmi_modb(hdmi
, HDMI_VIDEO_CONTRL
, m_VIDEO_AUTO_CSC
|
381 m_VIDEO_C0_C2_SWAP
, v_VIDEO_AUTO_CSC(auto_csc
) |
382 v_VIDEO_C0_C2_SWAP(c0_c2_change
));
387 static int inno_hdmi_config_video_timing(struct inno_hdmi
*hdmi
,
388 struct drm_display_mode
*mode
)
392 /* Set detail external video timing polarity and interlace mode */
393 value
= v_EXTERANL_VIDEO(1);
394 value
|= mode
->flags
& DRM_MODE_FLAG_PHSYNC
?
395 v_HSYNC_POLARITY(1) : v_HSYNC_POLARITY(0);
396 value
|= mode
->flags
& DRM_MODE_FLAG_PVSYNC
?
397 v_VSYNC_POLARITY(1) : v_VSYNC_POLARITY(0);
398 value
|= mode
->flags
& DRM_MODE_FLAG_INTERLACE
?
399 v_INETLACE(1) : v_INETLACE(0);
400 hdmi_writeb(hdmi
, HDMI_VIDEO_TIMING_CTL
, value
);
402 /* Set detail external video timing */
403 value
= mode
->htotal
;
404 hdmi_writeb(hdmi
, HDMI_VIDEO_EXT_HTOTAL_L
, value
& 0xFF);
405 hdmi_writeb(hdmi
, HDMI_VIDEO_EXT_HTOTAL_H
, (value
>> 8) & 0xFF);
407 value
= mode
->htotal
- mode
->hdisplay
;
408 hdmi_writeb(hdmi
, HDMI_VIDEO_EXT_HBLANK_L
, value
& 0xFF);
409 hdmi_writeb(hdmi
, HDMI_VIDEO_EXT_HBLANK_H
, (value
>> 8) & 0xFF);
411 value
= mode
->hsync_start
- mode
->hdisplay
;
412 hdmi_writeb(hdmi
, HDMI_VIDEO_EXT_HDELAY_L
, value
& 0xFF);
413 hdmi_writeb(hdmi
, HDMI_VIDEO_EXT_HDELAY_H
, (value
>> 8) & 0xFF);
415 value
= mode
->hsync_end
- mode
->hsync_start
;
416 hdmi_writeb(hdmi
, HDMI_VIDEO_EXT_HDURATION_L
, value
& 0xFF);
417 hdmi_writeb(hdmi
, HDMI_VIDEO_EXT_HDURATION_H
, (value
>> 8) & 0xFF);
419 value
= mode
->vtotal
;
420 hdmi_writeb(hdmi
, HDMI_VIDEO_EXT_VTOTAL_L
, value
& 0xFF);
421 hdmi_writeb(hdmi
, HDMI_VIDEO_EXT_VTOTAL_H
, (value
>> 8) & 0xFF);
423 value
= mode
->vtotal
- mode
->vdisplay
;
424 hdmi_writeb(hdmi
, HDMI_VIDEO_EXT_VBLANK
, value
& 0xFF);
426 value
= mode
->vsync_start
- mode
->vdisplay
;
427 hdmi_writeb(hdmi
, HDMI_VIDEO_EXT_VDELAY
, value
& 0xFF);
429 value
= mode
->vsync_end
- mode
->vsync_start
;
430 hdmi_writeb(hdmi
, HDMI_VIDEO_EXT_VDURATION
, value
& 0xFF);
432 hdmi_writeb(hdmi
, HDMI_PHY_PRE_DIV_RATIO
, 0x1e);
433 hdmi_writeb(hdmi
, HDMI_PHY_FEEDBACK_DIV_RATIO_LOW
, 0x2c);
434 hdmi_writeb(hdmi
, HDMI_PHY_FEEDBACK_DIV_RATIO_HIGH
, 0x01);
439 static int inno_hdmi_setup(struct inno_hdmi
*hdmi
,
440 struct drm_display_mode
*mode
)
442 hdmi
->hdmi_data
.vic
= drm_match_cea_mode(mode
);
444 hdmi
->hdmi_data
.enc_in_format
= HDMI_COLORSPACE_RGB
;
445 hdmi
->hdmi_data
.enc_out_format
= HDMI_COLORSPACE_RGB
;
447 if ((hdmi
->hdmi_data
.vic
== 6) || (hdmi
->hdmi_data
.vic
== 7) ||
448 (hdmi
->hdmi_data
.vic
== 21) || (hdmi
->hdmi_data
.vic
== 22) ||
449 (hdmi
->hdmi_data
.vic
== 2) || (hdmi
->hdmi_data
.vic
== 3) ||
450 (hdmi
->hdmi_data
.vic
== 17) || (hdmi
->hdmi_data
.vic
== 18))
451 hdmi
->hdmi_data
.colorimetry
= HDMI_COLORIMETRY_ITU_601
;
453 hdmi
->hdmi_data
.colorimetry
= HDMI_COLORIMETRY_ITU_709
;
455 /* Mute video and audio output */
456 hdmi_modb(hdmi
, HDMI_AV_MUTE
, m_AUDIO_MUTE
| m_VIDEO_BLACK
,
457 v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
460 hdmi_writeb(hdmi
, HDMI_HDCP_CTRL
,
461 v_HDMI_DVI(hdmi
->hdmi_data
.sink_is_hdmi
));
463 inno_hdmi_config_video_timing(hdmi
, mode
);
465 inno_hdmi_config_video_csc(hdmi
);
467 if (hdmi
->hdmi_data
.sink_is_hdmi
) {
468 inno_hdmi_config_video_avi(hdmi
, mode
);
469 inno_hdmi_config_video_vsi(hdmi
, mode
);
473 * When IP controller have configured to an accurate video
474 * timing, then the TMDS clock source would be switched to
475 * DCLK_LCDC, so we need to init the TMDS rate to mode pixel
476 * clock rate, and reconfigure the DDC clock.
478 hdmi
->tmds_rate
= mode
->clock
* 1000;
479 inno_hdmi_i2c_init(hdmi
);
481 /* Unmute video and audio output */
482 hdmi_modb(hdmi
, HDMI_AV_MUTE
, m_AUDIO_MUTE
| m_VIDEO_BLACK
,
483 v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
488 static void inno_hdmi_encoder_mode_set(struct drm_encoder
*encoder
,
489 struct drm_display_mode
*mode
,
490 struct drm_display_mode
*adj_mode
)
492 struct inno_hdmi
*hdmi
= to_inno_hdmi(encoder
);
494 inno_hdmi_setup(hdmi
, adj_mode
);
496 /* Store the display mode for plugin/DPMS poweron events */
497 memcpy(&hdmi
->previous_mode
, adj_mode
, sizeof(hdmi
->previous_mode
));
500 static void inno_hdmi_encoder_enable(struct drm_encoder
*encoder
)
502 struct inno_hdmi
*hdmi
= to_inno_hdmi(encoder
);
504 inno_hdmi_set_pwr_mode(hdmi
, NORMAL
);
507 static void inno_hdmi_encoder_disable(struct drm_encoder
*encoder
)
509 struct inno_hdmi
*hdmi
= to_inno_hdmi(encoder
);
511 inno_hdmi_set_pwr_mode(hdmi
, LOWER_PWR
);
514 static bool inno_hdmi_encoder_mode_fixup(struct drm_encoder
*encoder
,
515 const struct drm_display_mode
*mode
,
516 struct drm_display_mode
*adj_mode
)
522 inno_hdmi_encoder_atomic_check(struct drm_encoder
*encoder
,
523 struct drm_crtc_state
*crtc_state
,
524 struct drm_connector_state
*conn_state
)
526 struct rockchip_crtc_state
*s
= to_rockchip_crtc_state(crtc_state
);
528 s
->output_mode
= ROCKCHIP_OUT_MODE_P888
;
529 s
->output_type
= DRM_MODE_CONNECTOR_HDMIA
;
534 static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs
= {
535 .enable
= inno_hdmi_encoder_enable
,
536 .disable
= inno_hdmi_encoder_disable
,
537 .mode_fixup
= inno_hdmi_encoder_mode_fixup
,
538 .mode_set
= inno_hdmi_encoder_mode_set
,
539 .atomic_check
= inno_hdmi_encoder_atomic_check
,
542 static struct drm_encoder_funcs inno_hdmi_encoder_funcs
= {
543 .destroy
= drm_encoder_cleanup
,
546 static enum drm_connector_status
547 inno_hdmi_connector_detect(struct drm_connector
*connector
, bool force
)
549 struct inno_hdmi
*hdmi
= to_inno_hdmi(connector
);
551 return (hdmi_readb(hdmi
, HDMI_STATUS
) & m_HOTPLUG
) ?
552 connector_status_connected
: connector_status_disconnected
;
555 static int inno_hdmi_connector_get_modes(struct drm_connector
*connector
)
557 struct inno_hdmi
*hdmi
= to_inno_hdmi(connector
);
564 edid
= drm_get_edid(connector
, hdmi
->ddc
);
566 hdmi
->hdmi_data
.sink_is_hdmi
= drm_detect_hdmi_monitor(edid
);
567 hdmi
->hdmi_data
.sink_has_audio
= drm_detect_monitor_audio(edid
);
568 drm_connector_update_edid_property(connector
, edid
);
569 ret
= drm_add_edid_modes(connector
, edid
);
576 static enum drm_mode_status
577 inno_hdmi_connector_mode_valid(struct drm_connector
*connector
,
578 struct drm_display_mode
*mode
)
584 inno_hdmi_probe_single_connector_modes(struct drm_connector
*connector
,
585 uint32_t maxX
, uint32_t maxY
)
587 return drm_helper_probe_single_connector_modes(connector
, 1920, 1080);
590 static void inno_hdmi_connector_destroy(struct drm_connector
*connector
)
592 drm_connector_unregister(connector
);
593 drm_connector_cleanup(connector
);
596 static const struct drm_connector_funcs inno_hdmi_connector_funcs
= {
597 .fill_modes
= inno_hdmi_probe_single_connector_modes
,
598 .detect
= inno_hdmi_connector_detect
,
599 .destroy
= inno_hdmi_connector_destroy
,
600 .reset
= drm_atomic_helper_connector_reset
,
601 .atomic_duplicate_state
= drm_atomic_helper_connector_duplicate_state
,
602 .atomic_destroy_state
= drm_atomic_helper_connector_destroy_state
,
605 static struct drm_connector_helper_funcs inno_hdmi_connector_helper_funcs
= {
606 .get_modes
= inno_hdmi_connector_get_modes
,
607 .mode_valid
= inno_hdmi_connector_mode_valid
,
610 static int inno_hdmi_register(struct drm_device
*drm
, struct inno_hdmi
*hdmi
)
612 struct drm_encoder
*encoder
= &hdmi
->encoder
;
613 struct device
*dev
= hdmi
->dev
;
615 encoder
->possible_crtcs
= drm_of_find_possible_crtcs(drm
, dev
->of_node
);
618 * If we failed to find the CRTC(s) which this encoder is
619 * supposed to be connected to, it's because the CRTC has
620 * not been registered yet. Defer probing, and hope that
621 * the required CRTC is added later.
623 if (encoder
->possible_crtcs
== 0)
624 return -EPROBE_DEFER
;
626 drm_encoder_helper_add(encoder
, &inno_hdmi_encoder_helper_funcs
);
627 drm_encoder_init(drm
, encoder
, &inno_hdmi_encoder_funcs
,
628 DRM_MODE_ENCODER_TMDS
, NULL
);
630 hdmi
->connector
.polled
= DRM_CONNECTOR_POLL_HPD
;
632 drm_connector_helper_add(&hdmi
->connector
,
633 &inno_hdmi_connector_helper_funcs
);
634 drm_connector_init(drm
, &hdmi
->connector
, &inno_hdmi_connector_funcs
,
635 DRM_MODE_CONNECTOR_HDMIA
);
637 drm_connector_attach_encoder(&hdmi
->connector
, encoder
);
642 static irqreturn_t
inno_hdmi_i2c_irq(struct inno_hdmi
*hdmi
)
644 struct inno_hdmi_i2c
*i2c
= hdmi
->i2c
;
647 stat
= hdmi_readb(hdmi
, HDMI_INTERRUPT_STATUS1
);
648 if (!(stat
& m_INT_EDID_READY
))
651 /* Clear HDMI EDID interrupt flag */
652 hdmi_writeb(hdmi
, HDMI_INTERRUPT_STATUS1
, m_INT_EDID_READY
);
659 static irqreturn_t
inno_hdmi_hardirq(int irq
, void *dev_id
)
661 struct inno_hdmi
*hdmi
= dev_id
;
662 irqreturn_t ret
= IRQ_NONE
;
666 ret
= inno_hdmi_i2c_irq(hdmi
);
668 interrupt
= hdmi_readb(hdmi
, HDMI_STATUS
);
669 if (interrupt
& m_INT_HOTPLUG
) {
670 hdmi_modb(hdmi
, HDMI_STATUS
, m_INT_HOTPLUG
, m_INT_HOTPLUG
);
671 ret
= IRQ_WAKE_THREAD
;
677 static irqreturn_t
inno_hdmi_irq(int irq
, void *dev_id
)
679 struct inno_hdmi
*hdmi
= dev_id
;
681 drm_helper_hpd_irq_event(hdmi
->connector
.dev
);
686 static int inno_hdmi_i2c_read(struct inno_hdmi
*hdmi
, struct i2c_msg
*msgs
)
688 int length
= msgs
->len
;
692 ret
= wait_for_completion_timeout(&hdmi
->i2c
->cmp
, HZ
/ 10);
697 *buf
++ = hdmi_readb(hdmi
, HDMI_EDID_FIFO_ADDR
);
702 static int inno_hdmi_i2c_write(struct inno_hdmi
*hdmi
, struct i2c_msg
*msgs
)
705 * The DDC module only support read EDID message, so
706 * we assume that each word write to this i2c adapter
707 * should be the offset of EDID word address.
709 if ((msgs
->len
!= 1) ||
710 ((msgs
->addr
!= DDC_ADDR
) && (msgs
->addr
!= DDC_SEGMENT_ADDR
)))
713 reinit_completion(&hdmi
->i2c
->cmp
);
715 if (msgs
->addr
== DDC_SEGMENT_ADDR
)
716 hdmi
->i2c
->segment_addr
= msgs
->buf
[0];
717 if (msgs
->addr
== DDC_ADDR
)
718 hdmi
->i2c
->ddc_addr
= msgs
->buf
[0];
720 /* Set edid fifo first addr */
721 hdmi_writeb(hdmi
, HDMI_EDID_FIFO_OFFSET
, 0x00);
723 /* Set edid word address 0x00/0x80 */
724 hdmi_writeb(hdmi
, HDMI_EDID_WORD_ADDR
, hdmi
->i2c
->ddc_addr
);
726 /* Set edid segment pointer */
727 hdmi_writeb(hdmi
, HDMI_EDID_SEGMENT_POINTER
, hdmi
->i2c
->segment_addr
);
732 static int inno_hdmi_i2c_xfer(struct i2c_adapter
*adap
,
733 struct i2c_msg
*msgs
, int num
)
735 struct inno_hdmi
*hdmi
= i2c_get_adapdata(adap
);
736 struct inno_hdmi_i2c
*i2c
= hdmi
->i2c
;
739 mutex_lock(&i2c
->lock
);
741 /* Clear the EDID interrupt flag and unmute the interrupt */
742 hdmi_writeb(hdmi
, HDMI_INTERRUPT_MASK1
, m_INT_EDID_READY
);
743 hdmi_writeb(hdmi
, HDMI_INTERRUPT_STATUS1
, m_INT_EDID_READY
);
745 for (i
= 0; i
< num
; i
++) {
746 DRM_DEV_DEBUG(hdmi
->dev
,
747 "xfer: num: %d/%d, len: %d, flags: %#x\n",
748 i
+ 1, num
, msgs
[i
].len
, msgs
[i
].flags
);
750 if (msgs
[i
].flags
& I2C_M_RD
)
751 ret
= inno_hdmi_i2c_read(hdmi
, &msgs
[i
]);
753 ret
= inno_hdmi_i2c_write(hdmi
, &msgs
[i
]);
762 /* Mute HDMI EDID interrupt */
763 hdmi_writeb(hdmi
, HDMI_INTERRUPT_MASK1
, 0);
765 mutex_unlock(&i2c
->lock
);
770 static u32
inno_hdmi_i2c_func(struct i2c_adapter
*adapter
)
772 return I2C_FUNC_I2C
| I2C_FUNC_SMBUS_EMUL
;
775 static const struct i2c_algorithm inno_hdmi_algorithm
= {
776 .master_xfer
= inno_hdmi_i2c_xfer
,
777 .functionality
= inno_hdmi_i2c_func
,
780 static struct i2c_adapter
*inno_hdmi_i2c_adapter(struct inno_hdmi
*hdmi
)
782 struct i2c_adapter
*adap
;
783 struct inno_hdmi_i2c
*i2c
;
786 i2c
= devm_kzalloc(hdmi
->dev
, sizeof(*i2c
), GFP_KERNEL
);
788 return ERR_PTR(-ENOMEM
);
790 mutex_init(&i2c
->lock
);
791 init_completion(&i2c
->cmp
);
794 adap
->class = I2C_CLASS_DDC
;
795 adap
->owner
= THIS_MODULE
;
796 adap
->dev
.parent
= hdmi
->dev
;
797 adap
->dev
.of_node
= hdmi
->dev
->of_node
;
798 adap
->algo
= &inno_hdmi_algorithm
;
799 strlcpy(adap
->name
, "Inno HDMI", sizeof(adap
->name
));
800 i2c_set_adapdata(adap
, hdmi
);
802 ret
= i2c_add_adapter(adap
);
804 dev_warn(hdmi
->dev
, "cannot add %s I2C adapter\n", adap
->name
);
805 devm_kfree(hdmi
->dev
, i2c
);
811 DRM_DEV_INFO(hdmi
->dev
, "registered %s I2C bus driver\n", adap
->name
);
816 static int inno_hdmi_bind(struct device
*dev
, struct device
*master
,
819 struct platform_device
*pdev
= to_platform_device(dev
);
820 struct drm_device
*drm
= data
;
821 struct inno_hdmi
*hdmi
;
822 struct resource
*iores
;
826 hdmi
= devm_kzalloc(dev
, sizeof(*hdmi
), GFP_KERNEL
);
833 iores
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
834 hdmi
->regs
= devm_ioremap_resource(dev
, iores
);
835 if (IS_ERR(hdmi
->regs
))
836 return PTR_ERR(hdmi
->regs
);
838 hdmi
->pclk
= devm_clk_get(hdmi
->dev
, "pclk");
839 if (IS_ERR(hdmi
->pclk
)) {
840 DRM_DEV_ERROR(hdmi
->dev
, "Unable to get HDMI pclk clk\n");
841 return PTR_ERR(hdmi
->pclk
);
844 ret
= clk_prepare_enable(hdmi
->pclk
);
846 DRM_DEV_ERROR(hdmi
->dev
,
847 "Cannot enable HDMI pclk clock: %d\n", ret
);
851 irq
= platform_get_irq(pdev
, 0);
854 goto err_disable_clk
;
857 inno_hdmi_reset(hdmi
);
859 hdmi
->ddc
= inno_hdmi_i2c_adapter(hdmi
);
860 if (IS_ERR(hdmi
->ddc
)) {
861 ret
= PTR_ERR(hdmi
->ddc
);
863 goto err_disable_clk
;
867 * When IP controller haven't configured to an accurate video
868 * timing, then the TMDS clock source would be switched to
869 * PCLK_HDMI, so we need to init the TMDS rate to PCLK rate,
870 * and reconfigure the DDC clock.
872 hdmi
->tmds_rate
= clk_get_rate(hdmi
->pclk
);
873 inno_hdmi_i2c_init(hdmi
);
875 ret
= inno_hdmi_register(drm
, hdmi
);
877 goto err_put_adapter
;
879 dev_set_drvdata(dev
, hdmi
);
881 /* Unmute hotplug interrupt */
882 hdmi_modb(hdmi
, HDMI_STATUS
, m_MASK_INT_HOTPLUG
, v_MASK_INT_HOTPLUG(1));
884 ret
= devm_request_threaded_irq(dev
, irq
, inno_hdmi_hardirq
,
885 inno_hdmi_irq
, IRQF_SHARED
,
886 dev_name(dev
), hdmi
);
888 goto err_cleanup_hdmi
;
892 hdmi
->connector
.funcs
->destroy(&hdmi
->connector
);
893 hdmi
->encoder
.funcs
->destroy(&hdmi
->encoder
);
895 i2c_put_adapter(hdmi
->ddc
);
897 clk_disable_unprepare(hdmi
->pclk
);
901 static void inno_hdmi_unbind(struct device
*dev
, struct device
*master
,
904 struct inno_hdmi
*hdmi
= dev_get_drvdata(dev
);
906 hdmi
->connector
.funcs
->destroy(&hdmi
->connector
);
907 hdmi
->encoder
.funcs
->destroy(&hdmi
->encoder
);
909 i2c_put_adapter(hdmi
->ddc
);
910 clk_disable_unprepare(hdmi
->pclk
);
913 static const struct component_ops inno_hdmi_ops
= {
914 .bind
= inno_hdmi_bind
,
915 .unbind
= inno_hdmi_unbind
,
918 static int inno_hdmi_probe(struct platform_device
*pdev
)
920 return component_add(&pdev
->dev
, &inno_hdmi_ops
);
923 static int inno_hdmi_remove(struct platform_device
*pdev
)
925 component_del(&pdev
->dev
, &inno_hdmi_ops
);
930 static const struct of_device_id inno_hdmi_dt_ids
[] = {
931 { .compatible
= "rockchip,rk3036-inno-hdmi",
935 MODULE_DEVICE_TABLE(of
, inno_hdmi_dt_ids
);
937 struct platform_driver inno_hdmi_driver
= {
938 .probe
= inno_hdmi_probe
,
939 .remove
= inno_hdmi_remove
,
941 .name
= "innohdmi-rockchip",
942 .of_match_table
= inno_hdmi_dt_ids
,