diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2011-01-07 06:57:55 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2011-01-10 22:07:49 -0500 |
commit | c7321d6f88e1f962d605923a93f9c255e4d0b8c9 (patch) | |
tree | 41d541c751f976b1fecec8f2d7f59751d84bb7b6 /drivers/video | |
parent | e9ab3207310e8acfa3a5cd8cbb44860f69270bfd (diff) |
fbdev: sh_mobile_hdmi: add command line option to use the preferred EDID mode
Currently, if no command-line option is specified, the sh_mobile_hdmi
will use the default 720p video mode. If a command line option of the
form "video=sh_mobile_lcdc:<width>x<height>@<refresh>" is provided,
the driver will look for that mode among those, available in the
monitor EDID. This patch adds the ability to request the driver to
use monitor's preferred mode by specifying 0 as width and hight in
the above string. If that mode is not supported by the system, the
driver will continue scanning through EDID modes, until it finds a
suitable one.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/sh_mobile_hdmi.c | 60 |
1 files changed, 41 insertions, 19 deletions
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c index 8c59cc8c5a9c..571bd9f74513 100644 --- a/drivers/video/sh_mobile_hdmi.c +++ b/drivers/video/sh_mobile_hdmi.c | |||
@@ -737,7 +737,7 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate, | |||
737 | struct fb_modelist *modelist = NULL; | 737 | struct fb_modelist *modelist = NULL; |
738 | unsigned int f_width = 0, f_height = 0, f_refresh = 0; | 738 | unsigned int f_width = 0, f_height = 0, f_refresh = 0; |
739 | unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */ | 739 | unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */ |
740 | bool exact_match = false; | 740 | bool scanning = false, preferred_bad = false; |
741 | u8 edid[128]; | 741 | u8 edid[128]; |
742 | char *forced; | 742 | char *forced; |
743 | int i; | 743 | int i; |
@@ -800,6 +800,9 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate, | |||
800 | if (i < 2) { | 800 | if (i < 2) { |
801 | f_width = 0; | 801 | f_width = 0; |
802 | f_height = 0; | 802 | f_height = 0; |
803 | } else { | ||
804 | /* The user wants us to use the EDID data */ | ||
805 | scanning = true; | ||
803 | } | 806 | } |
804 | dev_dbg(hdmi->dev, "Forced mode %ux%u@%uHz\n", | 807 | dev_dbg(hdmi->dev, "Forced mode %ux%u@%uHz\n", |
805 | f_width, f_height, f_refresh); | 808 | f_width, f_height, f_refresh); |
@@ -807,37 +810,56 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate, | |||
807 | 810 | ||
808 | /* Walk monitor modes to find the best or the exact match */ | 811 | /* Walk monitor modes to find the best or the exact match */ |
809 | for (i = 0, mode = hdmi->monspec.modedb; | 812 | for (i = 0, mode = hdmi->monspec.modedb; |
810 | f_width && f_height && i < hdmi->monspec.modedb_len && !exact_match; | 813 | i < hdmi->monspec.modedb_len && scanning; |
811 | i++, mode++) { | 814 | i++, mode++) { |
812 | unsigned long rate_error; | 815 | unsigned long rate_error; |
813 | 816 | ||
814 | /* No interest in unmatching modes */ | 817 | if (!f_width && !f_height) { |
815 | if (f_width != mode->xres || f_height != mode->yres) | 818 | /* |
819 | * A parameter string "video=sh_mobile_lcdc:0x0" means | ||
820 | * use the preferred EDID mode. If it is rejected by | ||
821 | * .fb_check_var(), keep looking, until an acceptable | ||
822 | * one is found. | ||
823 | */ | ||
824 | if ((mode->flag & FB_MODE_IS_FIRST) || preferred_bad) | ||
825 | scanning = false; | ||
826 | else | ||
827 | continue; | ||
828 | } else if (f_width != mode->xres || f_height != mode->yres) { | ||
829 | /* No interest in unmatching modes */ | ||
816 | continue; | 830 | continue; |
831 | } | ||
817 | 832 | ||
818 | rate_error = sh_hdmi_rate_error(hdmi, mode, hdmi_rate, parent_rate); | 833 | rate_error = sh_hdmi_rate_error(hdmi, mode, hdmi_rate, parent_rate); |
819 | 834 | ||
820 | if (f_refresh == mode->refresh || (!f_refresh && !rate_error)) | 835 | if (scanning) { |
821 | /* | 836 | if (f_refresh == mode->refresh || (!f_refresh && !rate_error)) |
822 | * Exact match if either the refresh rate matches or it | 837 | /* |
823 | * hasn't been specified and we've found a mode, for | 838 | * Exact match if either the refresh rate |
824 | * which we can configure the clock precisely | 839 | * matches or it hasn't been specified and we've |
825 | */ | 840 | * found a mode, for which we can configure the |
826 | exact_match = true; | 841 | * clock precisely |
827 | else if (found && found_rate_error <= rate_error) | 842 | */ |
828 | /* | 843 | scanning = false; |
829 | * We otherwise search for the closest matching clock | 844 | else if (found && found_rate_error <= rate_error) |
830 | * rate - either if no refresh rate has been specified | 845 | /* |
831 | * or we cannot find an exactly matching one | 846 | * We otherwise search for the closest matching |
832 | */ | 847 | * clock rate - either if no refresh rate has |
833 | continue; | 848 | * been specified or we cannot find an exactly |
849 | * matching one | ||
850 | */ | ||
851 | continue; | ||
852 | } | ||
834 | 853 | ||
835 | /* Check if supported: sufficient fb memory, supported clock-rate */ | 854 | /* Check if supported: sufficient fb memory, supported clock-rate */ |
836 | fb_videomode_to_var(var, mode); | 855 | fb_videomode_to_var(var, mode); |
837 | 856 | ||
857 | var->bits_per_pixel = info->var.bits_per_pixel; | ||
858 | |||
838 | if (info && info->fbops->fb_check_var && | 859 | if (info && info->fbops->fb_check_var && |
839 | info->fbops->fb_check_var(var, info)) { | 860 | info->fbops->fb_check_var(var, info)) { |
840 | exact_match = false; | 861 | scanning = true; |
862 | preferred_bad = true; | ||
841 | continue; | 863 | continue; |
842 | } | 864 | } |
843 | 865 | ||