diff options
author | Rakesh Iyer <riyer@nvidia.com> | 2012-11-09 17:53:19 -0800 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 01:28:06 -0700 |
commit | 013e1d019b088f7525dbfcc5b9aaa9efc6362644 (patch) | |
tree | bebd3094a4032e7688f2fc166cc1a586239480b0 /drivers | |
parent | 065332d33986efb6875f70ce233dd538fa3e7ac1 (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.c | 6 | ||||
-rw-r--r-- | drivers/video/tegra/dc/dc_priv.h | 2 | ||||
-rw-r--r-- | drivers/video/tegra/dc/mode.c | 12 | ||||
-rw-r--r-- | drivers/video/tegra/fb.c | 25 |
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; |