diff options
Diffstat (limited to 'drivers/gpu/drm/sun4i/sun4i_tcon.c')
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_tcon.c | 99 |
1 files changed, 54 insertions, 45 deletions
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 3c15cf24b503..2de586b7c98b 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c | |||
@@ -101,10 +101,12 @@ static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel, | |||
101 | return; | 101 | return; |
102 | } | 102 | } |
103 | 103 | ||
104 | if (enabled) | 104 | if (enabled) { |
105 | clk_prepare_enable(clk); | 105 | clk_prepare_enable(clk); |
106 | else | 106 | } else { |
107 | clk_rate_exclusive_put(clk); | ||
107 | clk_disable_unprepare(clk); | 108 | clk_disable_unprepare(clk); |
109 | } | ||
108 | } | 110 | } |
109 | 111 | ||
110 | static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon, | 112 | static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon, |
@@ -260,7 +262,7 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon, | |||
260 | const struct drm_display_mode *mode) | 262 | const struct drm_display_mode *mode) |
261 | { | 263 | { |
262 | /* Configure the dot clock */ | 264 | /* Configure the dot clock */ |
263 | clk_set_rate(tcon->dclk, mode->crtc_clock * 1000); | 265 | clk_set_rate_exclusive(tcon->dclk, mode->crtc_clock * 1000); |
264 | 266 | ||
265 | /* Set the resolution */ | 267 | /* Set the resolution */ |
266 | regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG, | 268 | regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG, |
@@ -335,6 +337,9 @@ static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon, | |||
335 | regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG, | 337 | regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG, |
336 | SUN4I_TCON_GCTL_IOMAP_MASK, | 338 | SUN4I_TCON_GCTL_IOMAP_MASK, |
337 | SUN4I_TCON_GCTL_IOMAP_TCON0); | 339 | SUN4I_TCON_GCTL_IOMAP_TCON0); |
340 | |||
341 | /* Enable the output on the pins */ | ||
342 | regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000); | ||
338 | } | 343 | } |
339 | 344 | ||
340 | static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon, | 345 | static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon, |
@@ -418,7 +423,7 @@ static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon, | |||
418 | WARN_ON(!tcon->quirks->has_channel_1); | 423 | WARN_ON(!tcon->quirks->has_channel_1); |
419 | 424 | ||
420 | /* Configure the dot clock */ | 425 | /* Configure the dot clock */ |
421 | clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000); | 426 | clk_set_rate_exclusive(tcon->sclk1, mode->crtc_clock * 1000); |
422 | 427 | ||
423 | /* Adjust clock delay */ | 428 | /* Adjust clock delay */ |
424 | clk_delay = sun4i_tcon_get_clk_delay(mode, 1); | 429 | clk_delay = sun4i_tcon_get_clk_delay(mode, 1); |
@@ -870,52 +875,56 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, | |||
870 | return ret; | 875 | return ret; |
871 | } | 876 | } |
872 | 877 | ||
873 | /* | 878 | if (tcon->quirks->supports_lvds) { |
874 | * This can only be made optional since we've had DT nodes | 879 | /* |
875 | * without the LVDS reset properties. | 880 | * This can only be made optional since we've had DT |
876 | * | 881 | * nodes without the LVDS reset properties. |
877 | * If the property is missing, just disable LVDS, and print a | 882 | * |
878 | * warning. | 883 | * If the property is missing, just disable LVDS, and |
879 | */ | 884 | * print a warning. |
880 | tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds"); | 885 | */ |
881 | if (IS_ERR(tcon->lvds_rst)) { | 886 | tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds"); |
882 | dev_err(dev, "Couldn't get our reset line\n"); | 887 | if (IS_ERR(tcon->lvds_rst)) { |
883 | return PTR_ERR(tcon->lvds_rst); | 888 | dev_err(dev, "Couldn't get our reset line\n"); |
884 | } else if (tcon->lvds_rst) { | 889 | return PTR_ERR(tcon->lvds_rst); |
885 | has_lvds_rst = true; | 890 | } else if (tcon->lvds_rst) { |
886 | reset_control_reset(tcon->lvds_rst); | 891 | has_lvds_rst = true; |
887 | } else { | 892 | reset_control_reset(tcon->lvds_rst); |
888 | has_lvds_rst = false; | 893 | } else { |
889 | } | 894 | has_lvds_rst = false; |
895 | } | ||
890 | 896 | ||
891 | /* | 897 | /* |
892 | * This can only be made optional since we've had DT nodes | 898 | * This can only be made optional since we've had DT |
893 | * without the LVDS reset properties. | 899 | * nodes without the LVDS reset properties. |
894 | * | 900 | * |
895 | * If the property is missing, just disable LVDS, and print a | 901 | * If the property is missing, just disable LVDS, and |
896 | * warning. | 902 | * print a warning. |
897 | */ | 903 | */ |
898 | if (tcon->quirks->has_lvds_alt) { | 904 | if (tcon->quirks->has_lvds_alt) { |
899 | tcon->lvds_pll = devm_clk_get(dev, "lvds-alt"); | 905 | tcon->lvds_pll = devm_clk_get(dev, "lvds-alt"); |
900 | if (IS_ERR(tcon->lvds_pll)) { | 906 | if (IS_ERR(tcon->lvds_pll)) { |
901 | if (PTR_ERR(tcon->lvds_pll) == -ENOENT) { | 907 | if (PTR_ERR(tcon->lvds_pll) == -ENOENT) { |
902 | has_lvds_alt = false; | 908 | has_lvds_alt = false; |
909 | } else { | ||
910 | dev_err(dev, "Couldn't get the LVDS PLL\n"); | ||
911 | return PTR_ERR(tcon->lvds_pll); | ||
912 | } | ||
903 | } else { | 913 | } else { |
904 | dev_err(dev, "Couldn't get the LVDS PLL\n"); | 914 | has_lvds_alt = true; |
905 | return PTR_ERR(tcon->lvds_pll); | ||
906 | } | 915 | } |
907 | } else { | ||
908 | has_lvds_alt = true; | ||
909 | } | 916 | } |
910 | } | ||
911 | 917 | ||
912 | if (!has_lvds_rst || (tcon->quirks->has_lvds_alt && !has_lvds_alt)) { | 918 | if (!has_lvds_rst || |
913 | dev_warn(dev, | 919 | (tcon->quirks->has_lvds_alt && !has_lvds_alt)) { |
914 | "Missing LVDS properties, Please upgrade your DT\n"); | 920 | dev_warn(dev, "Missing LVDS properties, Please upgrade your DT\n"); |
915 | dev_warn(dev, "LVDS output disabled\n"); | 921 | dev_warn(dev, "LVDS output disabled\n"); |
916 | can_lvds = false; | 922 | can_lvds = false; |
923 | } else { | ||
924 | can_lvds = true; | ||
925 | } | ||
917 | } else { | 926 | } else { |
918 | can_lvds = true; | 927 | can_lvds = false; |
919 | } | 928 | } |
920 | 929 | ||
921 | ret = sun4i_tcon_init_clocks(dev, tcon); | 930 | ret = sun4i_tcon_init_clocks(dev, tcon); |
@@ -1134,7 +1143,7 @@ static const struct sun4i_tcon_quirks sun8i_a33_quirks = { | |||
1134 | }; | 1143 | }; |
1135 | 1144 | ||
1136 | static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = { | 1145 | static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = { |
1137 | /* nothing is supported */ | 1146 | .supports_lvds = true, |
1138 | }; | 1147 | }; |
1139 | 1148 | ||
1140 | static const struct sun4i_tcon_quirks sun8i_v3s_quirks = { | 1149 | static const struct sun4i_tcon_quirks sun8i_v3s_quirks = { |