1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
4 * Zheng Yang <zhengyang@rock-chips.com>
5 * Yakir Yang <ykk@rock-chips.com>
10 #include <linux/delay.h>
11 #include <linux/err.h>
12 #include <linux/hdmi.h>
13 #include <linux/mfd/syscon.h>
14 #include <linux/module.h>
15 #include <linux/mutex.h>
16 #include <linux/of_device.h>
18 #include <drm/drm_atomic_helper.h>
19 #include <drm/drm_edid.h>
20 #include <drm/drm_of.h>
21 #include <drm/drm_probe_helper.h>
22 #include <drm/drm_simple_kms_helper.h>
24 #include "rockchip_drm_drv.h"
25 #include "rockchip_drm_vop.h"
27 #include "inno_hdmi.h"
29 #define to_inno_hdmi(x) container_of(x, struct inno_hdmi, x)
31 struct hdmi_data_info {
35 unsigned int enc_in_format;
36 unsigned int enc_out_format;
37 unsigned int colorimetry;
40 struct inno_hdmi_i2c {
41 struct i2c_adapter adap;
47 struct completion cmp;
52 struct drm_device *drm_dev;
58 struct drm_connector connector;
59 struct drm_encoder encoder;
61 struct inno_hdmi_i2c *i2c;
62 struct i2c_adapter *ddc;
64 unsigned int tmds_rate;
66 struct hdmi_data_info hdmi_data;
67 struct drm_display_mode previous_mode;
71 CSC_ITU601_16_235_TO_RGB_0_255_8BIT,
72 CSC_ITU601_0_255_TO_RGB_0_255_8BIT,
73 CSC_ITU709_16_235_TO_RGB_0_255_8BIT,
74 CSC_RGB_0_255_TO_ITU601_16_235_8BIT,
75 CSC_RGB_0_255_TO_ITU709_16_235_8BIT,
76 CSC_RGB_0_255_TO_RGB_16_235_8BIT,
79 static const char coeff_csc[][24] = {
81 * YUV2RGB:601 SD mode(Y[16:235], UV[16:240], RGB[0:255]):
82 * R = 1.164*Y + 1.596*V - 204
83 * G = 1.164*Y - 0.391*U - 0.813*V + 154
84 * B = 1.164*Y + 2.018*U - 258
87 0x04, 0xa7, 0x00, 0x00, 0x06, 0x62, 0x02, 0xcc,
88 0x04, 0xa7, 0x11, 0x90, 0x13, 0x40, 0x00, 0x9a,
89 0x04, 0xa7, 0x08, 0x12, 0x00, 0x00, 0x03, 0x02
92 * YUV2RGB:601 SD mode(YUV[0:255],RGB[0:255]):
93 * R = Y + 1.402*V - 248
94 * G = Y - 0.344*U - 0.714*V + 135
95 * B = Y + 1.772*U - 227
98 0x04, 0x00, 0x00, 0x00, 0x05, 0x9b, 0x02, 0xf8,
99 0x04, 0x00, 0x11, 0x60, 0x12, 0xdb, 0x00, 0x87,
100 0x04, 0x00, 0x07, 0x16, 0x00, 0x00, 0x02, 0xe3
103 * YUV2RGB:709 HD mode(Y[16:235],UV[16:240],RGB[0:255]):
104 * R = 1.164*Y + 1.793*V - 248
105 * G = 1.164*Y - 0.213*U - 0.534*V + 77
106 * B = 1.164*Y + 2.115*U - 289
109 0x04, 0xa7, 0x00, 0x00, 0x07, 0x2c, 0x02, 0xf8,
110 0x04, 0xa7, 0x10, 0xda, 0x12, 0x22, 0x00, 0x4d,
111 0x04, 0xa7, 0x08, 0x74, 0x00, 0x00, 0x03, 0x21
115 * RGB2YUV:601 SD mode:
116 * Cb = -0.291G - 0.148R + 0.439B + 128
117 * Y = 0.504G + 0.257R + 0.098B + 16
118 * Cr = -0.368G + 0.439R - 0.071B + 128
121 0x11, 0x5f, 0x01, 0x82, 0x10, 0x23, 0x00, 0x80,
122 0x02, 0x1c, 0x00, 0xa1, 0x00, 0x36, 0x00, 0x1e,
123 0x11, 0x29, 0x10, 0x59, 0x01, 0x82, 0x00, 0x80
126 * RGB2YUV:709 HD mode:
127 * Cb = - 0.338G - 0.101R + 0.439B + 128
128 * Y = 0.614G + 0.183R + 0.062B + 16
129 * Cr = - 0.399G + 0.439R - 0.040B + 128
132 0x11, 0x98, 0x01, 0xc1, 0x10, 0x28, 0x00, 0x80,
133 0x02, 0x74, 0x00, 0xbb, 0x00, 0x3f, 0x00, 0x10,
134 0x11, 0x5a, 0x10, 0x67, 0x01, 0xc1, 0x00, 0x80
137 * RGB[0:255]2RGB[16:235]:
138 * R' = R x (235-16)/255 + 16;
139 * G' = G x (235-16)/255 + 16;
140 * B' = B x (235-16)/255 + 16;
143 0x00, 0x00, 0x03, 0x6F, 0x00, 0x00, 0x00, 0x10,
144 0x03, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
145 0x00, 0x00, 0x00, 0x00, 0x03, 0x6F, 0x00, 0x10
149 static inline u8 hdmi_readb(struct inno_hdmi *hdmi, u16 offset)
151 return readl_relaxed(hdmi->regs + (offset) * 0x04);
154 static inline void hdmi_writeb(struct inno_hdmi *hdmi, u16 offset, u32 val)
156 writel_relaxed(val, hdmi->regs + (offset) * 0x04);
159 static inline void hdmi_modb(struct inno_hdmi *hdmi, u16 offset,
162 u8 temp = hdmi_readb(hdmi, offset) & ~msk;
165 hdmi_writeb(hdmi, offset, temp);
168 static void inno_hdmi_i2c_init(struct inno_hdmi *hdmi)
172 ddc_bus_freq = (hdmi->tmds_rate >> 2) / HDMI_SCL_RATE;
174 hdmi_writeb(hdmi, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
175 hdmi_writeb(hdmi, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
177 /* Clear the EDID interrupt flag and mute the interrupt */
178 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
179 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
182 static void inno_hdmi_sys_power(struct inno_hdmi *hdmi, bool enable)
185 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_ON);
187 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_OFF);
190 static void inno_hdmi_set_pwr_mode(struct inno_hdmi *hdmi, int mode)
194 inno_hdmi_sys_power(hdmi, false);
196 hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x6f);
197 hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0xbb);
199 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
200 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x14);
201 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x10);
202 hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x0f);
203 hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x00);
204 hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x01);
206 inno_hdmi_sys_power(hdmi, true);
210 inno_hdmi_sys_power(hdmi, false);
211 hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0x00);
212 hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x00);
213 hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x00);
214 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
219 DRM_DEV_ERROR(hdmi->dev, "Unknown power mode %d\n", mode);
223 static void inno_hdmi_reset(struct inno_hdmi *hdmi)
228 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL);
231 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG);
234 msk = m_REG_CLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL;
235 val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH;
236 hdmi_modb(hdmi, HDMI_SYS_CTRL, msk, val);
238 inno_hdmi_set_pwr_mode(hdmi, NORMAL);
241 static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi, int setup_rc,
242 union hdmi_infoframe *frame, u32 frame_index,
243 u32 mask, u32 disable, u32 enable)
246 hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, disable);
248 hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, frame_index);
251 u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE];
254 rc = hdmi_infoframe_pack(frame, packed_frame,
255 sizeof(packed_frame));
259 for (i = 0; i < rc; i++)
260 hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i,
264 hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, enable);
270 static int inno_hdmi_config_video_vsi(struct inno_hdmi *hdmi,
271 struct drm_display_mode *mode)
273 union hdmi_infoframe frame;
276 rc = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
280 return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_VSI,
281 m_PACKET_VSI_EN, v_PACKET_VSI_EN(0), v_PACKET_VSI_EN(1));
284 static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi,
285 struct drm_display_mode *mode)
287 union hdmi_infoframe frame;
290 rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
294 if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444)
295 frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
296 else if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV422)
297 frame.avi.colorspace = HDMI_COLORSPACE_YUV422;
299 frame.avi.colorspace = HDMI_COLORSPACE_RGB;
301 return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_AVI, 0, 0, 0);
304 static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi)
306 struct hdmi_data_info *data = &hdmi->hdmi_data;
307 int c0_c2_change = 0;
314 /* Input video mode is SDR RGB24bit, data enable signal from external */
315 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL1, v_DE_EXTERNAL |
316 v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444));
318 /* Input color hardcode to RGB, and output color hardcode to RGB888 */
319 value = v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS) |
320 v_VIDEO_OUTPUT_COLOR(0) |
321 v_VIDEO_INPUT_CSP(0);
322 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value);
324 if (data->enc_in_format == data->enc_out_format) {
325 if ((data->enc_in_format == HDMI_COLORSPACE_RGB) ||
326 (data->enc_in_format >= HDMI_COLORSPACE_YUV444)) {
327 value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1);
328 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
330 hdmi_modb(hdmi, HDMI_VIDEO_CONTRL,
331 m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_SWAP,
332 v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) |
333 v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE));
338 if (data->colorimetry == HDMI_COLORIMETRY_ITU_601) {
339 if ((data->enc_in_format == HDMI_COLORSPACE_RGB) &&
340 (data->enc_out_format == HDMI_COLORSPACE_YUV444)) {
341 csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
342 auto_csc = AUTO_CSC_DISABLE;
343 c0_c2_change = C0_C2_CHANGE_DISABLE;
344 csc_enable = v_CSC_ENABLE;
345 } else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) &&
346 (data->enc_out_format == HDMI_COLORSPACE_RGB)) {
347 csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
348 auto_csc = AUTO_CSC_ENABLE;
349 c0_c2_change = C0_C2_CHANGE_DISABLE;
350 csc_enable = v_CSC_DISABLE;
353 if ((data->enc_in_format == HDMI_COLORSPACE_RGB) &&
354 (data->enc_out_format == HDMI_COLORSPACE_YUV444)) {
355 csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
356 auto_csc = AUTO_CSC_DISABLE;
357 c0_c2_change = C0_C2_CHANGE_DISABLE;
358 csc_enable = v_CSC_ENABLE;
359 } else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) &&
360 (data->enc_out_format == HDMI_COLORSPACE_RGB)) {
361 csc_mode = CSC_ITU709_16_235_TO_RGB_0_255_8BIT;
362 auto_csc = AUTO_CSC_ENABLE;
363 c0_c2_change = C0_C2_CHANGE_DISABLE;
364 csc_enable = v_CSC_DISABLE;
368 for (i = 0; i < 24; i++)
369 hdmi_writeb(hdmi, HDMI_VIDEO_CSC_COEF + i,
370 coeff_csc[csc_mode][i]);
372 value = v_SOF_DISABLE | csc_enable | v_COLOR_DEPTH_NOT_INDICATED(1);
373 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
374 hdmi_modb(hdmi, HDMI_VIDEO_CONTRL, m_VIDEO_AUTO_CSC |
375 m_VIDEO_C0_C2_SWAP, v_VIDEO_AUTO_CSC(auto_csc) |
376 v_VIDEO_C0_C2_SWAP(c0_c2_change));
381 static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
382 struct drm_display_mode *mode)
386 /* Set detail external video timing polarity and interlace mode */
387 value = v_EXTERANL_VIDEO(1);
388 value |= mode->flags & DRM_MODE_FLAG_PHSYNC ?
389 v_HSYNC_POLARITY(1) : v_HSYNC_POLARITY(0);
390 value |= mode->flags & DRM_MODE_FLAG_PVSYNC ?
391 v_VSYNC_POLARITY(1) : v_VSYNC_POLARITY(0);
392 value |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
393 v_INETLACE(1) : v_INETLACE(0);
394 hdmi_writeb(hdmi, HDMI_VIDEO_TIMING_CTL, value);
396 /* Set detail external video timing */
397 value = mode->htotal;
398 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_L, value & 0xFF);
399 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
401 value = mode->htotal - mode->hdisplay;
402 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_L, value & 0xFF);
403 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
405 value = mode->hsync_start - mode->hdisplay;
406 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_L, value & 0xFF);
407 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
409 value = mode->hsync_end - mode->hsync_start;
410 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_L, value & 0xFF);
411 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF);
413 value = mode->vtotal;
414 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_L, value & 0xFF);
415 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
417 value = mode->vtotal - mode->vdisplay;
418 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VBLANK, value & 0xFF);
420 value = mode->vsync_start - mode->vdisplay;
421 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDELAY, value & 0xFF);
423 value = mode->vsync_end - mode->vsync_start;
424 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDURATION, value & 0xFF);
426 hdmi_writeb(hdmi, HDMI_PHY_PRE_DIV_RATIO, 0x1e);
427 hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_LOW, 0x2c);
428 hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_HIGH, 0x01);
433 static int inno_hdmi_setup(struct inno_hdmi *hdmi,
434 struct drm_display_mode *mode)
436 hdmi->hdmi_data.vic = drm_match_cea_mode(mode);
438 hdmi->hdmi_data.enc_in_format = HDMI_COLORSPACE_RGB;
439 hdmi->hdmi_data.enc_out_format = HDMI_COLORSPACE_RGB;
441 if ((hdmi->hdmi_data.vic == 6) || (hdmi->hdmi_data.vic == 7) ||
442 (hdmi->hdmi_data.vic == 21) || (hdmi->hdmi_data.vic == 22) ||
443 (hdmi->hdmi_data.vic == 2) || (hdmi->hdmi_data.vic == 3) ||
444 (hdmi->hdmi_data.vic == 17) || (hdmi->hdmi_data.vic == 18))
445 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
447 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
449 /* Mute video and audio output */
450 hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
451 v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
454 hdmi_writeb(hdmi, HDMI_HDCP_CTRL,
455 v_HDMI_DVI(hdmi->hdmi_data.sink_is_hdmi));
457 inno_hdmi_config_video_timing(hdmi, mode);
459 inno_hdmi_config_video_csc(hdmi);
461 if (hdmi->hdmi_data.sink_is_hdmi) {
462 inno_hdmi_config_video_avi(hdmi, mode);
463 inno_hdmi_config_video_vsi(hdmi, mode);
467 * When IP controller have configured to an accurate video
468 * timing, then the TMDS clock source would be switched to
469 * DCLK_LCDC, so we need to init the TMDS rate to mode pixel
470 * clock rate, and reconfigure the DDC clock.
472 hdmi->tmds_rate = mode->clock * 1000;
473 inno_hdmi_i2c_init(hdmi);
475 /* Unmute video and audio output */
476 hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
477 v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
482 static void inno_hdmi_encoder_mode_set(struct drm_encoder *encoder,
483 struct drm_display_mode *mode,
484 struct drm_display_mode *adj_mode)
486 struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
488 inno_hdmi_setup(hdmi, adj_mode);
490 /* Store the display mode for plugin/DPMS poweron events */
491 memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode));
494 static void inno_hdmi_encoder_enable(struct drm_encoder *encoder)
496 struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
498 inno_hdmi_set_pwr_mode(hdmi, NORMAL);
501 static void inno_hdmi_encoder_disable(struct drm_encoder *encoder)
503 struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
505 inno_hdmi_set_pwr_mode(hdmi, LOWER_PWR);
508 static bool inno_hdmi_encoder_mode_fixup(struct drm_encoder *encoder,
509 const struct drm_display_mode *mode,
510 struct drm_display_mode *adj_mode)
516 inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
517 struct drm_crtc_state *crtc_state,
518 struct drm_connector_state *conn_state)
520 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
522 s->output_mode = ROCKCHIP_OUT_MODE_P888;
523 s->output_type = DRM_MODE_CONNECTOR_HDMIA;
528 static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = {
529 .enable = inno_hdmi_encoder_enable,
530 .disable = inno_hdmi_encoder_disable,
531 .mode_fixup = inno_hdmi_encoder_mode_fixup,
532 .mode_set = inno_hdmi_encoder_mode_set,
533 .atomic_check = inno_hdmi_encoder_atomic_check,
536 static enum drm_connector_status
537 inno_hdmi_connector_detect(struct drm_connector *connector, bool force)
539 struct inno_hdmi *hdmi = to_inno_hdmi(connector);
541 return (hdmi_readb(hdmi, HDMI_STATUS) & m_HOTPLUG) ?
542 connector_status_connected : connector_status_disconnected;
545 static int inno_hdmi_connector_get_modes(struct drm_connector *connector)
547 struct inno_hdmi *hdmi = to_inno_hdmi(connector);
554 edid = drm_get_edid(connector, hdmi->ddc);
556 hdmi->hdmi_data.sink_is_hdmi = drm_detect_hdmi_monitor(edid);
557 hdmi->hdmi_data.sink_has_audio = drm_detect_monitor_audio(edid);
558 drm_connector_update_edid_property(connector, edid);
559 ret = drm_add_edid_modes(connector, edid);
566 static enum drm_mode_status
567 inno_hdmi_connector_mode_valid(struct drm_connector *connector,
568 struct drm_display_mode *mode)
574 inno_hdmi_probe_single_connector_modes(struct drm_connector *connector,
575 uint32_t maxX, uint32_t maxY)
577 return drm_helper_probe_single_connector_modes(connector, 1920, 1080);
580 static void inno_hdmi_connector_destroy(struct drm_connector *connector)
582 drm_connector_unregister(connector);
583 drm_connector_cleanup(connector);
586 static const struct drm_connector_funcs inno_hdmi_connector_funcs = {
587 .fill_modes = inno_hdmi_probe_single_connector_modes,
588 .detect = inno_hdmi_connector_detect,
589 .destroy = inno_hdmi_connector_destroy,
590 .reset = drm_atomic_helper_connector_reset,
591 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
592 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
595 static struct drm_connector_helper_funcs inno_hdmi_connector_helper_funcs = {
596 .get_modes = inno_hdmi_connector_get_modes,
597 .mode_valid = inno_hdmi_connector_mode_valid,
600 static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi)
602 struct drm_encoder *encoder = &hdmi->encoder;
603 struct device *dev = hdmi->dev;
605 encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
608 * If we failed to find the CRTC(s) which this encoder is
609 * supposed to be connected to, it's because the CRTC has
610 * not been registered yet. Defer probing, and hope that
611 * the required CRTC is added later.
613 if (encoder->possible_crtcs == 0)
614 return -EPROBE_DEFER;
616 drm_encoder_helper_add(encoder, &inno_hdmi_encoder_helper_funcs);
617 drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
619 hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
621 drm_connector_helper_add(&hdmi->connector,
622 &inno_hdmi_connector_helper_funcs);
623 drm_connector_init_with_ddc(drm, &hdmi->connector,
624 &inno_hdmi_connector_funcs,
625 DRM_MODE_CONNECTOR_HDMIA,
628 drm_connector_attach_encoder(&hdmi->connector, encoder);
633 static irqreturn_t inno_hdmi_i2c_irq(struct inno_hdmi *hdmi)
635 struct inno_hdmi_i2c *i2c = hdmi->i2c;
638 stat = hdmi_readb(hdmi, HDMI_INTERRUPT_STATUS1);
639 if (!(stat & m_INT_EDID_READY))
642 /* Clear HDMI EDID interrupt flag */
643 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
650 static irqreturn_t inno_hdmi_hardirq(int irq, void *dev_id)
652 struct inno_hdmi *hdmi = dev_id;
653 irqreturn_t ret = IRQ_NONE;
657 ret = inno_hdmi_i2c_irq(hdmi);
659 interrupt = hdmi_readb(hdmi, HDMI_STATUS);
660 if (interrupt & m_INT_HOTPLUG) {
661 hdmi_modb(hdmi, HDMI_STATUS, m_INT_HOTPLUG, m_INT_HOTPLUG);
662 ret = IRQ_WAKE_THREAD;
668 static irqreturn_t inno_hdmi_irq(int irq, void *dev_id)
670 struct inno_hdmi *hdmi = dev_id;
672 drm_helper_hpd_irq_event(hdmi->connector.dev);
677 static int inno_hdmi_i2c_read(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
679 int length = msgs->len;
683 ret = wait_for_completion_timeout(&hdmi->i2c->cmp, HZ / 10);
688 *buf++ = hdmi_readb(hdmi, HDMI_EDID_FIFO_ADDR);
693 static int inno_hdmi_i2c_write(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
696 * The DDC module only support read EDID message, so
697 * we assume that each word write to this i2c adapter
698 * should be the offset of EDID word address.
700 if ((msgs->len != 1) ||
701 ((msgs->addr != DDC_ADDR) && (msgs->addr != DDC_SEGMENT_ADDR)))
704 reinit_completion(&hdmi->i2c->cmp);
706 if (msgs->addr == DDC_SEGMENT_ADDR)
707 hdmi->i2c->segment_addr = msgs->buf[0];
708 if (msgs->addr == DDC_ADDR)
709 hdmi->i2c->ddc_addr = msgs->buf[0];
711 /* Set edid fifo first addr */
712 hdmi_writeb(hdmi, HDMI_EDID_FIFO_OFFSET, 0x00);
714 /* Set edid word address 0x00/0x80 */
715 hdmi_writeb(hdmi, HDMI_EDID_WORD_ADDR, hdmi->i2c->ddc_addr);
717 /* Set edid segment pointer */
718 hdmi_writeb(hdmi, HDMI_EDID_SEGMENT_POINTER, hdmi->i2c->segment_addr);
723 static int inno_hdmi_i2c_xfer(struct i2c_adapter *adap,
724 struct i2c_msg *msgs, int num)
726 struct inno_hdmi *hdmi = i2c_get_adapdata(adap);
727 struct inno_hdmi_i2c *i2c = hdmi->i2c;
730 mutex_lock(&i2c->lock);
732 /* Clear the EDID interrupt flag and unmute the interrupt */
733 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, m_INT_EDID_READY);
734 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
736 for (i = 0; i < num; i++) {
737 DRM_DEV_DEBUG(hdmi->dev,
738 "xfer: num: %d/%d, len: %d, flags: %#x\n",
739 i + 1, num, msgs[i].len, msgs[i].flags);
741 if (msgs[i].flags & I2C_M_RD)
742 ret = inno_hdmi_i2c_read(hdmi, &msgs[i]);
744 ret = inno_hdmi_i2c_write(hdmi, &msgs[i]);
753 /* Mute HDMI EDID interrupt */
754 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
756 mutex_unlock(&i2c->lock);
761 static u32 inno_hdmi_i2c_func(struct i2c_adapter *adapter)
763 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
766 static const struct i2c_algorithm inno_hdmi_algorithm = {
767 .master_xfer = inno_hdmi_i2c_xfer,
768 .functionality = inno_hdmi_i2c_func,
771 static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
773 struct i2c_adapter *adap;
774 struct inno_hdmi_i2c *i2c;
777 i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
779 return ERR_PTR(-ENOMEM);
781 mutex_init(&i2c->lock);
782 init_completion(&i2c->cmp);
785 adap->class = I2C_CLASS_DDC;
786 adap->owner = THIS_MODULE;
787 adap->dev.parent = hdmi->dev;
788 adap->dev.of_node = hdmi->dev->of_node;
789 adap->algo = &inno_hdmi_algorithm;
790 strlcpy(adap->name, "Inno HDMI", sizeof(adap->name));
791 i2c_set_adapdata(adap, hdmi);
793 ret = i2c_add_adapter(adap);
795 dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
796 devm_kfree(hdmi->dev, i2c);
802 DRM_DEV_INFO(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
807 static int inno_hdmi_bind(struct device *dev, struct device *master,
810 struct platform_device *pdev = to_platform_device(dev);
811 struct drm_device *drm = data;
812 struct inno_hdmi *hdmi;
813 struct resource *iores;
817 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
824 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
825 hdmi->regs = devm_ioremap_resource(dev, iores);
826 if (IS_ERR(hdmi->regs))
827 return PTR_ERR(hdmi->regs);
829 hdmi->pclk = devm_clk_get(hdmi->dev, "pclk");
830 if (IS_ERR(hdmi->pclk)) {
831 DRM_DEV_ERROR(hdmi->dev, "Unable to get HDMI pclk clk\n");
832 return PTR_ERR(hdmi->pclk);
835 ret = clk_prepare_enable(hdmi->pclk);
837 DRM_DEV_ERROR(hdmi->dev,
838 "Cannot enable HDMI pclk clock: %d\n", ret);
842 irq = platform_get_irq(pdev, 0);
845 goto err_disable_clk;
848 inno_hdmi_reset(hdmi);
850 hdmi->ddc = inno_hdmi_i2c_adapter(hdmi);
851 if (IS_ERR(hdmi->ddc)) {
852 ret = PTR_ERR(hdmi->ddc);
854 goto err_disable_clk;
858 * When IP controller haven't configured to an accurate video
859 * timing, then the TMDS clock source would be switched to
860 * PCLK_HDMI, so we need to init the TMDS rate to PCLK rate,
861 * and reconfigure the DDC clock.
863 hdmi->tmds_rate = clk_get_rate(hdmi->pclk);
864 inno_hdmi_i2c_init(hdmi);
866 ret = inno_hdmi_register(drm, hdmi);
868 goto err_put_adapter;
870 dev_set_drvdata(dev, hdmi);
872 /* Unmute hotplug interrupt */
873 hdmi_modb(hdmi, HDMI_STATUS, m_MASK_INT_HOTPLUG, v_MASK_INT_HOTPLUG(1));
875 ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq,
876 inno_hdmi_irq, IRQF_SHARED,
877 dev_name(dev), hdmi);
879 goto err_cleanup_hdmi;
883 hdmi->connector.funcs->destroy(&hdmi->connector);
884 hdmi->encoder.funcs->destroy(&hdmi->encoder);
886 i2c_put_adapter(hdmi->ddc);
888 clk_disable_unprepare(hdmi->pclk);
892 static void inno_hdmi_unbind(struct device *dev, struct device *master,
895 struct inno_hdmi *hdmi = dev_get_drvdata(dev);
897 hdmi->connector.funcs->destroy(&hdmi->connector);
898 hdmi->encoder.funcs->destroy(&hdmi->encoder);
900 i2c_put_adapter(hdmi->ddc);
901 clk_disable_unprepare(hdmi->pclk);
904 static const struct component_ops inno_hdmi_ops = {
905 .bind = inno_hdmi_bind,
906 .unbind = inno_hdmi_unbind,
909 static int inno_hdmi_probe(struct platform_device *pdev)
911 return component_add(&pdev->dev, &inno_hdmi_ops);
914 static int inno_hdmi_remove(struct platform_device *pdev)
916 component_del(&pdev->dev, &inno_hdmi_ops);
921 static const struct of_device_id inno_hdmi_dt_ids[] = {
922 { .compatible = "rockchip,rk3036-inno-hdmi",
926 MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids);
928 struct platform_driver inno_hdmi_driver = {
929 .probe = inno_hdmi_probe,
930 .remove = inno_hdmi_remove,
932 .name = "innohdmi-rockchip",
933 .of_match_table = inno_hdmi_dt_ids,