diff options
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_crtc.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_rgb.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_tcon.c | 87 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_tcon.h | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_tv.c | 6 |
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 | */ | ||
38 | static 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 | |||
33 | static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc, | 49 | static 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, | |||
72 | static void sun4i_crtc_atomic_disable(struct drm_crtc *crtc, | 88 | static 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, | |||
90 | static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc, | 107 | static 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 | ||
100 | static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = { | 118 | static 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, | |||
86 | static void sun4i_hdmi_disable(struct drm_encoder *encoder) | 86 | static 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 | ||
102 | static void sun4i_hdmi_enable(struct drm_encoder *encoder) | 98 | static 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 | ||
146 | static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder) | 143 | static 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 | ||
162 | static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder, | 156 | static 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 | ||
38 | void sun4i_tcon_disable(struct sun4i_tcon *tcon) | 38 | static 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 | } | ||
46 | EXPORT_SYMBOL(sun4i_tcon_disable); | ||
47 | |||
48 | void 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 | } | ||
57 | EXPORT_SYMBOL(sun4i_tcon_enable); | ||
58 | |||
59 | void 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 | } |
76 | EXPORT_SYMBOL(sun4i_tcon_channel_disable); | ||
77 | 67 | ||
78 | void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel) | 68 | void 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 | } |
97 | EXPORT_SYMBOL(sun4i_tcon_channel_enable); | ||
98 | 93 | ||
99 | void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable) | 94 | void 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 { | |||
190 | struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node); | 190 | struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node); |
191 | struct drm_panel *sun4i_tcon_find_panel(struct device_node *node); | 191 | struct drm_panel *sun4i_tcon_find_panel(struct device_node *node); |
192 | 192 | ||
193 | /* Global Control */ | ||
194 | void sun4i_tcon_disable(struct sun4i_tcon *tcon); | ||
195 | void sun4i_tcon_enable(struct sun4i_tcon *tcon); | ||
196 | |||
197 | /* Channel Control */ | ||
198 | void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel); | ||
199 | void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel); | ||
200 | |||
201 | void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable); | 193 | void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable); |
194 | void 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 */ |
204 | void sun4i_tcon_set_mux(struct sun4i_tcon *tcon, int channel, | 198 | void 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 | ||
378 | static void sun4i_tv_mode_set(struct drm_encoder *encoder, | 372 | static void sun4i_tv_mode_set(struct drm_encoder *encoder, |