aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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,