summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShashank Sharma <shashanks@nvidia.com>2012-02-27 15:06:54 +0530
committerSimone Willett <swillett@nvidia.com>2012-03-23 13:57:17 -0700
commit11f2194618140f7a6628554f732e3a7f82a20dfb (patch)
tree09be16925058adc4a70b31fcd86a4ac97116338d
parent23bd23f414d1b3e677ac42b3ef1dfd8e09553d88 (diff)
video: tegra3: dc: remove hard coded HDMI rates
Set dc clock rate dynamically to requested pixel rate. Using modes specified in monitor's EDID data. Return mode set errors on unsupported clock tolerances. Bug 931908 Change-Id: I60990ecbc2fbeab542987036b8ccc30b8dababe8 Signed-off-by: Shashank Sharma <shashanks@nvidia.com> Reviewed-on: http://git-master/r/86073 Reviewed-by: Simone Willett <swillett@nvidia.com> Tested-by: Simone Willett <swillett@nvidia.com>
-rw-r--r--drivers/video/tegra/dc/dc.c45
1 files changed, 32 insertions, 13 deletions
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index ac024f68b371..3d09a13eaa64 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -66,6 +66,8 @@
static int no_vsync;
+static void _tegra_dc_controller_disable(struct tegra_dc *dc);
+
module_param_named(no_vsync, no_vsync, int, S_IRUGO | S_IWUSR);
static int use_dynamic_emc = 1;
@@ -1445,15 +1447,13 @@ void tegra_dc_setup_clk(struct tegra_dc *dc, struct clk *clk)
clk_get_sys(NULL, dc->out->parent_clk ? : "pll_d_out0");
struct clk *base_clk = clk_get_parent(parent_clk);
- /* needs to match tegra_dc_hdmi_supported_modes[]
- and tegra_pll_d_freq_table[] */
- if (dc->mode.pclk > 70000000)
- rate = 594000000;
- else if (dc->mode.pclk > 25200000)
- rate = 216000000;
- else
- rate = 504000000;
+ /*
+ * Providing dynamic frequency rate setting for T20/T30 HDMI.
+ * The required rate needs to be setup at 4x multiplier,
+ * as out0 is 1/2 of the actual PLL output.
+ */
+ rate = dc->mode.pclk * 4;
if (rate != clk_get_rate(base_clk))
clk_set_rate(base_clk, rate);
@@ -2374,7 +2374,7 @@ static u32 get_syncpt(struct tegra_dc *dc, int idx)
return syncpt_id;
}
-static void tegra_dc_init(struct tegra_dc *dc)
+static int tegra_dc_init(struct tegra_dc *dc)
{
int i;
@@ -2440,15 +2440,20 @@ static void tegra_dc_init(struct tegra_dc *dc)
print_mode(dc, &dc->mode, __func__);
if (dc->mode.pclk)
- tegra_dc_program_mode(dc, &dc->mode);
+ if (tegra_dc_program_mode(dc, &dc->mode))
+ return -EINVAL;
/* Initialize SD AFTER the modeset.
nvsd_init handles the sd_settings = NULL case. */
nvsd_init(dc, dc->out->sd_settings);
+
+ return 0;
}
static bool _tegra_dc_controller_enable(struct tegra_dc *dc)
{
+ int failed_init = 0;
+
if (dc->out->enable)
dc->out->enable();
@@ -2461,7 +2466,11 @@ static bool _tegra_dc_controller_enable(struct tegra_dc *dc)
enable_dc_irq(dc->irq);
- tegra_dc_init(dc);
+ failed_init = tegra_dc_init(dc);
+ if (failed_init) {
+ _tegra_dc_controller_disable(dc);
+ return false;
+ }
if (dc->out_ops && dc->out_ops->enable)
dc->out_ops->enable(dc);
@@ -2480,6 +2489,8 @@ static bool _tegra_dc_controller_enable(struct tegra_dc *dc)
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
static bool _tegra_dc_controller_reset_enable(struct tegra_dc *dc)
{
+ bool ret = true;
+
if (dc->out->enable)
dc->out->enable();
@@ -2512,7 +2523,10 @@ static bool _tegra_dc_controller_reset_enable(struct tegra_dc *dc)
enable_dc_irq(dc->irq);
- tegra_dc_init(dc);
+ if (tegra_dc_init(dc)) {
+ dev_err(&dc->ndev->dev, "cannot initialize\n");
+ ret = false;
+ }
if (dc->out_ops && dc->out_ops->enable)
dc->out_ops->enable(dc);
@@ -2525,7 +2539,12 @@ static bool _tegra_dc_controller_reset_enable(struct tegra_dc *dc)
tegra_dc_ext_enable(dc->ext);
- return true;
+ if (!ret) {
+ dev_err(&dc->ndev->dev, "initialization failed,disabling");
+ _tegra_dc_controller_disable(dc);
+ }
+
+ return ret;
}
#endif