1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
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>
23 #include "rockchip_drm_drv.h"
24 #include "rockchip_drm_vop.h"
26 #include "inno_hdmi.h"
28 #define to_inno_hdmi(x) container_of(x, struct inno_hdmi, x)
30 struct hdmi_data_info {
34 unsigned int enc_in_format;
35 unsigned int enc_out_format;
36 unsigned int colorimetry;
39 struct inno_hdmi_i2c {
40 struct i2c_adapter adap;
46 struct completion cmp;
51 struct drm_device *drm_dev;
57 struct drm_connector connector;
58 struct drm_encoder encoder;
60 struct inno_hdmi_i2c *i2c;
61 struct i2c_adapter *ddc;
63 unsigned int tmds_rate;
65 struct hdmi_data_info hdmi_data;
66 struct drm_display_mode previous_mode;
70 CSC_ITU601_16_235_TO_RGB_0_255_8BIT,
71 CSC_ITU601_0_255_TO_RGB_0_255_8BIT,
72 CSC_ITU709_16_235_TO_RGB_0_255_8BIT,
73 CSC_RGB_0_255_TO_ITU601_16_235_8BIT,
74 CSC_RGB_0_255_TO_ITU709_16_235_8BIT,
75 CSC_RGB_0_255_TO_RGB_16_235_8BIT,
78 static const char coeff_csc[][24] = {
80 * YUV2RGB:601 SD mode(Y[16:235], UV[16:240], RGB[0:255]):
81 * R = 1.164*Y + 1.596*V - 204
82 * G = 1.164*Y - 0.391*U - 0.813*V + 154
83 * B = 1.164*Y + 2.018*U - 258
86 0x04, 0xa7, 0x00, 0x00, 0x06, 0x62, 0x02, 0xcc,
87 0x04, 0xa7, 0x11, 0x90, 0x13, 0x40, 0x00, 0x9a,
88 0x04, 0xa7, 0x08, 0x12, 0x00, 0x00, 0x03, 0x02
91 * YUV2RGB:601 SD mode(YUV[0:255],RGB[0:255]):
92 * R = Y + 1.402*V - 248
93 * G = Y - 0.344*U - 0.714*V + 135
94 * B = Y + 1.772*U - 227
97 0x04, 0x00, 0x00, 0x00, 0x05, 0x9b, 0x02, 0xf8,
98 0x04, 0x00, 0x11, 0x60, 0x12, 0xdb, 0x00, 0x87,
99 0x04, 0x00, 0x07, 0x16, 0x00, 0x00, 0x02, 0xe3
102 * YUV2RGB:709 HD mode(Y[16:235],UV[16:240],RGB[0:255]):
103 * R = 1.164*Y + 1.793*V - 248
104 * G = 1.164*Y - 0.213*U - 0.534*V + 77
105 * B = 1.164*Y + 2.115*U - 289
108 0x04, 0xa7, 0x00, 0x00, 0x07, 0x2c, 0x02, 0xf8,
109 0x04, 0xa7, 0x10, 0xda, 0x12, 0x22, 0x00, 0x4d,
110 0x04, 0xa7, 0x08, 0x74, 0x00, 0x00, 0x03, 0x21
114 * RGB2YUV:601 SD mode:
115 * Cb = -0.291G - 0.148R + 0.439B + 128
116 * Y = 0.504G + 0.257R + 0.098B + 16
117 * Cr = -0.368G + 0.439R - 0.071B + 128
120 0x11, 0x5f, 0x01, 0x82, 0x10, 0x23, 0x00, 0x80,
121 0x02, 0x1c, 0x00, 0xa1, 0x00, 0x36, 0x00, 0x1e,
122 0x11, 0x29, 0x10, 0x59, 0x01, 0x82, 0x00, 0x80
125 * RGB2YUV:709 HD mode:
126 * Cb = - 0.338G - 0.101R + 0.439B + 128
127 * Y = 0.614G + 0.183R + 0.062B + 16
128 * Cr = - 0.399G + 0.439R - 0.040B + 128
131 0x11, 0x98, 0x01, 0xc1, 0x10, 0x28, 0x00, 0x80,
132 0x02, 0x74, 0x00, 0xbb, 0x00, 0x3f, 0x00, 0x10,
133 0x11, 0x5a, 0x10, 0x67, 0x01, 0xc1, 0x00, 0x80
136 * RGB[0:255]2RGB[16:235]:
137 * R' = R x (235-16)/255 + 16;
138 * G' = G x (235-16)/255 + 16;
139 * B' = B x (235-16)/255 + 16;
142 0x00, 0x00, 0x03, 0x6F, 0x00, 0x00, 0x00, 0x10,
143 0x03, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
144 0x00, 0x00, 0x00, 0x00, 0x03, 0x6F, 0x00, 0x10
148 static inline u8 hdmi_readb(struct inno_hdmi *hdmi, u16 offset)
150 return readl_relaxed(hdmi->regs + (offset) * 0x04);
153 static inline void hdmi_writeb(struct inno_hdmi *hdmi, u16 offset, u32 val)
155 writel_relaxed(val, hdmi->regs + (offset) * 0x04);
158 static inline void hdmi_modb(struct inno_hdmi *hdmi, u16 offset,
161 u8 temp = hdmi_readb(hdmi, offset) & ~msk;
164 hdmi_writeb(hdmi, offset, temp);
167 static void inno_hdmi_i2c_init(struct inno_hdmi *hdmi)
171 ddc_bus_freq = (hdmi->tmds_rate >> 2) / HDMI_SCL_RATE;
173 hdmi_writeb(hdmi, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
174 hdmi_writeb(hdmi, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
176 /* Clear the EDID interrupt flag and mute the interrupt */
177 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
178 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
181 static void inno_hdmi_sys_power(struct inno_hdmi *hdmi, bool enable)
184 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_ON);
186 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_OFF);
189 static void inno_hdmi_set_pwr_mode(struct inno_hdmi *hdmi, int mode)
193 inno_hdmi_sys_power(hdmi, false);
195 hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x6f);
196 hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0xbb);
198 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
199 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x14);
200 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x10);
201 hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x0f);
202 hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x00);
203 hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x01);
205 inno_hdmi_sys_power(hdmi, true);
209 inno_hdmi_sys_power(hdmi, false);
210 hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0x00);
211 hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x00);
212 hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x00);
213 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
218 DRM_DEV_ERROR(hdmi->dev, "Unknown power mode %d\n", mode);
222 static void inno_hdmi_reset(struct inno_hdmi *hdmi)
227 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL);
230 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG);
233 msk = m_REG_CLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL;
234 val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH;
235 hdmi_modb(hdmi, HDMI_SYS_CTRL, msk, val);
237 inno_hdmi_set_pwr_mode(hdmi, NORMAL);
240 static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi, int setup_rc,
241 union hdmi_infoframe *frame, u32 frame_index,
242 u32 mask, u32 disable, u32 enable)
245 hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, disable);
247 hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, frame_index);
250 u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE];
253 rc = hdmi_infoframe_pack(frame, packed_frame,
254 sizeof(packed_frame));
258 for (i = 0; i < rc; i++)
259 hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i,
263 hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, enable);
269 static int inno_hdmi_config_video_vsi(struct inno_hdmi *hdmi,
270 struct drm_display_mode *mode)
272 union hdmi_infoframe frame;
275 rc = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
279 return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_VSI,
280 m_PACKET_VSI_EN, v_PACKET_VSI_EN(0), v_PACKET_VSI_EN(1));
283 static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi,
284 struct drm_display_mode *mode)
286 union hdmi_infoframe frame;
289 rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
293 if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444)
294 frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
295 else if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV422)
296 frame.avi.colorspace = HDMI_COLORSPACE_YUV422;
298 frame.avi.colorspace = HDMI_COLORSPACE_RGB;
300 return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_AVI, 0, 0, 0);
303 static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi)
305 struct hdmi_data_info *data = &hdmi->hdmi_data;
306 int c0_c2_change = 0;
313 /* Input video mode is SDR RGB24bit, data enable signal from external */
314 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL1, v_DE_EXTERNAL |
315 v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444));
317 /* Input color hardcode to RGB, and output color hardcode to RGB888 */
318 value = v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS) |
319 v_VIDEO_OUTPUT_COLOR(0) |
320 v_VIDEO_INPUT_CSP(0);
321 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value);
323 if (data->enc_in_format == data->enc_out_format) {
324 if ((data->enc_in_format == HDMI_COLORSPACE_RGB) ||
325 (data->enc_in_format >= HDMI_COLORSPACE_YUV444)) {
326 value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1);
327 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
329 hdmi_modb(hdmi, HDMI_VIDEO_CONTRL,
330 m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_SWAP,
331 v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) |
332 v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE));
337 if (data->colorimetry == HDMI_COLORIMETRY_ITU_601) {
338 if ((data->enc_in_format == HDMI_COLORSPACE_RGB) &&
339 (data->enc_out_format == HDMI_COLORSPACE_YUV444)) {
340 csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
341 auto_csc = AUTO_CSC_DISABLE;
342 c0_c2_change = C0_C2_CHANGE_DISABLE;
343 csc_enable = v_CSC_ENABLE;
344 } else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) &&
345 (data->enc_out_format == HDMI_COLORSPACE_RGB)) {
346 csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
347 auto_csc = AUTO_CSC_ENABLE;
348 c0_c2_change = C0_C2_CHANGE_DISABLE;
349 csc_enable = v_CSC_DISABLE;
352 if ((data->enc_in_format == HDMI_COLORSPACE_RGB) &&
353 (data->enc_out_format == HDMI_COLORSPACE_YUV444)) {
354 csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
355 auto_csc = AUTO_CSC_DISABLE;
356 c0_c2_change = C0_C2_CHANGE_DISABLE;
357 csc_enable = v_CSC_ENABLE;
358 } else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) &&
359 (data->enc_out_format == HDMI_COLORSPACE_RGB)) {
360 csc_mode = CSC_ITU709_16_235_TO_RGB_0_255_8BIT;
361 auto_csc = AUTO_CSC_ENABLE;
362 c0_c2_change = C0_C2_CHANGE_DISABLE;
363 csc_enable = v_CSC_DISABLE;
367 for (i = 0; i < 24; i++)
368 hdmi_writeb(hdmi, HDMI_VIDEO_CSC_COEF + i,
369 coeff_csc[csc_mode][i]);
371 value = v_SOF_DISABLE | csc_enable | v_COLOR_DEPTH_NOT_INDICATED(1);
372 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
373 hdmi_modb(hdmi, HDMI_VIDEO_CONTRL, m_VIDEO_AUTO_CSC |
374 m_VIDEO_C0_C2_SWAP, v_VIDEO_AUTO_CSC(auto_csc) |
375 v_VIDEO_C0_C2_SWAP(c0_c2_change));
380 static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
381 struct drm_display_mode *mode)
385 /* Set detail external video timing polarity and interlace mode */
386 value = v_EXTERANL_VIDEO(1);
387 value |= mode->flags & DRM_MODE_FLAG_PHSYNC ?
388 v_HSYNC_POLARITY(1) : v_HSYNC_POLARITY(0);
389 value |= mode->flags & DRM_MODE_FLAG_PVSYNC ?
390 v_VSYNC_POLARITY(1) : v_VSYNC_POLARITY(0);
391 value |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
392 v_INETLACE(1) : v_INETLACE(0);
393 hdmi_writeb(hdmi, HDMI_VIDEO_TIMING_CTL, value);
395 /* Set detail external video timing */
396 value = mode->htotal;
397 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_L, value & 0xFF);
398 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
400 value = mode->htotal - mode->hdisplay;
401 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_L, value & 0xFF);
402 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
404 value = mode->hsync_start - mode->hdisplay;
405 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_L, value & 0xFF);
406 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
408 value = mode->hsync_end - mode->hsync_start;
409 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_L, value & 0xFF);
410 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF);
412 value = mode->vtotal;
413 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_L, value & 0xFF);
414 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
416 value = mode->vtotal - mode->vdisplay;
417 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VBLANK, value & 0xFF);
419 value = mode->vsync_start - mode->vdisplay;
420 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDELAY, value & 0xFF);
422 value = mode->vsync_end - mode->vsync_start;
423 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDURATION, value & 0xFF);
425 hdmi_writeb(hdmi, HDMI_PHY_PRE_DIV_RATIO, 0x1e);
426 hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_LOW, 0x2c);
427 hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_HIGH, 0x01);
432 static int inno_hdmi_setup(struct inno_hdmi *hdmi,
433 struct drm_display_mode *mode)
435 hdmi->hdmi_data.vic = drm_match_cea_mode(mode);
437 hdmi->hdmi_data.enc_in_format = HDMI_COLORSPACE_RGB;
438 hdmi->hdmi_data.enc_out_format = HDMI_COLORSPACE_RGB;
440 if ((hdmi->hdmi_data.vic == 6) || (hdmi->hdmi_data.vic == 7) ||
441 (hdmi->hdmi_data.vic == 21) || (hdmi->hdmi_data.vic == 22) ||
442 (hdmi->hdmi_data.vic == 2) || (hdmi->hdmi_data.vic == 3) ||
443 (hdmi->hdmi_data.vic == 17) || (hdmi->hdmi_data.vic == 18))
444 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
446 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
448 /* Mute video and audio output */
449 hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
450 v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
453 hdmi_writeb(hdmi, HDMI_HDCP_CTRL,
454 v_HDMI_DVI(hdmi->hdmi_data.sink_is_hdmi));
456 inno_hdmi_config_video_timing(hdmi, mode);
458 inno_hdmi_config_video_csc(hdmi);
460 if (hdmi->hdmi_data.sink_is_hdmi) {
461 inno_hdmi_config_video_avi(hdmi, mode);
462 inno_hdmi_config_video_vsi(hdmi, mode);
466 * When IP controller have configured to an accurate video
467 * timing, then the TMDS clock source would be switched to
468 * DCLK_LCDC, so we need to init the TMDS rate to mode pixel
469 * clock rate, and reconfigure the DDC clock.
471 hdmi->tmds_rate = mode->clock * 1000;
472 inno_hdmi_i2c_init(hdmi);
474 /* Unmute video and audio output */
475 hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
476 v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
481 static void inno_hdmi_encoder_mode_set(struct drm_encoder *encoder,
482 struct drm_display_mode *mode,
483 struct drm_display_mode *adj_mode)
485 struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
487 inno_hdmi_setup(hdmi, adj_mode);
489 /* Store the display mode for plugin/DPMS poweron events */
490 memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode));
493 static void inno_hdmi_encoder_enable(struct drm_encoder *encoder)
495 struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
497 inno_hdmi_set_pwr_mode(hdmi, NORMAL);
500 static void inno_hdmi_encoder_disable(struct drm_encoder *encoder)
502 struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
504 inno_hdmi_set_pwr_mode(hdmi, LOWER_PWR);
507 static bool inno_hdmi_encoder_mode_fixup(struct drm_encoder *encoder,
508 const struct drm_display_mode *mode,
509 struct drm_display_mode *adj_mode)
515 inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
516 struct drm_crtc_state *crtc_state,
517 struct drm_connector_state *conn_state)
519 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
521 s->output_mode = ROCKCHIP_OUT_MODE_P888;
522 s->output_type = DRM_MODE_CONNECTOR_HDMIA;
527 static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = {
528 .enable = inno_hdmi_encoder_enable,
529 .disable = inno_hdmi_encoder_disable,
530 .mode_fixup = inno_hdmi_encoder_mode_fixup,
531 .mode_set = inno_hdmi_encoder_mode_set,
532 .atomic_check = inno_hdmi_encoder_atomic_check,
535 static struct drm_encoder_funcs inno_hdmi_encoder_funcs = {
536 .destroy = drm_encoder_cleanup,
539 static enum drm_connector_status
540 inno_hdmi_connector_detect(struct drm_connector *connector, bool force)
542 struct inno_hdmi *hdmi = to_inno_hdmi(connector);
544 return (hdmi_readb(hdmi, HDMI_STATUS) & m_HOTPLUG) ?
545 connector_status_connected : connector_status_disconnected;
548 static int inno_hdmi_connector_get_modes(struct drm_connector *connector)
550 struct inno_hdmi *hdmi = to_inno_hdmi(connector);
557 edid = drm_get_edid(connector, hdmi->ddc);
559 hdmi->hdmi_data.sink_is_hdmi = drm_detect_hdmi_monitor(edid);
560 hdmi->hdmi_data.sink_has_audio = drm_detect_monitor_audio(edid);
561 drm_connector_update_edid_property(connector, edid);
562 ret = drm_add_edid_modes(connector, edid);
569 static enum drm_mode_status
570 inno_hdmi_connector_mode_valid(struct drm_connector *connector,
571 struct drm_display_mode *mode)
577 inno_hdmi_probe_single_connector_modes(struct drm_connector *connector,
578 uint32_t maxX, uint32_t maxY)
580 return drm_helper_probe_single_connector_modes(connector, 1920, 1080);
583 static void inno_hdmi_connector_destroy(struct drm_connector *connector)
585 drm_connector_unregister(connector);
586 drm_connector_cleanup(connector);
589 static const struct drm_connector_funcs inno_hdmi_connector_funcs = {
590 .fill_modes = inno_hdmi_probe_single_connector_modes,
591 .detect = inno_hdmi_connector_detect,
592 .destroy = inno_hdmi_connector_destroy,
593 .reset = drm_atomic_helper_connector_reset,
594 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
595 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
598 static struct drm_connector_helper_funcs inno_hdmi_connector_helper_funcs = {
599 .get_modes = inno_hdmi_connector_get_modes,
600 .mode_valid = inno_hdmi_connector_mode_valid,
603 static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi)
605 struct drm_encoder *encoder = &hdmi->encoder;
606 struct device *dev = hdmi->dev;
608 encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
611 * If we failed to find the CRTC(s) which this encoder is
612 * supposed to be connected to, it's because the CRTC has
613 * not been registered yet. Defer probing, and hope that
614 * the required CRTC is added later.
616 if (encoder->possible_crtcs == 0)
617 return -EPROBE_DEFER;
619 drm_encoder_helper_add(encoder, &inno_hdmi_encoder_helper_funcs);
620 drm_encoder_init(drm, encoder, &inno_hdmi_encoder_funcs,
621 DRM_MODE_ENCODER_TMDS, NULL);
623 hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
625 drm_connector_helper_add(&hdmi->connector,
626 &inno_hdmi_connector_helper_funcs);
627 drm_connector_init(drm, &hdmi->connector, &inno_hdmi_connector_funcs,
628 DRM_MODE_CONNECTOR_HDMIA);
630 drm_connector_attach_encoder(&hdmi->connector, encoder);
635 static irqreturn_t inno_hdmi_i2c_irq(struct inno_hdmi *hdmi)
637 struct inno_hdmi_i2c *i2c = hdmi->i2c;
640 stat = hdmi_readb(hdmi, HDMI_INTERRUPT_STATUS1);
641 if (!(stat & m_INT_EDID_READY))
644 /* Clear HDMI EDID interrupt flag */
645 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
652 static irqreturn_t inno_hdmi_hardirq(int irq, void *dev_id)
654 struct inno_hdmi *hdmi = dev_id;
655 irqreturn_t ret = IRQ_NONE;
659 ret = inno_hdmi_i2c_irq(hdmi);
661 interrupt = hdmi_readb(hdmi, HDMI_STATUS);
662 if (interrupt & m_INT_HOTPLUG) {
663 hdmi_modb(hdmi, HDMI_STATUS, m_INT_HOTPLUG, m_INT_HOTPLUG);
664 ret = IRQ_WAKE_THREAD;
670 static irqreturn_t inno_hdmi_irq(int irq, void *dev_id)
672 struct inno_hdmi *hdmi = dev_id;
674 drm_helper_hpd_irq_event(hdmi->connector.dev);
679 static int inno_hdmi_i2c_read(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
681 int length = msgs->len;
685 ret = wait_for_completion_timeout(&hdmi->i2c->cmp, HZ / 10);
690 *buf++ = hdmi_readb(hdmi, HDMI_EDID_FIFO_ADDR);
695 static int inno_hdmi_i2c_write(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
698 * The DDC module only support read EDID message, so
699 * we assume that each word write to this i2c adapter
700 * should be the offset of EDID word address.
702 if ((msgs->len != 1) ||
703 ((msgs->addr != DDC_ADDR) && (msgs->addr != DDC_SEGMENT_ADDR)))
706 reinit_completion(&hdmi->i2c->cmp);
708 if (msgs->addr == DDC_SEGMENT_ADDR)
709 hdmi->i2c->segment_addr = msgs->buf[0];
710 if (msgs->addr == DDC_ADDR)
711 hdmi->i2c->ddc_addr = msgs->buf[0];
713 /* Set edid fifo first addr */
714 hdmi_writeb(hdmi, HDMI_EDID_FIFO_OFFSET, 0x00);
716 /* Set edid word address 0x00/0x80 */
717 hdmi_writeb(hdmi, HDMI_EDID_WORD_ADDR, hdmi->i2c->ddc_addr);
719 /* Set edid segment pointer */
720 hdmi_writeb(hdmi, HDMI_EDID_SEGMENT_POINTER, hdmi->i2c->segment_addr);
725 static int inno_hdmi_i2c_xfer(struct i2c_adapter *adap,
726 struct i2c_msg *msgs, int num)
728 struct inno_hdmi *hdmi = i2c_get_adapdata(adap);
729 struct inno_hdmi_i2c *i2c = hdmi->i2c;
732 mutex_lock(&i2c->lock);
734 /* Clear the EDID interrupt flag and unmute the interrupt */
735 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, m_INT_EDID_READY);
736 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
738 for (i = 0; i < num; i++) {
739 DRM_DEV_DEBUG(hdmi->dev,
740 "xfer: num: %d/%d, len: %d, flags: %#x\n",
741 i + 1, num, msgs[i].len, msgs[i].flags);
743 if (msgs[i].flags & I2C_M_RD)
744 ret = inno_hdmi_i2c_read(hdmi, &msgs[i]);
746 ret = inno_hdmi_i2c_write(hdmi, &msgs[i]);
755 /* Mute HDMI EDID interrupt */
756 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
758 mutex_unlock(&i2c->lock);
763 static u32 inno_hdmi_i2c_func(struct i2c_adapter *adapter)
765 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
768 static const struct i2c_algorithm inno_hdmi_algorithm = {
769 .master_xfer = inno_hdmi_i2c_xfer,
770 .functionality = inno_hdmi_i2c_func,
773 static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
775 struct i2c_adapter *adap;
776 struct inno_hdmi_i2c *i2c;
779 i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
781 return ERR_PTR(-ENOMEM);
783 mutex_init(&i2c->lock);
784 init_completion(&i2c->cmp);
787 adap->class = I2C_CLASS_DDC;
788 adap->owner = THIS_MODULE;
789 adap->dev.parent = hdmi->dev;
790 adap->dev.of_node = hdmi->dev->of_node;
791 adap->algo = &inno_hdmi_algorithm;
792 strlcpy(adap->name, "Inno HDMI", sizeof(adap->name));
793 i2c_set_adapdata(adap, hdmi);
795 ret = i2c_add_adapter(adap);
797 dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
798 devm_kfree(hdmi->dev, i2c);
804 DRM_DEV_INFO(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
809 static int inno_hdmi_bind(struct device *dev, struct device *master,
812 struct platform_device *pdev = to_platform_device(dev);
813 struct drm_device *drm = data;
814 struct inno_hdmi *hdmi;
815 struct resource *iores;
819 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
826 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
827 hdmi->regs = devm_ioremap_resource(dev, iores);
828 if (IS_ERR(hdmi->regs))
829 return PTR_ERR(hdmi->regs);
831 hdmi->pclk = devm_clk_get(hdmi->dev, "pclk");
832 if (IS_ERR(hdmi->pclk)) {
833 DRM_DEV_ERROR(hdmi->dev, "Unable to get HDMI pclk clk\n");
834 return PTR_ERR(hdmi->pclk);
837 ret = clk_prepare_enable(hdmi->pclk);
839 DRM_DEV_ERROR(hdmi->dev,
840 "Cannot enable HDMI pclk clock: %d\n", ret);
844 irq = platform_get_irq(pdev, 0);
847 goto err_disable_clk;
850 inno_hdmi_reset(hdmi);
852 hdmi->ddc = inno_hdmi_i2c_adapter(hdmi);
853 if (IS_ERR(hdmi->ddc)) {
854 ret = PTR_ERR(hdmi->ddc);
856 goto err_disable_clk;
860 * When IP controller haven't configured to an accurate video
861 * timing, then the TMDS clock source would be switched to
862 * PCLK_HDMI, so we need to init the TMDS rate to PCLK rate,
863 * and reconfigure the DDC clock.
865 hdmi->tmds_rate = clk_get_rate(hdmi->pclk);
866 inno_hdmi_i2c_init(hdmi);
868 ret = inno_hdmi_register(drm, hdmi);
870 goto err_put_adapter;
872 dev_set_drvdata(dev, hdmi);
874 /* Unmute hotplug interrupt */
875 hdmi_modb(hdmi, HDMI_STATUS, m_MASK_INT_HOTPLUG, v_MASK_INT_HOTPLUG(1));
877 ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq,
878 inno_hdmi_irq, IRQF_SHARED,
879 dev_name(dev), hdmi);
881 goto err_cleanup_hdmi;
885 hdmi->connector.funcs->destroy(&hdmi->connector);
886 hdmi->encoder.funcs->destroy(&hdmi->encoder);
888 i2c_put_adapter(hdmi->ddc);
890 clk_disable_unprepare(hdmi->pclk);
894 static void inno_hdmi_unbind(struct device *dev, struct device *master,
897 struct inno_hdmi *hdmi = dev_get_drvdata(dev);
899 hdmi->connector.funcs->destroy(&hdmi->connector);
900 hdmi->encoder.funcs->destroy(&hdmi->encoder);
902 i2c_put_adapter(hdmi->ddc);
903 clk_disable_unprepare(hdmi->pclk);
906 static const struct component_ops inno_hdmi_ops = {
907 .bind = inno_hdmi_bind,
908 .unbind = inno_hdmi_unbind,
911 static int inno_hdmi_probe(struct platform_device *pdev)
913 return component_add(&pdev->dev, &inno_hdmi_ops);
916 static int inno_hdmi_remove(struct platform_device *pdev)
918 component_del(&pdev->dev, &inno_hdmi_ops);
923 static const struct of_device_id inno_hdmi_dt_ids[] = {
924 { .compatible = "rockchip,rk3036-inno-hdmi",
928 MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids);
930 struct platform_driver inno_hdmi_driver = {
931 .probe = inno_hdmi_probe,
932 .remove = inno_hdmi_remove,
934 .name = "innohdmi-rockchip",
935 .of_match_table = inno_hdmi_dt_ids,