summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorRakesh Iyer <riyer@nvidia.com>2012-11-09 17:53:19 -0800
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 01:28:06 -0700
commit013e1d019b088f7525dbfcc5b9aaa9efc6362644 (patch)
treebebd3094a4032e7688f2fc166cc1a586239480b0 /drivers
parent065332d33986efb6875f70ce233dd538fa3e7ac1 (diff)
video: tegra: dc: multiple mode support
Support multiple modes in platform device mode list. Bug 1166276 Bug 560152 Change-Id: I94f9458f3ae006d2dd50cd3c3b704ea2153c3e1d Signed-off-by: Rakesh Iyer <riyer@nvidia.com> Signed-off-by: Jon Mayo <jmayo@nvidia.com> Reviewed-on: http://git-master/r/162840 Reviewed-by: Simone Willett <swillett@nvidia.com> Tested-by: Simone Willett <swillett@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/tegra/dc/dc.c6
-rw-r--r--drivers/video/tegra/dc/dc_priv.h2
-rw-r--r--drivers/video/tegra/dc/mode.c12
-rw-r--r--drivers/video/tegra/fb.c25
4 files changed, 23 insertions, 22 deletions
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index 8aafdafae3ed..abe912e5707d 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -1536,6 +1536,7 @@ static irqreturn_t tegra_dc_irq(int irq, void *ptr)
unsigned long status;
unsigned long underflow_mask;
u32 val;
+ int need_disable = 0;
mutex_lock(&dc->lock);
if (!dc->enabled) {
@@ -1586,13 +1587,16 @@ static irqreturn_t tegra_dc_irq(int irq, void *ptr)
/* update video mode if it has changed since the last frame */
if (status & (FRAME_END_INT | V_BLANK_INT))
- tegra_dc_update_mode(dc);
+ if (tegra_dc_update_mode(dc))
+ need_disable = 1; /* force display off on error */
tegra_dc_release_dc_out(dc);
tegra_dc_io_end(dc);
clk_disable_unprepare(dc->clk);
mutex_unlock(&dc->lock);
+ if (need_disable)
+ tegra_dc_disable(dc);
return IRQ_HANDLED;
#else /* CONFIG_TEGRA_FPGA_PLATFORM */
return IRQ_NONE;
diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h
index ec98b5984123..51aeae3daae6 100644
--- a/drivers/video/tegra/dc/dc_priv.h
+++ b/drivers/video/tegra/dc/dc_priv.h
@@ -266,7 +266,7 @@ int tegra_dc_set_dynamic_emc(struct tegra_dc_win *windows[], int n);
/* defined in mode.c, used in dc.c and window.c */
int tegra_dc_program_mode(struct tegra_dc *dc, struct tegra_dc_mode *mode);
int tegra_dc_calc_refresh(const struct tegra_dc_mode *m);
-void tegra_dc_update_mode(struct tegra_dc *dc);
+int tegra_dc_update_mode(struct tegra_dc *dc);
/* defined in clock.c, used in dc.c, rgb.c, dsi.c and hdmi.c */
void tegra_dc_setup_clk(struct tegra_dc *dc, struct clk *clk);
diff --git a/drivers/video/tegra/dc/mode.c b/drivers/video/tegra/dc/mode.c
index f972648f2399..57a045518077 100644
--- a/drivers/video/tegra/dc/mode.c
+++ b/drivers/video/tegra/dc/mode.c
@@ -327,16 +327,20 @@ int tegra_dc_to_fb_videomode(struct fb_videomode *fbmode,
fbmode->sync |= FB_SYNC_HOR_HIGH_ACT;
if (!(mode->flags & TEGRA_DC_MODE_FLAG_NEG_V_SYNC))
fbmode->sync |= FB_SYNC_VERT_HIGH_ACT;
- /* round up refresh rate for fractions above 0.500Hz */
- fbmode->refresh = (tegra_dc_calc_refresh(mode) + 500) / 1000;
+ if (mode->rated_pclk >= 1000)
+ fbmode->pixclock = KHZ2PICOS(mode->rated_pclk / 1000);
+ else if (mode->pclk >= 1000)
+ fbmode->pixclock = KHZ2PICOS(mode->pclk / 1000);
+ fbmode->refresh = tegra_dc_calc_refresh(mode) / 1000;
return 0;
}
-void tegra_dc_update_mode(struct tegra_dc *dc)
+int tegra_dc_update_mode(struct tegra_dc *dc)
{
if (dc->mode_dirty)
- tegra_dc_program_mode(dc, &dc->mode);
+ return tegra_dc_program_mode(dc, &dc->mode);
+ return 0;
}
int tegra_dc_set_fb_mode(struct tegra_dc *dc,
diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c
index 8d4d43dd5ea9..9100885b7356 100644
--- a/drivers/video/tegra/fb.c
+++ b/drivers/video/tegra/fb.c
@@ -531,6 +531,7 @@ struct tegra_fb_info *tegra_fb_register(struct platform_device *ndev,
unsigned long fb_size = 0;
unsigned long fb_phys = 0;
int ret = 0;
+ int mode_idx;
unsigned stride;
struct fb_videomode m;
@@ -635,24 +636,16 @@ struct tegra_fb_info *tegra_fb_register(struct platform_device *ndev,
tegra_dc_sync_windows(&tegra_fb->win, 1);
}
- if (dc->mode.pclk > 1000) {
- struct tegra_dc_mode *mode = &dc->mode;
+ for (mode_idx = 1; mode_idx < dc->out->n_modes; mode_idx++) {
+ struct tegra_dc_mode mode = dc->out->modes[mode_idx];
struct fb_videomode vmode;
- if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
- info->var.pixclock = KHZ2PICOS(mode->rated_pclk / 1000);
- else
- info->var.pixclock = KHZ2PICOS(mode->pclk / 1000);
- info->var.left_margin = mode->h_back_porch;
- info->var.right_margin = mode->h_front_porch;
- info->var.upper_margin = mode->v_back_porch;
- info->var.lower_margin = mode->v_front_porch;
- info->var.hsync_len = mode->h_sync_width;
- info->var.vsync_len = mode->v_sync_width;
-
- /* Keep info->var consistent with info->modelist. */
- fb_var_to_videomode(&vmode, &info->var);
- fb_add_videomode(&vmode, &info->modelist);
+ mode.pclk = dc->mode.pclk;
+
+ if (mode.pclk > 1000) {
+ tegra_dc_to_fb_videomode(&vmode, &mode);
+ fb_add_videomode(&vmode, &info->modelist);
+ }
}
return tegra_fb;