aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/sh_mobile_hdmi.c138
1 files changed, 88 insertions, 50 deletions
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
index 94a94fde2c67..f0ff2848700c 100644
--- a/drivers/video/sh_mobile_hdmi.c
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -611,14 +611,39 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi)
611 hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL); 611 hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL);
612} 612}
613 613
614static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
615 const struct fb_videomode *mode)
616{
617 long target = PICOS2KHZ(mode->pixclock) * 1000,
618 rate = clk_round_rate(hdmi->hdmi_clk, target);
619 unsigned long rate_error = rate > 0 ? abs(rate - target) : ULONG_MAX;
620
621 dev_dbg(hdmi->dev, "%u-%u-%u-%u x %u-%u-%u-%u\n",
622 mode->left_margin, mode->xres,
623 mode->right_margin, mode->hsync_len,
624 mode->upper_margin, mode->yres,
625 mode->lower_margin, mode->vsync_len);
626
627 dev_dbg(hdmi->dev, "\t@%lu(+/-%lu)Hz, e=%lu / 1000, r=%uHz\n", target,
628 rate_error, rate_error ? 10000 / (10 * target / rate_error) : 0,
629 mode->refresh);
630
631 return rate_error;
632}
633
614static int sh_hdmi_read_edid(struct sh_hdmi *hdmi) 634static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)
615{ 635{
616 struct fb_var_screeninfo tmpvar; 636 struct fb_var_screeninfo tmpvar;
617 /* TODO: When we are ready to use EDID, use this to fill &hdmi->var */
618 struct fb_var_screeninfo *var = &tmpvar; 637 struct fb_var_screeninfo *var = &tmpvar;
619 const struct fb_videomode *mode, *found = NULL; 638 const struct fb_videomode *mode, *found = NULL;
620 int i; 639 struct fb_info *info = hdmi->info;
640 struct fb_modelist *modelist = NULL;
641 unsigned int f_width = 0, f_height = 0, f_refresh = 0;
642 unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */
643 bool exact_match = false;
621 u8 edid[128]; 644 u8 edid[128];
645 char *forced;
646 int i;
622 647
623 /* Read EDID */ 648 /* Read EDID */
624 dev_dbg(hdmi->dev, "Read back EDID code:"); 649 dev_dbg(hdmi->dev, "Read back EDID code:");
@@ -639,69 +664,82 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)
639 664
640 fb_edid_to_monspecs(edid, &hdmi->monspec); 665 fb_edid_to_monspecs(edid, &hdmi->monspec);
641 666
642 /* First look for an exact match */ 667 fb_get_options("sh_mobile_lcdc", &forced);
643 for (i = 0, mode = hdmi->monspec.modedb; i < hdmi->monspec.modedb_len; 668 if (forced && *forced) {
669 /* Only primitive parsing so far */
670 i = sscanf(forced, "%ux%u@%u",
671 &f_width, &f_height, &f_refresh);
672 if (i < 2) {
673 f_width = 0;
674 f_height = 0;
675 }
676 dev_dbg(hdmi->dev, "Forced mode %ux%u@%uHz\n",
677 f_width, f_height, f_refresh);
678 }
679
680 /* Walk monitor modes to find the best or the exact match */
681 for (i = 0, mode = hdmi->monspec.modedb;
682 f_width && f_height && i < hdmi->monspec.modedb_len && !exact_match;
644 i++, mode++) { 683 i++, mode++) {
645 dev_dbg(hdmi->dev, "%u-%u-%u-%u x %u-%u-%u-%u @ %lu kHz monitor detected\n", 684 unsigned long rate_error = sh_hdmi_rate_error(hdmi, mode);
646 mode->left_margin, mode->xres, 685
647 mode->right_margin, mode->hsync_len, 686 /* No interest in unmatching modes */
648 mode->upper_margin, mode->yres, 687 if (f_width != mode->xres || f_height != mode->yres)
649 mode->lower_margin, mode->vsync_len, 688 continue;
650 PICOS2KHZ(mode->pixclock)); 689 if (f_refresh == mode->refresh || (!f_refresh && !rate_error))
651 if (!found && hdmi->info) { 690 /*
652 fb_videomode_to_var(var, mode); 691 * Exact match if either the refresh rate matches or it
653 found = fb_match_mode(var, &hdmi->info->modelist); 692 * hasn't been specified and we've found a mode, for
693 * which we can configure the clock precisely
694 */
695 exact_match = true;
696 else if (found && found_rate_error <= rate_error)
654 /* 697 /*
655 * If an exact match found, we're good to bail out, but 698 * We otherwise search for the closest matching clock
656 * continue to print out all modes 699 * rate - either if no refresh rate has been specified
700 * or we cannot find an exactly matching one
657 */ 701 */
702 continue;
703
704 /* Check if supported: sufficient fb memory, supported clock-rate */
705 fb_videomode_to_var(var, mode);
706
707 if (info && info->fbops->fb_check_var &&
708 info->fbops->fb_check_var(var, info)) {
709 exact_match = false;
710 continue;
658 } 711 }
712
713 found = mode;
714 found_rate_error = rate_error;
659 } 715 }
660 716
661 /* 717 /*
662 * The monitor might also work with a mode, that is smaller, than one of 718 * TODO 1: if no ->info is present, postpone running the config until
663 * its modes, use the first (default) one for this 719 * after ->info first gets registered.
720 * TODO 2: consider registering the HDMI platform device from the LCDC
721 * driver, and passing ->info with HDMI platform data.
664 */ 722 */
665 if (!found && hdmi->info && hdmi->monspec.modedb_len) { 723 if (info && !found) {
666 struct fb_modelist *modelist; 724 modelist = hdmi->info->modelist.next &&
667 unsigned int min_err = UINT_MAX, err; 725 !list_empty(&hdmi->info->modelist) ?
668 const struct fb_videomode *mon_mode = hdmi->monspec.modedb; 726 list_entry(hdmi->info->modelist.next,
669 727 struct fb_modelist, list) :
670 list_for_each_entry(modelist, &hdmi->info->modelist, list) { 728 NULL;
671 mode = &modelist->mode; 729
672 dev_dbg(hdmi->dev, "matching %ux%u to %ux%u\n", mode->xres, mode->yres, 730 if (modelist) {
673 mon_mode->xres, mon_mode->yres); 731 found = &modelist->mode;
674 if (mode->xres <= mon_mode->xres && mode->yres <= mon_mode->yres) { 732 found_rate_error = sh_hdmi_rate_error(hdmi, found);
675 err = mon_mode->xres - mode->xres + mon_mode->yres - mode->yres;
676 if (!err) {
677 found = mode;
678 break;
679 }
680 if (err < min_err) {
681 found = mode;
682 min_err = err;
683 }
684 }
685 } 733 }
686 } 734 }
687 735
688 /* Nothing suitable specified by the platform: use monitor's first mode */
689 if (!found && hdmi->monspec.modedb_len)
690 found = hdmi->monspec.modedb;
691
692 /* No valid timing info in EDID - last resort: use platform default mode */
693 if (!found && hdmi->info) {
694 struct fb_modelist *modelist = list_entry(hdmi->info->modelist.next,
695 struct fb_modelist, list);
696 found = &modelist->mode;
697 }
698
699 /* No cookie today */ 736 /* No cookie today */
700 if (!found) 737 if (!found)
701 return -ENXIO; 738 return -ENXIO;
702 739
703 dev_dbg(hdmi->dev, "best \"%s\" %ux%u@%ups\n", found->name, 740 dev_info(hdmi->dev, "Using %s mode %ux%u@%uHz (%luHz), clock error %luHz\n",
704 found->xres, found->yres, found->pixclock); 741 modelist ? "default" : "EDID", found->xres, found->yres,
742 found->refresh, PICOS2KHZ(found->pixclock) * 1000, found_rate_error);
705 743
706 if ((found->xres == 720 && found->yres == 480) || 744 if ((found->xres == 720 && found->yres == 480) ||
707 (found->xres == 1280 && found->yres == 720) || 745 (found->xres == 1280 && found->yres == 720) ||