1 #include "rockchip-hdmi.h"
3 static const struct hdmi_video_timing hdmi_mode[] = {
4 /* name refresh xres yres pixclock h_bp h_fp v_bp v_fp h_pw v_pw polariry PorI flag vic 2ndvic pixelrepeat interface */
6 { { "720x480i@60Hz", 60, 720, 480, 27000000, 57, 19, 15, 4, 62, 3, 0, 1, 0 }, 6, HDMI_720X480I_60HZ_16_9, 2, OUT_P888},
7 { { "720x576i@50Hz", 50, 720, 576, 27000000, 69, 12, 19, 2, 63, 3, 0, 1, 0 }, 21, HDMI_720X576I_50HZ_16_9, 2, OUT_P888},
8 { { "720x480p@60Hz", 60, 720, 480, 27000000, 60, 16, 30, 9, 62, 6, 0, 0, 0 }, 2, HDMI_720X480P_60HZ_16_9, 1, OUT_P888},
9 { { "720x576p@50Hz", 50, 720, 576, 27000000, 68, 12, 39, 5, 64, 5, 0, 0, 0 }, 17, HDMI_720X576P_50HZ_16_9, 1, OUT_P888},
10 { { "1280x720p@24Hz", 24, 1280, 720, 59400000, 220, 1760, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 60, HDMI_1280X720P_24HZ_4_3, 1, OUT_P888},
11 { { "1280x720p@25Hz", 25, 1280, 720, 74250000, 220, 2420, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 61, HDMI_1280X720P_25HZ_4_3, 1, OUT_P888},
12 { { "1280x720p@30Hz", 30, 1280, 720, 74250000, 220, 1760, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 62, HDMI_1280X720P_30HZ_4_3, 1, OUT_P888},
13 { { "1280x720p@50Hz", 50, 1280, 720, 74250000, 220, 440, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 19, HDMI_1280X720P_50HZ_4_3, 1, OUT_P888},
14 { { "1280x720p@60Hz", 60, 1280, 720, 74250000, 220, 110, 20, 5, 40, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 4, HDMI_1280X720P_60HZ_4_3, 1, OUT_P888},
15 { { "1920x1080i@50Hz", 50, 1920, 1080, 74250000, 148, 528, 15, 2, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 1, 0 }, 20, 0, 1, OUT_P888},
16 { { "1920x1080i@60Hz", 60, 1920, 1080, 74250000, 148, 88, 15, 2, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 1, 0 }, 5, 0, 1, OUT_P888},
17 { { "1920x1080p@24Hz", 24, 1920, 1080, 74250000, 148, 638, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 32, HDMI_1920X1080P_24HZ_4_3, 1, OUT_P888},
18 { { "1920x1080p@25Hz", 25, 1920, 1080, 74250000, 148, 528, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 33, HDMI_1920X1080P_25HZ_4_3, 1, OUT_P888},
19 { { "1920x1080p@30Hz", 30, 1920, 1080, 74250000, 148, 88, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 34, HDMI_1920X1080P_30HZ_4_3, 1, OUT_P888},
20 { { "1920x1080p@50Hz", 50, 1920, 1080, 148500000, 148, 528, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 31, HDMI_1920X1080P_50HZ_4_3, 1, OUT_P888},
21 { { "1920x1080p@60Hz", 60, 1920, 1080, 148500000, 148, 88, 36, 4, 44, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 16, HDMI_1920X1080P_60HZ_4_3, 1, OUT_P888},
22 { { "3840x2160p@24Hz", 24, 3840, 2160, 297000000, 296, 1276, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 93, HDMI_3840X2160P_24HZ_4_3, 1, OUT_P888},
23 { { "3840x2160p@25Hz", 25, 3840, 2160, 297000000, 296, 1056, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 94, HDMI_3840X2160P_25HZ_4_3, 1, OUT_P888},
24 { { "3840x2160p@30Hz", 30, 3840, 2160, 297000000, 296, 176, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 95, HDMI_3840X2160P_30HZ_4_3, 1, OUT_P888},
25 { { "4096x2160p@24Hz", 24, 4096, 2160, 297000000, 296, 1020, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 98, 0, 1, OUT_P888},
26 { { "4096x2160p@25Hz", 25, 4096, 2160, 297000000, 128, 968, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 99, 0, 1, OUT_P888},
27 { { "4096x2160p@30Hz", 30, 4096, 2160, 297000000, 128, 88, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 100, 0, 1, OUT_P888},
28 { { "3840x2160p@50Hz", 50, 3840, 2160, 594000000, 296, 1056, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 96, HDMI_3840X2160P_50HZ_4_3, 1, OUT_P888},
29 { { "3840x2160p@60Hz", 60, 3840, 2160, 594000000, 296, 176, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 97, HDMI_3840X2160P_60HZ_4_3, 1, OUT_P888},
30 { { "4096x2160p@50Hz", 50, 4096, 2160, 594000000, 128, 968, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 101, 0, 1, OUT_P888},
31 { { "4096x2160p@60Hz", 60, 4096, 2160, 594000000, 128, 88, 72, 8, 88, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0 }, 102, 0, 1, OUT_P888},
34 static int hdmi_set_info(struct rk_screen *screen, struct hdmi *hdmi)
37 struct fb_videomode *mode;
39 if (screen == NULL || hdmi == NULL)
40 return HDMI_ERROR_FALSE;
43 hdmi->vic = hdmi->property->defaultmode;
45 for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
46 if (hdmi_mode[i].vic == (hdmi->vic & HDMI_VIC_MASK) ||
47 hdmi_mode[i].vic_2nd == (hdmi->vic & HDMI_VIC_MASK))
50 if (i == ARRAY_SIZE(hdmi_mode))
51 return HDMI_ERROR_FALSE;
53 memset(screen, 0, sizeof(struct rk_screen));
55 /* screen type & face */
56 screen->type = SCREEN_HDMI;
57 if (hdmi->colormode_input == HDMI_COLOR_RGB_0_255)
58 screen->color_mode = COLOR_RGB;
60 screen->color_mode = COLOR_YCBCR;
61 if (hdmi->vic & HDMI_VIDEO_YUV420)
62 screen->face = OUT_YUV_420;
64 screen->face = hdmi_mode[i].interface;
65 screen->pixelrepeat = hdmi_mode[i].pixelrepeat - 1;
66 mode = (struct fb_videomode *)&(hdmi_mode[i].mode);
71 #ifdef CONFIG_HDMI_RK616
72 screen->pin_hsync = 0;
73 screen->pin_vsync = 0;
75 if (FB_SYNC_HOR_HIGH_ACT & mode->sync)
76 screen->pin_hsync = 1;
78 screen->pin_hsync = 0;
79 if (FB_SYNC_VERT_HIGH_ACT & mode->sync)
80 screen->pin_vsync = 1;
82 screen->pin_vsync = 0;
88 if (hdmi->soctype == HDMI_SOC_RK3368 &&
89 screen->color_mode == COLOR_YCBCR &&
90 screen->face == OUT_P888)
96 screen->swap_delta = 0;
97 screen->swap_dumy = 0;
99 /* Operation function*/
101 screen->standby = NULL;
103 screen->overscan.left = hdmi->xscale;
104 screen->overscan.top = hdmi->yscale;
105 screen->overscan.right = hdmi->xscale;
106 screen->overscan.bottom = hdmi->yscale;
111 * hdmi_find_best_mode: find the video mode nearest to input vic
116 * If vic is zero, return the high resolution video mode vic.
118 int hdmi_find_best_mode(struct hdmi *hdmi, int vic)
120 struct list_head *pos, *head = &hdmi->edid.modelist;
121 struct display_modelist *modelist;
123 /* pr_info("%s vic %d\n", __FUNCTION__, vic); */
125 list_for_each(pos, head) {
128 struct display_modelist, list);
129 if (modelist->vic == vic) {
135 if ((vic == 0 || found == 0) && head->next != head) {
136 /* If parse edid error, we select default mode; */
137 if (hdmi->edid.specs == NULL ||
138 hdmi->edid.specs->modedb_len == 0)
139 return hdmi->property->defaultmode;
140 /*modelist = list_entry(head->prev,
141 struct display_modelist, list);*/
143 modelist = list_entry(head->next,
144 struct display_modelist, list);
147 if (modelist != NULL)
148 return modelist->vic;
153 * hdmi_set_lcdc: switch lcdc mode to required video mode
159 int hdmi_set_lcdc(struct hdmi *hdmi)
162 struct rk_screen screen;
165 hdmi->vic = hdmi_find_best_mode(hdmi, 0);
167 hdmi->vic = hdmi_find_best_mode(hdmi, hdmi->vic);
170 hdmi->vic = hdmi->property->defaultmode;
172 rc = hdmi_set_info(&screen, hdmi);
175 rk_fb_switch_screen(&screen, 1, hdmi->lcdc->id);
176 /* if (rk_fb_get_display_policy() != DISPLAY_POLICY_BOX)
177 rk_fb_disp_scale(hdmi->xscale,
185 * hdmi_videomode_compare - compare 2 videomodes
186 * @mode1: first videomode
187 * @mode2: second videomode
190 * 1 if mode1 > mode2, 0 if mode1 = mode2, -1 mode1 < mode2
192 static int hdmi_videomode_compare(const struct fb_videomode *mode1,
193 const struct fb_videomode *mode2)
195 if (mode1->xres > mode2->xres)
198 if (mode1->xres == mode2->xres) {
199 if (mode1->yres > mode2->yres)
201 if (mode1->yres == mode2->yres) {
202 if (mode1->vmode < mode2->vmode)
204 if (mode1->pixclock > mode2->pixclock)
206 if (mode1->pixclock == mode2->pixclock) {
207 if (mode1->refresh > mode2->refresh)
209 if (mode1->refresh == mode2->refresh) {
210 if (mode2->flag > mode1->flag)
212 if (mode2->flag < mode1->flag)
214 if (mode2->vmode > mode1->vmode)
216 if (mode2->vmode == mode1->vmode)
226 * hdmi_add_vic - add entry to modelist according vic
227 * @vic: vic to be added
228 * @head: struct list_head of modelist
231 * Will only add unmatched mode entries
233 int hdmi_add_vic(int vic, struct list_head *head)
235 struct list_head *pos;
236 struct display_modelist *modelist;
239 /* DBG("%s vic %d", __FUNCTION__, vic); */
243 list_for_each(pos, head) {
244 modelist = list_entry(pos, struct display_modelist, list);
252 modelist = kmalloc(sizeof(*modelist),
257 memset(modelist, 0, sizeof(struct display_modelist));
259 list_add_tail(&modelist->list, head);
265 * hdmi_add_videomode: adds videomode entry to modelist
266 * @mode: videomode to be added
267 * @head: struct list_head of modelist
270 * Will only add unmatched mode entries
272 static int hdmi_add_videomode(const struct fb_videomode *mode,
273 struct list_head *head)
275 struct list_head *pos;
276 struct display_modelist *modelist, *modelist_new;
277 struct fb_videomode *m;
280 for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
281 m = (struct fb_videomode *)&(hdmi_mode[i].mode);
282 if (fb_mode_is_equal(m, mode)) {
289 list_for_each(pos, head) {
290 modelist = list_entry(pos,
291 struct display_modelist, list);
293 if (fb_mode_is_equal(m, mode))
295 else if (hdmi_videomode_compare(m, mode) == -1)
299 modelist_new = kmalloc(sizeof(*modelist_new), GFP_KERNEL);
302 memset(modelist_new, 0, sizeof(struct display_modelist));
303 modelist_new->mode = hdmi_mode[i].mode;
304 modelist_new->vic = hdmi_mode[i].vic;
305 list_add_tail(&modelist_new->list, pos);
312 * hdmi_show_sink_info: show hdmi sink device infomation
313 * @hdmi: handle of hdmi
315 static void hdmi_show_sink_info(struct hdmi *hdmi)
317 struct list_head *pos, *head = &hdmi->edid.modelist;
318 struct display_modelist *modelist;
319 struct fb_videomode *m;
321 struct hdmi_audio *audio;
323 pr_info("******** Show Sink Info ********\n");
324 pr_info("Max tmds clk is %u\n", hdmi->edid.maxtmdsclock);
325 if (hdmi->edid.hf_vsdb_version)
326 pr_info("Support HFVSDB\n");
327 if (hdmi->edid.scdc_present)
328 pr_info("Support SCDC\n");
329 pr_info("Support video mode:\n");
330 list_for_each(pos, head) {
331 modelist = list_entry(pos, struct display_modelist, list);
334 pr_info(" %s(YCbCr420)\n", m->name);
336 pr_info(" %s\n", m->name);
338 pr_info("Support video color mode:\n");
340 if (hdmi->edid.ycbcr420)
341 pr_info(" YCbCr420\n");
342 if (hdmi->edid.ycbcr422)
343 pr_info(" YCbCr422\n");
344 if (hdmi->edid.ycbcr444)
345 pr_info(" YCbCr444\n");
346 pr_info("Support video color depth:\n");
348 if (hdmi->edid.deepcolor & HDMI_DEEP_COLOR_30BITS)
350 if (hdmi->edid.deepcolor & HDMI_DEEP_COLOR_36BITS)
352 if (hdmi->edid.deepcolor & HDMI_DEEP_COLOR_48BITS)
354 if (hdmi->edid.ycbcr420)
355 pr_info(" 420_24bit\n");
356 if (hdmi->edid.deepcolor_420 & HDMI_DEEP_COLOR_30BITS)
357 pr_info(" 420_30bit\n");
358 if (hdmi->edid.deepcolor_420 & HDMI_DEEP_COLOR_36BITS)
359 pr_info(" 420_36bit\n");
360 if (hdmi->edid.deepcolor_420 & HDMI_DEEP_COLOR_48BITS)
361 pr_info(" 420_48bit\n");
362 pr_info("Support audio type:\n");
363 for (i = 0; i < hdmi->edid.audio_num; i++) {
364 audio = &(hdmi->edid.audio[i]);
365 switch (audio->type) {
366 case HDMI_AUDIO_LPCM:
372 case HDMI_AUDIO_MPEG1:
378 case HDMI_AUDIO_MPEG2:
381 case HDMI_AUDIO_AAC_LC:
387 case HDMI_AUDIO_ATARC:
393 case HDMI_AUDIO_E_AC3:
396 case HDMI_AUDIO_DTS_HD:
397 pr_info(" DTS-HD\n");
405 case HDMI_AUDIO_WMA_PRO:
406 pr_info(" WMP-PRO\n");
409 pr_info(" Unkown\n");
412 pr_info("Support max audio channel is %d\n", audio->channel);
413 pr_info("Support audio sample rate:\n");
414 if (audio->rate & HDMI_AUDIO_FS_32000)
416 if (audio->rate & HDMI_AUDIO_FS_44100)
418 if (audio->rate & HDMI_AUDIO_FS_48000)
420 if (audio->rate & HDMI_AUDIO_FS_88200)
422 if (audio->rate & HDMI_AUDIO_FS_96000)
424 if (audio->rate & HDMI_AUDIO_FS_176400)
425 pr_info(" 176400\n");
426 if (audio->rate & HDMI_AUDIO_FS_192000)
427 pr_info(" 192000\n");
428 pr_info("Support audio word lenght:\n");
429 if (audio->rate & HDMI_AUDIO_WORD_LENGTH_16bit)
431 if (audio->rate & HDMI_AUDIO_WORD_LENGTH_20bit)
433 if (audio->rate & HDMI_AUDIO_WORD_LENGTH_24bit)
437 pr_info("******** Show Sink Info ********\n");
441 * hdmi_sort_modelist: sort modelist of edid
442 * @edid: edid to be sort
444 static void hdmi_sort_modelist(struct hdmi_edid *edid, int feature)
446 struct list_head *pos, *pos_new;
447 struct list_head head_new, *head = &edid->modelist;
448 struct display_modelist *modelist, *modelist_new, *modelist_n;
449 struct fb_videomode *m, *m_new;
452 INIT_LIST_HEAD(&head_new);
453 list_for_each(pos, head) {
454 modelist = list_entry(pos, struct display_modelist, list);
455 /*pr_info("%s vic %d\n", __function__, modelist->vic);*/
456 for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
457 vic = modelist->vic & HDMI_VIC_MASK;
458 if (vic == hdmi_mode[i].vic ||
459 vic == hdmi_mode[i].vic_2nd) {
460 if ((feature & SUPPORT_4K) == 0 &&
461 hdmi_mode[i].mode.xres >= 3840)
463 if ((feature & SUPPORT_4K_4096) == 0 &&
464 hdmi_mode[i].mode.xres == 4096)
466 if ((feature & SUPPORT_TMDS_600M) == 0 &&
467 !(modelist->vic & HDMI_VIDEO_YUV420) &&
468 hdmi_mode[i].mode.pixclock > 340000000)
470 if ((modelist->vic & HDMI_VIDEO_YUV420) &&
471 (feature & SUPPORT_YUV420) == 0)
473 if ((feature & SUPPORT_1080I) == 0 &&
474 hdmi_mode[i].mode.xres == 1920 &&
475 hdmi_mode[i].mode.vmode ==
478 if ((feature & SUPPORT_480I_576I) == 0 &&
479 hdmi_mode[i].mode.xres == 720 &&
480 hdmi_mode[i].mode.vmode ==
484 modelist->vic = hdmi_mode[i].vic;
485 modelist->mode = hdmi_mode[i].mode;
486 if (vic & HDMI_VIDEO_YUV420) {
487 modelist->vic |= HDMI_VIDEO_YUV420;
488 modelist->mode.flag = 1;
491 m = (struct fb_videomode *)&(modelist->mode);
492 list_for_each(pos_new, &head_new) {
495 struct display_modelist,
497 m_new = &modelist_new->mode;
499 hdmi_videomode_compare(m, m_new);
505 kmalloc(sizeof(*modelist_n),
509 *modelist_n = *modelist;
510 list_add_tail(&modelist_n->list,
517 fb_destroy_modelist(head);
518 if (head_new.next == &head_new) {
519 pr_info("There is no available video mode in EDID.\n");
520 INIT_LIST_HEAD(&edid->modelist);
522 edid->modelist = head_new;
523 edid->modelist.prev->next = &edid->modelist;
524 edid->modelist.next->prev = &edid->modelist;
529 * hdmi_ouputmode_select - select hdmi transmitter output mode: hdmi or dvi?
530 * @hdmi: handle of hdmi
531 * @edid_ok: get EDID data success or not, HDMI_ERROR_SUCESS means success.
533 int hdmi_ouputmode_select(struct hdmi *hdmi, int edid_ok)
535 struct list_head *head = &hdmi->edid.modelist;
536 struct fb_monspecs *specs = hdmi->edid.specs;
537 struct fb_videomode *modedb = NULL, *mode = NULL;
538 int i, pixclock, feature = hdmi->property->feature;
540 if (edid_ok != HDMI_ERROR_SUCESS) {
541 dev_err(hdmi->dev, "warning: EDID error, assume sink as HDMI !!!!");
542 hdmi->edid.status = -1;
543 hdmi->edid.sink_hdmi = 1;
544 hdmi->edid.baseaudio_support = 1;
545 hdmi->edid.ycbcr444 = 0;
546 hdmi->edid.ycbcr422 = 0;
549 if (head->next == head) {
551 "warning: no CEA video mode parsed from EDID !!!!\n");
552 /* If EDID get error, list all system supported mode.
553 If output mode is set to DVI and EDID is ok, check
556 if (hdmi->edid.sink_hdmi == 0 && specs && specs->modedb_len) {
557 /* Get max resolution timing */
558 modedb = &specs->modedb[0];
559 for (i = 0; i < specs->modedb_len; i++) {
560 if (specs->modedb[i].xres > modedb->xres)
561 modedb = &specs->modedb[i];
562 else if (specs->modedb[i].xres ==
564 specs->modedb[i].yres > modedb->yres)
565 modedb = &specs->modedb[i];
567 /* For some monitor, the max pixclock read from EDID
568 is smaller than the clock of max resolution mode
569 supported. We fix it. */
570 pixclock = PICOS2KHZ(modedb->pixclock);
574 if (pixclock == 148250000)
575 pixclock = 148500000;
576 if (pixclock > specs->dclkmax)
577 specs->dclkmax = pixclock;
580 for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
581 mode = (struct fb_videomode *)&(hdmi_mode[i].mode);
583 if ((mode->pixclock < specs->dclkmin) ||
584 (mode->pixclock > specs->dclkmax) ||
585 (mode->refresh < specs->vfmin) ||
586 (mode->refresh > specs->vfmax) ||
587 (mode->xres > modedb->xres) ||
588 (mode->yres > modedb->yres))
591 /* If there is no valid information in EDID,
592 just list common hdmi foramt. */
593 if (mode->xres > 3840 ||
594 mode->refresh < 50 ||
595 mode->vmode == FB_VMODE_INTERLACED)
598 if ((feature & SUPPORT_TMDS_600M) == 0 &&
599 mode->pixclock > 340000000)
601 if ((feature & SUPPORT_4K) == 0 &&
604 if ((feature & SUPPORT_4K_4096) == 0 &&
607 if ((feature & SUPPORT_1080I) == 0 &&
608 mode->xres == 1920 &&
609 mode->vmode == FB_VMODE_INTERLACED)
611 if ((feature & SUPPORT_480I_576I) == 0 &&
613 mode->vmode == FB_VMODE_INTERLACED)
615 hdmi_add_videomode(mode, head);
618 /* There are some video mode is not defined in EDID extend
619 block, so we need to check first block data.*/
620 if (specs && specs->modedb_len) {
621 for (i = 0; i < specs->modedb_len; i++) {
622 modedb = &specs->modedb[0];
623 pixclock = hdmi_videomode_to_vic(modedb);
625 hdmi_add_vic(pixclock, head);
628 hdmi_sort_modelist(&hdmi->edid, hdmi->property->feature);
630 hdmi_show_sink_info(hdmi);
632 return HDMI_ERROR_SUCESS;
636 * hdmi_videomode_to_vic: transverse video mode to vic
637 * @vmode: videomode to transverse
640 int hdmi_videomode_to_vic(struct fb_videomode *vmode)
642 struct fb_videomode *mode;
643 unsigned char vic = 0;
646 for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
647 mode = (struct fb_videomode *)&(hdmi_mode[i].mode);
648 if (vmode->vmode == mode->vmode &&
649 vmode->refresh == mode->refresh &&
650 vmode->xres == mode->xres &&
651 vmode->yres == mode->yres &&
652 vmode->left_margin == mode->left_margin &&
653 vmode->right_margin == mode->right_margin &&
654 vmode->upper_margin == mode->upper_margin &&
655 vmode->lower_margin == mode->lower_margin &&
656 vmode->hsync_len == mode->hsync_len &&
657 vmode->vsync_len == mode->vsync_len) {
658 vic = hdmi_mode[i].vic;
666 * hdmi_vic2timing: transverse vic mode to video timing
667 * @vmode: vic to transverse
670 const struct hdmi_video_timing *hdmi_vic2timing(int vic)
677 for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
678 if (hdmi_mode[i].vic == vic || hdmi_mode[i].vic_2nd == vic)
679 return &(hdmi_mode[i]);
685 * hdmi_vic_to_videomode: transverse vic mode to video mode
686 * @vmode: vic to transverse
689 const struct fb_videomode *hdmi_vic_to_videomode(int vic)
696 for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
697 if (hdmi_mode[i].vic == (vic & HDMI_VIC_MASK) ||
698 hdmi_mode[i].vic_2nd == (vic & HDMI_VIC_MASK))
699 return &hdmi_mode[i].mode;
705 * hdmi_init_modelist: initial hdmi mode list
711 void hdmi_init_modelist(struct hdmi *hdmi)
714 struct list_head *head = &hdmi->edid.modelist;
716 feature = hdmi->property->feature;
717 INIT_LIST_HEAD(&hdmi->edid.modelist);
718 for (i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
719 if ((feature & SUPPORT_TMDS_600M) == 0 &&
720 hdmi_mode[i].mode.pixclock > 340000000)
722 if ((feature & SUPPORT_4K) == 0 &&
723 hdmi_mode[i].mode.xres >= 3840)
725 if ((feature & SUPPORT_4K_4096) == 0 &&
726 hdmi_mode[i].mode.xres == 4096)
728 if ((feature & SUPPORT_1080I) == 0 &&
729 hdmi_mode[i].mode.xres == 1920 &&
730 hdmi_mode[i].mode.vmode == FB_VMODE_INTERLACED)
732 if ((feature & SUPPORT_480I_576I) == 0 &&
733 hdmi_mode[i].mode.xres == 720 &&
734 hdmi_mode[i].mode.vmode == FB_VMODE_INTERLACED)
736 hdmi_add_videomode(&(hdmi_mode[i].mode), head);