dt-bindings: mtd: ingenic: Use standard ecc-engine property
[linux/fpc-iii.git] / drivers / gpu / drm / rockchip / inno_hdmi.c
blobce1545862b6ce433a3ef97e82a978904c27e4a9a
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_edid.h>
30 #include <drm/drm_probe_helper.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,
299 &hdmi->connector,
300 mode);
302 if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444)
303 frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
304 else if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV422)
305 frame.avi.colorspace = HDMI_COLORSPACE_YUV422;
306 else
307 frame.avi.colorspace = HDMI_COLORSPACE_RGB;
309 return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_AVI, 0, 0, 0);
312 static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi)
314 struct hdmi_data_info *data = &hdmi->hdmi_data;
315 int c0_c2_change = 0;
316 int csc_enable = 0;
317 int csc_mode = 0;
318 int auto_csc = 0;
319 int value;
320 int i;
322 /* Input video mode is SDR RGB24bit, data enable signal from external */
323 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL1, v_DE_EXTERNAL |
324 v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444));
326 /* Input color hardcode to RGB, and output color hardcode to RGB888 */
327 value = v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS) |
328 v_VIDEO_OUTPUT_COLOR(0) |
329 v_VIDEO_INPUT_CSP(0);
330 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value);
332 if (data->enc_in_format == data->enc_out_format) {
333 if ((data->enc_in_format == HDMI_COLORSPACE_RGB) ||
334 (data->enc_in_format >= HDMI_COLORSPACE_YUV444)) {
335 value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1);
336 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
338 hdmi_modb(hdmi, HDMI_VIDEO_CONTRL,
339 m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_SWAP,
340 v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) |
341 v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE));
342 return 0;
346 if (data->colorimetry == HDMI_COLORIMETRY_ITU_601) {
347 if ((data->enc_in_format == HDMI_COLORSPACE_RGB) &&
348 (data->enc_out_format == HDMI_COLORSPACE_YUV444)) {
349 csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
350 auto_csc = AUTO_CSC_DISABLE;
351 c0_c2_change = C0_C2_CHANGE_DISABLE;
352 csc_enable = v_CSC_ENABLE;
353 } else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) &&
354 (data->enc_out_format == HDMI_COLORSPACE_RGB)) {
355 csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
356 auto_csc = AUTO_CSC_ENABLE;
357 c0_c2_change = C0_C2_CHANGE_DISABLE;
358 csc_enable = v_CSC_DISABLE;
360 } else {
361 if ((data->enc_in_format == HDMI_COLORSPACE_RGB) &&
362 (data->enc_out_format == HDMI_COLORSPACE_YUV444)) {
363 csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
364 auto_csc = AUTO_CSC_DISABLE;
365 c0_c2_change = C0_C2_CHANGE_DISABLE;
366 csc_enable = v_CSC_ENABLE;
367 } else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) &&
368 (data->enc_out_format == HDMI_COLORSPACE_RGB)) {
369 csc_mode = CSC_ITU709_16_235_TO_RGB_0_255_8BIT;
370 auto_csc = AUTO_CSC_ENABLE;
371 c0_c2_change = C0_C2_CHANGE_DISABLE;
372 csc_enable = v_CSC_DISABLE;
376 for (i = 0; i < 24; i++)
377 hdmi_writeb(hdmi, HDMI_VIDEO_CSC_COEF + i,
378 coeff_csc[csc_mode][i]);
380 value = v_SOF_DISABLE | csc_enable | v_COLOR_DEPTH_NOT_INDICATED(1);
381 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
382 hdmi_modb(hdmi, HDMI_VIDEO_CONTRL, m_VIDEO_AUTO_CSC |
383 m_VIDEO_C0_C2_SWAP, v_VIDEO_AUTO_CSC(auto_csc) |
384 v_VIDEO_C0_C2_SWAP(c0_c2_change));
386 return 0;
389 static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
390 struct drm_display_mode *mode)
392 int value;
394 /* Set detail external video timing polarity and interlace mode */
395 value = v_EXTERANL_VIDEO(1);
396 value |= mode->flags & DRM_MODE_FLAG_PHSYNC ?
397 v_HSYNC_POLARITY(1) : v_HSYNC_POLARITY(0);
398 value |= mode->flags & DRM_MODE_FLAG_PVSYNC ?
399 v_VSYNC_POLARITY(1) : v_VSYNC_POLARITY(0);
400 value |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
401 v_INETLACE(1) : v_INETLACE(0);
402 hdmi_writeb(hdmi, HDMI_VIDEO_TIMING_CTL, value);
404 /* Set detail external video timing */
405 value = mode->htotal;
406 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_L, value & 0xFF);
407 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
409 value = mode->htotal - mode->hdisplay;
410 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_L, value & 0xFF);
411 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
413 value = mode->hsync_start - mode->hdisplay;
414 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_L, value & 0xFF);
415 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
417 value = mode->hsync_end - mode->hsync_start;
418 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_L, value & 0xFF);
419 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF);
421 value = mode->vtotal;
422 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_L, value & 0xFF);
423 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
425 value = mode->vtotal - mode->vdisplay;
426 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VBLANK, value & 0xFF);
428 value = mode->vsync_start - mode->vdisplay;
429 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDELAY, value & 0xFF);
431 value = mode->vsync_end - mode->vsync_start;
432 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDURATION, value & 0xFF);
434 hdmi_writeb(hdmi, HDMI_PHY_PRE_DIV_RATIO, 0x1e);
435 hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_LOW, 0x2c);
436 hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_HIGH, 0x01);
438 return 0;
441 static int inno_hdmi_setup(struct inno_hdmi *hdmi,
442 struct drm_display_mode *mode)
444 hdmi->hdmi_data.vic = drm_match_cea_mode(mode);
446 hdmi->hdmi_data.enc_in_format = HDMI_COLORSPACE_RGB;
447 hdmi->hdmi_data.enc_out_format = HDMI_COLORSPACE_RGB;
449 if ((hdmi->hdmi_data.vic == 6) || (hdmi->hdmi_data.vic == 7) ||
450 (hdmi->hdmi_data.vic == 21) || (hdmi->hdmi_data.vic == 22) ||
451 (hdmi->hdmi_data.vic == 2) || (hdmi->hdmi_data.vic == 3) ||
452 (hdmi->hdmi_data.vic == 17) || (hdmi->hdmi_data.vic == 18))
453 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
454 else
455 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
457 /* Mute video and audio output */
458 hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
459 v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
461 /* Set HDMI Mode */
462 hdmi_writeb(hdmi, HDMI_HDCP_CTRL,
463 v_HDMI_DVI(hdmi->hdmi_data.sink_is_hdmi));
465 inno_hdmi_config_video_timing(hdmi, mode);
467 inno_hdmi_config_video_csc(hdmi);
469 if (hdmi->hdmi_data.sink_is_hdmi) {
470 inno_hdmi_config_video_avi(hdmi, mode);
471 inno_hdmi_config_video_vsi(hdmi, mode);
475 * When IP controller have configured to an accurate video
476 * timing, then the TMDS clock source would be switched to
477 * DCLK_LCDC, so we need to init the TMDS rate to mode pixel
478 * clock rate, and reconfigure the DDC clock.
480 hdmi->tmds_rate = mode->clock * 1000;
481 inno_hdmi_i2c_init(hdmi);
483 /* Unmute video and audio output */
484 hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
485 v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
487 return 0;
490 static void inno_hdmi_encoder_mode_set(struct drm_encoder *encoder,
491 struct drm_display_mode *mode,
492 struct drm_display_mode *adj_mode)
494 struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
496 inno_hdmi_setup(hdmi, adj_mode);
498 /* Store the display mode for plugin/DPMS poweron events */
499 memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode));
502 static void inno_hdmi_encoder_enable(struct drm_encoder *encoder)
504 struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
506 inno_hdmi_set_pwr_mode(hdmi, NORMAL);
509 static void inno_hdmi_encoder_disable(struct drm_encoder *encoder)
511 struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
513 inno_hdmi_set_pwr_mode(hdmi, LOWER_PWR);
516 static bool inno_hdmi_encoder_mode_fixup(struct drm_encoder *encoder,
517 const struct drm_display_mode *mode,
518 struct drm_display_mode *adj_mode)
520 return true;
523 static int
524 inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
525 struct drm_crtc_state *crtc_state,
526 struct drm_connector_state *conn_state)
528 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
530 s->output_mode = ROCKCHIP_OUT_MODE_P888;
531 s->output_type = DRM_MODE_CONNECTOR_HDMIA;
533 return 0;
536 static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = {
537 .enable = inno_hdmi_encoder_enable,
538 .disable = inno_hdmi_encoder_disable,
539 .mode_fixup = inno_hdmi_encoder_mode_fixup,
540 .mode_set = inno_hdmi_encoder_mode_set,
541 .atomic_check = inno_hdmi_encoder_atomic_check,
544 static struct drm_encoder_funcs inno_hdmi_encoder_funcs = {
545 .destroy = drm_encoder_cleanup,
548 static enum drm_connector_status
549 inno_hdmi_connector_detect(struct drm_connector *connector, bool force)
551 struct inno_hdmi *hdmi = to_inno_hdmi(connector);
553 return (hdmi_readb(hdmi, HDMI_STATUS) & m_HOTPLUG) ?
554 connector_status_connected : connector_status_disconnected;
557 static int inno_hdmi_connector_get_modes(struct drm_connector *connector)
559 struct inno_hdmi *hdmi = to_inno_hdmi(connector);
560 struct edid *edid;
561 int ret = 0;
563 if (!hdmi->ddc)
564 return 0;
566 edid = drm_get_edid(connector, hdmi->ddc);
567 if (edid) {
568 hdmi->hdmi_data.sink_is_hdmi = drm_detect_hdmi_monitor(edid);
569 hdmi->hdmi_data.sink_has_audio = drm_detect_monitor_audio(edid);
570 drm_connector_update_edid_property(connector, edid);
571 ret = drm_add_edid_modes(connector, edid);
572 kfree(edid);
575 return ret;
578 static enum drm_mode_status
579 inno_hdmi_connector_mode_valid(struct drm_connector *connector,
580 struct drm_display_mode *mode)
582 return MODE_OK;
585 static int
586 inno_hdmi_probe_single_connector_modes(struct drm_connector *connector,
587 uint32_t maxX, uint32_t maxY)
589 return drm_helper_probe_single_connector_modes(connector, 1920, 1080);
592 static void inno_hdmi_connector_destroy(struct drm_connector *connector)
594 drm_connector_unregister(connector);
595 drm_connector_cleanup(connector);
598 static const struct drm_connector_funcs inno_hdmi_connector_funcs = {
599 .fill_modes = inno_hdmi_probe_single_connector_modes,
600 .detect = inno_hdmi_connector_detect,
601 .destroy = inno_hdmi_connector_destroy,
602 .reset = drm_atomic_helper_connector_reset,
603 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
604 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
607 static struct drm_connector_helper_funcs inno_hdmi_connector_helper_funcs = {
608 .get_modes = inno_hdmi_connector_get_modes,
609 .mode_valid = inno_hdmi_connector_mode_valid,
612 static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi)
614 struct drm_encoder *encoder = &hdmi->encoder;
615 struct device *dev = hdmi->dev;
617 encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
620 * If we failed to find the CRTC(s) which this encoder is
621 * supposed to be connected to, it's because the CRTC has
622 * not been registered yet. Defer probing, and hope that
623 * the required CRTC is added later.
625 if (encoder->possible_crtcs == 0)
626 return -EPROBE_DEFER;
628 drm_encoder_helper_add(encoder, &inno_hdmi_encoder_helper_funcs);
629 drm_encoder_init(drm, encoder, &inno_hdmi_encoder_funcs,
630 DRM_MODE_ENCODER_TMDS, NULL);
632 hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
634 drm_connector_helper_add(&hdmi->connector,
635 &inno_hdmi_connector_helper_funcs);
636 drm_connector_init(drm, &hdmi->connector, &inno_hdmi_connector_funcs,
637 DRM_MODE_CONNECTOR_HDMIA);
639 drm_connector_attach_encoder(&hdmi->connector, encoder);
641 return 0;
644 static irqreturn_t inno_hdmi_i2c_irq(struct inno_hdmi *hdmi)
646 struct inno_hdmi_i2c *i2c = hdmi->i2c;
647 u8 stat;
649 stat = hdmi_readb(hdmi, HDMI_INTERRUPT_STATUS1);
650 if (!(stat & m_INT_EDID_READY))
651 return IRQ_NONE;
653 /* Clear HDMI EDID interrupt flag */
654 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
656 complete(&i2c->cmp);
658 return IRQ_HANDLED;
661 static irqreturn_t inno_hdmi_hardirq(int irq, void *dev_id)
663 struct inno_hdmi *hdmi = dev_id;
664 irqreturn_t ret = IRQ_NONE;
665 u8 interrupt;
667 if (hdmi->i2c)
668 ret = inno_hdmi_i2c_irq(hdmi);
670 interrupt = hdmi_readb(hdmi, HDMI_STATUS);
671 if (interrupt & m_INT_HOTPLUG) {
672 hdmi_modb(hdmi, HDMI_STATUS, m_INT_HOTPLUG, m_INT_HOTPLUG);
673 ret = IRQ_WAKE_THREAD;
676 return ret;
679 static irqreturn_t inno_hdmi_irq(int irq, void *dev_id)
681 struct inno_hdmi *hdmi = dev_id;
683 drm_helper_hpd_irq_event(hdmi->connector.dev);
685 return IRQ_HANDLED;
688 static int inno_hdmi_i2c_read(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
690 int length = msgs->len;
691 u8 *buf = msgs->buf;
692 int ret;
694 ret = wait_for_completion_timeout(&hdmi->i2c->cmp, HZ / 10);
695 if (!ret)
696 return -EAGAIN;
698 while (length--)
699 *buf++ = hdmi_readb(hdmi, HDMI_EDID_FIFO_ADDR);
701 return 0;
704 static int inno_hdmi_i2c_write(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
707 * The DDC module only support read EDID message, so
708 * we assume that each word write to this i2c adapter
709 * should be the offset of EDID word address.
711 if ((msgs->len != 1) ||
712 ((msgs->addr != DDC_ADDR) && (msgs->addr != DDC_SEGMENT_ADDR)))
713 return -EINVAL;
715 reinit_completion(&hdmi->i2c->cmp);
717 if (msgs->addr == DDC_SEGMENT_ADDR)
718 hdmi->i2c->segment_addr = msgs->buf[0];
719 if (msgs->addr == DDC_ADDR)
720 hdmi->i2c->ddc_addr = msgs->buf[0];
722 /* Set edid fifo first addr */
723 hdmi_writeb(hdmi, HDMI_EDID_FIFO_OFFSET, 0x00);
725 /* Set edid word address 0x00/0x80 */
726 hdmi_writeb(hdmi, HDMI_EDID_WORD_ADDR, hdmi->i2c->ddc_addr);
728 /* Set edid segment pointer */
729 hdmi_writeb(hdmi, HDMI_EDID_SEGMENT_POINTER, hdmi->i2c->segment_addr);
731 return 0;
734 static int inno_hdmi_i2c_xfer(struct i2c_adapter *adap,
735 struct i2c_msg *msgs, int num)
737 struct inno_hdmi *hdmi = i2c_get_adapdata(adap);
738 struct inno_hdmi_i2c *i2c = hdmi->i2c;
739 int i, ret = 0;
741 mutex_lock(&i2c->lock);
743 /* Clear the EDID interrupt flag and unmute the interrupt */
744 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, m_INT_EDID_READY);
745 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
747 for (i = 0; i < num; i++) {
748 DRM_DEV_DEBUG(hdmi->dev,
749 "xfer: num: %d/%d, len: %d, flags: %#x\n",
750 i + 1, num, msgs[i].len, msgs[i].flags);
752 if (msgs[i].flags & I2C_M_RD)
753 ret = inno_hdmi_i2c_read(hdmi, &msgs[i]);
754 else
755 ret = inno_hdmi_i2c_write(hdmi, &msgs[i]);
757 if (ret < 0)
758 break;
761 if (!ret)
762 ret = num;
764 /* Mute HDMI EDID interrupt */
765 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
767 mutex_unlock(&i2c->lock);
769 return ret;
772 static u32 inno_hdmi_i2c_func(struct i2c_adapter *adapter)
774 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
777 static const struct i2c_algorithm inno_hdmi_algorithm = {
778 .master_xfer = inno_hdmi_i2c_xfer,
779 .functionality = inno_hdmi_i2c_func,
782 static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
784 struct i2c_adapter *adap;
785 struct inno_hdmi_i2c *i2c;
786 int ret;
788 i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
789 if (!i2c)
790 return ERR_PTR(-ENOMEM);
792 mutex_init(&i2c->lock);
793 init_completion(&i2c->cmp);
795 adap = &i2c->adap;
796 adap->class = I2C_CLASS_DDC;
797 adap->owner = THIS_MODULE;
798 adap->dev.parent = hdmi->dev;
799 adap->dev.of_node = hdmi->dev->of_node;
800 adap->algo = &inno_hdmi_algorithm;
801 strlcpy(adap->name, "Inno HDMI", sizeof(adap->name));
802 i2c_set_adapdata(adap, hdmi);
804 ret = i2c_add_adapter(adap);
805 if (ret) {
806 dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
807 devm_kfree(hdmi->dev, i2c);
808 return ERR_PTR(ret);
811 hdmi->i2c = i2c;
813 DRM_DEV_INFO(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
815 return adap;
818 static int inno_hdmi_bind(struct device *dev, struct device *master,
819 void *data)
821 struct platform_device *pdev = to_platform_device(dev);
822 struct drm_device *drm = data;
823 struct inno_hdmi *hdmi;
824 struct resource *iores;
825 int irq;
826 int ret;
828 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
829 if (!hdmi)
830 return -ENOMEM;
832 hdmi->dev = dev;
833 hdmi->drm_dev = drm;
835 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
836 hdmi->regs = devm_ioremap_resource(dev, iores);
837 if (IS_ERR(hdmi->regs))
838 return PTR_ERR(hdmi->regs);
840 hdmi->pclk = devm_clk_get(hdmi->dev, "pclk");
841 if (IS_ERR(hdmi->pclk)) {
842 DRM_DEV_ERROR(hdmi->dev, "Unable to get HDMI pclk clk\n");
843 return PTR_ERR(hdmi->pclk);
846 ret = clk_prepare_enable(hdmi->pclk);
847 if (ret) {
848 DRM_DEV_ERROR(hdmi->dev,
849 "Cannot enable HDMI pclk clock: %d\n", ret);
850 return ret;
853 irq = platform_get_irq(pdev, 0);
854 if (irq < 0) {
855 ret = irq;
856 goto err_disable_clk;
859 inno_hdmi_reset(hdmi);
861 hdmi->ddc = inno_hdmi_i2c_adapter(hdmi);
862 if (IS_ERR(hdmi->ddc)) {
863 ret = PTR_ERR(hdmi->ddc);
864 hdmi->ddc = NULL;
865 goto err_disable_clk;
869 * When IP controller haven't configured to an accurate video
870 * timing, then the TMDS clock source would be switched to
871 * PCLK_HDMI, so we need to init the TMDS rate to PCLK rate,
872 * and reconfigure the DDC clock.
874 hdmi->tmds_rate = clk_get_rate(hdmi->pclk);
875 inno_hdmi_i2c_init(hdmi);
877 ret = inno_hdmi_register(drm, hdmi);
878 if (ret)
879 goto err_put_adapter;
881 dev_set_drvdata(dev, hdmi);
883 /* Unmute hotplug interrupt */
884 hdmi_modb(hdmi, HDMI_STATUS, m_MASK_INT_HOTPLUG, v_MASK_INT_HOTPLUG(1));
886 ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq,
887 inno_hdmi_irq, IRQF_SHARED,
888 dev_name(dev), hdmi);
889 if (ret < 0)
890 goto err_cleanup_hdmi;
892 return 0;
893 err_cleanup_hdmi:
894 hdmi->connector.funcs->destroy(&hdmi->connector);
895 hdmi->encoder.funcs->destroy(&hdmi->encoder);
896 err_put_adapter:
897 i2c_put_adapter(hdmi->ddc);
898 err_disable_clk:
899 clk_disable_unprepare(hdmi->pclk);
900 return ret;
903 static void inno_hdmi_unbind(struct device *dev, struct device *master,
904 void *data)
906 struct inno_hdmi *hdmi = dev_get_drvdata(dev);
908 hdmi->connector.funcs->destroy(&hdmi->connector);
909 hdmi->encoder.funcs->destroy(&hdmi->encoder);
911 i2c_put_adapter(hdmi->ddc);
912 clk_disable_unprepare(hdmi->pclk);
915 static const struct component_ops inno_hdmi_ops = {
916 .bind = inno_hdmi_bind,
917 .unbind = inno_hdmi_unbind,
920 static int inno_hdmi_probe(struct platform_device *pdev)
922 return component_add(&pdev->dev, &inno_hdmi_ops);
925 static int inno_hdmi_remove(struct platform_device *pdev)
927 component_del(&pdev->dev, &inno_hdmi_ops);
929 return 0;
932 static const struct of_device_id inno_hdmi_dt_ids[] = {
933 { .compatible = "rockchip,rk3036-inno-hdmi",
937 MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids);
939 struct platform_driver inno_hdmi_driver = {
940 .probe = inno_hdmi_probe,
941 .remove = inno_hdmi_remove,
942 .driver = {
943 .name = "innohdmi-rockchip",
944 .of_match_table = inno_hdmi_dt_ids,