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/mod_devicetable.h>
14 #include <linux/module.h>
15 #include <linux/mutex.h>
16 #include <linux/platform_device.h>
18 #include <drm/drm_atomic.h>
19 #include <drm/drm_atomic_helper.h>
20 #include <drm/drm_edid.h>
21 #include <drm/drm_of.h>
22 #include <drm/drm_probe_helper.h>
23 #include <drm/drm_simple_kms_helper.h>
25 #include <drm/display/drm_hdmi_helper.h>
26 #include <drm/display/drm_hdmi_state_helper.h>
28 #include "rockchip_drm_drv.h"
30 #include "inno_hdmi.h"
32 #define INNO_HDMI_MIN_TMDS_CLOCK 25000000U
34 struct inno_hdmi_phy_config {
35 unsigned long pixelclock;
37 u8 voltage_level_control;
40 struct inno_hdmi_variant {
41 struct inno_hdmi_phy_config *phy_configs;
42 struct inno_hdmi_phy_config *default_phy_config;
45 struct inno_hdmi_i2c {
46 struct i2c_adapter adap;
52 struct completion cmp;
62 struct drm_connector connector;
63 struct rockchip_encoder encoder;
65 struct inno_hdmi_i2c *i2c;
66 struct i2c_adapter *ddc;
68 const struct inno_hdmi_variant *variant;
71 struct inno_hdmi_connector_state {
72 struct drm_connector_state base;
73 unsigned int colorimetry;
76 static struct inno_hdmi *encoder_to_inno_hdmi(struct drm_encoder *encoder)
78 struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
80 return container_of(rkencoder, struct inno_hdmi, encoder);
83 static struct inno_hdmi *connector_to_inno_hdmi(struct drm_connector *connector)
85 return container_of(connector, struct inno_hdmi, connector);
88 #define to_inno_hdmi_conn_state(conn_state) \
89 container_of_const(conn_state, struct inno_hdmi_connector_state, base)
92 CSC_RGB_0_255_TO_ITU601_16_235_8BIT,
93 CSC_RGB_0_255_TO_ITU709_16_235_8BIT,
94 CSC_RGB_0_255_TO_RGB_16_235_8BIT,
97 static const char coeff_csc[][24] = {
99 * RGB2YUV:601 SD mode:
100 * Cb = -0.291G - 0.148R + 0.439B + 128
101 * Y = 0.504G + 0.257R + 0.098B + 16
102 * Cr = -0.368G + 0.439R - 0.071B + 128
105 0x11, 0x5f, 0x01, 0x82, 0x10, 0x23, 0x00, 0x80,
106 0x02, 0x1c, 0x00, 0xa1, 0x00, 0x36, 0x00, 0x1e,
107 0x11, 0x29, 0x10, 0x59, 0x01, 0x82, 0x00, 0x80
110 * RGB2YUV:709 HD mode:
111 * Cb = - 0.338G - 0.101R + 0.439B + 128
112 * Y = 0.614G + 0.183R + 0.062B + 16
113 * Cr = - 0.399G + 0.439R - 0.040B + 128
116 0x11, 0x98, 0x01, 0xc1, 0x10, 0x28, 0x00, 0x80,
117 0x02, 0x74, 0x00, 0xbb, 0x00, 0x3f, 0x00, 0x10,
118 0x11, 0x5a, 0x10, 0x67, 0x01, 0xc1, 0x00, 0x80
121 * RGB[0:255]2RGB[16:235]:
122 * R' = R x (235-16)/255 + 16;
123 * G' = G x (235-16)/255 + 16;
124 * B' = B x (235-16)/255 + 16;
127 0x00, 0x00, 0x03, 0x6F, 0x00, 0x00, 0x00, 0x10,
128 0x03, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
129 0x00, 0x00, 0x00, 0x00, 0x03, 0x6F, 0x00, 0x10
133 static struct inno_hdmi_phy_config rk3036_hdmi_phy_configs[] = {
134 { 74250000, 0x3f, 0xbb },
135 { 165000000, 0x6f, 0xbb },
139 static struct inno_hdmi_phy_config rk3128_hdmi_phy_configs[] = {
140 { 74250000, 0x3f, 0xaa },
141 { 165000000, 0x5f, 0xaa },
145 static int inno_hdmi_find_phy_config(struct inno_hdmi *hdmi,
146 unsigned long pixelclk)
148 const struct inno_hdmi_phy_config *phy_configs =
149 hdmi->variant->phy_configs;
152 for (i = 0; phy_configs[i].pixelclock != ~0UL; i++) {
153 if (pixelclk <= phy_configs[i].pixelclock)
157 DRM_DEV_DEBUG(hdmi->dev, "No phy configuration for pixelclock %lu\n",
163 static inline u8 hdmi_readb(struct inno_hdmi *hdmi, u16 offset)
165 return readl_relaxed(hdmi->regs + (offset) * 0x04);
168 static inline void hdmi_writeb(struct inno_hdmi *hdmi, u16 offset, u32 val)
170 writel_relaxed(val, hdmi->regs + (offset) * 0x04);
173 static inline void hdmi_modb(struct inno_hdmi *hdmi, u16 offset,
176 u8 temp = hdmi_readb(hdmi, offset) & ~msk;
179 hdmi_writeb(hdmi, offset, temp);
182 static void inno_hdmi_i2c_init(struct inno_hdmi *hdmi, unsigned long long rate)
184 unsigned long long ddc_bus_freq = rate >> 2;
186 do_div(ddc_bus_freq, HDMI_SCL_RATE);
188 hdmi_writeb(hdmi, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
189 hdmi_writeb(hdmi, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
191 /* Clear the EDID interrupt flag and mute the interrupt */
192 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
193 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
196 static void inno_hdmi_sys_power(struct inno_hdmi *hdmi, bool enable)
199 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_ON);
201 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_OFF);
204 static void inno_hdmi_standby(struct inno_hdmi *hdmi)
206 inno_hdmi_sys_power(hdmi, false);
208 hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0x00);
209 hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x00);
210 hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x00);
211 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
214 static void inno_hdmi_power_up(struct inno_hdmi *hdmi,
215 unsigned long mpixelclock)
217 struct inno_hdmi_phy_config *phy_config;
218 int ret = inno_hdmi_find_phy_config(hdmi, mpixelclock);
221 phy_config = hdmi->variant->default_phy_config;
222 DRM_DEV_ERROR(hdmi->dev,
223 "Using default phy configuration for TMDS rate %lu",
226 phy_config = &hdmi->variant->phy_configs[ret];
229 inno_hdmi_sys_power(hdmi, false);
231 hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, phy_config->pre_emphasis);
232 hdmi_writeb(hdmi, HDMI_PHY_DRIVER, phy_config->voltage_level_control);
233 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
234 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x14);
235 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x10);
236 hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x0f);
237 hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x00);
238 hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x01);
240 inno_hdmi_sys_power(hdmi, true);
243 static void inno_hdmi_reset(struct inno_hdmi *hdmi)
248 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL);
251 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG);
254 msk = m_REG_CLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL;
255 val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH;
256 hdmi_modb(hdmi, HDMI_SYS_CTRL, msk, val);
258 inno_hdmi_standby(hdmi);
261 static int inno_hdmi_disable_frame(struct drm_connector *connector,
262 enum hdmi_infoframe_type type)
264 struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector);
266 if (type != HDMI_INFOFRAME_TYPE_AVI) {
267 drm_err(connector->dev,
268 "Unsupported infoframe type: %u\n", type);
272 hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
277 static int inno_hdmi_upload_frame(struct drm_connector *connector,
278 enum hdmi_infoframe_type type,
279 const u8 *buffer, size_t len)
281 struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector);
284 if (type != HDMI_INFOFRAME_TYPE_AVI) {
285 drm_err(connector->dev,
286 "Unsupported infoframe type: %u\n", type);
290 inno_hdmi_disable_frame(connector, type);
292 for (i = 0; i < len; i++)
293 hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i, buffer[i]);
298 static const struct drm_connector_hdmi_funcs inno_hdmi_hdmi_connector_funcs = {
299 .clear_infoframe = inno_hdmi_disable_frame,
300 .write_infoframe = inno_hdmi_upload_frame,
303 static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi)
305 struct drm_connector *connector = &hdmi->connector;
306 struct drm_connector_state *conn_state = connector->state;
307 struct inno_hdmi_connector_state *inno_conn_state =
308 to_inno_hdmi_conn_state(conn_state);
309 int c0_c2_change = 0;
316 /* Input video mode is SDR RGB24bit, data enable signal from external */
317 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL1, v_DE_EXTERNAL |
318 v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444));
320 /* Input color hardcode to RGB, and output color hardcode to RGB888 */
321 value = v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS) |
322 v_VIDEO_OUTPUT_COLOR(0) |
323 v_VIDEO_INPUT_CSP(0);
324 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value);
326 if (conn_state->hdmi.output_format == HDMI_COLORSPACE_RGB) {
327 if (conn_state->hdmi.is_limited_range) {
328 csc_mode = CSC_RGB_0_255_TO_RGB_16_235_8BIT;
329 auto_csc = AUTO_CSC_DISABLE;
330 c0_c2_change = C0_C2_CHANGE_DISABLE;
331 csc_enable = v_CSC_ENABLE;
334 value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1);
335 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
337 hdmi_modb(hdmi, HDMI_VIDEO_CONTRL,
338 m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_SWAP,
339 v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) |
340 v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE));
344 if (inno_conn_state->colorimetry == HDMI_COLORIMETRY_ITU_601) {
345 if (conn_state->hdmi.output_format == HDMI_COLORSPACE_YUV444) {
346 csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
347 auto_csc = AUTO_CSC_DISABLE;
348 c0_c2_change = C0_C2_CHANGE_DISABLE;
349 csc_enable = v_CSC_ENABLE;
352 if (conn_state->hdmi.output_format == HDMI_COLORSPACE_YUV444) {
353 csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
354 auto_csc = AUTO_CSC_DISABLE;
355 c0_c2_change = C0_C2_CHANGE_DISABLE;
356 csc_enable = v_CSC_ENABLE;
361 for (i = 0; i < 24; i++)
362 hdmi_writeb(hdmi, HDMI_VIDEO_CSC_COEF + i,
363 coeff_csc[csc_mode][i]);
365 value = v_SOF_DISABLE | csc_enable | v_COLOR_DEPTH_NOT_INDICATED(1);
366 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
367 hdmi_modb(hdmi, HDMI_VIDEO_CONTRL, m_VIDEO_AUTO_CSC |
368 m_VIDEO_C0_C2_SWAP, v_VIDEO_AUTO_CSC(auto_csc) |
369 v_VIDEO_C0_C2_SWAP(c0_c2_change));
374 static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
375 struct drm_display_mode *mode)
379 /* Set detail external video timing polarity and interlace mode */
380 value = v_EXTERANL_VIDEO(1);
381 value |= mode->flags & DRM_MODE_FLAG_PHSYNC ?
382 v_HSYNC_POLARITY(1) : v_HSYNC_POLARITY(0);
383 value |= mode->flags & DRM_MODE_FLAG_PVSYNC ?
384 v_VSYNC_POLARITY(1) : v_VSYNC_POLARITY(0);
385 value |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
386 v_INETLACE(1) : v_INETLACE(0);
387 hdmi_writeb(hdmi, HDMI_VIDEO_TIMING_CTL, value);
389 /* Set detail external video timing */
390 value = mode->htotal;
391 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_L, value & 0xFF);
392 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
394 value = mode->htotal - mode->hdisplay;
395 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_L, value & 0xFF);
396 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
398 value = mode->htotal - mode->hsync_start;
399 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_L, value & 0xFF);
400 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
402 value = mode->hsync_end - mode->hsync_start;
403 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_L, value & 0xFF);
404 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF);
406 value = mode->vtotal;
407 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_L, value & 0xFF);
408 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
410 value = mode->vtotal - mode->vdisplay;
411 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VBLANK, value & 0xFF);
413 value = mode->vtotal - mode->vsync_start;
414 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDELAY, value & 0xFF);
416 value = mode->vsync_end - mode->vsync_start;
417 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDURATION, value & 0xFF);
419 hdmi_writeb(hdmi, HDMI_PHY_PRE_DIV_RATIO, 0x1e);
420 hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_LOW, 0x2c);
421 hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_HIGH, 0x01);
426 static int inno_hdmi_setup(struct inno_hdmi *hdmi,
427 struct drm_atomic_state *state)
429 struct drm_connector *connector = &hdmi->connector;
430 struct drm_display_info *display = &connector->display_info;
431 struct drm_connector_state *new_conn_state;
432 struct drm_crtc_state *new_crtc_state;
434 new_conn_state = drm_atomic_get_new_connector_state(state, connector);
435 if (WARN_ON(!new_conn_state))
438 new_crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc);
439 if (WARN_ON(!new_crtc_state))
442 /* Mute video and audio output */
443 hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
444 v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
447 hdmi_writeb(hdmi, HDMI_HDCP_CTRL,
448 v_HDMI_DVI(display->is_hdmi));
450 inno_hdmi_config_video_timing(hdmi, &new_crtc_state->adjusted_mode);
452 inno_hdmi_config_video_csc(hdmi);
454 drm_atomic_helper_connector_hdmi_update_infoframes(connector, state);
457 * When IP controller have configured to an accurate video
458 * timing, then the TMDS clock source would be switched to
459 * DCLK_LCDC, so we need to init the TMDS rate to mode pixel
460 * clock rate, and reconfigure the DDC clock.
462 inno_hdmi_i2c_init(hdmi, new_conn_state->hdmi.tmds_char_rate);
464 /* Unmute video and audio output */
465 hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
466 v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
468 inno_hdmi_power_up(hdmi, new_conn_state->hdmi.tmds_char_rate);
473 static enum drm_mode_status inno_hdmi_display_mode_valid(struct inno_hdmi *hdmi,
474 struct drm_display_mode *mode)
476 unsigned long mpixelclk, max_tolerance;
479 /* No support for double-clock modes */
480 if (mode->flags & DRM_MODE_FLAG_DBLCLK)
483 mpixelclk = mode->clock * 1000;
485 if (mpixelclk < INNO_HDMI_MIN_TMDS_CLOCK)
486 return MODE_CLOCK_LOW;
488 if (inno_hdmi_find_phy_config(hdmi, mpixelclk) < 0)
489 return MODE_CLOCK_HIGH;
492 rounded_refclk = clk_round_rate(hdmi->refclk, mpixelclk);
493 if (rounded_refclk < 0)
496 /* Vesa DMT standard mentions +/- 0.5% max tolerance */
497 max_tolerance = mpixelclk / 200;
498 if (abs_diff((unsigned long)rounded_refclk, mpixelclk) > max_tolerance)
505 static void inno_hdmi_encoder_enable(struct drm_encoder *encoder,
506 struct drm_atomic_state *state)
508 struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder);
510 inno_hdmi_setup(hdmi, state);
513 static void inno_hdmi_encoder_disable(struct drm_encoder *encoder,
514 struct drm_atomic_state *state)
516 struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder);
518 inno_hdmi_standby(hdmi);
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);
527 struct drm_display_mode *mode = &crtc_state->adjusted_mode;
528 u8 vic = drm_match_cea_mode(mode);
529 struct inno_hdmi_connector_state *inno_conn_state =
530 to_inno_hdmi_conn_state(conn_state);
532 s->output_mode = ROCKCHIP_OUT_MODE_P888;
533 s->output_type = DRM_MODE_CONNECTOR_HDMIA;
535 if (vic == 6 || vic == 7 ||
536 vic == 21 || vic == 22 ||
537 vic == 2 || vic == 3 ||
538 vic == 17 || vic == 18)
539 inno_conn_state->colorimetry = HDMI_COLORIMETRY_ITU_601;
541 inno_conn_state->colorimetry = HDMI_COLORIMETRY_ITU_709;
546 static const struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = {
547 .atomic_check = inno_hdmi_encoder_atomic_check,
548 .atomic_enable = inno_hdmi_encoder_enable,
549 .atomic_disable = inno_hdmi_encoder_disable,
552 static enum drm_connector_status
553 inno_hdmi_connector_detect(struct drm_connector *connector, bool force)
555 struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector);
557 return (hdmi_readb(hdmi, HDMI_STATUS) & m_HOTPLUG) ?
558 connector_status_connected : connector_status_disconnected;
561 static int inno_hdmi_connector_get_modes(struct drm_connector *connector)
563 struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector);
564 const struct drm_edid *drm_edid;
570 drm_edid = drm_edid_read_ddc(connector, hdmi->ddc);
571 drm_edid_connector_update(connector, drm_edid);
572 ret = drm_edid_connector_add_modes(connector);
573 drm_edid_free(drm_edid);
578 static enum drm_mode_status
579 inno_hdmi_connector_mode_valid(struct drm_connector *connector,
580 struct drm_display_mode *mode)
582 struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector);
584 return inno_hdmi_display_mode_valid(hdmi, mode);
588 inno_hdmi_connector_destroy_state(struct drm_connector *connector,
589 struct drm_connector_state *state)
591 struct inno_hdmi_connector_state *inno_conn_state =
592 to_inno_hdmi_conn_state(state);
594 __drm_atomic_helper_connector_destroy_state(&inno_conn_state->base);
595 kfree(inno_conn_state);
598 static void inno_hdmi_connector_reset(struct drm_connector *connector)
600 struct inno_hdmi_connector_state *inno_conn_state;
602 if (connector->state) {
603 inno_hdmi_connector_destroy_state(connector, connector->state);
604 connector->state = NULL;
607 inno_conn_state = kzalloc(sizeof(*inno_conn_state), GFP_KERNEL);
608 if (!inno_conn_state)
611 __drm_atomic_helper_connector_reset(connector, &inno_conn_state->base);
612 __drm_atomic_helper_connector_hdmi_reset(connector, connector->state);
614 inno_conn_state->colorimetry = HDMI_COLORIMETRY_ITU_709;
617 static struct drm_connector_state *
618 inno_hdmi_connector_duplicate_state(struct drm_connector *connector)
620 struct inno_hdmi_connector_state *inno_conn_state;
622 if (WARN_ON(!connector->state))
625 inno_conn_state = kmemdup(to_inno_hdmi_conn_state(connector->state),
626 sizeof(*inno_conn_state), GFP_KERNEL);
628 if (!inno_conn_state)
631 __drm_atomic_helper_connector_duplicate_state(connector,
632 &inno_conn_state->base);
634 return &inno_conn_state->base;
637 static const struct drm_connector_funcs inno_hdmi_connector_funcs = {
638 .fill_modes = drm_helper_probe_single_connector_modes,
639 .detect = inno_hdmi_connector_detect,
640 .reset = inno_hdmi_connector_reset,
641 .atomic_duplicate_state = inno_hdmi_connector_duplicate_state,
642 .atomic_destroy_state = inno_hdmi_connector_destroy_state,
645 static struct drm_connector_helper_funcs inno_hdmi_connector_helper_funcs = {
646 .atomic_check = drm_atomic_helper_connector_hdmi_check,
647 .get_modes = inno_hdmi_connector_get_modes,
648 .mode_valid = inno_hdmi_connector_mode_valid,
651 static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi)
653 struct drm_encoder *encoder = &hdmi->encoder.encoder;
654 struct device *dev = hdmi->dev;
656 encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
659 * If we failed to find the CRTC(s) which this encoder is
660 * supposed to be connected to, it's because the CRTC has
661 * not been registered yet. Defer probing, and hope that
662 * the required CRTC is added later.
664 if (encoder->possible_crtcs == 0)
665 return -EPROBE_DEFER;
667 drm_encoder_helper_add(encoder, &inno_hdmi_encoder_helper_funcs);
668 drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
670 hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
672 drm_connector_helper_add(&hdmi->connector,
673 &inno_hdmi_connector_helper_funcs);
674 drmm_connector_hdmi_init(drm, &hdmi->connector,
675 "Rockchip", "Inno HDMI",
676 &inno_hdmi_connector_funcs,
677 &inno_hdmi_hdmi_connector_funcs,
678 DRM_MODE_CONNECTOR_HDMIA,
680 BIT(HDMI_COLORSPACE_RGB),
683 drm_connector_attach_encoder(&hdmi->connector, encoder);
688 static irqreturn_t inno_hdmi_i2c_irq(struct inno_hdmi *hdmi)
690 struct inno_hdmi_i2c *i2c = hdmi->i2c;
693 stat = hdmi_readb(hdmi, HDMI_INTERRUPT_STATUS1);
694 if (!(stat & m_INT_EDID_READY))
697 /* Clear HDMI EDID interrupt flag */
698 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
705 static irqreturn_t inno_hdmi_hardirq(int irq, void *dev_id)
707 struct inno_hdmi *hdmi = dev_id;
708 irqreturn_t ret = IRQ_NONE;
712 ret = inno_hdmi_i2c_irq(hdmi);
714 interrupt = hdmi_readb(hdmi, HDMI_STATUS);
715 if (interrupt & m_INT_HOTPLUG) {
716 hdmi_modb(hdmi, HDMI_STATUS, m_INT_HOTPLUG, m_INT_HOTPLUG);
717 ret = IRQ_WAKE_THREAD;
723 static irqreturn_t inno_hdmi_irq(int irq, void *dev_id)
725 struct inno_hdmi *hdmi = dev_id;
727 drm_helper_hpd_irq_event(hdmi->connector.dev);
732 static int inno_hdmi_i2c_read(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
734 int length = msgs->len;
738 ret = wait_for_completion_timeout(&hdmi->i2c->cmp, HZ / 10);
743 *buf++ = hdmi_readb(hdmi, HDMI_EDID_FIFO_ADDR);
748 static int inno_hdmi_i2c_write(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
751 * The DDC module only support read EDID message, so
752 * we assume that each word write to this i2c adapter
753 * should be the offset of EDID word address.
755 if ((msgs->len != 1) ||
756 ((msgs->addr != DDC_ADDR) && (msgs->addr != DDC_SEGMENT_ADDR)))
759 reinit_completion(&hdmi->i2c->cmp);
761 if (msgs->addr == DDC_SEGMENT_ADDR)
762 hdmi->i2c->segment_addr = msgs->buf[0];
763 if (msgs->addr == DDC_ADDR)
764 hdmi->i2c->ddc_addr = msgs->buf[0];
766 /* Set edid fifo first addr */
767 hdmi_writeb(hdmi, HDMI_EDID_FIFO_OFFSET, 0x00);
769 /* Set edid word address 0x00/0x80 */
770 hdmi_writeb(hdmi, HDMI_EDID_WORD_ADDR, hdmi->i2c->ddc_addr);
772 /* Set edid segment pointer */
773 hdmi_writeb(hdmi, HDMI_EDID_SEGMENT_POINTER, hdmi->i2c->segment_addr);
778 static int inno_hdmi_i2c_xfer(struct i2c_adapter *adap,
779 struct i2c_msg *msgs, int num)
781 struct inno_hdmi *hdmi = i2c_get_adapdata(adap);
782 struct inno_hdmi_i2c *i2c = hdmi->i2c;
785 mutex_lock(&i2c->lock);
787 /* Clear the EDID interrupt flag and unmute the interrupt */
788 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, m_INT_EDID_READY);
789 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
791 for (i = 0; i < num; i++) {
792 DRM_DEV_DEBUG(hdmi->dev,
793 "xfer: num: %d/%d, len: %d, flags: %#x\n",
794 i + 1, num, msgs[i].len, msgs[i].flags);
796 if (msgs[i].flags & I2C_M_RD)
797 ret = inno_hdmi_i2c_read(hdmi, &msgs[i]);
799 ret = inno_hdmi_i2c_write(hdmi, &msgs[i]);
808 /* Mute HDMI EDID interrupt */
809 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
811 mutex_unlock(&i2c->lock);
816 static u32 inno_hdmi_i2c_func(struct i2c_adapter *adapter)
818 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
821 static const struct i2c_algorithm inno_hdmi_algorithm = {
822 .master_xfer = inno_hdmi_i2c_xfer,
823 .functionality = inno_hdmi_i2c_func,
826 static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
828 struct i2c_adapter *adap;
829 struct inno_hdmi_i2c *i2c;
832 i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
834 return ERR_PTR(-ENOMEM);
836 mutex_init(&i2c->lock);
837 init_completion(&i2c->cmp);
840 adap->owner = THIS_MODULE;
841 adap->dev.parent = hdmi->dev;
842 adap->dev.of_node = hdmi->dev->of_node;
843 adap->algo = &inno_hdmi_algorithm;
844 strscpy(adap->name, "Inno HDMI", sizeof(adap->name));
845 i2c_set_adapdata(adap, hdmi);
847 ret = i2c_add_adapter(adap);
849 dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
850 devm_kfree(hdmi->dev, i2c);
856 DRM_DEV_INFO(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
861 static int inno_hdmi_bind(struct device *dev, struct device *master,
864 struct platform_device *pdev = to_platform_device(dev);
865 struct drm_device *drm = data;
866 struct inno_hdmi *hdmi;
867 const struct inno_hdmi_variant *variant;
871 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
877 variant = of_device_get_match_data(hdmi->dev);
881 hdmi->variant = variant;
883 hdmi->regs = devm_platform_ioremap_resource(pdev, 0);
884 if (IS_ERR(hdmi->regs))
885 return PTR_ERR(hdmi->regs);
887 hdmi->pclk = devm_clk_get(hdmi->dev, "pclk");
888 if (IS_ERR(hdmi->pclk)) {
889 DRM_DEV_ERROR(hdmi->dev, "Unable to get HDMI pclk clk\n");
890 return PTR_ERR(hdmi->pclk);
893 ret = clk_prepare_enable(hdmi->pclk);
895 DRM_DEV_ERROR(hdmi->dev,
896 "Cannot enable HDMI pclk clock: %d\n", ret);
900 hdmi->refclk = devm_clk_get_optional(hdmi->dev, "ref");
901 if (IS_ERR(hdmi->refclk)) {
902 DRM_DEV_ERROR(hdmi->dev, "Unable to get HDMI reference clock\n");
903 ret = PTR_ERR(hdmi->refclk);
904 goto err_disable_pclk;
907 ret = clk_prepare_enable(hdmi->refclk);
909 DRM_DEV_ERROR(hdmi->dev,
910 "Cannot enable HDMI reference clock: %d\n", ret);
911 goto err_disable_pclk;
914 irq = platform_get_irq(pdev, 0);
917 goto err_disable_clk;
920 inno_hdmi_reset(hdmi);
922 hdmi->ddc = inno_hdmi_i2c_adapter(hdmi);
923 if (IS_ERR(hdmi->ddc)) {
924 ret = PTR_ERR(hdmi->ddc);
926 goto err_disable_clk;
930 * When the controller isn't configured to an accurate
931 * video timing and there is no reference clock available,
932 * then the TMDS clock source would be switched to PCLK_HDMI,
933 * so we need to init the TMDS rate to PCLK rate, and
934 * reconfigure the DDC clock.
937 inno_hdmi_i2c_init(hdmi, clk_get_rate(hdmi->refclk));
939 inno_hdmi_i2c_init(hdmi, clk_get_rate(hdmi->pclk));
941 ret = inno_hdmi_register(drm, hdmi);
943 goto err_put_adapter;
945 dev_set_drvdata(dev, hdmi);
947 /* Unmute hotplug interrupt */
948 hdmi_modb(hdmi, HDMI_STATUS, m_MASK_INT_HOTPLUG, v_MASK_INT_HOTPLUG(1));
950 ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq,
951 inno_hdmi_irq, IRQF_SHARED,
952 dev_name(dev), hdmi);
954 goto err_cleanup_hdmi;
958 hdmi->connector.funcs->destroy(&hdmi->connector);
959 hdmi->encoder.encoder.funcs->destroy(&hdmi->encoder.encoder);
961 i2c_put_adapter(hdmi->ddc);
963 clk_disable_unprepare(hdmi->refclk);
965 clk_disable_unprepare(hdmi->pclk);
969 static void inno_hdmi_unbind(struct device *dev, struct device *master,
972 struct inno_hdmi *hdmi = dev_get_drvdata(dev);
974 hdmi->connector.funcs->destroy(&hdmi->connector);
975 hdmi->encoder.encoder.funcs->destroy(&hdmi->encoder.encoder);
977 i2c_put_adapter(hdmi->ddc);
978 clk_disable_unprepare(hdmi->refclk);
979 clk_disable_unprepare(hdmi->pclk);
982 static const struct component_ops inno_hdmi_ops = {
983 .bind = inno_hdmi_bind,
984 .unbind = inno_hdmi_unbind,
987 static int inno_hdmi_probe(struct platform_device *pdev)
989 return component_add(&pdev->dev, &inno_hdmi_ops);
992 static void inno_hdmi_remove(struct platform_device *pdev)
994 component_del(&pdev->dev, &inno_hdmi_ops);
997 static const struct inno_hdmi_variant rk3036_inno_hdmi_variant = {
998 .phy_configs = rk3036_hdmi_phy_configs,
999 .default_phy_config = &rk3036_hdmi_phy_configs[1],
1002 static const struct inno_hdmi_variant rk3128_inno_hdmi_variant = {
1003 .phy_configs = rk3128_hdmi_phy_configs,
1004 .default_phy_config = &rk3128_hdmi_phy_configs[1],
1007 static const struct of_device_id inno_hdmi_dt_ids[] = {
1008 { .compatible = "rockchip,rk3036-inno-hdmi",
1009 .data = &rk3036_inno_hdmi_variant,
1011 { .compatible = "rockchip,rk3128-inno-hdmi",
1012 .data = &rk3128_inno_hdmi_variant,
1016 MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids);
1018 struct platform_driver inno_hdmi_driver = {
1019 .probe = inno_hdmi_probe,
1020 .remove = inno_hdmi_remove,
1022 .name = "innohdmi-rockchip",
1023 .of_match_table = inno_hdmi_dt_ids,