diff options
| -rw-r--r-- | drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 60 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c | 119 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c | 34 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c | 154 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 61 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c | 89 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 14 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/msm_atomic.c | 25 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/msm_fbdev.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/msm_kms.h | 3 |
12 files changed, 303 insertions, 263 deletions
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c index b4e70e0e3cfa..6bd38c73c6f7 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c | |||
| @@ -386,7 +386,7 @@ hdmi_connector_best_encoder(struct drm_connector *connector) | |||
| 386 | } | 386 | } |
| 387 | 387 | ||
| 388 | static const struct drm_connector_funcs hdmi_connector_funcs = { | 388 | static const struct drm_connector_funcs hdmi_connector_funcs = { |
| 389 | .dpms = drm_helper_connector_dpms, | 389 | .dpms = drm_atomic_helper_connector_dpms, |
| 390 | .detect = hdmi_connector_detect, | 390 | .detect = hdmi_connector_detect, |
| 391 | .fill_modes = drm_helper_probe_single_connector_modes, | 391 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 392 | .destroy = hdmi_connector_destroy, | 392 | .destroy = hdmi_connector_destroy, |
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c index 67b42a43a1b1..73afa21822b4 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | |||
| @@ -140,26 +140,6 @@ static void mdp4_crtc_destroy(struct drm_crtc *crtc) | |||
| 140 | kfree(mdp4_crtc); | 140 | kfree(mdp4_crtc); |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | static void mdp4_crtc_dpms(struct drm_crtc *crtc, int mode) | ||
| 144 | { | ||
| 145 | struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); | ||
| 146 | struct mdp4_kms *mdp4_kms = get_kms(crtc); | ||
| 147 | bool enabled = (mode == DRM_MODE_DPMS_ON); | ||
| 148 | |||
| 149 | DBG("%s: mode=%d", mdp4_crtc->name, mode); | ||
| 150 | |||
| 151 | if (enabled != mdp4_crtc->enabled) { | ||
| 152 | if (enabled) { | ||
| 153 | mdp4_enable(mdp4_kms); | ||
| 154 | mdp_irq_register(&mdp4_kms->base, &mdp4_crtc->err); | ||
| 155 | } else { | ||
| 156 | mdp_irq_unregister(&mdp4_kms->base, &mdp4_crtc->err); | ||
| 157 | mdp4_disable(mdp4_kms); | ||
| 158 | } | ||
| 159 | mdp4_crtc->enabled = enabled; | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | static bool mdp4_crtc_mode_fixup(struct drm_crtc *crtc, | 143 | static bool mdp4_crtc_mode_fixup(struct drm_crtc *crtc, |
| 164 | const struct drm_display_mode *mode, | 144 | const struct drm_display_mode *mode, |
| 165 | struct drm_display_mode *adjusted_mode) | 145 | struct drm_display_mode *adjusted_mode) |
| @@ -304,23 +284,38 @@ static void mdp4_crtc_mode_set_nofb(struct drm_crtc *crtc) | |||
| 304 | } | 284 | } |
| 305 | } | 285 | } |
| 306 | 286 | ||
| 307 | static void mdp4_crtc_prepare(struct drm_crtc *crtc) | 287 | static void mdp4_crtc_disable(struct drm_crtc *crtc) |
| 308 | { | 288 | { |
| 309 | struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); | 289 | struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); |
| 290 | struct mdp4_kms *mdp4_kms = get_kms(crtc); | ||
| 291 | |||
| 310 | DBG("%s", mdp4_crtc->name); | 292 | DBG("%s", mdp4_crtc->name); |
| 311 | /* make sure we hold a ref to mdp clks while setting up mode: */ | 293 | |
| 312 | drm_crtc_vblank_get(crtc); | 294 | if (WARN_ON(!mdp4_crtc->enabled)) |
| 313 | mdp4_enable(get_kms(crtc)); | 295 | return; |
| 314 | mdp4_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); | 296 | |
| 297 | mdp_irq_unregister(&mdp4_kms->base, &mdp4_crtc->err); | ||
| 298 | mdp4_disable(mdp4_kms); | ||
| 299 | |||
| 300 | mdp4_crtc->enabled = false; | ||
| 315 | } | 301 | } |
| 316 | 302 | ||
| 317 | static void mdp4_crtc_commit(struct drm_crtc *crtc) | 303 | static void mdp4_crtc_enable(struct drm_crtc *crtc) |
| 318 | { | 304 | { |
| 319 | mdp4_crtc_dpms(crtc, DRM_MODE_DPMS_ON); | 305 | struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); |
| 306 | struct mdp4_kms *mdp4_kms = get_kms(crtc); | ||
| 307 | |||
| 308 | DBG("%s", mdp4_crtc->name); | ||
| 309 | |||
| 310 | if (WARN_ON(mdp4_crtc->enabled)) | ||
| 311 | return; | ||
| 312 | |||
| 313 | mdp4_enable(mdp4_kms); | ||
| 314 | mdp_irq_register(&mdp4_kms->base, &mdp4_crtc->err); | ||
| 315 | |||
| 320 | crtc_flush(crtc); | 316 | crtc_flush(crtc); |
| 321 | /* drop the ref to mdp clk's that we got in prepare: */ | 317 | |
| 322 | mdp4_disable(get_kms(crtc)); | 318 | mdp4_crtc->enabled = true; |
| 323 | drm_crtc_vblank_put(crtc); | ||
| 324 | } | 319 | } |
| 325 | 320 | ||
| 326 | static int mdp4_crtc_atomic_check(struct drm_crtc *crtc, | 321 | static int mdp4_crtc_atomic_check(struct drm_crtc *crtc, |
| @@ -504,11 +499,10 @@ static const struct drm_crtc_funcs mdp4_crtc_funcs = { | |||
| 504 | }; | 499 | }; |
| 505 | 500 | ||
| 506 | static const struct drm_crtc_helper_funcs mdp4_crtc_helper_funcs = { | 501 | static const struct drm_crtc_helper_funcs mdp4_crtc_helper_funcs = { |
| 507 | .dpms = mdp4_crtc_dpms, | ||
| 508 | .mode_fixup = mdp4_crtc_mode_fixup, | 502 | .mode_fixup = mdp4_crtc_mode_fixup, |
| 509 | .mode_set_nofb = mdp4_crtc_mode_set_nofb, | 503 | .mode_set_nofb = mdp4_crtc_mode_set_nofb, |
| 510 | .prepare = mdp4_crtc_prepare, | 504 | .disable = mdp4_crtc_disable, |
| 511 | .commit = mdp4_crtc_commit, | 505 | .enable = mdp4_crtc_enable, |
| 512 | .atomic_check = mdp4_crtc_atomic_check, | 506 | .atomic_check = mdp4_crtc_atomic_check, |
| 513 | .atomic_begin = mdp4_crtc_atomic_begin, | 507 | .atomic_begin = mdp4_crtc_atomic_begin, |
| 514 | .atomic_flush = mdp4_crtc_atomic_flush, | 508 | .atomic_flush = mdp4_crtc_atomic_flush, |
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c index c3878420180b..7896323b2631 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c | |||
| @@ -94,61 +94,6 @@ static const struct drm_encoder_funcs mdp4_dtv_encoder_funcs = { | |||
| 94 | .destroy = mdp4_dtv_encoder_destroy, | 94 | .destroy = mdp4_dtv_encoder_destroy, |
| 95 | }; | 95 | }; |
| 96 | 96 | ||
| 97 | static void mdp4_dtv_encoder_dpms(struct drm_encoder *encoder, int mode) | ||
| 98 | { | ||
| 99 | struct drm_device *dev = encoder->dev; | ||
| 100 | struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder); | ||
| 101 | struct mdp4_kms *mdp4_kms = get_kms(encoder); | ||
| 102 | bool enabled = (mode == DRM_MODE_DPMS_ON); | ||
| 103 | |||
| 104 | DBG("mode=%d", mode); | ||
| 105 | |||
| 106 | if (enabled == mdp4_dtv_encoder->enabled) | ||
| 107 | return; | ||
| 108 | |||
| 109 | if (enabled) { | ||
| 110 | unsigned long pc = mdp4_dtv_encoder->pixclock; | ||
| 111 | int ret; | ||
| 112 | |||
| 113 | bs_set(mdp4_dtv_encoder, 1); | ||
| 114 | |||
| 115 | DBG("setting src_clk=%lu", pc); | ||
| 116 | |||
| 117 | ret = clk_set_rate(mdp4_dtv_encoder->src_clk, pc); | ||
| 118 | if (ret) | ||
| 119 | dev_err(dev->dev, "failed to set src_clk to %lu: %d\n", pc, ret); | ||
| 120 | clk_prepare_enable(mdp4_dtv_encoder->src_clk); | ||
| 121 | ret = clk_prepare_enable(mdp4_dtv_encoder->hdmi_clk); | ||
| 122 | if (ret) | ||
| 123 | dev_err(dev->dev, "failed to enable hdmi_clk: %d\n", ret); | ||
| 124 | ret = clk_prepare_enable(mdp4_dtv_encoder->mdp_clk); | ||
| 125 | if (ret) | ||
| 126 | dev_err(dev->dev, "failed to enabled mdp_clk: %d\n", ret); | ||
| 127 | |||
| 128 | mdp4_write(mdp4_kms, REG_MDP4_DTV_ENABLE, 1); | ||
| 129 | } else { | ||
| 130 | mdp4_write(mdp4_kms, REG_MDP4_DTV_ENABLE, 0); | ||
| 131 | |||
| 132 | /* | ||
| 133 | * Wait for a vsync so we know the ENABLE=0 latched before | ||
| 134 | * the (connector) source of the vsync's gets disabled, | ||
| 135 | * otherwise we end up in a funny state if we re-enable | ||
| 136 | * before the disable latches, which results that some of | ||
| 137 | * the settings changes for the new modeset (like new | ||
| 138 | * scanout buffer) don't latch properly.. | ||
| 139 | */ | ||
| 140 | mdp_irq_wait(&mdp4_kms->base, MDP4_IRQ_EXTERNAL_VSYNC); | ||
| 141 | |||
| 142 | clk_disable_unprepare(mdp4_dtv_encoder->src_clk); | ||
| 143 | clk_disable_unprepare(mdp4_dtv_encoder->hdmi_clk); | ||
| 144 | clk_disable_unprepare(mdp4_dtv_encoder->mdp_clk); | ||
| 145 | |||
| 146 | bs_set(mdp4_dtv_encoder, 0); | ||
| 147 | } | ||
| 148 | |||
| 149 | mdp4_dtv_encoder->enabled = enabled; | ||
| 150 | } | ||
| 151 | |||
| 152 | static bool mdp4_dtv_encoder_mode_fixup(struct drm_encoder *encoder, | 97 | static bool mdp4_dtv_encoder_mode_fixup(struct drm_encoder *encoder, |
| 153 | const struct drm_display_mode *mode, | 98 | const struct drm_display_mode *mode, |
| 154 | struct drm_display_mode *adjusted_mode) | 99 | struct drm_display_mode *adjusted_mode) |
| @@ -221,28 +166,78 @@ static void mdp4_dtv_encoder_mode_set(struct drm_encoder *encoder, | |||
| 221 | mdp4_write(mdp4_kms, REG_MDP4_DTV_ACTIVE_VEND, 0); | 166 | mdp4_write(mdp4_kms, REG_MDP4_DTV_ACTIVE_VEND, 0); |
| 222 | } | 167 | } |
| 223 | 168 | ||
| 224 | static void mdp4_dtv_encoder_prepare(struct drm_encoder *encoder) | 169 | static void mdp4_dtv_encoder_disable(struct drm_encoder *encoder) |
| 225 | { | 170 | { |
| 226 | mdp4_dtv_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); | 171 | struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder); |
| 172 | struct mdp4_kms *mdp4_kms = get_kms(encoder); | ||
| 173 | |||
| 174 | if (WARN_ON(!mdp4_dtv_encoder->enabled)) | ||
| 175 | return; | ||
| 176 | |||
| 177 | mdp4_write(mdp4_kms, REG_MDP4_DTV_ENABLE, 0); | ||
| 178 | |||
| 179 | /* | ||
| 180 | * Wait for a vsync so we know the ENABLE=0 latched before | ||
| 181 | * the (connector) source of the vsync's gets disabled, | ||
| 182 | * otherwise we end up in a funny state if we re-enable | ||
| 183 | * before the disable latches, which results that some of | ||
| 184 | * the settings changes for the new modeset (like new | ||
| 185 | * scanout buffer) don't latch properly.. | ||
| 186 | */ | ||
| 187 | mdp_irq_wait(&mdp4_kms->base, MDP4_IRQ_EXTERNAL_VSYNC); | ||
| 188 | |||
| 189 | clk_disable_unprepare(mdp4_dtv_encoder->src_clk); | ||
| 190 | clk_disable_unprepare(mdp4_dtv_encoder->hdmi_clk); | ||
| 191 | clk_disable_unprepare(mdp4_dtv_encoder->mdp_clk); | ||
| 192 | |||
| 193 | bs_set(mdp4_dtv_encoder, 0); | ||
| 194 | |||
| 195 | mdp4_dtv_encoder->enabled = false; | ||
| 227 | } | 196 | } |
| 228 | 197 | ||
| 229 | static void mdp4_dtv_encoder_commit(struct drm_encoder *encoder) | 198 | static void mdp4_dtv_encoder_enable(struct drm_encoder *encoder) |
| 230 | { | 199 | { |
| 200 | struct drm_device *dev = encoder->dev; | ||
| 201 | struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder); | ||
| 202 | struct mdp4_kms *mdp4_kms = get_kms(encoder); | ||
| 203 | unsigned long pc = mdp4_dtv_encoder->pixclock; | ||
| 204 | int ret; | ||
| 205 | |||
| 206 | if (WARN_ON(mdp4_dtv_encoder->enabled)) | ||
| 207 | return; | ||
| 208 | |||
| 231 | mdp4_crtc_set_config(encoder->crtc, | 209 | mdp4_crtc_set_config(encoder->crtc, |
| 232 | MDP4_DMA_CONFIG_R_BPC(BPC8) | | 210 | MDP4_DMA_CONFIG_R_BPC(BPC8) | |
| 233 | MDP4_DMA_CONFIG_G_BPC(BPC8) | | 211 | MDP4_DMA_CONFIG_G_BPC(BPC8) | |
| 234 | MDP4_DMA_CONFIG_B_BPC(BPC8) | | 212 | MDP4_DMA_CONFIG_B_BPC(BPC8) | |
| 235 | MDP4_DMA_CONFIG_PACK(0x21)); | 213 | MDP4_DMA_CONFIG_PACK(0x21)); |
| 236 | mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 1); | 214 | mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 1); |
| 237 | mdp4_dtv_encoder_dpms(encoder, DRM_MODE_DPMS_ON); | 215 | |
| 216 | bs_set(mdp4_dtv_encoder, 1); | ||
| 217 | |||
| 218 | DBG("setting src_clk=%lu", pc); | ||
| 219 | |||
| 220 | ret = clk_set_rate(mdp4_dtv_encoder->src_clk, pc); | ||
| 221 | if (ret) | ||
| 222 | dev_err(dev->dev, "failed to set src_clk to %lu: %d\n", pc, ret); | ||
| 223 | clk_prepare_enable(mdp4_dtv_encoder->src_clk); | ||
| 224 | ret = clk_prepare_enable(mdp4_dtv_encoder->hdmi_clk); | ||
| 225 | if (ret) | ||
| 226 | dev_err(dev->dev, "failed to enable hdmi_clk: %d\n", ret); | ||
| 227 | ret = clk_prepare_enable(mdp4_dtv_encoder->mdp_clk); | ||
| 228 | if (ret) | ||
| 229 | dev_err(dev->dev, "failed to enabled mdp_clk: %d\n", ret); | ||
| 230 | |||
| 231 | mdp4_write(mdp4_kms, REG_MDP4_DTV_ENABLE, 1); | ||
| 232 | |||
| 233 | mdp4_dtv_encoder->enabled = true; | ||
| 238 | } | 234 | } |
| 239 | 235 | ||
| 240 | static const struct drm_encoder_helper_funcs mdp4_dtv_encoder_helper_funcs = { | 236 | static const struct drm_encoder_helper_funcs mdp4_dtv_encoder_helper_funcs = { |
| 241 | .dpms = mdp4_dtv_encoder_dpms, | ||
| 242 | .mode_fixup = mdp4_dtv_encoder_mode_fixup, | 237 | .mode_fixup = mdp4_dtv_encoder_mode_fixup, |
| 243 | .mode_set = mdp4_dtv_encoder_mode_set, | 238 | .mode_set = mdp4_dtv_encoder_mode_set, |
| 244 | .prepare = mdp4_dtv_encoder_prepare, | 239 | .enable = mdp4_dtv_encoder_enable, |
| 245 | .commit = mdp4_dtv_encoder_commit, | 240 | .disable = mdp4_dtv_encoder_disable, |
| 246 | }; | 241 | }; |
| 247 | 242 | ||
| 248 | long mdp4_dtv_round_pixclk(struct drm_encoder *encoder, unsigned long rate) | 243 | long mdp4_dtv_round_pixclk(struct drm_encoder *encoder, unsigned long rate) |
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c index a62109e4ae0d..d847b9436194 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c | |||
| @@ -125,6 +125,38 @@ out: | |||
| 125 | return ret; | 125 | return ret; |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | static void mdp4_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *state) | ||
| 129 | { | ||
| 130 | struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms)); | ||
| 131 | int i, ncrtcs = state->dev->mode_config.num_crtc; | ||
| 132 | |||
| 133 | mdp4_enable(mdp4_kms); | ||
| 134 | |||
| 135 | /* see 119ecb7fd */ | ||
| 136 | for (i = 0; i < ncrtcs; i++) { | ||
| 137 | struct drm_crtc *crtc = state->crtcs[i]; | ||
| 138 | if (!crtc) | ||
| 139 | continue; | ||
| 140 | drm_crtc_vblank_get(crtc); | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | static void mdp4_complete_commit(struct msm_kms *kms, struct drm_atomic_state *state) | ||
| 145 | { | ||
| 146 | struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms)); | ||
| 147 | int i, ncrtcs = state->dev->mode_config.num_crtc; | ||
| 148 | |||
| 149 | /* see 119ecb7fd */ | ||
| 150 | for (i = 0; i < ncrtcs; i++) { | ||
| 151 | struct drm_crtc *crtc = state->crtcs[i]; | ||
| 152 | if (!crtc) | ||
| 153 | continue; | ||
| 154 | drm_crtc_vblank_put(crtc); | ||
| 155 | } | ||
| 156 | |||
| 157 | mdp4_disable(mdp4_kms); | ||
| 158 | } | ||
| 159 | |||
| 128 | static long mdp4_round_pixclk(struct msm_kms *kms, unsigned long rate, | 160 | static long mdp4_round_pixclk(struct msm_kms *kms, unsigned long rate, |
| 129 | struct drm_encoder *encoder) | 161 | struct drm_encoder *encoder) |
| 130 | { | 162 | { |
| @@ -161,6 +193,8 @@ static const struct mdp_kms_funcs kms_funcs = { | |||
| 161 | .irq = mdp4_irq, | 193 | .irq = mdp4_irq, |
| 162 | .enable_vblank = mdp4_enable_vblank, | 194 | .enable_vblank = mdp4_enable_vblank, |
| 163 | .disable_vblank = mdp4_disable_vblank, | 195 | .disable_vblank = mdp4_disable_vblank, |
| 196 | .prepare_commit = mdp4_prepare_commit, | ||
| 197 | .complete_commit = mdp4_complete_commit, | ||
| 164 | .get_format = mdp_get_format, | 198 | .get_format = mdp_get_format, |
| 165 | .round_pixclk = mdp4_round_pixclk, | 199 | .round_pixclk = mdp4_round_pixclk, |
| 166 | .preclose = mdp4_preclose, | 200 | .preclose = mdp4_preclose, |
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c index 41f6436754fc..60ec8222c9f6 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c | |||
| @@ -259,77 +259,6 @@ static void setup_phy(struct drm_encoder *encoder) | |||
| 259 | mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG0, lvds_phy_cfg0); | 259 | mdp4_write(mdp4_kms, REG_MDP4_LVDS_PHY_CFG0, lvds_phy_cfg0); |
| 260 | } | 260 | } |
| 261 | 261 | ||
| 262 | static void mdp4_lcdc_encoder_dpms(struct drm_encoder *encoder, int mode) | ||
| 263 | { | ||
| 264 | struct drm_device *dev = encoder->dev; | ||
| 265 | struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = | ||
| 266 | to_mdp4_lcdc_encoder(encoder); | ||
| 267 | struct mdp4_kms *mdp4_kms = get_kms(encoder); | ||
| 268 | struct drm_panel *panel = mdp4_lcdc_encoder->panel; | ||
| 269 | bool enabled = (mode == DRM_MODE_DPMS_ON); | ||
| 270 | int i, ret; | ||
| 271 | |||
| 272 | DBG("mode=%d", mode); | ||
| 273 | |||
| 274 | if (enabled == mdp4_lcdc_encoder->enabled) | ||
| 275 | return; | ||
| 276 | |||
| 277 | if (enabled) { | ||
| 278 | unsigned long pc = mdp4_lcdc_encoder->pixclock; | ||
| 279 | int ret; | ||
| 280 | |||
| 281 | bs_set(mdp4_lcdc_encoder, 1); | ||
| 282 | |||
| 283 | for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) { | ||
| 284 | ret = regulator_enable(mdp4_lcdc_encoder->regs[i]); | ||
| 285 | if (ret) | ||
| 286 | dev_err(dev->dev, "failed to enable regulator: %d\n", ret); | ||
| 287 | } | ||
| 288 | |||
| 289 | DBG("setting lcdc_clk=%lu", pc); | ||
| 290 | ret = clk_set_rate(mdp4_lcdc_encoder->lcdc_clk, pc); | ||
| 291 | if (ret) | ||
| 292 | dev_err(dev->dev, "failed to configure lcdc_clk: %d\n", ret); | ||
| 293 | ret = clk_prepare_enable(mdp4_lcdc_encoder->lcdc_clk); | ||
| 294 | if (ret) | ||
| 295 | dev_err(dev->dev, "failed to enable lcdc_clk: %d\n", ret); | ||
| 296 | |||
| 297 | if (panel) | ||
| 298 | drm_panel_enable(panel); | ||
| 299 | |||
| 300 | setup_phy(encoder); | ||
| 301 | |||
| 302 | mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 1); | ||
| 303 | } else { | ||
| 304 | mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 0); | ||
| 305 | |||
| 306 | if (panel) | ||
| 307 | drm_panel_disable(panel); | ||
| 308 | |||
| 309 | /* | ||
| 310 | * Wait for a vsync so we know the ENABLE=0 latched before | ||
| 311 | * the (connector) source of the vsync's gets disabled, | ||
| 312 | * otherwise we end up in a funny state if we re-enable | ||
| 313 | * before the disable latches, which results that some of | ||
| 314 | * the settings changes for the new modeset (like new | ||
| 315 | * scanout buffer) don't latch properly.. | ||
| 316 | */ | ||
| 317 | mdp_irq_wait(&mdp4_kms->base, MDP4_IRQ_PRIMARY_VSYNC); | ||
| 318 | |||
| 319 | clk_disable_unprepare(mdp4_lcdc_encoder->lcdc_clk); | ||
| 320 | |||
| 321 | for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) { | ||
| 322 | ret = regulator_disable(mdp4_lcdc_encoder->regs[i]); | ||
| 323 | if (ret) | ||
| 324 | dev_err(dev->dev, "failed to disable regulator: %d\n", ret); | ||
| 325 | } | ||
| 326 | |||
| 327 | bs_set(mdp4_lcdc_encoder, 0); | ||
| 328 | } | ||
| 329 | |||
| 330 | mdp4_lcdc_encoder->enabled = enabled; | ||
| 331 | } | ||
| 332 | |||
| 333 | static bool mdp4_lcdc_encoder_mode_fixup(struct drm_encoder *encoder, | 262 | static bool mdp4_lcdc_encoder_mode_fixup(struct drm_encoder *encoder, |
| 334 | const struct drm_display_mode *mode, | 263 | const struct drm_display_mode *mode, |
| 335 | struct drm_display_mode *adjusted_mode) | 264 | struct drm_display_mode *adjusted_mode) |
| @@ -403,13 +332,59 @@ static void mdp4_lcdc_encoder_mode_set(struct drm_encoder *encoder, | |||
| 403 | mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_VEND, 0); | 332 | mdp4_write(mdp4_kms, REG_MDP4_LCDC_ACTIVE_VEND, 0); |
| 404 | } | 333 | } |
| 405 | 334 | ||
| 406 | static void mdp4_lcdc_encoder_prepare(struct drm_encoder *encoder) | 335 | static void mdp4_lcdc_encoder_disable(struct drm_encoder *encoder) |
| 407 | { | 336 | { |
| 408 | mdp4_lcdc_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); | 337 | struct drm_device *dev = encoder->dev; |
| 338 | struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = | ||
| 339 | to_mdp4_lcdc_encoder(encoder); | ||
| 340 | struct mdp4_kms *mdp4_kms = get_kms(encoder); | ||
| 341 | struct drm_panel *panel = mdp4_lcdc_encoder->panel; | ||
| 342 | int i, ret; | ||
| 343 | |||
| 344 | if (WARN_ON(!mdp4_lcdc_encoder->enabled)) | ||
| 345 | return; | ||
| 346 | |||
| 347 | mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 0); | ||
| 348 | |||
| 349 | if (panel) | ||
| 350 | drm_panel_disable(panel); | ||
| 351 | |||
| 352 | /* | ||
| 353 | * Wait for a vsync so we know the ENABLE=0 latched before | ||
| 354 | * the (connector) source of the vsync's gets disabled, | ||
| 355 | * otherwise we end up in a funny state if we re-enable | ||
| 356 | * before the disable latches, which results that some of | ||
| 357 | * the settings changes for the new modeset (like new | ||
| 358 | * scanout buffer) don't latch properly.. | ||
| 359 | */ | ||
| 360 | mdp_irq_wait(&mdp4_kms->base, MDP4_IRQ_PRIMARY_VSYNC); | ||
| 361 | |||
| 362 | clk_disable_unprepare(mdp4_lcdc_encoder->lcdc_clk); | ||
| 363 | |||
| 364 | for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) { | ||
| 365 | ret = regulator_disable(mdp4_lcdc_encoder->regs[i]); | ||
| 366 | if (ret) | ||
| 367 | dev_err(dev->dev, "failed to disable regulator: %d\n", ret); | ||
| 368 | } | ||
| 369 | |||
| 370 | bs_set(mdp4_lcdc_encoder, 0); | ||
| 371 | |||
| 372 | mdp4_lcdc_encoder->enabled = false; | ||
| 409 | } | 373 | } |
| 410 | 374 | ||
| 411 | static void mdp4_lcdc_encoder_commit(struct drm_encoder *encoder) | 375 | static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder) |
| 412 | { | 376 | { |
| 377 | struct drm_device *dev = encoder->dev; | ||
| 378 | struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = | ||
| 379 | to_mdp4_lcdc_encoder(encoder); | ||
| 380 | unsigned long pc = mdp4_lcdc_encoder->pixclock; | ||
| 381 | struct mdp4_kms *mdp4_kms = get_kms(encoder); | ||
| 382 | struct drm_panel *panel = mdp4_lcdc_encoder->panel; | ||
| 383 | int i, ret; | ||
| 384 | |||
| 385 | if (WARN_ON(mdp4_lcdc_encoder->enabled)) | ||
| 386 | return; | ||
| 387 | |||
| 413 | /* TODO: hard-coded for 18bpp: */ | 388 | /* TODO: hard-coded for 18bpp: */ |
| 414 | mdp4_crtc_set_config(encoder->crtc, | 389 | mdp4_crtc_set_config(encoder->crtc, |
| 415 | MDP4_DMA_CONFIG_R_BPC(BPC6) | | 390 | MDP4_DMA_CONFIG_R_BPC(BPC6) | |
| @@ -420,15 +395,38 @@ static void mdp4_lcdc_encoder_commit(struct drm_encoder *encoder) | |||
| 420 | MDP4_DMA_CONFIG_DEFLKR_EN | | 395 | MDP4_DMA_CONFIG_DEFLKR_EN | |
| 421 | MDP4_DMA_CONFIG_DITHER_EN); | 396 | MDP4_DMA_CONFIG_DITHER_EN); |
| 422 | mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 0); | 397 | mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 0); |
| 423 | mdp4_lcdc_encoder_dpms(encoder, DRM_MODE_DPMS_ON); | 398 | |
| 399 | bs_set(mdp4_lcdc_encoder, 1); | ||
| 400 | |||
| 401 | for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) { | ||
| 402 | ret = regulator_enable(mdp4_lcdc_encoder->regs[i]); | ||
| 403 | if (ret) | ||
| 404 | dev_err(dev->dev, "failed to enable regulator: %d\n", ret); | ||
| 405 | } | ||
| 406 | |||
| 407 | DBG("setting lcdc_clk=%lu", pc); | ||
| 408 | ret = clk_set_rate(mdp4_lcdc_encoder->lcdc_clk, pc); | ||
| 409 | if (ret) | ||
| 410 | dev_err(dev->dev, "failed to configure lcdc_clk: %d\n", ret); | ||
| 411 | ret = clk_prepare_enable(mdp4_lcdc_encoder->lcdc_clk); | ||
| 412 | if (ret) | ||
| 413 | dev_err(dev->dev, "failed to enable lcdc_clk: %d\n", ret); | ||
| 414 | |||
| 415 | if (panel) | ||
| 416 | drm_panel_enable(panel); | ||
| 417 | |||
| 418 | setup_phy(encoder); | ||
| 419 | |||
| 420 | mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 1); | ||
| 421 | |||
| 422 | mdp4_lcdc_encoder->enabled = true; | ||
| 424 | } | 423 | } |
| 425 | 424 | ||
| 426 | static const struct drm_encoder_helper_funcs mdp4_lcdc_encoder_helper_funcs = { | 425 | static const struct drm_encoder_helper_funcs mdp4_lcdc_encoder_helper_funcs = { |
| 427 | .dpms = mdp4_lcdc_encoder_dpms, | ||
| 428 | .mode_fixup = mdp4_lcdc_encoder_mode_fixup, | 426 | .mode_fixup = mdp4_lcdc_encoder_mode_fixup, |
| 429 | .mode_set = mdp4_lcdc_encoder_mode_set, | 427 | .mode_set = mdp4_lcdc_encoder_mode_set, |
| 430 | .prepare = mdp4_lcdc_encoder_prepare, | 428 | .disable = mdp4_lcdc_encoder_disable, |
| 431 | .commit = mdp4_lcdc_encoder_commit, | 429 | .enable = mdp4_lcdc_encoder_enable, |
| 432 | }; | 430 | }; |
| 433 | 431 | ||
| 434 | long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate) | 432 | long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, unsigned long rate) |
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c index 4ddc28e1275b..921185133d38 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c | |||
| @@ -94,7 +94,7 @@ mdp4_lvds_connector_best_encoder(struct drm_connector *connector) | |||
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | static const struct drm_connector_funcs mdp4_lvds_connector_funcs = { | 96 | static const struct drm_connector_funcs mdp4_lvds_connector_funcs = { |
| 97 | .dpms = drm_helper_connector_dpms, | 97 | .dpms = drm_atomic_helper_connector_dpms, |
| 98 | .detect = mdp4_lvds_connector_detect, | 98 | .detect = mdp4_lvds_connector_detect, |
| 99 | .fill_modes = drm_helper_probe_single_connector_modes, | 99 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 100 | .destroy = mdp4_lvds_connector_destroy, | 100 | .destroy = mdp4_lvds_connector_destroy, |
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index 47f101d2f9fa..7416cae60479 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | |||
| @@ -138,28 +138,6 @@ static void mdp5_crtc_destroy(struct drm_crtc *crtc) | |||
| 138 | kfree(mdp5_crtc); | 138 | kfree(mdp5_crtc); |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | static void mdp5_crtc_dpms(struct drm_crtc *crtc, int mode) | ||
| 142 | { | ||
| 143 | struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); | ||
| 144 | struct mdp5_kms *mdp5_kms = get_kms(crtc); | ||
| 145 | bool enabled = (mode == DRM_MODE_DPMS_ON); | ||
| 146 | |||
| 147 | DBG("%s: mode=%d", mdp5_crtc->name, mode); | ||
| 148 | |||
| 149 | if (enabled != mdp5_crtc->enabled) { | ||
| 150 | if (enabled) { | ||
| 151 | mdp5_enable(mdp5_kms); | ||
| 152 | mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->err); | ||
| 153 | } else { | ||
| 154 | /* set STAGE_UNUSED for all layers */ | ||
| 155 | mdp5_ctl_blend(mdp5_crtc->ctl, mdp5_crtc->lm, 0x00000000); | ||
| 156 | mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->err); | ||
| 157 | mdp5_disable(mdp5_kms); | ||
| 158 | } | ||
| 159 | mdp5_crtc->enabled = enabled; | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | static bool mdp5_crtc_mode_fixup(struct drm_crtc *crtc, | 141 | static bool mdp5_crtc_mode_fixup(struct drm_crtc *crtc, |
| 164 | const struct drm_display_mode *mode, | 142 | const struct drm_display_mode *mode, |
| 165 | struct drm_display_mode *adjusted_mode) | 143 | struct drm_display_mode *adjusted_mode) |
| @@ -256,23 +234,41 @@ static void mdp5_crtc_mode_set_nofb(struct drm_crtc *crtc) | |||
| 256 | spin_unlock_irqrestore(&mdp5_crtc->lm_lock, flags); | 234 | spin_unlock_irqrestore(&mdp5_crtc->lm_lock, flags); |
| 257 | } | 235 | } |
| 258 | 236 | ||
| 259 | static void mdp5_crtc_prepare(struct drm_crtc *crtc) | 237 | static void mdp5_crtc_disable(struct drm_crtc *crtc) |
| 260 | { | 238 | { |
| 261 | struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); | 239 | struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); |
| 240 | struct mdp5_kms *mdp5_kms = get_kms(crtc); | ||
| 241 | |||
| 262 | DBG("%s", mdp5_crtc->name); | 242 | DBG("%s", mdp5_crtc->name); |
| 263 | /* make sure we hold a ref to mdp clks while setting up mode: */ | 243 | |
| 264 | mdp5_enable(get_kms(crtc)); | 244 | if (WARN_ON(!mdp5_crtc->enabled)) |
| 265 | mdp5_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); | 245 | return; |
| 246 | |||
| 247 | /* set STAGE_UNUSED for all layers */ | ||
| 248 | mdp5_ctl_blend(mdp5_crtc->ctl, mdp5_crtc->lm, 0x00000000); | ||
| 249 | |||
| 250 | mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->err); | ||
| 251 | mdp5_disable(mdp5_kms); | ||
| 252 | |||
| 253 | mdp5_crtc->enabled = false; | ||
| 266 | } | 254 | } |
| 267 | 255 | ||
| 268 | static void mdp5_crtc_commit(struct drm_crtc *crtc) | 256 | static void mdp5_crtc_enable(struct drm_crtc *crtc) |
| 269 | { | 257 | { |
| 270 | struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); | 258 | struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); |
| 259 | struct mdp5_kms *mdp5_kms = get_kms(crtc); | ||
| 260 | |||
| 271 | DBG("%s", mdp5_crtc->name); | 261 | DBG("%s", mdp5_crtc->name); |
| 272 | mdp5_crtc_dpms(crtc, DRM_MODE_DPMS_ON); | 262 | |
| 263 | if (WARN_ON(mdp5_crtc->enabled)) | ||
| 264 | return; | ||
| 265 | |||
| 266 | mdp5_enable(mdp5_kms); | ||
| 267 | mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->err); | ||
| 268 | |||
| 273 | crtc_flush_all(crtc); | 269 | crtc_flush_all(crtc); |
| 274 | /* drop the ref to mdp clk's that we got in prepare: */ | 270 | |
| 275 | mdp5_disable(get_kms(crtc)); | 271 | mdp5_crtc->enabled = true; |
| 276 | } | 272 | } |
| 277 | 273 | ||
| 278 | struct plane_state { | 274 | struct plane_state { |
| @@ -391,11 +387,10 @@ static const struct drm_crtc_funcs mdp5_crtc_funcs = { | |||
| 391 | }; | 387 | }; |
| 392 | 388 | ||
| 393 | static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = { | 389 | static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = { |
| 394 | .dpms = mdp5_crtc_dpms, | ||
| 395 | .mode_fixup = mdp5_crtc_mode_fixup, | 390 | .mode_fixup = mdp5_crtc_mode_fixup, |
| 396 | .mode_set_nofb = mdp5_crtc_mode_set_nofb, | 391 | .mode_set_nofb = mdp5_crtc_mode_set_nofb, |
| 397 | .prepare = mdp5_crtc_prepare, | 392 | .prepare = mdp5_crtc_disable, |
| 398 | .commit = mdp5_crtc_commit, | 393 | .commit = mdp5_crtc_enable, |
| 399 | .atomic_check = mdp5_crtc_atomic_check, | 394 | .atomic_check = mdp5_crtc_atomic_check, |
| 400 | .atomic_begin = mdp5_crtc_atomic_begin, | 395 | .atomic_begin = mdp5_crtc_atomic_begin, |
| 401 | .atomic_flush = mdp5_crtc_atomic_flush, | 396 | .atomic_flush = mdp5_crtc_atomic_flush, |
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c index 0254bfdeb92f..b5494315345d 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c | |||
| @@ -110,45 +110,6 @@ static const struct drm_encoder_funcs mdp5_encoder_funcs = { | |||
| 110 | .destroy = mdp5_encoder_destroy, | 110 | .destroy = mdp5_encoder_destroy, |
| 111 | }; | 111 | }; |
| 112 | 112 | ||
| 113 | static void mdp5_encoder_dpms(struct drm_encoder *encoder, int mode) | ||
| 114 | { | ||
| 115 | struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); | ||
| 116 | struct mdp5_kms *mdp5_kms = get_kms(encoder); | ||
| 117 | int intf = mdp5_encoder->intf; | ||
| 118 | bool enabled = (mode == DRM_MODE_DPMS_ON); | ||
| 119 | unsigned long flags; | ||
| 120 | |||
| 121 | DBG("mode=%d", mode); | ||
| 122 | |||
| 123 | if (enabled == mdp5_encoder->enabled) | ||
| 124 | return; | ||
| 125 | |||
| 126 | if (enabled) { | ||
| 127 | bs_set(mdp5_encoder, 1); | ||
| 128 | spin_lock_irqsave(&mdp5_encoder->intf_lock, flags); | ||
| 129 | mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 1); | ||
| 130 | spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags); | ||
| 131 | } else { | ||
| 132 | spin_lock_irqsave(&mdp5_encoder->intf_lock, flags); | ||
| 133 | mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 0); | ||
| 134 | spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags); | ||
| 135 | |||
| 136 | /* | ||
| 137 | * Wait for a vsync so we know the ENABLE=0 latched before | ||
| 138 | * the (connector) source of the vsync's gets disabled, | ||
| 139 | * otherwise we end up in a funny state if we re-enable | ||
| 140 | * before the disable latches, which results that some of | ||
| 141 | * the settings changes for the new modeset (like new | ||
| 142 | * scanout buffer) don't latch properly.. | ||
| 143 | */ | ||
| 144 | mdp_irq_wait(&mdp5_kms->base, intf2vblank(intf)); | ||
| 145 | |||
| 146 | bs_set(mdp5_encoder, 0); | ||
| 147 | } | ||
| 148 | |||
| 149 | mdp5_encoder->enabled = enabled; | ||
| 150 | } | ||
| 151 | |||
| 152 | static bool mdp5_encoder_mode_fixup(struct drm_encoder *encoder, | 113 | static bool mdp5_encoder_mode_fixup(struct drm_encoder *encoder, |
| 153 | const struct drm_display_mode *mode, | 114 | const struct drm_display_mode *mode, |
| 154 | struct drm_display_mode *adjusted_mode) | 115 | struct drm_display_mode *adjusted_mode) |
| @@ -225,25 +186,61 @@ static void mdp5_encoder_mode_set(struct drm_encoder *encoder, | |||
| 225 | spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags); | 186 | spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags); |
| 226 | } | 187 | } |
| 227 | 188 | ||
| 228 | static void mdp5_encoder_prepare(struct drm_encoder *encoder) | 189 | static void mdp5_encoder_disable(struct drm_encoder *encoder) |
| 229 | { | 190 | { |
| 230 | mdp5_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); | 191 | struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); |
| 192 | struct mdp5_kms *mdp5_kms = get_kms(encoder); | ||
| 193 | int intf = mdp5_encoder->intf; | ||
| 194 | unsigned long flags; | ||
| 195 | |||
| 196 | if (WARN_ON(!mdp5_encoder->enabled)) | ||
| 197 | return; | ||
| 198 | |||
| 199 | spin_lock_irqsave(&mdp5_encoder->intf_lock, flags); | ||
| 200 | mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 0); | ||
| 201 | spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags); | ||
| 202 | |||
| 203 | /* | ||
| 204 | * Wait for a vsync so we know the ENABLE=0 latched before | ||
| 205 | * the (connector) source of the vsync's gets disabled, | ||
| 206 | * otherwise we end up in a funny state if we re-enable | ||
| 207 | * before the disable latches, which results that some of | ||
| 208 | * the settings changes for the new modeset (like new | ||
| 209 | * scanout buffer) don't latch properly.. | ||
| 210 | */ | ||
| 211 | mdp_irq_wait(&mdp5_kms->base, intf2vblank(intf)); | ||
| 212 | |||
| 213 | bs_set(mdp5_encoder, 0); | ||
| 214 | |||
| 215 | mdp5_encoder->enabled = false; | ||
| 231 | } | 216 | } |
| 232 | 217 | ||
| 233 | static void mdp5_encoder_commit(struct drm_encoder *encoder) | 218 | static void mdp5_encoder_enable(struct drm_encoder *encoder) |
| 234 | { | 219 | { |
| 235 | struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); | 220 | struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder); |
| 221 | struct mdp5_kms *mdp5_kms = get_kms(encoder); | ||
| 222 | int intf = mdp5_encoder->intf; | ||
| 223 | unsigned long flags; | ||
| 224 | |||
| 225 | if (WARN_ON(mdp5_encoder->enabled)) | ||
| 226 | return; | ||
| 227 | |||
| 236 | mdp5_crtc_set_intf(encoder->crtc, mdp5_encoder->intf, | 228 | mdp5_crtc_set_intf(encoder->crtc, mdp5_encoder->intf, |
| 237 | mdp5_encoder->intf_id); | 229 | mdp5_encoder->intf_id); |
| 238 | mdp5_encoder_dpms(encoder, DRM_MODE_DPMS_ON); | 230 | |
| 231 | bs_set(mdp5_encoder, 1); | ||
| 232 | spin_lock_irqsave(&mdp5_encoder->intf_lock, flags); | ||
| 233 | mdp5_write(mdp5_kms, REG_MDP5_INTF_TIMING_ENGINE_EN(intf), 1); | ||
| 234 | spin_unlock_irqrestore(&mdp5_encoder->intf_lock, flags); | ||
| 235 | |||
| 236 | mdp5_encoder->enabled = false; | ||
| 239 | } | 237 | } |
| 240 | 238 | ||
| 241 | static const struct drm_encoder_helper_funcs mdp5_encoder_helper_funcs = { | 239 | static const struct drm_encoder_helper_funcs mdp5_encoder_helper_funcs = { |
| 242 | .dpms = mdp5_encoder_dpms, | ||
| 243 | .mode_fixup = mdp5_encoder_mode_fixup, | 240 | .mode_fixup = mdp5_encoder_mode_fixup, |
| 244 | .mode_set = mdp5_encoder_mode_set, | 241 | .mode_set = mdp5_encoder_mode_set, |
| 245 | .prepare = mdp5_encoder_prepare, | 242 | .prepare = mdp5_encoder_disable, |
| 246 | .commit = mdp5_encoder_commit, | 243 | .commit = mdp5_encoder_enable, |
| 247 | }; | 244 | }; |
| 248 | 245 | ||
| 249 | /* initialize encoder */ | 246 | /* initialize encoder */ |
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c index 9f01a4f21af2..e13e102372f5 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | |||
| @@ -68,6 +68,18 @@ static int mdp5_hw_init(struct msm_kms *kms) | |||
| 68 | return 0; | 68 | return 0; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | static void mdp5_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *state) | ||
| 72 | { | ||
| 73 | struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); | ||
| 74 | mdp5_enable(mdp5_kms); | ||
| 75 | } | ||
| 76 | |||
| 77 | static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *state) | ||
| 78 | { | ||
| 79 | struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms)); | ||
| 80 | mdp5_disable(mdp5_kms); | ||
| 81 | } | ||
| 82 | |||
| 71 | static long mdp5_round_pixclk(struct msm_kms *kms, unsigned long rate, | 83 | static long mdp5_round_pixclk(struct msm_kms *kms, unsigned long rate, |
| 72 | struct drm_encoder *encoder) | 84 | struct drm_encoder *encoder) |
| 73 | { | 85 | { |
| @@ -115,6 +127,8 @@ static const struct mdp_kms_funcs kms_funcs = { | |||
| 115 | .irq = mdp5_irq, | 127 | .irq = mdp5_irq, |
| 116 | .enable_vblank = mdp5_enable_vblank, | 128 | .enable_vblank = mdp5_enable_vblank, |
| 117 | .disable_vblank = mdp5_disable_vblank, | 129 | .disable_vblank = mdp5_disable_vblank, |
| 130 | .prepare_commit = mdp5_prepare_commit, | ||
| 131 | .complete_commit = mdp5_complete_commit, | ||
| 118 | .get_format = mdp_get_format, | 132 | .get_format = mdp_get_format, |
| 119 | .round_pixclk = mdp5_round_pixclk, | 133 | .round_pixclk = mdp5_round_pixclk, |
| 120 | .preclose = mdp5_preclose, | 134 | .preclose = mdp5_preclose, |
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index 2c396540e279..2beef4e670d0 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include "msm_gem.h" | 20 | #include "msm_gem.h" |
| 21 | 21 | ||
| 22 | struct msm_commit { | 22 | struct msm_commit { |
| 23 | struct drm_device *dev; | ||
| 23 | struct drm_atomic_state *state; | 24 | struct drm_atomic_state *state; |
| 24 | uint32_t fence; | 25 | uint32_t fence; |
| 25 | struct msm_fence_cb fence_cb; | 26 | struct msm_fence_cb fence_cb; |
| @@ -58,14 +59,16 @@ static void end_atomic(struct msm_drm_private *priv, uint32_t crtc_mask) | |||
| 58 | spin_unlock(&priv->pending_crtcs_event.lock); | 59 | spin_unlock(&priv->pending_crtcs_event.lock); |
| 59 | } | 60 | } |
| 60 | 61 | ||
| 61 | static struct msm_commit *new_commit(struct drm_atomic_state *state) | 62 | static struct msm_commit *commit_init(struct drm_atomic_state *state) |
| 62 | { | 63 | { |
| 63 | struct msm_commit *c = kzalloc(sizeof(*c), GFP_KERNEL); | 64 | struct msm_commit *c = kzalloc(sizeof(*c), GFP_KERNEL); |
| 64 | 65 | ||
| 65 | if (!c) | 66 | if (!c) |
| 66 | return NULL; | 67 | return NULL; |
| 67 | 68 | ||
| 69 | c->dev = state->dev; | ||
| 68 | c->state = state; | 70 | c->state = state; |
| 71 | |||
| 69 | /* TODO we might need a way to indicate to run the cb on a | 72 | /* TODO we might need a way to indicate to run the cb on a |
| 70 | * different wq so wait_for_vblanks() doesn't block retiring | 73 | * different wq so wait_for_vblanks() doesn't block retiring |
| 71 | * bo's.. | 74 | * bo's.. |
| @@ -75,6 +78,12 @@ static struct msm_commit *new_commit(struct drm_atomic_state *state) | |||
| 75 | return c; | 78 | return c; |
| 76 | } | 79 | } |
| 77 | 80 | ||
| 81 | static void commit_destroy(struct msm_commit *c) | ||
| 82 | { | ||
| 83 | end_atomic(c->dev->dev_private, c->crtc_mask); | ||
| 84 | kfree(c); | ||
| 85 | } | ||
| 86 | |||
| 78 | /* The (potentially) asynchronous part of the commit. At this point | 87 | /* The (potentially) asynchronous part of the commit. At this point |
| 79 | * nothing can fail short of armageddon. | 88 | * nothing can fail short of armageddon. |
| 80 | */ | 89 | */ |
| @@ -82,6 +91,10 @@ static void complete_commit(struct msm_commit *c) | |||
| 82 | { | 91 | { |
| 83 | struct drm_atomic_state *state = c->state; | 92 | struct drm_atomic_state *state = c->state; |
| 84 | struct drm_device *dev = state->dev; | 93 | struct drm_device *dev = state->dev; |
| 94 | struct msm_drm_private *priv = dev->dev_private; | ||
| 95 | struct msm_kms *kms = priv->kms; | ||
| 96 | |||
| 97 | kms->funcs->prepare_commit(kms, state); | ||
| 85 | 98 | ||
| 86 | drm_atomic_helper_commit_pre_planes(dev, state); | 99 | drm_atomic_helper_commit_pre_planes(dev, state); |
| 87 | 100 | ||
| @@ -106,11 +119,11 @@ static void complete_commit(struct msm_commit *c) | |||
| 106 | 119 | ||
| 107 | drm_atomic_helper_cleanup_planes(dev, state); | 120 | drm_atomic_helper_cleanup_planes(dev, state); |
| 108 | 121 | ||
| 109 | drm_atomic_state_free(state); | 122 | kms->funcs->complete_commit(kms, state); |
| 110 | 123 | ||
| 111 | end_atomic(dev->dev_private, c->crtc_mask); | 124 | drm_atomic_state_free(state); |
| 112 | 125 | ||
| 113 | kfree(c); | 126 | commit_destroy(c); |
| 114 | } | 127 | } |
| 115 | 128 | ||
| 116 | static void fence_cb(struct msm_fence_cb *cb) | 129 | static void fence_cb(struct msm_fence_cb *cb) |
| @@ -172,7 +185,7 @@ int msm_atomic_commit(struct drm_device *dev, | |||
| 172 | if (ret) | 185 | if (ret) |
| 173 | return ret; | 186 | return ret; |
| 174 | 187 | ||
| 175 | c = new_commit(state); | 188 | c = commit_init(state); |
| 176 | if (!c) | 189 | if (!c) |
| 177 | return -ENOMEM; | 190 | return -ENOMEM; |
| 178 | 191 | ||
| @@ -240,7 +253,7 @@ int msm_atomic_commit(struct drm_device *dev, | |||
| 240 | ret = msm_wait_fence_interruptable(dev, c->fence, NULL); | 253 | ret = msm_wait_fence_interruptable(dev, c->fence, NULL); |
| 241 | if (ret) { | 254 | if (ret) { |
| 242 | WARN_ON(ret); // TODO unswap state back? or?? | 255 | WARN_ON(ret); // TODO unswap state back? or?? |
| 243 | kfree(c); | 256 | commit_destroy(c); |
| 244 | return ret; | 257 | return ret; |
| 245 | } | 258 | } |
| 246 | 259 | ||
diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c index 115b509a4a00..df60f65728ff 100644 --- a/drivers/gpu/drm/msm/msm_fbdev.c +++ b/drivers/gpu/drm/msm/msm_fbdev.c | |||
| @@ -245,9 +245,6 @@ struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev) | |||
| 245 | if (ret) | 245 | if (ret) |
| 246 | goto fini; | 246 | goto fini; |
| 247 | 247 | ||
| 248 | /* disable all the possible outputs/crtcs before entering KMS mode */ | ||
| 249 | drm_helper_disable_unused_functions(dev); | ||
| 250 | |||
| 251 | ret = drm_fb_helper_initial_config(helper, 32); | 248 | ret = drm_fb_helper_initial_config(helper, 32); |
| 252 | if (ret) | 249 | if (ret) |
| 253 | goto fini; | 250 | goto fini; |
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index 06437745bc2c..867672eb1fee 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h | |||
| @@ -38,6 +38,9 @@ struct msm_kms_funcs { | |||
| 38 | irqreturn_t (*irq)(struct msm_kms *kms); | 38 | irqreturn_t (*irq)(struct msm_kms *kms); |
| 39 | int (*enable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc); | 39 | int (*enable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc); |
| 40 | void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc); | 40 | void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc); |
| 41 | /* modeset, bracketing atomic_commit(): */ | ||
| 42 | void (*prepare_commit)(struct msm_kms *kms, struct drm_atomic_state *state); | ||
| 43 | void (*complete_commit)(struct msm_kms *kms, struct drm_atomic_state *state); | ||
| 41 | /* misc: */ | 44 | /* misc: */ |
| 42 | const struct msm_format *(*get_format)(struct msm_kms *kms, uint32_t format); | 45 | const struct msm_format *(*get_format)(struct msm_kms *kms, uint32_t format); |
| 43 | long (*round_pixclk)(struct msm_kms *kms, unsigned long rate, | 46 | long (*round_pixclk)(struct msm_kms *kms, unsigned long rate, |
