Input: xpad - add support for Xbox1 PDP Camo series gamepad
[linux/fpc-iii.git] / drivers / gpu / drm / rockchip / inno_hdmi.c
blob006260de9dbd22a0be6fda85e1c17ec8a04f1b44
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 dev_err(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 mode);
287 return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_VSI,
288 m_PACKET_VSI_EN, v_PACKET_VSI_EN(0), v_PACKET_VSI_EN(1));
291 static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi,
292 struct drm_display_mode *mode)
294 union hdmi_infoframe frame;
295 int rc;
297 rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
299 if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444)
300 frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
301 else if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV422)
302 frame.avi.colorspace = HDMI_COLORSPACE_YUV422;
303 else
304 frame.avi.colorspace = HDMI_COLORSPACE_RGB;
306 return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_AVI, 0, 0, 0);
309 static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi)
311 struct hdmi_data_info *data = &hdmi->hdmi_data;
312 int c0_c2_change = 0;
313 int csc_enable = 0;
314 int csc_mode = 0;
315 int auto_csc = 0;
316 int value;
317 int i;
319 /* Input video mode is SDR RGB24bit, data enable signal from external */
320 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL1, v_DE_EXTERNAL |
321 v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444));
323 /* Input color hardcode to RGB, and output color hardcode to RGB888 */
324 value = v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS) |
325 v_VIDEO_OUTPUT_COLOR(0) |
326 v_VIDEO_INPUT_CSP(0);
327 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value);
329 if (data->enc_in_format == data->enc_out_format) {
330 if ((data->enc_in_format == HDMI_COLORSPACE_RGB) ||
331 (data->enc_in_format >= HDMI_COLORSPACE_YUV444)) {
332 value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1);
333 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
335 hdmi_modb(hdmi, HDMI_VIDEO_CONTRL,
336 m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_SWAP,
337 v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) |
338 v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE));
339 return 0;
343 if (data->colorimetry == HDMI_COLORIMETRY_ITU_601) {
344 if ((data->enc_in_format == HDMI_COLORSPACE_RGB) &&
345 (data->enc_out_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;
350 } else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) &&
351 (data->enc_out_format == HDMI_COLORSPACE_RGB)) {
352 csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
353 auto_csc = AUTO_CSC_ENABLE;
354 c0_c2_change = C0_C2_CHANGE_DISABLE;
355 csc_enable = v_CSC_DISABLE;
357 } else {
358 if ((data->enc_in_format == HDMI_COLORSPACE_RGB) &&
359 (data->enc_out_format == HDMI_COLORSPACE_YUV444)) {
360 csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
361 auto_csc = AUTO_CSC_DISABLE;
362 c0_c2_change = C0_C2_CHANGE_DISABLE;
363 csc_enable = v_CSC_ENABLE;
364 } else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) &&
365 (data->enc_out_format == HDMI_COLORSPACE_RGB)) {
366 csc_mode = CSC_ITU709_16_235_TO_RGB_0_255_8BIT;
367 auto_csc = AUTO_CSC_ENABLE;
368 c0_c2_change = C0_C2_CHANGE_DISABLE;
369 csc_enable = v_CSC_DISABLE;
373 for (i = 0; i < 24; i++)
374 hdmi_writeb(hdmi, HDMI_VIDEO_CSC_COEF + i,
375 coeff_csc[csc_mode][i]);
377 value = v_SOF_DISABLE | csc_enable | v_COLOR_DEPTH_NOT_INDICATED(1);
378 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
379 hdmi_modb(hdmi, HDMI_VIDEO_CONTRL, m_VIDEO_AUTO_CSC |
380 m_VIDEO_C0_C2_SWAP, v_VIDEO_AUTO_CSC(auto_csc) |
381 v_VIDEO_C0_C2_SWAP(c0_c2_change));
383 return 0;
386 static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
387 struct drm_display_mode *mode)
389 int value;
391 /* Set detail external video timing polarity and interlace mode */
392 value = v_EXTERANL_VIDEO(1);
393 value |= mode->flags & DRM_MODE_FLAG_PHSYNC ?
394 v_HSYNC_POLARITY(1) : v_HSYNC_POLARITY(0);
395 value |= mode->flags & DRM_MODE_FLAG_PVSYNC ?
396 v_VSYNC_POLARITY(1) : v_VSYNC_POLARITY(0);
397 value |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
398 v_INETLACE(1) : v_INETLACE(0);
399 hdmi_writeb(hdmi, HDMI_VIDEO_TIMING_CTL, value);
401 /* Set detail external video timing */
402 value = mode->htotal;
403 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_L, value & 0xFF);
404 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
406 value = mode->htotal - mode->hdisplay;
407 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_L, value & 0xFF);
408 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
410 value = mode->hsync_start - mode->hdisplay;
411 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_L, value & 0xFF);
412 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
414 value = mode->hsync_end - mode->hsync_start;
415 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_L, value & 0xFF);
416 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF);
418 value = mode->vtotal;
419 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_L, value & 0xFF);
420 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
422 value = mode->vtotal - mode->vdisplay;
423 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VBLANK, value & 0xFF);
425 value = mode->vsync_start - mode->vdisplay;
426 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDELAY, value & 0xFF);
428 value = mode->vsync_end - mode->vsync_start;
429 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDURATION, value & 0xFF);
431 hdmi_writeb(hdmi, HDMI_PHY_PRE_DIV_RATIO, 0x1e);
432 hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_LOW, 0x2c);
433 hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_HIGH, 0x01);
435 return 0;
438 static int inno_hdmi_setup(struct inno_hdmi *hdmi,
439 struct drm_display_mode *mode)
441 hdmi->hdmi_data.vic = drm_match_cea_mode(mode);
443 hdmi->hdmi_data.enc_in_format = HDMI_COLORSPACE_RGB;
444 hdmi->hdmi_data.enc_out_format = HDMI_COLORSPACE_RGB;
446 if ((hdmi->hdmi_data.vic == 6) || (hdmi->hdmi_data.vic == 7) ||
447 (hdmi->hdmi_data.vic == 21) || (hdmi->hdmi_data.vic == 22) ||
448 (hdmi->hdmi_data.vic == 2) || (hdmi->hdmi_data.vic == 3) ||
449 (hdmi->hdmi_data.vic == 17) || (hdmi->hdmi_data.vic == 18))
450 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
451 else
452 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
454 /* Mute video and audio output */
455 hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
456 v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
458 /* Set HDMI Mode */
459 hdmi_writeb(hdmi, HDMI_HDCP_CTRL,
460 v_HDMI_DVI(hdmi->hdmi_data.sink_is_hdmi));
462 inno_hdmi_config_video_timing(hdmi, mode);
464 inno_hdmi_config_video_csc(hdmi);
466 if (hdmi->hdmi_data.sink_is_hdmi) {
467 inno_hdmi_config_video_avi(hdmi, mode);
468 inno_hdmi_config_video_vsi(hdmi, mode);
472 * When IP controller have configured to an accurate video
473 * timing, then the TMDS clock source would be switched to
474 * DCLK_LCDC, so we need to init the TMDS rate to mode pixel
475 * clock rate, and reconfigure the DDC clock.
477 hdmi->tmds_rate = mode->clock * 1000;
478 inno_hdmi_i2c_init(hdmi);
480 /* Unmute video and audio output */
481 hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
482 v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
484 return 0;
487 static void inno_hdmi_encoder_mode_set(struct drm_encoder *encoder,
488 struct drm_display_mode *mode,
489 struct drm_display_mode *adj_mode)
491 struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
493 inno_hdmi_setup(hdmi, adj_mode);
495 /* Store the display mode for plugin/DPMS poweron events */
496 memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode));
499 static void inno_hdmi_encoder_enable(struct drm_encoder *encoder)
501 struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
503 inno_hdmi_set_pwr_mode(hdmi, NORMAL);
506 static void inno_hdmi_encoder_disable(struct drm_encoder *encoder)
508 struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
510 inno_hdmi_set_pwr_mode(hdmi, LOWER_PWR);
513 static bool inno_hdmi_encoder_mode_fixup(struct drm_encoder *encoder,
514 const struct drm_display_mode *mode,
515 struct drm_display_mode *adj_mode)
517 return true;
520 static int
521 inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
522 struct drm_crtc_state *crtc_state,
523 struct drm_connector_state *conn_state)
525 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
527 s->output_mode = ROCKCHIP_OUT_MODE_P888;
528 s->output_type = DRM_MODE_CONNECTOR_HDMIA;
530 return 0;
533 static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = {
534 .enable = inno_hdmi_encoder_enable,
535 .disable = inno_hdmi_encoder_disable,
536 .mode_fixup = inno_hdmi_encoder_mode_fixup,
537 .mode_set = inno_hdmi_encoder_mode_set,
538 .atomic_check = inno_hdmi_encoder_atomic_check,
541 static struct drm_encoder_funcs inno_hdmi_encoder_funcs = {
542 .destroy = drm_encoder_cleanup,
545 static enum drm_connector_status
546 inno_hdmi_connector_detect(struct drm_connector *connector, bool force)
548 struct inno_hdmi *hdmi = to_inno_hdmi(connector);
550 return (hdmi_readb(hdmi, HDMI_STATUS) & m_HOTPLUG) ?
551 connector_status_connected : connector_status_disconnected;
554 static int inno_hdmi_connector_get_modes(struct drm_connector *connector)
556 struct inno_hdmi *hdmi = to_inno_hdmi(connector);
557 struct edid *edid;
558 int ret = 0;
560 if (!hdmi->ddc)
561 return 0;
563 edid = drm_get_edid(connector, hdmi->ddc);
564 if (edid) {
565 hdmi->hdmi_data.sink_is_hdmi = drm_detect_hdmi_monitor(edid);
566 hdmi->hdmi_data.sink_has_audio = drm_detect_monitor_audio(edid);
567 drm_mode_connector_update_edid_property(connector, edid);
568 ret = drm_add_edid_modes(connector, edid);
569 kfree(edid);
572 return ret;
575 static enum drm_mode_status
576 inno_hdmi_connector_mode_valid(struct drm_connector *connector,
577 struct drm_display_mode *mode)
579 return MODE_OK;
582 static int
583 inno_hdmi_probe_single_connector_modes(struct drm_connector *connector,
584 uint32_t maxX, uint32_t maxY)
586 return drm_helper_probe_single_connector_modes(connector, 1920, 1080);
589 static void inno_hdmi_connector_destroy(struct drm_connector *connector)
591 drm_connector_unregister(connector);
592 drm_connector_cleanup(connector);
595 static struct drm_connector_funcs inno_hdmi_connector_funcs = {
596 .dpms = drm_atomic_helper_connector_dpms,
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_mode_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 dev_dbg(hdmi->dev, "xfer: num: %d/%d, len: %d, flags: %#x\n",
747 i + 1, num, msgs[i].len, msgs[i].flags);
749 if (msgs[i].flags & I2C_M_RD)
750 ret = inno_hdmi_i2c_read(hdmi, &msgs[i]);
751 else
752 ret = inno_hdmi_i2c_write(hdmi, &msgs[i]);
754 if (ret < 0)
755 break;
758 if (!ret)
759 ret = num;
761 /* Mute HDMI EDID interrupt */
762 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
764 mutex_unlock(&i2c->lock);
766 return ret;
769 static u32 inno_hdmi_i2c_func(struct i2c_adapter *adapter)
771 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
774 static const struct i2c_algorithm inno_hdmi_algorithm = {
775 .master_xfer = inno_hdmi_i2c_xfer,
776 .functionality = inno_hdmi_i2c_func,
779 static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
781 struct i2c_adapter *adap;
782 struct inno_hdmi_i2c *i2c;
783 int ret;
785 i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
786 if (!i2c)
787 return ERR_PTR(-ENOMEM);
789 mutex_init(&i2c->lock);
790 init_completion(&i2c->cmp);
792 adap = &i2c->adap;
793 adap->class = I2C_CLASS_DDC;
794 adap->owner = THIS_MODULE;
795 adap->dev.parent = hdmi->dev;
796 adap->dev.of_node = hdmi->dev->of_node;
797 adap->algo = &inno_hdmi_algorithm;
798 strlcpy(adap->name, "Inno HDMI", sizeof(adap->name));
799 i2c_set_adapdata(adap, hdmi);
801 ret = i2c_add_adapter(adap);
802 if (ret) {
803 dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
804 devm_kfree(hdmi->dev, i2c);
805 return ERR_PTR(ret);
808 hdmi->i2c = i2c;
810 dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
812 return adap;
815 static int inno_hdmi_bind(struct device *dev, struct device *master,
816 void *data)
818 struct platform_device *pdev = to_platform_device(dev);
819 struct drm_device *drm = data;
820 struct inno_hdmi *hdmi;
821 struct resource *iores;
822 int irq;
823 int ret;
825 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
826 if (!hdmi)
827 return -ENOMEM;
829 hdmi->dev = dev;
830 hdmi->drm_dev = drm;
832 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
833 if (!iores)
834 return -ENXIO;
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 dev_err(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 dev_err(hdmi->dev, "Cannot enable HDMI pclk clock: %d\n", ret);
849 return ret;
852 irq = platform_get_irq(pdev, 0);
853 if (irq < 0)
854 return irq;
856 inno_hdmi_reset(hdmi);
858 hdmi->ddc = inno_hdmi_i2c_adapter(hdmi);
859 if (IS_ERR(hdmi->ddc)) {
860 ret = PTR_ERR(hdmi->ddc);
861 hdmi->ddc = NULL;
862 return ret;
866 * When IP controller haven't configured to an accurate video
867 * timing, then the TMDS clock source would be switched to
868 * PCLK_HDMI, so we need to init the TMDS rate to PCLK rate,
869 * and reconfigure the DDC clock.
871 hdmi->tmds_rate = clk_get_rate(hdmi->pclk);
872 inno_hdmi_i2c_init(hdmi);
874 ret = inno_hdmi_register(drm, hdmi);
875 if (ret)
876 return ret;
878 dev_set_drvdata(dev, hdmi);
880 /* Unmute hotplug interrupt */
881 hdmi_modb(hdmi, HDMI_STATUS, m_MASK_INT_HOTPLUG, v_MASK_INT_HOTPLUG(1));
883 ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq,
884 inno_hdmi_irq, IRQF_SHARED,
885 dev_name(dev), hdmi);
887 return ret;
890 static void inno_hdmi_unbind(struct device *dev, struct device *master,
891 void *data)
893 struct inno_hdmi *hdmi = dev_get_drvdata(dev);
895 hdmi->connector.funcs->destroy(&hdmi->connector);
896 hdmi->encoder.funcs->destroy(&hdmi->encoder);
898 clk_disable_unprepare(hdmi->pclk);
899 i2c_put_adapter(hdmi->ddc);
902 static const struct component_ops inno_hdmi_ops = {
903 .bind = inno_hdmi_bind,
904 .unbind = inno_hdmi_unbind,
907 static int inno_hdmi_probe(struct platform_device *pdev)
909 return component_add(&pdev->dev, &inno_hdmi_ops);
912 static int inno_hdmi_remove(struct platform_device *pdev)
914 component_del(&pdev->dev, &inno_hdmi_ops);
916 return 0;
919 static const struct of_device_id inno_hdmi_dt_ids[] = {
920 { .compatible = "rockchip,rk3036-inno-hdmi",
924 MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids);
926 static struct platform_driver inno_hdmi_driver = {
927 .probe = inno_hdmi_probe,
928 .remove = inno_hdmi_remove,
929 .driver = {
930 .name = "innohdmi-rockchip",
931 .of_match_table = inno_hdmi_dt_ids,
935 module_platform_driver(inno_hdmi_driver);
937 MODULE_AUTHOR("Zheng Yang <zhengyang@rock-chips.com>");
938 MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
939 MODULE_DESCRIPTION("Rockchip Specific INNO-HDMI Driver");
940 MODULE_LICENSE("GPL v2");
941 MODULE_ALIAS("platform:innohdmi-rockchip");