1 #include <linux/delay.h>
3 #include <linux/interrupt.h>
4 #include <linux/of_irq.h>
5 #include "rk3036_hdmi.h"
6 #include "rk3036_hdmi_hw.h"
7 static unsigned int rk3036_hdmi_support_vic[] = {
8 HDMI_720X480P_60HZ_VIC,
9 HDMI_720X480I_60HZ_VIC,
10 HDMI_720X576P_50HZ_VIC,
11 HDMI_720X576I_50HZ_VIC,
12 HDMI_1280X720P_50HZ_VIC,
13 HDMI_1280X720P_60HZ_VIC,
14 HDMI_1920X1080P_50HZ_VIC,
15 HDMI_1920X1080I_50HZ_VIC,
16 HDMI_1920X1080P_60HZ_VIC,
17 HDMI_1920X1080I_60HZ_VIC
19 static int __maybe_unused rk3036_hdmi_show_reg(struct hdmi *hdmi_drv)
23 struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
24 struct rk_hdmi_device,
27 printk("\n>>>rk3036_ctl reg");
28 for (i = 0; i < 16; i++)
31 printk("\n-----------------------------------------------------------------");
33 for (i = 0; i <= PHY_PRE_DIV_RATIO; i++) {
34 hdmi_readl(hdmi_dev, i, &val);
36 printk("\n>>>rk3036_ctl %2x:", i);
39 printk("\n-----------------------------------------------------------------\n");
44 static inline void delay100us(void)
49 static void rk3036_hdmi_av_mute(struct hdmi *hdmi_drv, bool enable)
51 struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
52 struct rk_hdmi_device,
55 hdmi_msk_reg(hdmi_dev, AV_MUTE,
56 m_AVMUTE_CLEAR | m_AVMUTE_ENABLE,
57 v_AVMUTE_CLEAR(0) | v_AVMUTE_ENABLE(1));
59 hdmi_msk_reg(hdmi_dev, AV_MUTE,
60 m_AVMUTE_CLEAR | m_AVMUTE_ENABLE,
61 v_AVMUTE_CLEAR(1) | v_AVMUTE_ENABLE(0));
63 hdmi_writel(hdmi_dev, PACKET_SEND_AUTO, m_PACKET_GCP_EN);
66 static void rk3036_hdmi_sys_power(struct hdmi *hdmi_drv, bool enable)
68 struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
69 struct rk_hdmi_device,
73 hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_POWER, v_PWR_ON);
75 hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_POWER, v_PWR_OFF);
78 static void rk3036_hdmi_set_pwr_mode(struct hdmi *hdmi_drv, int mode)
80 struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
81 struct rk_hdmi_device,
84 if (hdmi_drv->pwr_mode == mode)
87 hdmi_dbg(hdmi_drv->dev, "%s change pwr_mode %d --> %d\n", __func__,
88 hdmi_drv->pwr_mode, mode);
92 hdmi_dbg(hdmi_drv->dev,
93 "%s change pwr_mode NORMAL pwr_mode = %d, mode = %d\n",
94 __func__, hdmi_drv->pwr_mode, mode);
95 rk3036_hdmi_sys_power(hdmi_drv, false);
96 if (hdmi_drv->data->soc_type == HDMI_SOC_RK3036) {
97 hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x6f);
98 hdmi_writel(hdmi_dev, PHY_DRIVER, 0xbb);
100 else if (hdmi_drv->data->soc_type == HDMI_SOC_RK312X) {
101 hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x5f);
102 hdmi_writel(hdmi_dev, PHY_DRIVER, 0xaa);
104 hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x15);
105 hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x14);
106 hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x10);
107 hdmi_writel(hdmi_dev, PHY_CHG_PWR, 0x0f);
108 hdmi_writel(hdmi_dev, 0xce, 0x00);
109 hdmi_writel(hdmi_dev, 0xce, 0x01);
110 rk3036_hdmi_sys_power(hdmi_drv, true);
113 hdmi_dbg(hdmi_drv->dev,
114 "%s change pwr_mode LOWER_PWR pwr_mode = %d, mode = %d\n",
115 __func__, hdmi_drv->pwr_mode, mode);
116 rk3036_hdmi_sys_power(hdmi_drv, false);
117 hdmi_writel(hdmi_dev, PHY_DRIVER, 0x00);
118 hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x00);
119 hdmi_writel(hdmi_dev, PHY_CHG_PWR, 0x00);
120 hdmi_writel(hdmi_dev, PHY_SYS_CTL, 0x17);
123 hdmi_dbg(hdmi_drv->dev, "unkown rk3036 hdmi pwr mode %d\n",
127 hdmi_drv->pwr_mode = mode;
130 int rk3036_hdmi_detect_hotplug(struct hdmi *hdmi_drv)
133 struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
134 struct rk_hdmi_device,
137 hdmi_dbg(hdmi_drv->dev, "[%s] value %02x\n", __func__, value);
138 hdmi_readl(hdmi_dev, HDMI_STATUS, &value);
140 if (value == m_HOTPLUG)
141 return HDMI_HPD_ACTIVED;
143 return HDMI_HPD_INSERT;
145 return HDMI_HPD_REMOVED;
147 int rk3036_hdmi_insert(struct hdmi *hdmi_drv)
149 rk3036_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
154 int rk3036_hdmi_read_edid(struct hdmi *hdmi_drv, int block, u8 *buf)
164 struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
165 struct rk_hdmi_device,
168 offset = HDMI_EDID_BLOCK_SIZE;
172 ddc_bus_freq = (hdmi_dev->hclk_rate >> 2) / HDMI_SCL_RATE;
173 hdmi_writel(hdmi_dev, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
174 hdmi_writel(hdmi_dev, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
176 hdmi_dbg(hdmi_drv->dev,
177 "EDID DATA (Segment = %d Block = %d Offset = %d):\n",
178 (int)segment, (int)block, (int)offset);
179 disable_irq(hdmi_drv->irq);
181 /* Enable edid interrupt */
182 hdmi_writel(hdmi_dev, INTERRUPT_MASK1, m_INT_EDID_READY);
184 for (trytime = 0; trytime < 10; trytime++) {
186 hdmi_writel(hdmi_dev, INTERRUPT_STATUS1, 0x04);
188 /* Set edid fifo first addr */
189 hdmi_writel(hdmi_dev, EDID_FIFO_OFFSET, 0x00);
191 /* Set edid word address 0x00/0x80 */
192 hdmi_writel(hdmi_dev, EDID_WORD_ADDR, offset);
194 /* Set edid segment pointer */
195 hdmi_writel(hdmi_dev, EDID_SEGMENT_POINTER, segment);
197 for (i = 0; i < 10; i++) {
198 /* Wait edid interrupt */
201 hdmi_readl(hdmi_dev, INTERRUPT_STATUS1, &c);
203 if (c & m_INT_EDID_READY)
207 if (c & m_INT_EDID_READY) {
208 for (j = 0; j < HDMI_EDID_BLOCK_SIZE; j++) {
210 hdmi_readl(hdmi_dev, 0x50, &c);
215 printk("\n>>>0x%02x: ",j);
217 printk("0x%02x ", c);
221 if ((checksum & 0xff) == 0) {
223 hdmi_dbg(hdmi_drv->dev,
224 "[%s] edid read sucess\n", __func__);
230 hdmi_writel(hdmi_dev, INTERRUPT_MASK1, 0);
231 /* clear EDID interrupt reg */
232 hdmi_writel(hdmi_dev, INTERRUPT_STATUS1,
235 enable_irq(hdmi_drv->irq);
240 static const char coeff_csc[][24] = {
241 /*YUV2RGB:601 SD mode(Y[16:235],UV[16:240],RGB[0:255]):
242 R = 1.164*Y +1.596*V - 204
243 G = 1.164*Y - 0.391*U - 0.813*V + 154
244 B = 1.164*Y + 2.018*U - 258*/
246 0x04, 0xa7, 0x00, 0x00, 0x06, 0x62, 0x02, 0xcc,
247 0x04, 0xa7, 0x11, 0x90, 0x13, 0x40, 0x00, 0x9a,
248 0x04, 0xa7, 0x08, 0x12, 0x00, 0x00, 0x03, 0x02},
250 /*YUV2RGB:601 SD mode(YUV[0:255],RGB[0:255]):
251 R = Y + 1.402*V - 248
252 G = Y - 0.344*U - 0.714*V + 135
253 B = Y + 1.772*U - 227*/
255 0x04, 0x00, 0x00, 0x00, 0x05, 0x9b, 0x02, 0xf8,
256 0x04, 0x00, 0x11, 0x60, 0x12, 0xdb, 0x00, 0x87,
257 0x04, 0x00, 0x07, 0x16, 0x00, 0x00, 0x02, 0xe3},
258 /*YUV2RGB:709 HD mode(Y[16:235],UV[16:240],RGB[0:255]):
259 R = 1.164*Y +1.793*V - 248
260 G = 1.164*Y - 0.213*U - 0.534*V + 77
261 B = 1.164*Y + 2.115*U - 289*/
263 0x04, 0xa7, 0x00, 0x00, 0x07, 0x2c, 0x02, 0xf8,
264 0x04, 0xa7, 0x10, 0xda, 0x12, 0x22, 0x00, 0x4d,
265 0x04, 0xa7, 0x08, 0x74, 0x00, 0x00, 0x03, 0x21},
266 /*RGB2YUV:601 SD mode:
267 Cb = -0.291G - 0.148R + 0.439B + 128
268 Y = 0.504G + 0.257R + 0.098B + 16
269 Cr = -0.368G + 0.439R - 0.071B + 128*/
271 /*0x11, 0x78, 0x01, 0xc1, 0x10, 0x48, 0x00, 0x80,
272 0x02, 0x04, 0x01, 0x07, 0x00, 0x64, 0x00, 0x10,
273 0x11, 0x29, 0x10, 0x97, 0x01, 0xc1, 0x00, 0x80*/
275 /*0x11,0x4b,0x01,0x8a,0x10,0x3f,0x00,0x80,
276 0x01,0xbb,0x00,0xe2,0x00,0x56,0x00,0x1d,
277 0x11,0x05,0x10,0x85,0x01,0x8a,0x00,0x80*/
279 0x11,0x5f,0x01,0x82,0x10,0x23,0x00,0x80,
280 0x02,0x1c,0x00,0xa1,0x00,0x36,0x00,0x1e,
281 0x11,0x29,0x10,0x59,0x01,0x82,0x00,0x80
284 /*RGB2YUV:709 HD mode:
285 Cb = - 0.338G - 0.101R + 0.439B + 128
286 Y = 0.614G + 0.183R + 0.062B + 16
287 Cr = - 0.399G + 0.439R - 0.040B + 128*/
289 0x11, 0x98, 0x01, 0xc1, 0x10, 0x28, 0x00, 0x80,
290 0x02, 0x74, 0x00, 0xbb, 0x00, 0x3f, 0x00, 0x10,
291 0x11, 0x5a, 0x10, 0x67, 0x01, 0xc1, 0x00, 0x80
293 /*RGB[0:255]2RGB[16:235]:
294 R' = R x (235-16)/255 + 16;
295 G' = G x (235-16)/255 + 16;
296 B' = B x (235-16)/255 + 16;*/
298 0x00, 0x00, 0x03, 0x6F, 0x00, 0x00, 0x00, 0x10,
299 0x03, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
300 0x00, 0x00, 0x00, 0x00, 0x03, 0x6F, 0x00, 0x10},
302 static int rk3036_hdmi_video_csc(struct hdmi *hdmi_drv,
303 struct hdmi_video_para *vpara)
305 int value,i,csc_mode,c0_c2_change,auto_csc,csc_enable;
306 const char *coeff = NULL;
307 struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
308 struct rk_hdmi_device,
310 /* Enable or disalbe color space convert */
311 hdmi_dbg(hdmi_drv->dev, "[%s] input_color=%d,output_color=%d\n",
312 __func__, vpara->input_color, vpara->output_color);
313 if (vpara->input_color == vpara->output_color) {
314 if ((vpara->input_color >= VIDEO_INPUT_COLOR_YCBCR444) ||
315 ((vpara->input_color == VIDEO_INPUT_COLOR_RGB) &&
316 (vpara->color_limit_range == COLOR_LIMIT_RANGE_0_255))) {
317 value = v_SOF_DISABLE;
318 hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
319 hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
320 m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
321 v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) |
322 v_VIDEO_C0_C2_EXCHANGE(C0_C2_CHANGE_DISABLE));
324 } else if ((vpara->input_color == VIDEO_INPUT_COLOR_RGB) &&
325 (vpara->color_limit_range == COLOR_LIMIT_RANGE_16_235)) {
326 csc_mode = CSC_RGB_0_255_TO_RGB_16_235_8BIT;
327 auto_csc = AUTO_CSC_DISABLE;
328 c0_c2_change = C0_C2_CHANGE_DISABLE;
329 csc_enable = v_CSC_ENABLE;
333 switch (vpara->vic) {
334 case HDMI_720x480i_60Hz_4_3:
335 case HDMI_720x576i_50Hz_4_3:
336 case HDMI_720x480p_60Hz_4_3:
337 case HDMI_720x576p_50Hz_4_3:
338 case HDMI_720x480i_60Hz_16_9:
339 case HDMI_720x576i_50Hz_16_9:
340 case HDMI_720x480p_60Hz_16_9:
341 case HDMI_720x576p_50Hz_16_9:
342 if (vpara->input_color == VIDEO_INPUT_COLOR_RGB
343 && vpara->output_color >= VIDEO_OUTPUT_YCBCR444) {
344 csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
345 auto_csc = AUTO_CSC_DISABLE;
346 c0_c2_change = C0_C2_CHANGE_DISABLE;
347 csc_enable = v_CSC_ENABLE;
348 } else if (vpara->input_color >= VIDEO_OUTPUT_YCBCR444
349 && vpara->output_color == VIDEO_OUTPUT_RGB444) {
350 #ifdef AUTO_DEFINE_CSC
351 csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
352 auto_csc = AUTO_CSC_ENABLE;
353 c0_c2_change = C0_C2_CHANGE_DISABLE;
354 csc_enable = v_CSC_DISABLE;
356 csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
357 auto_csc = AUTO_CSC_DISABLE;
358 c0_c2_change = C0_C2_CHANGE_ENABLE;
359 csc_enable = v_CSC_ENABLE;
364 if (vpara->input_color == VIDEO_INPUT_COLOR_RGB
365 && vpara->output_color >= VIDEO_OUTPUT_YCBCR444) {
366 csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
367 auto_csc = AUTO_CSC_DISABLE;
368 c0_c2_change = C0_C2_CHANGE_DISABLE;
369 csc_enable = v_CSC_ENABLE;
370 } else if (vpara->input_color >= VIDEO_OUTPUT_YCBCR444
371 && vpara->output_color == VIDEO_OUTPUT_RGB444) {
372 #ifdef AUTO_DEFINE_CSC
373 csc_mode = CSC_ITU709_16_235_TO_RGB_0_255_8BIT;
374 auto_csc = AUTO_CSC_ENABLE;
375 c0_c2_change = C0_C2_CHANGE_DISABLE;
376 csc_enable = v_CSC_DISABLE;
378 csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;//CSC_ITU709_16_235_TO_RGB_0_255_8BIT;
379 auto_csc = AUTO_CSC_DISABLE;
380 c0_c2_change = C0_C2_CHANGE_ENABLE;
381 csc_enable = v_CSC_ENABLE;
387 coeff = coeff_csc[csc_mode];
388 for (i = 0; i < 24; i++) {
389 hdmi_writel(hdmi_dev, VIDEO_CSC_COEF+i, coeff[i]);
392 value = v_SOF_DISABLE | csc_enable;
393 hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
394 hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
395 m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
396 v_VIDEO_AUTO_CSC(auto_csc) | v_VIDEO_C0_C2_EXCHANGE(c0_c2_change));
399 if (vpara->input_color != vpara->output_color) {
400 if(vpara->input_color == VIDEO_INPUT_COLOR_RGB) {/*rgb2yuv*/
401 coeff = coeff_csc[3];
402 for (i = 0; i < 24; i++) {
403 hdmi_writel(hdmi_dev, VIDEO_CSC_COEF+i, coeff[i]);
406 value = v_SOF_DISABLE | v_CSC_ENABLE;
407 hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
408 hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
409 m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
410 v_VIDEO_AUTO_CSC(0) | v_VIDEO_C0_C2_EXCHANGE(1));
412 #ifdef AUTO_DEFINE_CSC
413 value = v_SOF_DISABLE | v_CSC_DISABLE;
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(1) | v_VIDEO_C0_C2_EXCHANGE(1));
419 if(hdmi_drv->lcdc->cur_screen->mode.xres <= 576)/*x <= 576,REC-601*/ {
420 coeff = coeff_csc[0];
421 printk("xres<=576,xres=%d\n",hdmi_drv->lcdc->cur_screen->mode.xres);
422 } else/*x > 576,REC-709*/{
423 coeff = coeff_csc[2];
424 printk("xres>576,xres=%d\n",hdmi_drv->lcdc->cur_screen->mode.xres);
426 for (i = 0; i < 24; i++) {
427 hdmi_writel(hdmi_dev, VIDEO_CSC_COEF+i, coeff[i]);
430 value = v_SOF_DISABLE | v_CSC_ENABLE;
431 hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
432 hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
433 m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
434 v_VIDEO_AUTO_CSC(0) | v_VIDEO_C0_C2_EXCHANGE(0));
438 if(vpara->input_color == VIDEO_INPUT_COLOR_RGB) {/*rgb[0:255]->rbg[16:235]*/
439 coeff = coeff_csc[5];
440 for (i = 0; i < 24; i++) {
441 hdmi_writel(hdmi_dev, VIDEO_CSC_COEF+i, coeff[i]);
444 value = v_SOF_DISABLE | v_CSC_ENABLE;
445 hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
446 hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
447 m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
448 v_VIDEO_AUTO_CSC(0) | v_VIDEO_C0_C2_EXCHANGE(1));
450 value = v_SOF_DISABLE;
451 hdmi_writel(hdmi_dev, VIDEO_CONTRL3, value);
452 hdmi_msk_reg(hdmi_dev, VIDEO_CONTRL,
453 m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_EXCHANGE,
454 v_VIDEO_AUTO_CSC(0) | v_VIDEO_C0_C2_EXCHANGE(1));
461 static void rk3036_hdmi_config_avi(struct hdmi *hdmi_drv,
462 unsigned char vic, unsigned char output_color)
466 char info[SIZE_AVI_INFOFRAME];
467 struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
468 struct rk_hdmi_device,
471 memset(info, 0, SIZE_AVI_INFOFRAME);
472 hdmi_writel(hdmi_dev, CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
476 info[3] = info[0] + info[1] + info[2];
478 if (output_color == VIDEO_OUTPUT_RGB444)
479 avi_color_mode = AVI_COLOR_MODE_RGB;
480 else if(output_color == VIDEO_OUTPUT_YCBCR444)
481 avi_color_mode = AVI_COLOR_MODE_YCBCR444;
482 else if(output_color == VIDEO_OUTPUT_YCBCR422)
483 avi_color_mode = AVI_COLOR_MODE_YCBCR422;
485 info[4] = (avi_color_mode << 5);
487 (AVI_COLORIMETRY_NO_DATA << 6) | (AVI_CODED_FRAME_ASPECT_NO_DATA << 4) |
488 ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME;
491 if ((vic == HDMI_720X480I_60HZ_VIC) || (vic == HDMI_720X576I_50HZ_VIC))
496 /* Calculate AVI InfoFrame ChecKsum */
497 for (i = 4; i < SIZE_AVI_INFOFRAME; i++)
500 info[3] = 0x100 - info[3];
502 for (i = 0; i < SIZE_AVI_INFOFRAME; i++)
503 hdmi_writel(hdmi_dev, CONTROL_PACKET_ADDR + i, info[i]);
506 static int rk3036_hdmi_config_video(struct hdmi *hdmi_drv,
507 struct hdmi_video_para *vpara)
509 struct fb_videomode *mode;
510 struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
511 struct rk_hdmi_device,
515 hdmi_dbg(hdmi_drv->dev, "[%s]\n", __func__);
518 hdmi_err(hdmi_drv->dev, "[%s] input parameter error\n",
523 if (hdmi_drv->data->soc_type == HDMI_SOC_RK3036) {
524 vpara->input_color = VIDEO_INPUT_COLOR_RGB;
525 /*vpara->output_color = VIDEO_OUTPUT_RGB444;*//*rk3036 vop only can output rgb fmt*/
526 } else if (hdmi_drv->data->soc_type == HDMI_SOC_RK312X) {
527 /* rk3128 vop can output yuv444 fmt */
528 /*if (vpara->input_color == VIDEO_INPUT_COLOR_YCBCR444)
529 vpara->output_color = VIDEO_OUTPUT_YCBCR444;
531 vpara->output_color = VIDEO_OUTPUT_RGB444;*/
534 /* if (hdmi_drv->pwr_mode == LOWER_PWR)
535 rk3036_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
537 /* Disable video and audio output */
538 hdmi_msk_reg(hdmi_dev, AV_MUTE,
539 m_AUDIO_MUTE | m_VIDEO_BLACK,
540 v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
542 /* Input video mode is SDR RGB24bit, Data enable signal from external */
543 hdmi_writel(hdmi_dev, VIDEO_CONTRL1,
544 v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444) |
546 val = v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS) |
547 v_VIDEO_OUTPUT_FORMAT(vpara->output_color & 0x3) |
548 v_VIDEO_INPUT_CSP(vpara->input_color && 0x1);
549 hdmi_writel(hdmi_dev, VIDEO_CONTRL2,val);
552 hdmi_writel(hdmi_dev, HDCP_CTRL, v_HDMI_DVI(vpara->output_mode));
554 /* Enable or disalbe color space convert */
555 rk3036_hdmi_video_csc(hdmi_drv, vpara);
557 /* Set ext video timing */
559 hdmi_writel(hdmi_dev, VIDEO_TIMING_CTL, 0);
560 mode = (struct fb_videomode *)hdmi_vic_to_videomode(vpara->vic);
562 hdmi_err(hdmi_drv->dev, "[%s] not found vic %d\n", __func__,
566 hdmi_drv->tmdsclk = mode->pixclock;
568 value = v_EXTERANL_VIDEO(1) | v_INETLACE(mode->vmode);
569 if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
570 value |= v_HSYNC_POLARITY(1);
571 if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
572 value |= v_VSYNC_POLARITY(1);
573 hdmi_writel(hdmi_dev, VIDEO_TIMING_CTL, value);
575 value = mode->left_margin + mode->xres + mode->right_margin +
577 hdmi_writel(hdmi_dev, VIDEO_EXT_HTOTAL_L, value & 0xFF);
578 hdmi_writel(hdmi_dev, VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
580 value = mode->left_margin + mode->right_margin + mode->hsync_len;
581 hdmi_writel(hdmi_dev, VIDEO_EXT_HBLANK_L, value & 0xFF);
582 hdmi_writel(hdmi_dev, VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
584 value = mode->left_margin + mode->hsync_len;
585 hdmi_writel(hdmi_dev, VIDEO_EXT_HDELAY_L, value & 0xFF);
586 hdmi_writel(hdmi_dev, VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
588 value = mode->hsync_len;
589 hdmi_writel(hdmi_dev, VIDEO_EXT_HDURATION_L, value & 0xFF);
590 hdmi_writel(hdmi_dev, VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF);
592 value = mode->upper_margin + mode->yres + mode->lower_margin +
594 hdmi_writel(hdmi_dev, VIDEO_EXT_VTOTAL_L, value & 0xFF);
595 hdmi_writel(hdmi_dev, VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
597 value = mode->upper_margin + mode->vsync_len + mode->lower_margin;
598 hdmi_writel(hdmi_dev, VIDEO_EXT_VBLANK, value & 0xFF);
600 if (vpara->vic == HDMI_720x480p_60Hz_4_3 ||
601 vpara->vic == HDMI_720x480p_60Hz_16_9)
604 value = mode->upper_margin + mode->vsync_len;
606 hdmi_writel(hdmi_dev, VIDEO_EXT_VDELAY, value & 0xFF);
608 value = mode->vsync_len;
609 hdmi_writel(hdmi_dev, VIDEO_EXT_VDURATION, value & 0xFF);
611 if (vpara->output_mode == OUTPUT_HDMI) {
612 rk3036_hdmi_config_avi(hdmi_drv, vpara->vic,
613 vpara->output_color);
614 hdmi_dbg(hdmi_drv->dev, "[%s] sucess output HDMI.\n", __func__);
616 hdmi_dbg(hdmi_drv->dev, "[%s] sucess output DVI.\n", __func__);
620 hdmi_writel(hdmi_dev, PHY_PRE_DIV_RATIO, 0x1e);
621 hdmi_writel(hdmi_dev, PHY_FEEDBACK_DIV_RATIO_LOW, 0x2c);
622 hdmi_writel(hdmi_dev, PHY_FEEDBACK_DIV_RATIO_HIGH, 0x01);
627 static void rk3036_hdmi_config_aai(struct hdmi *hdmi_drv)
630 char info[SIZE_AUDIO_INFOFRAME];
631 struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
632 struct rk_hdmi_device,
635 memset(info, 0, SIZE_AUDIO_INFOFRAME);
641 info[3] = info[0] + info[1] + info[2];
642 for (i = 4; i < SIZE_AUDIO_INFOFRAME; i++)
645 info[3] = 0x100 - info[3];
647 hdmi_writel(hdmi_dev, CONTROL_PACKET_BUF_INDEX, INFOFRAME_AAI);
648 for (i = 0; i < SIZE_AUDIO_INFOFRAME; i++)
649 hdmi_writel(hdmi_dev, CONTROL_PACKET_ADDR + i, info[i]);
652 static int rk3036_hdmi_config_audio(struct hdmi *hdmi_drv,
653 struct hdmi_audio *audio)
655 int rate, N, channel, mclk_fs;
656 struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
657 struct rk_hdmi_device,
660 if (audio->channel < 3)
661 channel = I2S_CHANNEL_1_2;
662 else if (audio->channel < 5)
663 channel = I2S_CHANNEL_3_4;
664 else if (audio->channel < 7)
665 channel = I2S_CHANNEL_5_6;
667 channel = I2S_CHANNEL_7_8;
669 switch (audio->rate) {
670 case HDMI_AUDIO_FS_32000:
673 mclk_fs = MCLK_384FS;
675 case HDMI_AUDIO_FS_44100:
678 mclk_fs = MCLK_256FS;
680 case HDMI_AUDIO_FS_48000:
683 mclk_fs = MCLK_256FS;
685 case HDMI_AUDIO_FS_88200:
688 mclk_fs = MCLK_128FS;
690 case HDMI_AUDIO_FS_96000:
693 mclk_fs = MCLK_128FS;
695 case HDMI_AUDIO_FS_176400:
698 mclk_fs = MCLK_128FS;
700 case HDMI_AUDIO_FS_192000:
703 mclk_fs = MCLK_128FS;
706 dev_err(hdmi_drv->dev, "[%s] not support such sample rate %d\n",
707 __func__, audio->rate);
711 /* set_audio source I2S */
712 if (HDMI_CODEC_SOURCE_SELECT == INPUT_IIS) {
713 hdmi_writel(hdmi_dev, AUDIO_CTRL1, 0x00);
714 hdmi_writel(hdmi_dev, AUDIO_SAMPLE_RATE, rate);
715 hdmi_writel(hdmi_dev, AUDIO_I2S_MODE,
716 v_I2S_MODE(I2S_STANDARD) | v_I2S_CHANNEL(channel));
717 hdmi_writel(hdmi_dev, AUDIO_I2S_MAP, 0x00);
719 hdmi_writel(hdmi_dev, AUDIO_I2S_SWAPS_SPDIF, 0);
721 hdmi_writel(hdmi_dev, AUDIO_CTRL1, 0x08);
723 hdmi_writel(hdmi_dev, AUDIO_I2S_SWAPS_SPDIF, 0);
727 hdmi_writel(hdmi_dev, AUDIO_N_H, (N >> 16) & 0x0F);
728 hdmi_writel(hdmi_dev, AUDIO_N_M, (N >> 8) & 0xFF);
729 hdmi_writel(hdmi_dev, AUDIO_N_L, N & 0xFF);
730 rk3036_hdmi_config_aai(hdmi_drv);
735 void rk3036_hdmi_control_output(struct hdmi *hdmi_drv, int enable)
738 struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
739 struct rk_hdmi_device,
741 if (hdmi_drv->uboot_logo) {
742 hdmi_drv->uboot_logo = 0;
747 if (hdmi_drv->pwr_mode == LOWER_PWR)
748 rk3036_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
750 rk3036_hdmi_sys_power(hdmi_drv, true);
751 rk3036_hdmi_sys_power(hdmi_drv, false);
753 rk3036_hdmi_sys_power(hdmi_drv, true);
754 hdmi_writel(hdmi_dev, 0xce, 0x00);
756 hdmi_writel(hdmi_dev, 0xce, 0x01);
758 hdmi_readl(hdmi_dev, AV_MUTE, &mutestatus);
759 if (mutestatus && (m_AUDIO_MUTE | m_VIDEO_BLACK)) {
760 hdmi_msk_reg(hdmi_dev, AV_MUTE,
761 m_AUDIO_MUTE | m_VIDEO_BLACK,
762 v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
764 rk3036_hdmi_av_mute(hdmi_drv, 0);
766 hdmi_msk_reg(hdmi_dev, AV_MUTE,
767 m_AUDIO_MUTE | m_VIDEO_BLACK,
768 v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
769 rk3036_hdmi_av_mute(hdmi_drv, 1);
771 rk3036_hdmi_set_pwr_mode(hdmi_drv, LOWER_PWR);
775 int rk3036_hdmi_removed(struct hdmi *hdmi_drv)
777 dev_info(hdmi_drv->dev, "Removed.\n");
778 if (hdmi_drv->hdcp_power_off_cb)
779 hdmi_drv->hdcp_power_off_cb();
780 rk3036_hdmi_set_pwr_mode(hdmi_drv, LOWER_PWR);
782 return HDMI_ERROR_SUCESS;
785 void rk3036_hdmi_irq(struct hdmi *hdmi_drv)
788 struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
789 struct rk_hdmi_device,
791 hdmi_readl(hdmi_dev, INTERRUPT_STATUS1, &interrupt);
793 hdmi_writel(hdmi_dev, INTERRUPT_STATUS1, interrupt);
794 dev_info(hdmi_drv->dev, "Clear edid irq.\n");
797 hdmi_readl(hdmi_dev, HDMI_STATUS, &interrupt);
799 hdmi_writel(hdmi_dev, HDMI_STATUS, interrupt);
801 if (interrupt & m_INT_HOTPLUG) {
802 if (hdmi_drv->state == HDMI_SLEEP)
803 hdmi_drv->state = WAIT_HOTPLUG;
805 queue_delayed_work(hdmi_drv->workqueue, &hdmi_drv->delay_work,
806 msecs_to_jiffies(20));
810 if (hdmi_drv->hdcp_irq_cb)
811 hdmi_drv->hdcp_irq_cb(0);
812 if (hdmi_drv->cec_irq)
816 static void rk3036_hdmi_reset(struct hdmi *hdmi_drv)
820 struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
821 struct rk_hdmi_device,
824 hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL);
826 hdmi_msk_reg(hdmi_dev, SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG);
828 msk = m_REG_CLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL;
829 val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH;
830 hdmi_msk_reg(hdmi_dev, SYS_CTRL, msk, val);
832 rk3036_hdmi_set_pwr_mode(hdmi_drv, LOWER_PWR);
834 static int rk3036_hdmi_debug(struct hdmi *hdmi_drv,int cmd)
838 printk("%s[%d]:cmd=%d\n",__func__,__LINE__,cmd);
839 rk3036_hdmi_irq(hdmi_drv);
842 printk("%s[%d]:cmd=%d\n",__func__,__LINE__,cmd);
845 printk("%s[%d]:cmd=%d\n",__func__,__LINE__,cmd);
851 static struct rk_hdmi_drv_ops hdmi_drv_ops = {
852 .hdmi_debug = rk3036_hdmi_debug,
855 int rk3036_hdmi_initial(struct hdmi *hdmi_drv)
857 int rc = HDMI_ERROR_SUCESS;
859 hdmi_drv->pwr_mode = NORMAL;
860 hdmi_drv->remove = rk3036_hdmi_removed;
861 hdmi_drv->control_output = rk3036_hdmi_control_output;
862 hdmi_drv->config_video = rk3036_hdmi_config_video;
863 hdmi_drv->config_audio = rk3036_hdmi_config_audio;
864 hdmi_drv->detect_hotplug = rk3036_hdmi_detect_hotplug;
865 hdmi_drv->read_edid = rk3036_hdmi_read_edid;
866 hdmi_drv->insert = rk3036_hdmi_insert;
867 hdmi_drv->ops = &hdmi_drv_ops;
868 hdmi_drv->support_vic = rk3036_hdmi_support_vic;
869 hdmi_drv->support_vic_num = ARRAY_SIZE(rk3036_hdmi_support_vic);
871 if (!hdmi_drv->uboot_logo) {
872 rk3036_hdmi_reset_pclk();
873 rk3036_hdmi_reset(hdmi_drv);
875 hdmi_drv->hotplug = rk3036_hdmi_detect_hotplug(hdmi_drv);
876 if (hdmi_drv->hotplug == HDMI_HPD_REMOVED) {
877 rk3036_hdmi_removed(hdmi_drv);
878 hdmi_drv->state = HDMI_SLEEP;
879 hdmi_drv->lcdc->uboot_logo = 0;
880 hdmi_drv->uboot_logo = 0;
883 if (hdmi_drv->hdcp_power_on_cb)
884 rc = hdmi_drv->hdcp_power_on_cb();