drm/msm/hdmi: Enable HPD after HDMI IRQ is set up
[linux/fpc-iii.git] / drivers / gpu / drm / rockchip / inno_hdmi.c
blob1c02b3e61299c800549519a9f065ac2691f665fc
1 /*
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>
27 #include <drm/drmP.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 {
40 int vic;
41 bool sink_is_hdmi;
42 bool sink_has_audio;
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;
51 u8 ddc_addr;
52 u8 segment_addr;
54 struct mutex lock;
55 struct completion cmp;
58 struct inno_hdmi {
59 struct device *dev;
60 struct drm_device *drm_dev;
62 int irq;
63 struct clk *pclk;
64 void __iomem *regs;
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;
78 enum {
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,
168 u32 msk, u32 val)
170 u8 temp = hdmi_readb(hdmi, offset) & ~msk;
172 temp |= val & msk;
173 hdmi_writeb(hdmi, offset, temp);
176 static void inno_hdmi_i2c_init(struct inno_hdmi *hdmi)
178 int ddc_bus_freq;
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)
192 if (enable)
193 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_ON);
194 else
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)
200 switch (mode) {
201 case NORMAL:
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);
215 break;
217 case LOWER_PWR:
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);
224 break;
226 default:
227 DRM_DEV_ERROR(hdmi->dev, "Unknown power mode %d\n", mode);
231 static void inno_hdmi_reset(struct inno_hdmi *hdmi)
233 u32 val;
234 u32 msk;
236 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL);
237 udelay(100);
239 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG);
240 udelay(100);
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)
253 if (mask)
254 hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, disable);
256 hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, frame_index);
258 if (setup_rc >= 0) {
259 u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE];
260 ssize_t rc, i;
262 rc = hdmi_infoframe_pack(frame, packed_frame,
263 sizeof(packed_frame));
264 if (rc < 0)
265 return rc;
267 for (i = 0; i < rc; i++)
268 hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i,
269 packed_frame[i]);
271 if (mask)
272 hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, enable);
275 return setup_rc;
278 static int inno_hdmi_config_video_vsi(struct inno_hdmi *hdmi,
279 struct drm_display_mode *mode)
281 union hdmi_infoframe frame;
282 int rc;
284 rc = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
285 &hdmi->connector,
286 mode);
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;
296 int rc;
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;
304 else
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;
314 int csc_enable = 0;
315 int csc_mode = 0;
316 int auto_csc = 0;
317 int value;
318 int i;
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));
340 return 0;
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;
358 } else {
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));
384 return 0;
387 static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
388 struct drm_display_mode *mode)
390 int value;
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);
436 return 0;
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;
452 else
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));
459 /* Set HDMI Mode */
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));
485 return 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)
518 return true;
521 static int
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;
531 return 0;
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);
558 struct edid *edid;
559 int ret = 0;
561 if (!hdmi->ddc)
562 return 0;
564 edid = drm_get_edid(connector, hdmi->ddc);
565 if (edid) {
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);
570 kfree(edid);
573 return ret;
576 static enum drm_mode_status
577 inno_hdmi_connector_mode_valid(struct drm_connector *connector,
578 struct drm_display_mode *mode)
580 return MODE_OK;
583 static int
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);
639 return 0;
642 static irqreturn_t inno_hdmi_i2c_irq(struct inno_hdmi *hdmi)
644 struct inno_hdmi_i2c *i2c = hdmi->i2c;
645 u8 stat;
647 stat = hdmi_readb(hdmi, HDMI_INTERRUPT_STATUS1);
648 if (!(stat & m_INT_EDID_READY))
649 return IRQ_NONE;
651 /* Clear HDMI EDID interrupt flag */
652 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
654 complete(&i2c->cmp);
656 return IRQ_HANDLED;
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;
663 u8 interrupt;
665 if (hdmi->i2c)
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;
674 return ret;
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);
683 return IRQ_HANDLED;
686 static int inno_hdmi_i2c_read(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
688 int length = msgs->len;
689 u8 *buf = msgs->buf;
690 int ret;
692 ret = wait_for_completion_timeout(&hdmi->i2c->cmp, HZ / 10);
693 if (!ret)
694 return -EAGAIN;
696 while (length--)
697 *buf++ = hdmi_readb(hdmi, HDMI_EDID_FIFO_ADDR);
699 return 0;
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)))
711 return -EINVAL;
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);
729 return 0;
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;
737 int i, ret = 0;
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]);
752 else
753 ret = inno_hdmi_i2c_write(hdmi, &msgs[i]);
755 if (ret < 0)
756 break;
759 if (!ret)
760 ret = num;
762 /* Mute HDMI EDID interrupt */
763 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
765 mutex_unlock(&i2c->lock);
767 return ret;
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;
784 int ret;
786 i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
787 if (!i2c)
788 return ERR_PTR(-ENOMEM);
790 mutex_init(&i2c->lock);
791 init_completion(&i2c->cmp);
793 adap = &i2c->adap;
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);
803 if (ret) {
804 dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
805 devm_kfree(hdmi->dev, i2c);
806 return ERR_PTR(ret);
809 hdmi->i2c = i2c;
811 DRM_DEV_INFO(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
813 return adap;
816 static int inno_hdmi_bind(struct device *dev, struct device *master,
817 void *data)
819 struct platform_device *pdev = to_platform_device(dev);
820 struct drm_device *drm = data;
821 struct inno_hdmi *hdmi;
822 struct resource *iores;
823 int irq;
824 int ret;
826 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
827 if (!hdmi)
828 return -ENOMEM;
830 hdmi->dev = dev;
831 hdmi->drm_dev = drm;
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);
845 if (ret) {
846 DRM_DEV_ERROR(hdmi->dev,
847 "Cannot enable HDMI pclk clock: %d\n", ret);
848 return ret;
851 irq = platform_get_irq(pdev, 0);
852 if (irq < 0) {
853 ret = irq;
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);
862 hdmi->ddc = NULL;
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);
876 if (ret)
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);
887 if (ret < 0)
888 goto err_cleanup_hdmi;
890 return 0;
891 err_cleanup_hdmi:
892 hdmi->connector.funcs->destroy(&hdmi->connector);
893 hdmi->encoder.funcs->destroy(&hdmi->encoder);
894 err_put_adapter:
895 i2c_put_adapter(hdmi->ddc);
896 err_disable_clk:
897 clk_disable_unprepare(hdmi->pclk);
898 return ret;
901 static void inno_hdmi_unbind(struct device *dev, struct device *master,
902 void *data)
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);
927 return 0;
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,
940 .driver = {
941 .name = "innohdmi-rockchip",
942 .of_match_table = inno_hdmi_dt_ids,