summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDonghan Ryu <dryu@nvidia.com>2011-05-17 05:56:35 +0900
committerNiket Sirsi <nsirsi@nvidia.com>2011-05-19 17:49:49 -0700
commit6529eb1c8bf15d2111ff77cc830de0b67bc80038 (patch)
treebbffc60214fa3af0a4f5096b33d00a4f8076f0a5
parentc20a54d503e859b8b9c62c6fb446fcfe273d433b (diff)
tegra: dc: adding max pixclock check for hdmi
tegra_dc_hdmi_equal doesn't check pixclock. some devices doesn't support 14.85Mhz pixclock so 1080p@60 cannot be used. However, 1080p@30 is supported. Therefore, adding a max pixclock prevents 1080p@60 mode is falsely used for those devices Bug: 815409 Change-Id: Ia2d8dcf360afa51e160d0e997986fe1714254a6b Reviewed-on: http://git-master/r/31663 Reviewed-by: Donghan Ryu <dryu@nvidia.com> Tested-by: Donghan Ryu <dryu@nvidia.com> Reviewed-by: Jonathan Mayo <jmayo@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/board-ventana-panel.c2
-rw-r--r--arch/arm/mach-tegra/board-whistler-panel.c2
-rw-r--r--arch/arm/mach-tegra/include/mach/dc.h6
-rw-r--r--arch/arm/mach-tegra/include/mach/fb.h2
-rw-r--r--drivers/video/tegra/dc/dc.c13
-rw-r--r--drivers/video/tegra/dc/hdmi.c19
-rw-r--r--drivers/video/tegra/fb.c4
7 files changed, 38 insertions, 10 deletions
diff --git a/arch/arm/mach-tegra/board-ventana-panel.c b/arch/arm/mach-tegra/board-ventana-panel.c
index 4c9cee7b01ae..66bea3b0a9c7 100644
--- a/arch/arm/mach-tegra/board-ventana-panel.c
+++ b/arch/arm/mach-tegra/board-ventana-panel.c
@@ -245,6 +245,8 @@ static struct tegra_dc_out ventana_disp2_out = {
.dcc_bus = 1,
.hotplug_gpio = ventana_hdmi_hpd,
+ .max_pixclock = KHZ2PICOS(148500),
+
.align = TEGRA_DC_ALIGN_MSB,
.order = TEGRA_DC_ORDER_RED_BLUE,
diff --git a/arch/arm/mach-tegra/board-whistler-panel.c b/arch/arm/mach-tegra/board-whistler-panel.c
index c2333ce5953b..ddcc611e9a65 100644
--- a/arch/arm/mach-tegra/board-whistler-panel.c
+++ b/arch/arm/mach-tegra/board-whistler-panel.c
@@ -196,6 +196,8 @@ static struct tegra_dc_out whistler_disp2_out = {
.dcc_bus = 1,
.hotplug_gpio = whistler_hdmi_hpd,
+ .max_pixclock = KHZ2PICOS(148500),
+
.align = TEGRA_DC_ALIGN_MSB,
.order = TEGRA_DC_ORDER_RED_BLUE,
diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h
index 8d43c3814925..d6b953597b84 100644
--- a/arch/arm/mach-tegra/include/mach/dc.h
+++ b/arch/arm/mach-tegra/include/mach/dc.h
@@ -221,6 +221,7 @@ struct tegra_dc_out {
int dcc_bus;
int hotplug_gpio;
+ unsigned max_pixclock;
unsigned order;
unsigned align;
unsigned depth;
@@ -365,8 +366,9 @@ int tegra_dc_sync_windows(struct tegra_dc_win *windows[], int n);
int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode);
-unsigned tegra_dc_get_out_height(struct tegra_dc *dc);
-unsigned tegra_dc_get_out_width(struct tegra_dc *dc);
+unsigned tegra_dc_get_out_height(const struct tegra_dc *dc);
+unsigned tegra_dc_get_out_width(const struct tegra_dc *dc);
+unsigned tegra_dc_get_out_max_pixclock(const struct tegra_dc *dc);
/* PM0 and PM1 signal control */
#define TEGRA_PWM_PM0 0
diff --git a/arch/arm/mach-tegra/include/mach/fb.h b/arch/arm/mach-tegra/include/mach/fb.h
index 8130da0ed8e7..776e97b20902 100644
--- a/arch/arm/mach-tegra/include/mach/fb.h
+++ b/arch/arm/mach-tegra/include/mach/fb.h
@@ -36,7 +36,7 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
void tegra_fb_unregister(struct tegra_fb_info *fb_info);
void tegra_fb_update_monspecs(struct tegra_fb_info *fb_info,
struct fb_monspecs *specs,
- bool (*mode_filter)(struct fb_videomode *mode));
+ bool (*mode_filter)(const struct tegra_dc *dc, struct fb_videomode *mode));
/* called by display controller on suspend */
void tegra_fb_suspend(struct tegra_fb_info *tegra_fb);
#else
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index 15bda8329d28..b17689fa3b86 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -957,7 +957,7 @@ static void tegra_dc_set_out(struct tegra_dc *dc, struct tegra_dc_out *out)
}
-unsigned tegra_dc_get_out_height(struct tegra_dc *dc)
+unsigned tegra_dc_get_out_height(const struct tegra_dc *dc)
{
if (dc->out)
return dc->out->height;
@@ -966,7 +966,7 @@ unsigned tegra_dc_get_out_height(struct tegra_dc *dc)
}
EXPORT_SYMBOL(tegra_dc_get_out_height);
-unsigned tegra_dc_get_out_width(struct tegra_dc *dc)
+unsigned tegra_dc_get_out_width(const struct tegra_dc *dc)
{
if (dc->out)
return dc->out->width;
@@ -975,6 +975,15 @@ unsigned tegra_dc_get_out_width(struct tegra_dc *dc)
}
EXPORT_SYMBOL(tegra_dc_get_out_width);
+unsigned tegra_dc_get_out_max_pixclock(const struct tegra_dc *dc)
+{
+ if (dc->out && dc->out->max_pixclock)
+ return dc->out->max_pixclock;
+ else
+ return 0;
+}
+EXPORT_SYMBOL(tegra_dc_get_out_max_pixclock);
+
static irqreturn_t tegra_dc_irq(int irq, void *ptr)
{
struct tegra_dc *dc = ptr;
diff --git a/drivers/video/tegra/dc/hdmi.c b/drivers/video/tegra/dc/hdmi.c
index add3457705ca..58b457244887 100644
--- a/drivers/video/tegra/dc/hdmi.c
+++ b/drivers/video/tegra/dc/hdmi.c
@@ -496,14 +496,27 @@ static bool tegra_dc_hdmi_mode_equal(const struct fb_videomode *mode1,
mode1->vmode == mode2->vmode;
}
-static bool tegra_dc_hdmi_mode_filter(struct fb_videomode *mode)
+static bool tegra_dc_hdmi_valid_pixclock(const struct tegra_dc *dc,
+ const struct fb_videomode *mode)
+{
+ unsigned max_pixclock = tegra_dc_get_out_max_pixclock(dc);
+ if (max_pixclock) {
+ // this might look counter-intuitive, but pixclock's unit is picos(not Khz)
+ return mode->pixclock >= max_pixclock;
+ } else {
+ return true;
+ }
+}
+
+static bool tegra_dc_hdmi_mode_filter(const struct tegra_dc *dc,
+ struct fb_videomode *mode)
{
int i;
int clocks;
for (i = 0; i < ARRAY_SIZE(tegra_dc_hdmi_supported_modes); i++) {
- if (tegra_dc_hdmi_mode_equal(&tegra_dc_hdmi_supported_modes[i],
- mode)) {
+ if (tegra_dc_hdmi_mode_equal(&tegra_dc_hdmi_supported_modes[i], mode) &&
+ tegra_dc_hdmi_valid_pixclock(dc, &tegra_dc_hdmi_supported_modes[i])) {
memcpy(mode, &tegra_dc_hdmi_supported_modes[i], sizeof(*mode));
mode->flag = FB_MODE_IS_DETAILED;
clocks = (mode->left_margin + mode->xres + mode->right_margin + mode->hsync_len) *
diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c
index 2ec247633b16..defd1806c2db 100644
--- a/drivers/video/tegra/fb.c
+++ b/drivers/video/tegra/fb.c
@@ -672,7 +672,7 @@ static struct fb_ops tegra_fb_ops = {
void tegra_fb_update_monspecs(struct tegra_fb_info *fb_info,
struct fb_monspecs *specs,
- bool (*mode_filter)(struct fb_videomode *mode))
+ bool (*mode_filter)(const struct tegra_dc *dc, struct fb_videomode *mode))
{
struct fb_event event;
struct fb_modelist *m;
@@ -698,7 +698,7 @@ void tegra_fb_update_monspecs(struct tegra_fb_info *fb_info,
for (i = 0; i < specs->modedb_len; i++) {
if (mode_filter) {
- if (mode_filter(&specs->modedb[i]))
+ if (mode_filter(fb_info->win->dc, &specs->modedb[i]))
fb_add_videomode(&specs->modedb[i],
&fb_info->info->modelist);
} else {