treewide: remove redundant IS_ERR() before error code check
[linux/fpc-iii.git] / drivers / gpu / drm / rockchip / inno_hdmi.c
blobe5864e8230205f9a014d80bc8d235a5ca89f4794
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
4 * Zheng Yang <zhengyang@rock-chips.com>
5 * Yakir Yang <ykk@rock-chips.com>
6 */
8 #include <linux/irq.h>
9 #include <linux/clk.h>
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 {
31 int vic;
32 bool sink_is_hdmi;
33 bool sink_has_audio;
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;
42 u8 ddc_addr;
43 u8 segment_addr;
45 struct mutex lock;
46 struct completion cmp;
49 struct inno_hdmi {
50 struct device *dev;
51 struct drm_device *drm_dev;
53 int irq;
54 struct clk *pclk;
55 void __iomem *regs;
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;
69 enum {
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,
159 u32 msk, u32 val)
161 u8 temp = hdmi_readb(hdmi, offset) & ~msk;
163 temp |= val & msk;
164 hdmi_writeb(hdmi, offset, temp);
167 static void inno_hdmi_i2c_init(struct inno_hdmi *hdmi)
169 int ddc_bus_freq;
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)
183 if (enable)
184 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_ON);
185 else
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)
191 switch (mode) {
192 case NORMAL:
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);
206 break;
208 case LOWER_PWR:
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);
215 break;
217 default:
218 DRM_DEV_ERROR(hdmi->dev, "Unknown power mode %d\n", mode);
222 static void inno_hdmi_reset(struct inno_hdmi *hdmi)
224 u32 val;
225 u32 msk;
227 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL);
228 udelay(100);
230 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG);
231 udelay(100);
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)
244 if (mask)
245 hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, disable);
247 hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, frame_index);
249 if (setup_rc >= 0) {
250 u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE];
251 ssize_t rc, i;
253 rc = hdmi_infoframe_pack(frame, packed_frame,
254 sizeof(packed_frame));
255 if (rc < 0)
256 return rc;
258 for (i = 0; i < rc; i++)
259 hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i,
260 packed_frame[i]);
262 if (mask)
263 hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, enable);
266 return setup_rc;
269 static int inno_hdmi_config_video_vsi(struct inno_hdmi *hdmi,
270 struct drm_display_mode *mode)
272 union hdmi_infoframe frame;
273 int rc;
275 rc = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
276 &hdmi->connector,
277 mode);
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;
287 int rc;
289 rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
290 &hdmi->connector,
291 mode);
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;
297 else
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;
307 int csc_enable = 0;
308 int csc_mode = 0;
309 int auto_csc = 0;
310 int value;
311 int i;
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));
333 return 0;
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;
351 } else {
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));
377 return 0;
380 static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
381 struct drm_display_mode *mode)
383 int value;
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);
429 return 0;
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;
445 else
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));
452 /* Set HDMI Mode */
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));
478 return 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)
511 return true;
514 static int
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;
524 return 0;
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);
551 struct edid *edid;
552 int ret = 0;
554 if (!hdmi->ddc)
555 return 0;
557 edid = drm_get_edid(connector, hdmi->ddc);
558 if (edid) {
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);
563 kfree(edid);
566 return ret;
569 static enum drm_mode_status
570 inno_hdmi_connector_mode_valid(struct drm_connector *connector,
571 struct drm_display_mode *mode)
573 return MODE_OK;
576 static int
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_with_ddc(drm, &hdmi->connector,
628 &inno_hdmi_connector_funcs,
629 DRM_MODE_CONNECTOR_HDMIA,
630 hdmi->ddc);
632 drm_connector_attach_encoder(&hdmi->connector, encoder);
634 return 0;
637 static irqreturn_t inno_hdmi_i2c_irq(struct inno_hdmi *hdmi)
639 struct inno_hdmi_i2c *i2c = hdmi->i2c;
640 u8 stat;
642 stat = hdmi_readb(hdmi, HDMI_INTERRUPT_STATUS1);
643 if (!(stat & m_INT_EDID_READY))
644 return IRQ_NONE;
646 /* Clear HDMI EDID interrupt flag */
647 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
649 complete(&i2c->cmp);
651 return IRQ_HANDLED;
654 static irqreturn_t inno_hdmi_hardirq(int irq, void *dev_id)
656 struct inno_hdmi *hdmi = dev_id;
657 irqreturn_t ret = IRQ_NONE;
658 u8 interrupt;
660 if (hdmi->i2c)
661 ret = inno_hdmi_i2c_irq(hdmi);
663 interrupt = hdmi_readb(hdmi, HDMI_STATUS);
664 if (interrupt & m_INT_HOTPLUG) {
665 hdmi_modb(hdmi, HDMI_STATUS, m_INT_HOTPLUG, m_INT_HOTPLUG);
666 ret = IRQ_WAKE_THREAD;
669 return ret;
672 static irqreturn_t inno_hdmi_irq(int irq, void *dev_id)
674 struct inno_hdmi *hdmi = dev_id;
676 drm_helper_hpd_irq_event(hdmi->connector.dev);
678 return IRQ_HANDLED;
681 static int inno_hdmi_i2c_read(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
683 int length = msgs->len;
684 u8 *buf = msgs->buf;
685 int ret;
687 ret = wait_for_completion_timeout(&hdmi->i2c->cmp, HZ / 10);
688 if (!ret)
689 return -EAGAIN;
691 while (length--)
692 *buf++ = hdmi_readb(hdmi, HDMI_EDID_FIFO_ADDR);
694 return 0;
697 static int inno_hdmi_i2c_write(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
700 * The DDC module only support read EDID message, so
701 * we assume that each word write to this i2c adapter
702 * should be the offset of EDID word address.
704 if ((msgs->len != 1) ||
705 ((msgs->addr != DDC_ADDR) && (msgs->addr != DDC_SEGMENT_ADDR)))
706 return -EINVAL;
708 reinit_completion(&hdmi->i2c->cmp);
710 if (msgs->addr == DDC_SEGMENT_ADDR)
711 hdmi->i2c->segment_addr = msgs->buf[0];
712 if (msgs->addr == DDC_ADDR)
713 hdmi->i2c->ddc_addr = msgs->buf[0];
715 /* Set edid fifo first addr */
716 hdmi_writeb(hdmi, HDMI_EDID_FIFO_OFFSET, 0x00);
718 /* Set edid word address 0x00/0x80 */
719 hdmi_writeb(hdmi, HDMI_EDID_WORD_ADDR, hdmi->i2c->ddc_addr);
721 /* Set edid segment pointer */
722 hdmi_writeb(hdmi, HDMI_EDID_SEGMENT_POINTER, hdmi->i2c->segment_addr);
724 return 0;
727 static int inno_hdmi_i2c_xfer(struct i2c_adapter *adap,
728 struct i2c_msg *msgs, int num)
730 struct inno_hdmi *hdmi = i2c_get_adapdata(adap);
731 struct inno_hdmi_i2c *i2c = hdmi->i2c;
732 int i, ret = 0;
734 mutex_lock(&i2c->lock);
736 /* Clear the EDID interrupt flag and unmute the interrupt */
737 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, m_INT_EDID_READY);
738 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
740 for (i = 0; i < num; i++) {
741 DRM_DEV_DEBUG(hdmi->dev,
742 "xfer: num: %d/%d, len: %d, flags: %#x\n",
743 i + 1, num, msgs[i].len, msgs[i].flags);
745 if (msgs[i].flags & I2C_M_RD)
746 ret = inno_hdmi_i2c_read(hdmi, &msgs[i]);
747 else
748 ret = inno_hdmi_i2c_write(hdmi, &msgs[i]);
750 if (ret < 0)
751 break;
754 if (!ret)
755 ret = num;
757 /* Mute HDMI EDID interrupt */
758 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
760 mutex_unlock(&i2c->lock);
762 return ret;
765 static u32 inno_hdmi_i2c_func(struct i2c_adapter *adapter)
767 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
770 static const struct i2c_algorithm inno_hdmi_algorithm = {
771 .master_xfer = inno_hdmi_i2c_xfer,
772 .functionality = inno_hdmi_i2c_func,
775 static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
777 struct i2c_adapter *adap;
778 struct inno_hdmi_i2c *i2c;
779 int ret;
781 i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
782 if (!i2c)
783 return ERR_PTR(-ENOMEM);
785 mutex_init(&i2c->lock);
786 init_completion(&i2c->cmp);
788 adap = &i2c->adap;
789 adap->class = I2C_CLASS_DDC;
790 adap->owner = THIS_MODULE;
791 adap->dev.parent = hdmi->dev;
792 adap->dev.of_node = hdmi->dev->of_node;
793 adap->algo = &inno_hdmi_algorithm;
794 strlcpy(adap->name, "Inno HDMI", sizeof(adap->name));
795 i2c_set_adapdata(adap, hdmi);
797 ret = i2c_add_adapter(adap);
798 if (ret) {
799 dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
800 devm_kfree(hdmi->dev, i2c);
801 return ERR_PTR(ret);
804 hdmi->i2c = i2c;
806 DRM_DEV_INFO(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
808 return adap;
811 static int inno_hdmi_bind(struct device *dev, struct device *master,
812 void *data)
814 struct platform_device *pdev = to_platform_device(dev);
815 struct drm_device *drm = data;
816 struct inno_hdmi *hdmi;
817 struct resource *iores;
818 int irq;
819 int ret;
821 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
822 if (!hdmi)
823 return -ENOMEM;
825 hdmi->dev = dev;
826 hdmi->drm_dev = drm;
828 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
829 hdmi->regs = devm_ioremap_resource(dev, iores);
830 if (IS_ERR(hdmi->regs))
831 return PTR_ERR(hdmi->regs);
833 hdmi->pclk = devm_clk_get(hdmi->dev, "pclk");
834 if (IS_ERR(hdmi->pclk)) {
835 DRM_DEV_ERROR(hdmi->dev, "Unable to get HDMI pclk clk\n");
836 return PTR_ERR(hdmi->pclk);
839 ret = clk_prepare_enable(hdmi->pclk);
840 if (ret) {
841 DRM_DEV_ERROR(hdmi->dev,
842 "Cannot enable HDMI pclk clock: %d\n", ret);
843 return ret;
846 irq = platform_get_irq(pdev, 0);
847 if (irq < 0) {
848 ret = irq;
849 goto err_disable_clk;
852 inno_hdmi_reset(hdmi);
854 hdmi->ddc = inno_hdmi_i2c_adapter(hdmi);
855 if (IS_ERR(hdmi->ddc)) {
856 ret = PTR_ERR(hdmi->ddc);
857 hdmi->ddc = NULL;
858 goto err_disable_clk;
862 * When IP controller haven't configured to an accurate video
863 * timing, then the TMDS clock source would be switched to
864 * PCLK_HDMI, so we need to init the TMDS rate to PCLK rate,
865 * and reconfigure the DDC clock.
867 hdmi->tmds_rate = clk_get_rate(hdmi->pclk);
868 inno_hdmi_i2c_init(hdmi);
870 ret = inno_hdmi_register(drm, hdmi);
871 if (ret)
872 goto err_put_adapter;
874 dev_set_drvdata(dev, hdmi);
876 /* Unmute hotplug interrupt */
877 hdmi_modb(hdmi, HDMI_STATUS, m_MASK_INT_HOTPLUG, v_MASK_INT_HOTPLUG(1));
879 ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq,
880 inno_hdmi_irq, IRQF_SHARED,
881 dev_name(dev), hdmi);
882 if (ret < 0)
883 goto err_cleanup_hdmi;
885 return 0;
886 err_cleanup_hdmi:
887 hdmi->connector.funcs->destroy(&hdmi->connector);
888 hdmi->encoder.funcs->destroy(&hdmi->encoder);
889 err_put_adapter:
890 i2c_put_adapter(hdmi->ddc);
891 err_disable_clk:
892 clk_disable_unprepare(hdmi->pclk);
893 return ret;
896 static void inno_hdmi_unbind(struct device *dev, struct device *master,
897 void *data)
899 struct inno_hdmi *hdmi = dev_get_drvdata(dev);
901 hdmi->connector.funcs->destroy(&hdmi->connector);
902 hdmi->encoder.funcs->destroy(&hdmi->encoder);
904 i2c_put_adapter(hdmi->ddc);
905 clk_disable_unprepare(hdmi->pclk);
908 static const struct component_ops inno_hdmi_ops = {
909 .bind = inno_hdmi_bind,
910 .unbind = inno_hdmi_unbind,
913 static int inno_hdmi_probe(struct platform_device *pdev)
915 return component_add(&pdev->dev, &inno_hdmi_ops);
918 static int inno_hdmi_remove(struct platform_device *pdev)
920 component_del(&pdev->dev, &inno_hdmi_ops);
922 return 0;
925 static const struct of_device_id inno_hdmi_dt_ids[] = {
926 { .compatible = "rockchip,rk3036-inno-hdmi",
930 MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids);
932 struct platform_driver inno_hdmi_driver = {
933 .probe = inno_hdmi_probe,
934 .remove = inno_hdmi_remove,
935 .driver = {
936 .name = "innohdmi-rockchip",
937 .of_match_table = inno_hdmi_dt_ids,