summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/dc/dc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/tegra/dc/dc.c')
-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