1 #include <linux/delay.h>
3 #include <linux/interrupt.h>
4 #include <linux/of_irq.h>
5 #include "rockchip_hdmiv1.h"
6 #include "rockchip_hdmiv1_hw.h"
7 #include "rockchip_hdmiv1_hdcp.h"
9 static inline void delay100us(void)
11 usleep_range(99, 100);
14 static void rockchip_hdmiv1_av_mute(struct hdmi *hdmi_drv, bool enable)
16 struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
19 hdmi_msk_reg(hdmi_dev, AV_MUTE,
20 m_AVMUTE_CLEAR | m_AVMUTE_ENABLE,
21 v_AVMUTE_CLEAR(0) | v_AVMUTE_ENABLE(1));
23 hdmi_msk_reg(hdmi_dev, AV_MUTE,
24 m_AVMUTE_CLEAR | m_AVMUTE_ENABLE,
25 v_AVMUTE_CLEAR(1) | v_AVMUTE_ENABLE(0));
27 hdmi_msk_reg(hdmi_dev, PACKET_SEND_AUTO,
28 m_PACKET_GCP_EN, v_PACKET_GCP_EN(1));
31 static void rockchip_hdmiv1_sys_power(struct hdmi *hdmi_drv, bool enable)
33 struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
36 hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_POWER, v_PWR_ON);
38 hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_POWER, v_PWR_OFF);
41 static void rockchip_hdmiv1_set_pwr_mode(struct hdmi *hdmi_drv, int mode)
43 struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
45 if (hdmi_dev->pwr_mode == mode)
48 dev_info(hdmi_drv->dev, "%s change pwr_mode %d --> %d\n", __func__,
49 hdmi_dev->pwr_mode, mode);
53 dev_info(hdmi_drv->dev,
54 "%s change pwr_mode NORMAL\n",
56 rockchip_hdmiv1_sys_power(hdmi_drv, false);
57 if (hdmi_dev->soctype == HDMI_SOC_RK3036) {
58 hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x6f);
59 hdmi_writel(hdmi_dev, PHY_DRIVER, 0xbb);
60 } else if (hdmi_dev->soctype == HDMI_SOC_RK312X) {
61 hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x5f);
62 hdmi_writel(hdmi_dev, PHY_DRIVER, 0xaa);
65 hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x15);
66 hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x14);
67 hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x10);
68 hdmi_writel(hdmi_dev, PHY_CHG_PWR, 0x0f);
69 hdmi_writel(hdmi_dev, 0xce, 0x00);
70 hdmi_writel(hdmi_dev, 0xce, 0x01);
71 rockchip_hdmiv1_sys_power(hdmi_drv, true);
74 dev_info(hdmi_drv->dev,
75 "%s change pwr_mode LOWER_PWR\n",
77 rockchip_hdmiv1_sys_power(hdmi_drv, false);
78 hdmi_writel(hdmi_dev, PHY_DRIVER, 0x00);
79 hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x00);
80 hdmi_writel(hdmi_dev, PHY_CHG_PWR, 0x00);
81 hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x17);
84 dev_info(hdmi_drv->dev, "unkown rk3036 hdmi pwr mode %d\n",
88 hdmi_dev->pwr_mode = mode;
91 int rockchip_hdmiv1_detect_hotplug(struct hdmi *hdmi_drv)
94 struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
96 hdmi_readl(hdmi_dev, HDMI_STATUS, &value);
98 if (value == m_HOTPLUG)
99 return HDMI_HPD_ACTIVED;
101 return HDMI_HPD_INSERT;
103 return HDMI_HPD_REMOVED;
106 int rockchip_hdmiv1_insert(struct hdmi *hdmi_drv)
108 rockchip_hdmiv1_set_pwr_mode(hdmi_drv, NORMAL);
113 int rockchip_hdmiv1_read_edid(struct hdmi *hdmi_drv, int block, u8 *buf)
123 struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
126 offset = HDMI_EDID_BLOCK_SIZE;
130 ddc_bus_freq = (hdmi_dev->hclk_rate >> 2) / HDMI_SCL_RATE;
131 hdmi_writel(hdmi_dev, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
132 hdmi_writel(hdmi_dev, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
134 dev_info(hdmi_drv->dev,
135 "EDID DATA (Segment = %d Block = %d Offset = %d):\n",
136 (int)segment, (int)block, (int)offset);
137 disable_irq(hdmi_dev->irq);
139 /* Enable edid interrupt */
140 hdmi_writel(hdmi_dev, INTERRUPT_MASK1, m_INT_EDID_READY);
142 for (trytime = 0; trytime < 10; trytime++) {
144 hdmi_writel(hdmi_dev, INTERRUPT_STATUS1, 0x04);
146 /* Set edid fifo first addr */
147 hdmi_writel(hdmi_dev, EDID_FIFO_OFFSET, 0x00);
149 /* Set edid word address 0x00/0x80 */
150 hdmi_writel(hdmi_dev, EDID_WORD_ADDR, offset);
152 /* Set edid segment pointer */
153 hdmi_writel(hdmi_dev, EDID_SEGMENT_POINTER, segment);
155 for (i = 0; i < 200; i++) {
156 /* Wait edid interrupt */
157 usleep_range(900, 1000);
159 hdmi_readl(hdmi_dev, INTERRUPT_STATUS1, &c);
161 if (c & m_INT_EDID_READY)
165 if (c & m_INT_EDID_READY) {
166 for (j = 0; j < HDMI_EDID_BLOCK_SIZE; j++) {
168 hdmi_readl(hdmi_dev, 0x50, &c);
173 printk("\n>>>0x%02x: ", j);
174 printk("0x%02x ", c);
178 if ((checksum & 0xff) == 0) {
180 dev_info(hdmi_drv->dev,
181 "[%s] edid read sucess\n", __func__);
187 hdmi_writel(hdmi_dev, INTERRUPT_MASK1, 0);
188 /* clear EDID interrupt reg */
189 hdmi_writel(hdmi_dev, INTERRUPT_STATUS1,
192 enable_irq(hdmi_dev->irq);
197 static const char coeff_csc[][24] = {
198 /*YUV2RGB:601 SD mode(Y[16:235],UV[16:240],RGB[0:255]):
199 R = 1.164*Y +1.596*V - 204
200 G = 1.164*Y - 0.391*U - 0.813*V + 154
201 B = 1.164*Y + 2.018*U - 258*/
203 0x04, 0xa7, 0x00, 0x00, 0x06, 0x62, 0x02, 0xcc,
204 0x04, 0xa7, 0x11, 0x90, 0x13, 0x40, 0x00, 0x9a,
205 0x04, 0xa7, 0x08, 0x12, 0x00, 0x00, 0x03, 0x02},
207 /*YUV2RGB:601 SD mode(YUV[0:255],RGB[0:255]):
208 R = Y + 1.402*V - 248
209 G = Y - 0.344*U - 0.714*V + 135
210 B = Y + 1.772*U - 227*/
212 0x04, 0x00, 0x00, 0x00, 0x05, 0x9b, 0x02, 0xf8,
213 0x04, 0x00, 0x11, 0x60, 0x12, 0xdb, 0x00, 0x87,
214 0x04, 0x00, 0x07, 0x16, 0x00, 0x00, 0x02, 0xe3},
215 /*YUV2RGB:709 HD mode(Y[16:235],UV[16:240],RGB[0:255]):
216 R = 1.164*Y +1.793*V - 248
217 G = 1.164*Y - 0.213*U - 0.534*V + 77
218 B = 1.164*Y + 2.115*U - 289*/
220 0x04, 0xa7, 0x00, 0x00, 0x07, 0x2c, 0x02, 0xf8,
221 0x04, 0xa7, 0x10, 0xda, 0x12, 0x22, 0x00, 0x4d,
222 0x04, 0xa7, 0x08, 0x74, 0x00, 0x00, 0x03, 0x21},
223 /*RGB2YUV:601 SD mode:
224 Cb = -0.291G - 0.148R + 0.439B + 128
225 Y = 0.504G + 0.257R + 0.098B + 16
226 Cr = -0.368G + 0.439R - 0.071B + 128*/
228 /*0x11, 0x78, 0x01, 0xc1, 0x10, 0x48, 0x00, 0x80,
229 0x02, 0x04, 0x01, 0x07, 0x00, 0x64, 0x00, 0x10,
230 0x11, 0x29, 0x10, 0x97, 0x01, 0xc1, 0x00, 0x80*/
232 /*0x11,0x4b,0x01,0x8a,0x10,0x3f,0x00,0x80,
233 0x01,0xbb,0x00,0xe2,0x00,0x56,0x00,0x1d,
234 0x11,0x05,0x10,0x85,0x01,0x8a,0x00,0x80*/
236 0x11, 0x5f, 0x01, 0x82, 0x10, 0x23, 0x00, 0x80,
237 0x02, 0x1c, 0x00, 0xa1, 0x00, 0x36, 0x00, 0x1e,
238 0x11, 0x29, 0x10, 0x59, 0x01, 0x82, 0x00, 0x80
241 /*RGB2YUV:709 HD mode:
242 Cb = - 0.338G - 0.101R + 0.439B + 128
243 Y = 0.614G + 0.183R + 0.062B + 16
244 Cr = - 0.399G + 0.439R - 0.040B + 128*/
246 0x11, 0x98, 0x01, 0xc1, 0x10, 0x28, 0x00, 0x80,
247 0x02, 0x74, 0x00, 0xbb, 0x00, 0x3f, 0x00, 0x10,
248 0x11, 0x5a, 0x10, 0x67, 0x01, 0xc1, 0x00, 0x80
250 /*RGB[0:255]2RGB[16:235]:
251 R' = R x (235-16)/255 + 16;
252 G' = G x (235-16)/255 + 16;
253 B' = B x (235-16)/255 + 16;*/
255 0x00, 0x00, 0x03, 0x6F, 0x00, 0x00, 0x00, 0x10,
256 0x03, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
257 0x00, 0x00, 0x00, 0x00, 0x03, 0x6F, 0x00, 0x10},
260 static int rockchip_hdmiv1_video_csc(struct hdmi *hdmi_drv,
261 struct hdmi_video *vpara)
263 int value, i, csc_mode, c0_c2_change, auto_csc, csc_enable;
264 const char *coeff = NULL;
265 struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
267 /* Enable or disalbe color space convert */
268 dev_info(hdmi_drv->dev, "[%s] input_color=%d,output_color=%d\n",
269 __func__, vpara->color_input, vpara->color_output);
270 if (vpara->color_input == vpara->color_output) {
271 if ((vpara->color_input >= HDMI_COLOR_YCBCR444) ||
272 (vpara->color_input == HDMI_COLOR_RGB_0_255)) {
273 value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1);
274 hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
275 hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
276 m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_SWAP,
277 v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) |
278 v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE));
280 } else if (vpara->color_input == HDMI_COLOR_RGB_16_235) {
281 csc_mode = CSC_RGB_0_255_TO_RGB_16_235_8BIT;
282 auto_csc = AUTO_CSC_DISABLE;
283 c0_c2_change = C0_C2_CHANGE_DISABLE;
284 csc_enable = v_CSC_ENABLE;
288 switch (vpara->vic) {
289 case HDMI_720X480I_60HZ_4_3:
290 case HDMI_720X576I_50HZ_4_3:
291 case HDMI_720X480P_60HZ_4_3:
292 case HDMI_720X576P_50HZ_4_3:
293 case HDMI_720X480I_60HZ_16_9:
294 case HDMI_720X576I_50HZ_16_9:
295 case HDMI_720X480P_60HZ_16_9:
296 case HDMI_720X576P_50HZ_16_9:
297 if (((vpara->color_input == HDMI_COLOR_RGB_0_255) ||
298 (vpara->color_input == HDMI_COLOR_RGB_16_235)) &&
299 vpara->color_output >= HDMI_COLOR_YCBCR444) {
300 csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
301 auto_csc = AUTO_CSC_DISABLE;
302 c0_c2_change = C0_C2_CHANGE_DISABLE;
303 csc_enable = v_CSC_ENABLE;
304 } else if (vpara->color_input >= HDMI_COLOR_YCBCR444 &&
305 ((vpara->color_output == HDMI_COLOR_RGB_0_255) ||
306 (vpara->color_output == HDMI_COLOR_RGB_16_235))) {
307 #ifdef AUTO_DEFINE_CSC
308 csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
309 auto_csc = AUTO_CSC_ENABLE;
310 c0_c2_change = C0_C2_CHANGE_DISABLE;
311 csc_enable = v_CSC_DISABLE;
313 csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
314 auto_csc = AUTO_CSC_DISABLE;
315 c0_c2_change = C0_C2_CHANGE_ENABLE;
316 csc_enable = v_CSC_ENABLE;
321 if (((vpara->color_input == HDMI_COLOR_RGB_0_255) ||
322 (vpara->color_input == HDMI_COLOR_RGB_16_235)) &&
323 vpara->color_output >= HDMI_COLOR_YCBCR444) {
324 csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
325 auto_csc = AUTO_CSC_DISABLE;
326 c0_c2_change = C0_C2_CHANGE_DISABLE;
327 csc_enable = v_CSC_ENABLE;
328 } else if (vpara->color_input >= HDMI_COLOR_YCBCR444 &&
329 ((vpara->color_output == HDMI_COLOR_RGB_0_255) ||
330 (vpara->color_output == HDMI_COLOR_RGB_16_235))) {
331 #ifdef AUTO_DEFINE_CSC
332 csc_mode = CSC_ITU709_16_235_TO_RGB_0_255_8BIT;
333 auto_csc = AUTO_CSC_ENABLE;
334 c0_c2_change = C0_C2_CHANGE_DISABLE;
335 csc_enable = v_CSC_DISABLE;
337 /*CSC_ITU709_16_235_TO_RGB_0_255_8BIT;*/
338 csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
339 auto_csc = AUTO_CSC_DISABLE;
340 c0_c2_change = C0_C2_CHANGE_ENABLE;
341 csc_enable = v_CSC_ENABLE;
347 coeff = coeff_csc[csc_mode];
348 for (i = 0; i < 24; i++)
349 hdmi_writel(hdmi_dev, VIDEO_CSC_COEF+i, coeff[i]);
351 value = v_SOF_DISABLE | csc_enable | v_COLOR_DEPTH_NOT_INDICATED(1);
352 hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
353 hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
356 v_VIDEO_AUTO_CSC(auto_csc) |
357 v_VIDEO_C0_C2_SWAP(c0_c2_change));
360 if (vpara->input_color != vpara->output_color) {
361 if (vpara->input_color == VIDEO_INPUT_COLOR_RGB) {/*rgb2yuv*/
362 coeff = coeff_csc[3];
363 for (i = 0; i < 24; i++)
364 hdmi_writel(hdmi_dev,
365 VIDEO_CSC_COEF+i, coeff[i]);
367 value = v_SOF_DISABLE | v_CSC_ENABLE;
368 hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
369 hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
370 m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
371 v_VIDEO_AUTO_CSC(0) |
372 v_VIDEO_C0_C2_EXCHANGE(1));
374 #ifdef AUTO_DEFINE_CSC
375 value = v_SOF_DISABLE | v_CSC_DISABLE;
376 hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
377 hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
378 m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
379 v_VIDEO_AUTO_CSC(1) |
380 v_VIDEO_C0_C2_EXCHANGE(1));
382 if (hdmi_drv->lcdc->cur_screen->mode.xres <= 576) {
384 coeff = coeff_csc[0];
385 pr_info("xres<=576,xres=%d\n",
386 hdmi_drv->lcdc->cur_screen->mode.xres);
387 } else/*x > 576,REC-709*/{
388 coeff = coeff_csc[2];
389 pr_info("xres>576,xres=%d\n",
390 hdmi_drv->lcdc->cur_screen->mode.xres);
392 for (i = 0; i < 24; i++)
393 hdmi_writel(hdmi_dev,
394 VIDEO_CSC_COEF+i, coeff[i]);
396 value = v_SOF_DISABLE | v_CSC_ENABLE;
397 hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
398 hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
400 m_VIDEO_C0_C2_EXCHANGE,
401 v_VIDEO_AUTO_CSC(0) |
402 v_VIDEO_C0_C2_EXCHANGE(0));
406 if (vpara->input_color == VIDEO_INPUT_COLOR_RGB) {
407 /*rgb[0:255]->rbg[16:235]*/
408 coeff = coeff_csc[5];
409 for (i = 0; i < 24; i++)
410 hdmi_writel(hdmi_dev,
411 VIDEO_CSC_COEF+i, coeff[i]);
413 value = v_SOF_DISABLE | v_CSC_ENABLE;
414 hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
415 hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
416 m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
417 v_VIDEO_AUTO_CSC(0) |
418 v_VIDEO_C0_C2_EXCHANGE(1));
420 value = v_SOF_DISABLE;
421 hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
422 hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
424 m_VIDEO_C0_C2_EXCHANGE,
425 v_VIDEO_AUTO_CSC(0) |
426 v_VIDEO_C0_C2_EXCHANGE(1));
433 static int rockchip_hdmiv1_config_vsi(struct hdmi *hdmi,
434 unsigned char vic_3d,
435 unsigned char format)
437 struct hdmi_dev *hdmi_dev = hdmi->property->priv;
438 char info[SIZE_VSI_INFOFRAME];
441 DBG("[%s] vic_3d %d format %d.\n", __func__, vic_3d, format);
442 memset(info, 0, SIZE_VSI_INFOFRAME);
443 hdmi_msk_reg(hdmi_dev, PACKET_SEND_AUTO,
444 m_PACKET_VSI_EN, v_PACKET_VSI_EN(0));
445 hdmi_writel(hdmi_dev, CONTROL_PACKET_BUF_INDEX, INFOFRAME_VSI);
449 /* PB1 - PB3 contain the 24bit IEEE Registration Identifier */
453 /* PB4 - HDMI_Video_Format into bits 7:5 */
454 info[7] = format << 5;
455 /* PB5 - Depending on the video format, this byte will contain either
456 the HDMI_VIC code in buts 7:0, OR the 3D_Structure in bits 7:4. */
458 case HDMI_VIDEO_FORMAT_4KX2K:
459 /* This is a 2x4K mode, set the HDMI_VIC in buts 7:0. Values
460 are from HDMI 1.4 Spec, 8.2.3.1 (Table 8-13). */
465 case HDMI_VIDEO_FORMAT_3D:
466 /* This is a 3D mode, set the 3D_Structure in buts 7:4
467 Bits 3:0 are reseved so set to 0. Values are from HDMI 1.4
468 Spec, Appendix H (Table H-2). */
469 info[8] = vic_3d << 4;
470 /* Add the Extended data field when the 3D format is
471 Side-by-Side(Half). See Spec Table H-3 for details. */
472 if ((info[8] >> 4) == HDMI_3D_SIDE_BY_SIDE_HALF) {
485 info[3] = info[0] + info[1] + info[2];
486 /* Calculate InfoFrame ChecKsum */
487 for (i = 4; i < SIZE_VSI_INFOFRAME; i++)
489 info[3] = 0x100 - info[3];
491 for (i = 0; i < SIZE_VSI_INFOFRAME; i++)
492 hdmi_writel(hdmi_dev, CONTROL_PACKET_ADDR + i, info[i]);
493 hdmi_msk_reg(hdmi_dev, PACKET_SEND_AUTO,
494 m_PACKET_VSI_EN, v_PACKET_VSI_EN(1));
498 static void rockchip_hdmiv1_config_avi(struct hdmi *hdmi_drv,
500 unsigned char output_color)
504 char info[SIZE_AVI_INFOFRAME];
505 struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
507 memset(info, 0, SIZE_AVI_INFOFRAME);
508 hdmi_writel(hdmi_dev, CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
512 info[3] = info[0] + info[1] + info[2];
514 if ((output_color == HDMI_COLOR_RGB_0_255) ||
515 (output_color == HDMI_COLOR_RGB_16_235))
516 avi_color_mode = AVI_COLOR_MODE_RGB;
517 else if (output_color == HDMI_COLOR_YCBCR444)
518 avi_color_mode = AVI_COLOR_MODE_YCBCR444;
519 else if (output_color == HDMI_COLOR_YCBCR422)
520 avi_color_mode = AVI_COLOR_MODE_YCBCR422;
522 info[4] = (avi_color_mode << 5);
524 (AVI_COLORIMETRY_NO_DATA << 6) |
525 (AVI_CODED_FRAME_ASPECT_NO_DATA << 4) |
526 ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME;
529 if ((vic == HDMI_720X480I_60HZ_4_3) ||
530 (vic == HDMI_720X576I_50HZ_4_3) ||
531 (vic == HDMI_720X480I_60HZ_16_9) ||
532 (vic == HDMI_720X480I_60HZ_16_9))
537 /* Calculate AVI InfoFrame ChecKsum */
538 for (i = 4; i < SIZE_AVI_INFOFRAME; i++)
541 info[3] = 0x100 - info[3];
543 for (i = 0; i < SIZE_AVI_INFOFRAME; i++)
544 hdmi_writel(hdmi_dev, CONTROL_PACKET_ADDR + i, info[i]);
547 static int rockchip_hdmiv1_config_video(struct hdmi *hdmi_drv,
548 struct hdmi_video *vpara)
550 struct fb_videomode *mode;
551 struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
554 dev_dbg(hdmi_drv->dev, "[%s]\n", __func__);
557 dev_err(hdmi_drv->dev, "[%s] input parameter error\n",
562 if (hdmi_dev->soctype == HDMI_SOC_RK3036) {
563 /*rk3036 vop only can output rgb fmt*/
564 vpara->color_input = HDMI_COLOR_RGB_0_255;
565 } else if (hdmi_dev->soctype == HDMI_SOC_RK312X) {
566 /* rk3128 vop can output yuv444 fmt */
567 /*if (vpara->input_color == VIDEO_INPUT_COLOR_YCBCR444)
568 vpara->output_color = VIDEO_OUTPUT_YCBCR444;
570 vpara->output_color = VIDEO_OUTPUT_RGB444;*/
573 mode = (struct fb_videomode *)hdmi_vic_to_videomode(vpara->vic);
575 dev_err(hdmi_drv->dev, "[%s] not found vic %d\n", __func__,
579 hdmi_dev->tmdsclk = mode->pixclock;
582 /* Disable video and audio output */
583 hdmi_msk_reg(hdmi_dev, AV_MUTE,
584 m_AUDIO_MUTE | m_VIDEO_BLACK,
585 v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
587 /* Input video mode is SDR RGB24bit,
588 Data enable signal from external */
589 hdmi_writel(hdmi_dev, VIDEO_CONTRL1,
590 v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444) |
593 value = v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS);
594 if (vpara->color_output <= HDMI_COLOR_RGB_16_235)
595 value |= v_VIDEO_OUTPUT_COLOR(0);
597 value |= v_VIDEO_OUTPUT_COLOR((vpara->color_output - 2) & 0x3);
598 if (vpara->color_input <= HDMI_COLOR_RGB_16_235)
599 value |= v_VIDEO_INPUT_CSP(0);
601 value |= v_VIDEO_INPUT_CSP((vpara->color_input - 2) & 0x1);
603 hdmi_writel(hdmi_dev, VIDEO_CONTRL2, value);
605 hdmi_writel(hdmi_dev, HDCP_CTRL, v_HDMI_DVI(vpara->sink_hdmi));
607 /* Enable or disalbe color space convert */
608 rockchip_hdmiv1_video_csc(hdmi_drv, vpara);
610 /* Set ext video timing */
611 if (mode->vmode || mode->pixclock <= 27000000) {
612 hdmi_writel(hdmi_dev, VIDEO_TIMING_CTL, 0);
614 value = v_EXTERANL_VIDEO(1) | v_INETLACE(mode->vmode);
615 if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
616 value |= v_HSYNC_POLARITY(1);
617 if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
618 value |= v_VSYNC_POLARITY(1);
619 hdmi_writel(hdmi_dev, VIDEO_TIMING_CTL, value);
621 value = mode->left_margin +
622 mode->xres + mode->right_margin +
624 hdmi_writel(hdmi_dev, VIDEO_EXT_HTOTAL_L, value & 0xFF);
625 hdmi_writel(hdmi_dev, VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
627 value = mode->left_margin +
630 hdmi_writel(hdmi_dev, VIDEO_EXT_HBLANK_L, value & 0xFF);
631 hdmi_writel(hdmi_dev, VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
633 value = mode->left_margin + mode->hsync_len;
634 hdmi_writel(hdmi_dev, VIDEO_EXT_HDELAY_L, value & 0xFF);
635 hdmi_writel(hdmi_dev, VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
637 value = mode->hsync_len;
638 hdmi_writel(hdmi_dev, VIDEO_EXT_HDURATION_L,
640 hdmi_writel(hdmi_dev, VIDEO_EXT_HDURATION_H,
641 (value >> 8) & 0xFF);
643 value = mode->upper_margin + mode->yres + mode->lower_margin +
645 hdmi_writel(hdmi_dev, VIDEO_EXT_VTOTAL_L, value & 0xFF);
646 hdmi_writel(hdmi_dev, VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
648 value = mode->upper_margin +
651 hdmi_writel(hdmi_dev, VIDEO_EXT_VBLANK, value & 0xFF);
653 if (vpara->vic == HDMI_720X480P_60HZ_4_3 ||
654 vpara->vic == HDMI_720X480P_60HZ_16_9)
657 value = mode->upper_margin + mode->vsync_len;
659 hdmi_writel(hdmi_dev, VIDEO_EXT_VDELAY, value & 0xFF);
661 value = mode->vsync_len;
662 hdmi_writel(hdmi_dev, VIDEO_EXT_VDURATION, value & 0xFF);
664 if (vpara->sink_hdmi == OUTPUT_HDMI) {
665 rockchip_hdmiv1_config_avi(hdmi_drv, vpara->vic,
666 vpara->color_output);
667 if (vpara->format_3d != HDMI_3D_NONE) {
668 rockchip_hdmiv1_config_vsi(hdmi_drv,
670 HDMI_VIDEO_FORMAT_3D);
671 } else if ((vpara->vic > 92 && vpara->vic < 96) ||
672 (vpara->vic == 98)) {
673 vpara->vic = (vpara->vic == 98) ?
674 4 : (96 - vpara->vic);
675 rockchip_hdmiv1_config_vsi(hdmi_drv,
677 HDMI_VIDEO_FORMAT_4KX2K);
679 rockchip_hdmiv1_config_vsi(hdmi_drv,
681 HDMI_VIDEO_FORMAT_NORMAL);
683 dev_info(hdmi_drv->dev,
684 "[%s] sucess output HDMI.\n", __func__);
686 dev_info(hdmi_drv->dev,
687 "[%s] sucess output DVI.\n", __func__);
691 hdmi_writel(hdmi_dev, PHY_PRE_DIV_RATIO, 0x1e);
692 hdmi_writel(hdmi_dev, PHY_FEEDBACK_DIV_RATIO_LOW, 0x2c);
693 hdmi_writel(hdmi_dev, PHY_FEEDBACK_DIV_RATIO_HIGH, 0x01);
698 static void rockchip_hdmiv1_config_aai(struct hdmi *hdmi_drv)
701 char info[SIZE_AUDIO_INFOFRAME];
702 struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
704 memset(info, 0, SIZE_AUDIO_INFOFRAME);
710 info[3] = info[0] + info[1] + info[2];
711 for (i = 4; i < SIZE_AUDIO_INFOFRAME; i++)
714 info[3] = 0x100 - info[3];
716 hdmi_writel(hdmi_dev, CONTROL_PACKET_BUF_INDEX, INFOFRAME_AAI);
717 for (i = 0; i < SIZE_AUDIO_INFOFRAME; i++)
718 hdmi_writel(hdmi_dev, CONTROL_PACKET_ADDR + i, info[i]);
721 static int rockchip_hdmiv1_config_audio(struct hdmi *hdmi_drv,
722 struct hdmi_audio *audio)
724 int rate, N, channel, mclk_fs;
725 struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
727 if (audio->channel < 3)
728 channel = I2S_CHANNEL_1_2;
729 else if (audio->channel < 5)
730 channel = I2S_CHANNEL_3_4;
731 else if (audio->channel < 7)
732 channel = I2S_CHANNEL_5_6;
734 channel = I2S_CHANNEL_7_8;
736 switch (audio->rate) {
737 case HDMI_AUDIO_FS_32000:
740 mclk_fs = MCLK_384FS;
742 case HDMI_AUDIO_FS_44100:
745 mclk_fs = MCLK_256FS;
747 case HDMI_AUDIO_FS_48000:
750 mclk_fs = MCLK_256FS;
752 case HDMI_AUDIO_FS_88200:
755 mclk_fs = MCLK_128FS;
757 case HDMI_AUDIO_FS_96000:
760 mclk_fs = MCLK_128FS;
762 case HDMI_AUDIO_FS_176400:
765 mclk_fs = MCLK_128FS;
767 case HDMI_AUDIO_FS_192000:
770 mclk_fs = MCLK_128FS;
773 dev_err(hdmi_drv->dev,
774 "[%s] not support such sample rate %d\n",
775 __func__, audio->rate);
779 /* set_audio source I2S */
780 if (hdmi_dev->audiosrc == HDMI_AUDIO_SRC_IIS) {
781 hdmi_writel(hdmi_dev, AUDIO_CTRL1, 0x00);
782 hdmi_writel(hdmi_dev, AUDIO_SAMPLE_RATE, rate);
783 hdmi_writel(hdmi_dev, AUDIO_I2S_MODE,
784 v_I2S_MODE(I2S_STANDARD) |
785 v_I2S_CHANNEL(channel));
786 hdmi_writel(hdmi_dev, AUDIO_I2S_MAP, 0x00);
788 hdmi_writel(hdmi_dev, AUDIO_I2S_SWAPS_SPDIF, 0);
790 hdmi_writel(hdmi_dev, AUDIO_CTRL1, 0x08);
792 hdmi_writel(hdmi_dev, AUDIO_I2S_SWAPS_SPDIF, 0);
796 hdmi_writel(hdmi_dev, AUDIO_N_H, (N >> 16) & 0x0F);
797 hdmi_writel(hdmi_dev, AUDIO_N_M, (N >> 8) & 0xFF);
798 hdmi_writel(hdmi_dev, AUDIO_N_L, N & 0xFF);
799 rockchip_hdmiv1_config_aai(hdmi_drv);
804 int rockchip_hdmiv1_control_output(struct hdmi *hdmi_drv, int enable)
807 struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
809 if (hdmi_drv->uboot) {
814 if (enable == HDMI_AV_UNMUTE) {
815 if (hdmi_dev->pwr_mode == LOWER_PWR)
816 rockchip_hdmiv1_set_pwr_mode(hdmi_drv, NORMAL);
818 rockchip_hdmiv1_sys_power(hdmi_drv, true);
819 rockchip_hdmiv1_sys_power(hdmi_drv, false);
821 rockchip_hdmiv1_sys_power(hdmi_drv, true);
822 hdmi_writel(hdmi_dev, 0xce, 0x00);
824 hdmi_writel(hdmi_dev, 0xce, 0x01);
826 hdmi_readl(hdmi_dev, AV_MUTE, &mutestatus);
827 if (mutestatus && (m_AUDIO_MUTE | m_VIDEO_BLACK)) {
828 hdmi_msk_reg(hdmi_dev, AV_MUTE,
829 m_AUDIO_MUTE | m_VIDEO_BLACK,
830 v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
832 rockchip_hdmiv1_av_mute(hdmi_drv, 0);
834 hdmi_msk_reg(hdmi_dev, AV_MUTE,
835 m_AUDIO_MUTE | m_VIDEO_BLACK,
836 v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
837 rockchip_hdmiv1_av_mute(hdmi_drv, 1);
839 rockchip_hdmiv1_set_pwr_mode(hdmi_drv, LOWER_PWR);
844 int rockchip_hdmiv1_removed(struct hdmi *hdmi_drv)
846 dev_info(hdmi_drv->dev, "Removed.\n");
847 if (hdmi_drv->ops->hdcp_power_off_cb)
848 hdmi_drv->ops->hdcp_power_off_cb();
850 rockchip_hdmiv1_control_output(hdmi_drv, -1);
851 rockchip_hdmiv1_set_pwr_mode(hdmi_drv, LOWER_PWR);
853 return HDMI_ERROR_SUCESS;
856 static int rockchip_hdmiv1_enable(struct hdmi *hdmi_drv)
858 struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
860 if (!hdmi_dev->enable)
861 hdmi_dev->enable = 1;
862 hdmi_submit_work(hdmi_drv, HDMI_HPD_CHANGE, 10, NULL);
866 static int rockchip_hdmiv1_disable(struct hdmi *hdmi_drv)
868 struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
870 if (hdmi_dev->enable)
871 hdmi_dev->enable = 0;
876 void rockchip_hdmiv1_irq(struct hdmi *hdmi_drv)
879 struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
881 hdmi_readl(hdmi_dev, INTERRUPT_STATUS1, &interrupt);
883 hdmi_writel(hdmi_dev, INTERRUPT_STATUS1, interrupt);
884 dev_info(hdmi_drv->dev, "Clear edid irq.\n");
887 hdmi_readl(hdmi_dev, HDMI_STATUS, &interrupt);
889 hdmi_writel(hdmi_dev, HDMI_STATUS, interrupt);
890 if (interrupt & m_INT_HOTPLUG)
891 hdmi_submit_work(hdmi_drv, HDMI_HPD_CHANGE, 20, NULL);
893 if (hdmi_drv->ops->hdcp_irq_cb)
894 hdmi_drv->ops->hdcp_irq_cb(0);
895 if (hdmi_drv->property->feature & SUPPORT_CEC)
896 rockchip_hdmiv1_cec_isr(hdmi_dev);
899 static void rockchip_hdmiv1_reset(struct hdmi *hdmi_drv)
903 struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
905 hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL);
907 hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG);
909 msk = m_REG_CLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL;
910 val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH;
911 hdmi_msk_reg(hdmi_dev, SYS_CTRL, msk, val);
913 rockchip_hdmiv1_set_pwr_mode(hdmi_drv, LOWER_PWR);
916 void rockchip_hdmiv1_dev_init_ops(struct hdmi_ops *ops)
919 ops->disable = rockchip_hdmiv1_disable;
920 ops->enable = rockchip_hdmiv1_enable;
921 ops->remove = rockchip_hdmiv1_removed;
922 ops->setmute = rockchip_hdmiv1_control_output;
923 ops->setvideo = rockchip_hdmiv1_config_video;
924 ops->setaudio = rockchip_hdmiv1_config_audio;
925 ops->getstatus = rockchip_hdmiv1_detect_hotplug;
926 ops->getedid = rockchip_hdmiv1_read_edid;
927 ops->insert = rockchip_hdmiv1_insert;
928 ops->setvsi = rockchip_hdmiv1_config_vsi;
932 int rockchip_hdmiv1_initial(struct hdmi *hdmi_drv)
934 int rc = HDMI_ERROR_SUCESS;
935 struct hdmi_dev *hdmi_dev = hdmi_drv->property->priv;
937 hdmi_dev->pwr_mode = NORMAL;
939 if (!hdmi_drv->uboot) {
940 rockchip_hdmiv1_reset_pclk();
941 rockchip_hdmiv1_reset(hdmi_drv);
942 } else if (hdmi_drv->ops->getstatus(hdmi_drv) == HDMI_HPD_REMOVED) {
943 rockchip_hdmiv1_removed(hdmi_drv);
944 hdmi_drv->lcdc->uboot_logo = 0;
947 if (hdmi_drv->property->feature & SUPPORT_CEC)
948 rockchip_hdmiv1_cec_init(hdmi_drv);
949 if (hdmi_drv->property->feature & SUPPORT_HDCP)
950 rockchip_hdmiv1_hdcp_init(hdmi_drv);