Commit 34d698f6 authored by Jernej Skrabec's avatar Jernej Skrabec Committed by Maxime Ripard

drm/sun4i: Add has_channel_0 TCON quirk

Some TCONs on newer SoCs doesn't support channel 0, since they are meant
to be used only with TV or HDMI encoder.

Prepare support for them with adding has_channel_0 quirk.
Acked-by: default avatarMaxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: default avatarJernej Skrabec <jernej.skrabec@siol.net>
Signed-off-by: default avatarMaxime Ripard <maxime.ripard@bootlin.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180214200906.31509-8-jernej.skrabec@siol.net
parent a17a2611
...@@ -84,6 +84,7 @@ static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel, ...@@ -84,6 +84,7 @@ static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
switch (channel) { switch (channel) {
case 0: case 0:
WARN_ON(!tcon->quirks->has_channel_0);
regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
SUN4I_TCON0_CTL_TCON_ENABLE, SUN4I_TCON0_CTL_TCON_ENABLE,
enabled ? SUN4I_TCON0_CTL_TCON_ENABLE : 0); enabled ? SUN4I_TCON0_CTL_TCON_ENABLE : 0);
...@@ -276,6 +277,8 @@ static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon, ...@@ -276,6 +277,8 @@ static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
u8 clk_delay; u8 clk_delay;
u32 reg, val = 0; u32 reg, val = 0;
WARN_ON(!tcon->quirks->has_channel_0);
tcon->dclk_min_div = 7; tcon->dclk_min_div = 7;
tcon->dclk_max_div = 7; tcon->dclk_max_div = 7;
sun4i_tcon0_mode_set_common(tcon, mode); sun4i_tcon0_mode_set_common(tcon, mode);
...@@ -344,6 +347,8 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon, ...@@ -344,6 +347,8 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
u8 clk_delay; u8 clk_delay;
u32 val = 0; u32 val = 0;
WARN_ON(!tcon->quirks->has_channel_0);
tcon->dclk_min_div = 6; tcon->dclk_min_div = 6;
tcon->dclk_max_div = 127; tcon->dclk_max_div = 127;
sun4i_tcon0_mode_set_common(tcon, mode); sun4i_tcon0_mode_set_common(tcon, mode);
...@@ -574,10 +579,12 @@ static int sun4i_tcon_init_clocks(struct device *dev, ...@@ -574,10 +579,12 @@ static int sun4i_tcon_init_clocks(struct device *dev,
} }
clk_prepare_enable(tcon->clk); clk_prepare_enable(tcon->clk);
tcon->sclk0 = devm_clk_get(dev, "tcon-ch0"); if (tcon->quirks->has_channel_0) {
if (IS_ERR(tcon->sclk0)) { tcon->sclk0 = devm_clk_get(dev, "tcon-ch0");
dev_err(dev, "Couldn't get the TCON channel 0 clock\n"); if (IS_ERR(tcon->sclk0)) {
return PTR_ERR(tcon->sclk0); dev_err(dev, "Couldn't get the TCON channel 0 clock\n");
return PTR_ERR(tcon->sclk0);
}
} }
if (tcon->quirks->has_channel_1) { if (tcon->quirks->has_channel_1) {
...@@ -934,10 +941,12 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, ...@@ -934,10 +941,12 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
goto err_free_clocks; goto err_free_clocks;
} }
ret = sun4i_dclk_create(dev, tcon); if (tcon->quirks->has_channel_0) {
if (ret) { ret = sun4i_dclk_create(dev, tcon);
dev_err(dev, "Couldn't create our TCON dot clock\n"); if (ret) {
goto err_free_clocks; dev_err(dev, "Couldn't create our TCON dot clock\n");
goto err_free_clocks;
}
} }
ret = sun4i_tcon_init_irq(dev, tcon); ret = sun4i_tcon_init_irq(dev, tcon);
...@@ -995,7 +1004,8 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, ...@@ -995,7 +1004,8 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
return 0; return 0;
err_free_dotclock: err_free_dotclock:
sun4i_dclk_free(tcon); if (tcon->quirks->has_channel_0)
sun4i_dclk_free(tcon);
err_free_clocks: err_free_clocks:
sun4i_tcon_free_clocks(tcon); sun4i_tcon_free_clocks(tcon);
err_assert_reset: err_assert_reset:
...@@ -1009,7 +1019,8 @@ static void sun4i_tcon_unbind(struct device *dev, struct device *master, ...@@ -1009,7 +1019,8 @@ static void sun4i_tcon_unbind(struct device *dev, struct device *master,
struct sun4i_tcon *tcon = dev_get_drvdata(dev); struct sun4i_tcon *tcon = dev_get_drvdata(dev);
list_del(&tcon->list); list_del(&tcon->list);
sun4i_dclk_free(tcon); if (tcon->quirks->has_channel_0)
sun4i_dclk_free(tcon);
sun4i_tcon_free_clocks(tcon); sun4i_tcon_free_clocks(tcon);
} }
...@@ -1106,16 +1117,19 @@ static int sun6i_tcon_set_mux(struct sun4i_tcon *tcon, ...@@ -1106,16 +1117,19 @@ static int sun6i_tcon_set_mux(struct sun4i_tcon *tcon,
} }
static const struct sun4i_tcon_quirks sun4i_a10_quirks = { static const struct sun4i_tcon_quirks sun4i_a10_quirks = {
.has_channel_0 = true,
.has_channel_1 = true, .has_channel_1 = true,
.set_mux = sun4i_a10_tcon_set_mux, .set_mux = sun4i_a10_tcon_set_mux,
}; };
static const struct sun4i_tcon_quirks sun5i_a13_quirks = { static const struct sun4i_tcon_quirks sun5i_a13_quirks = {
.has_channel_0 = true,
.has_channel_1 = true, .has_channel_1 = true,
.set_mux = sun5i_a13_tcon_set_mux, .set_mux = sun5i_a13_tcon_set_mux,
}; };
static const struct sun4i_tcon_quirks sun6i_a31_quirks = { static const struct sun4i_tcon_quirks sun6i_a31_quirks = {
.has_channel_0 = true,
.has_channel_1 = true, .has_channel_1 = true,
.has_lvds_alt = true, .has_lvds_alt = true,
.needs_de_be_mux = true, .needs_de_be_mux = true,
...@@ -1123,26 +1137,29 @@ static const struct sun4i_tcon_quirks sun6i_a31_quirks = { ...@@ -1123,26 +1137,29 @@ static const struct sun4i_tcon_quirks sun6i_a31_quirks = {
}; };
static const struct sun4i_tcon_quirks sun6i_a31s_quirks = { static const struct sun4i_tcon_quirks sun6i_a31s_quirks = {
.has_channel_0 = true,
.has_channel_1 = true, .has_channel_1 = true,
.needs_de_be_mux = true, .needs_de_be_mux = true,
}; };
static const struct sun4i_tcon_quirks sun7i_a20_quirks = { static const struct sun4i_tcon_quirks sun7i_a20_quirks = {
.has_channel_0 = true,
.has_channel_1 = true, .has_channel_1 = true,
/* Same display pipeline structure as A10 */ /* Same display pipeline structure as A10 */
.set_mux = sun4i_a10_tcon_set_mux, .set_mux = sun4i_a10_tcon_set_mux,
}; };
static const struct sun4i_tcon_quirks sun8i_a33_quirks = { static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
.has_channel_0 = true,
.has_lvds_alt = true, .has_lvds_alt = true,
}; };
static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = { static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = {
/* nothing is supported */ .has_channel_0 = true,
}; };
static const struct sun4i_tcon_quirks sun8i_v3s_quirks = { static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
/* nothing is supported */ .has_channel_0 = true,
}; };
/* sun4i_drv uses this list to check if a device node is a TCON */ /* sun4i_drv uses this list to check if a device node is a TCON */
......
...@@ -172,6 +172,7 @@ ...@@ -172,6 +172,7 @@
struct sun4i_tcon; struct sun4i_tcon;
struct sun4i_tcon_quirks { struct sun4i_tcon_quirks {
bool has_channel_0; /* a83t does not have channel 0 on second TCON */
bool has_channel_1; /* a33 does not have channel 1 */ bool has_channel_1; /* a33 does not have channel 1 */
bool has_lvds_alt; /* Does the LVDS clock have a parent other than the TCON clock? */ bool has_lvds_alt; /* Does the LVDS clock have a parent other than the TCON clock? */
bool needs_de_be_mux; /* sun6i needs mux to select backend */ bool needs_de_be_mux; /* sun6i needs mux to select backend */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment