aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@free-electrons.com>2017-10-17 05:06:12 -0400
committerMaxime Ripard <maxime.ripard@free-electrons.com>2017-10-17 13:49:13 -0400
commit45e88f994add84d8cd3864d36064ea1ed1b08cdf (patch)
tree07b6fabc682b762f4ac5ecb5473cc39209f24a3b
parent961c645cf00c8be82b05ad10068179a86fdbc181 (diff)
drm/sun4i: tcon: Don't rely on encoders to enable the TCON
So far, we've required all the TCON-connected encoders to call the TCON enable and disable functions. This was made this way because in the RGB/LVDS case, the TCON is the CRTC and the encoder. However, in all the other cases (HDMI, TV, DSI, etc.), we have another encoder down the road that needs to be programmed. We also needed to know which channel the encoder is connected to, which is encoder-specific. The CRTC's enable and disable callbacks can work just fine for our use case, and we can get the channel to use just by looking at the type of encoder, since that is fixed. Implement those callbacks, which will remove some of the encoder boilerplate. Reviewed-by: Chen-Yu Tsai <wens@csie.org> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> Link: https://patchwork.freedesktop.org/patch/msgid/90b4396e19b3eca61b2ebfdae0672074b88ad74d.1508231063.git-series.maxime.ripard@free-electrons.com
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_crtc.c22
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c8
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_rgb.c14
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon.c87
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon.h10
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tv.c6
6 files changed, 67 insertions, 80 deletions
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index d097c6f93ad0..e86baa3746af 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -30,6 +30,22 @@
30#include "sunxi_engine.h" 30#include "sunxi_engine.h"
31#include "sun4i_tcon.h" 31#include "sun4i_tcon.h"
32 32
33/*
34 * While this isn't really working in the DRM theory, in practice we
35 * can only ever have one encoder per TCON since we have a mux in our
36 * TCON.
37 */
38static struct drm_encoder *sun4i_crtc_get_encoder(struct drm_crtc *crtc)
39{
40 struct drm_encoder *encoder;
41
42 drm_for_each_encoder(encoder, crtc->dev)
43 if (encoder->crtc == crtc)
44 return encoder;
45
46 return NULL;
47}
48
33static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc, 49static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
34 struct drm_crtc_state *old_state) 50 struct drm_crtc_state *old_state)
35{ 51{
@@ -72,11 +88,12 @@ static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
72static void sun4i_crtc_atomic_disable(struct drm_crtc *crtc, 88static void sun4i_crtc_atomic_disable(struct drm_crtc *crtc,
73 struct drm_crtc_state *old_state) 89 struct drm_crtc_state *old_state)
74{ 90{
91 struct drm_encoder *encoder = sun4i_crtc_get_encoder(crtc);
75 struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); 92 struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
76 93
77 DRM_DEBUG_DRIVER("Disabling the CRTC\n"); 94 DRM_DEBUG_DRIVER("Disabling the CRTC\n");
78 95
79 sun4i_tcon_disable(scrtc->tcon); 96 sun4i_tcon_set_status(scrtc->tcon, encoder, false);
80 97
81 if (crtc->state->event && !crtc->state->active) { 98 if (crtc->state->event && !crtc->state->active) {
82 spin_lock_irq(&crtc->dev->event_lock); 99 spin_lock_irq(&crtc->dev->event_lock);
@@ -90,11 +107,12 @@ static void sun4i_crtc_atomic_disable(struct drm_crtc *crtc,
90static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc, 107static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc,
91 struct drm_crtc_state *old_state) 108 struct drm_crtc_state *old_state)
92{ 109{
110 struct drm_encoder *encoder = sun4i_crtc_get_encoder(crtc);
93 struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc); 111 struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
94 112
95 DRM_DEBUG_DRIVER("Enabling the CRTC\n"); 113 DRM_DEBUG_DRIVER("Enabling the CRTC\n");
96 114
97 sun4i_tcon_enable(scrtc->tcon); 115 sun4i_tcon_set_status(scrtc->tcon, encoder, true);
98} 116}
99 117
100static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = { 118static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index 6ca6e6a74c4a..482bf03d55c1 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -86,8 +86,6 @@ static int sun4i_hdmi_atomic_check(struct drm_encoder *encoder,
86static void sun4i_hdmi_disable(struct drm_encoder *encoder) 86static void sun4i_hdmi_disable(struct drm_encoder *encoder)
87{ 87{
88 struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder); 88 struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
89 struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
90 struct sun4i_tcon *tcon = crtc->tcon;
91 u32 val; 89 u32 val;
92 90
93 DRM_DEBUG_DRIVER("Disabling the HDMI Output\n"); 91 DRM_DEBUG_DRIVER("Disabling the HDMI Output\n");
@@ -95,22 +93,16 @@ static void sun4i_hdmi_disable(struct drm_encoder *encoder)
95 val = readl(hdmi->base + SUN4I_HDMI_VID_CTRL_REG); 93 val = readl(hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
96 val &= ~SUN4I_HDMI_VID_CTRL_ENABLE; 94 val &= ~SUN4I_HDMI_VID_CTRL_ENABLE;
97 writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG); 95 writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
98
99 sun4i_tcon_channel_disable(tcon, 1);
100} 96}
101 97
102static void sun4i_hdmi_enable(struct drm_encoder *encoder) 98static void sun4i_hdmi_enable(struct drm_encoder *encoder)
103{ 99{
104 struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; 100 struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
105 struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder); 101 struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
106 struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
107 struct sun4i_tcon *tcon = crtc->tcon;
108 u32 val = 0; 102 u32 val = 0;
109 103
110 DRM_DEBUG_DRIVER("Enabling the HDMI Output\n"); 104 DRM_DEBUG_DRIVER("Enabling the HDMI Output\n");
111 105
112 sun4i_tcon_channel_enable(tcon, 1);
113
114 sun4i_hdmi_setup_avi_infoframes(hdmi, mode); 106 sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
115 val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI); 107 val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
116 val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END); 108 val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index 7cd7090ad63a..a7f297ed40c1 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -134,13 +134,10 @@ static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder)
134 134
135 DRM_DEBUG_DRIVER("Enabling RGB output\n"); 135 DRM_DEBUG_DRIVER("Enabling RGB output\n");
136 136
137 if (!IS_ERR(tcon->panel)) 137 if (!IS_ERR(tcon->panel)) {
138 drm_panel_prepare(tcon->panel); 138 drm_panel_prepare(tcon->panel);
139
140 sun4i_tcon_channel_enable(tcon, 0);
141
142 if (!IS_ERR(tcon->panel))
143 drm_panel_enable(tcon->panel); 139 drm_panel_enable(tcon->panel);
140 }
144} 141}
145 142
146static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder) 143static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
@@ -150,13 +147,10 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
150 147
151 DRM_DEBUG_DRIVER("Disabling RGB output\n"); 148 DRM_DEBUG_DRIVER("Disabling RGB output\n");
152 149
153 if (!IS_ERR(tcon->panel)) 150 if (!IS_ERR(tcon->panel)) {
154 drm_panel_disable(tcon->panel); 151 drm_panel_disable(tcon->panel);
155
156 sun4i_tcon_channel_disable(tcon, 0);
157
158 if (!IS_ERR(tcon->panel))
159 drm_panel_unprepare(tcon->panel); 152 drm_panel_unprepare(tcon->panel);
153 }
160} 154}
161 155
162static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder, 156static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 9b5b21ad8378..964cf22a1ced 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -35,66 +35,61 @@
35#include "sun4i_tcon.h" 35#include "sun4i_tcon.h"
36#include "sunxi_engine.h" 36#include "sunxi_engine.h"
37 37
38void sun4i_tcon_disable(struct sun4i_tcon *tcon) 38static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel,
39 bool enabled)
39{ 40{
40 DRM_DEBUG_DRIVER("Disabling TCON\n"); 41 struct clk *clk;
41 42
42 /* Disable the TCON */ 43 switch (channel) {
43 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG, 44 case 0:
44 SUN4I_TCON_GCTL_TCON_ENABLE, 0);
45}
46EXPORT_SYMBOL(sun4i_tcon_disable);
47
48void sun4i_tcon_enable(struct sun4i_tcon *tcon)
49{
50 DRM_DEBUG_DRIVER("Enabling TCON\n");
51
52 /* Enable the TCON */
53 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
54 SUN4I_TCON_GCTL_TCON_ENABLE,
55 SUN4I_TCON_GCTL_TCON_ENABLE);
56}
57EXPORT_SYMBOL(sun4i_tcon_enable);
58
59void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel)
60{
61 DRM_DEBUG_DRIVER("Disabling TCON channel %d\n", channel);
62
63 /* Disable the TCON's channel */
64 if (channel == 0) {
65 regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, 45 regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
66 SUN4I_TCON0_CTL_TCON_ENABLE, 0); 46 SUN4I_TCON0_CTL_TCON_ENABLE,
67 clk_disable_unprepare(tcon->dclk); 47 enabled ? SUN4I_TCON0_CTL_TCON_ENABLE : 0);
48 clk = tcon->dclk;
49 break;
50 case 1:
51 WARN_ON(!tcon->quirks->has_channel_1);
52 regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
53 SUN4I_TCON1_CTL_TCON_ENABLE,
54 enabled ? SUN4I_TCON1_CTL_TCON_ENABLE : 0);
55 clk = tcon->sclk1;
56 break;
57 default:
58 DRM_WARN("Unknown channel... doing nothing\n");
68 return; 59 return;
69 } 60 }
70 61
71 WARN_ON(!tcon->quirks->has_channel_1); 62 if (enabled)
72 regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG, 63 clk_prepare_enable(clk);
73 SUN4I_TCON1_CTL_TCON_ENABLE, 0); 64 else
74 clk_disable_unprepare(tcon->sclk1); 65 clk_disable_unprepare(clk);
75} 66}
76EXPORT_SYMBOL(sun4i_tcon_channel_disable);
77 67
78void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel) 68void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
69 const struct drm_encoder *encoder,
70 bool enabled)
79{ 71{
80 DRM_DEBUG_DRIVER("Enabling TCON channel %d\n", channel); 72 int channel;
81 73
82 /* Enable the TCON's channel */ 74 switch (encoder->encoder_type) {
83 if (channel == 0) { 75 case DRM_MODE_ENCODER_NONE:
84 regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, 76 channel = 0;
85 SUN4I_TCON0_CTL_TCON_ENABLE, 77 break;
86 SUN4I_TCON0_CTL_TCON_ENABLE); 78 case DRM_MODE_ENCODER_TMDS:
87 clk_prepare_enable(tcon->dclk); 79 case DRM_MODE_ENCODER_TVDAC:
80 channel = 1;
81 break;
82 default:
83 DRM_DEBUG_DRIVER("Unknown encoder type, doing nothing...\n");
88 return; 84 return;
89 } 85 }
90 86
91 WARN_ON(!tcon->quirks->has_channel_1); 87 regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
92 regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG, 88 SUN4I_TCON_GCTL_TCON_ENABLE,
93 SUN4I_TCON1_CTL_TCON_ENABLE, 89 enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
94 SUN4I_TCON1_CTL_TCON_ENABLE); 90
95 clk_prepare_enable(tcon->sclk1); 91 sun4i_tcon_channel_set_status(tcon, channel, enabled);
96} 92}
97EXPORT_SYMBOL(sun4i_tcon_channel_enable);
98 93
99void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable) 94void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable)
100{ 95{
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index d81c6e20efe6..03f983927baa 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -190,15 +190,9 @@ struct sun4i_tcon {
190struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node); 190struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node);
191struct drm_panel *sun4i_tcon_find_panel(struct device_node *node); 191struct drm_panel *sun4i_tcon_find_panel(struct device_node *node);
192 192
193/* Global Control */
194void sun4i_tcon_disable(struct sun4i_tcon *tcon);
195void sun4i_tcon_enable(struct sun4i_tcon *tcon);
196
197/* Channel Control */
198void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel);
199void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel);
200
201void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable); 193void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable);
194void sun4i_tcon_set_status(struct sun4i_tcon *crtc,
195 const struct drm_encoder *encoder, bool enable);
202 196
203/* Mode Related Controls */ 197/* Mode Related Controls */
204void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel, 198void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel,
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index 050cfd43c7a0..2e27ff9fc58f 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -345,12 +345,9 @@ static void sun4i_tv_disable(struct drm_encoder *encoder)
345{ 345{
346 struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder); 346 struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
347 struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc); 347 struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
348 struct sun4i_tcon *tcon = crtc->tcon;
349 348
350 DRM_DEBUG_DRIVER("Disabling the TV Output\n"); 349 DRM_DEBUG_DRIVER("Disabling the TV Output\n");
351 350
352 sun4i_tcon_channel_disable(tcon, 1);
353
354 regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG, 351 regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
355 SUN4I_TVE_EN_ENABLE, 352 SUN4I_TVE_EN_ENABLE,
356 0); 353 0);
@@ -362,7 +359,6 @@ static void sun4i_tv_enable(struct drm_encoder *encoder)
362{ 359{
363 struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder); 360 struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
364 struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc); 361 struct sun4i_crtc *crtc = drm_crtc_to_sun4i_crtc(encoder->crtc);
365 struct sun4i_tcon *tcon = crtc->tcon;
366 362
367 DRM_DEBUG_DRIVER("Enabling the TV Output\n"); 363 DRM_DEBUG_DRIVER("Enabling the TV Output\n");
368 364
@@ -371,8 +367,6 @@ static void sun4i_tv_enable(struct drm_encoder *encoder)
371 regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG, 367 regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
372 SUN4I_TVE_EN_ENABLE, 368 SUN4I_TVE_EN_ENABLE,
373 SUN4I_TVE_EN_ENABLE); 369 SUN4I_TVE_EN_ENABLE);
374
375 sun4i_tcon_channel_enable(tcon, 1);
376} 370}
377 371
378static void sun4i_tv_mode_set(struct drm_encoder *encoder, 372static void sun4i_tv_mode_set(struct drm_encoder *encoder,