diff options
| author | Dave Airlie <airlied@redhat.com> | 2017-02-15 22:27:24 -0500 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2017-02-15 22:27:24 -0500 |
| commit | 1e9d996645401f1a5bd6473e229a4d41575fc478 (patch) | |
| tree | 8565771a1e3fa0c9bbb03ebb34f3a288b9f77c34 | |
| parent | 13f62f54d174d3417c3caaafedf5e22a0a03e442 (diff) | |
| parent | c462c2f5f5ee5ed77a790c361e6aae807ef923ce (diff) | |
Merge tag 'sti-drm-next-2017-02-10' of https://github.com/vinceab/linux into drm-next
- remove deprecated stih416 chip functionnalities
- fix issues met around gdp panes
- fix STI driver unbind procedure
- DVI/HDMI mode is automatically detected
- allow fps statisitics resetting
* tag 'sti-drm-next-2017-02-10' of https://github.com/vinceab/linux:
drm/sti: debug fps reset
drm/sti: hdmi: automatically check DVI/HDMI mode
drm/sti: unbind all components while driver cleanup
drm/sti: do not post GDP command if no update
drm/sti: do not set gdp pixel clock rate if mode is not set
drm/sti: enable gdp pixel clock in atomic_update
drm/sti: remove deprecated legacy vtg slave
drm/sti: remove deprecated sink_term config
drm/sti: do not check hw scaling if mode is not set
drm/sti: Fix up crtc_state->event handling
drm/sti: use atomic_helper for commit
| -rw-r--r-- | drivers/gpu/drm/sti/sti_crtc.c | 46 | ||||
| -rw-r--r-- | drivers/gpu/drm/sti/sti_drv.c | 87 | ||||
| -rw-r--r-- | drivers/gpu/drm/sti/sti_drv.h | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/sti/sti_gdp.c | 85 | ||||
| -rw-r--r-- | drivers/gpu/drm/sti/sti_hdmi.c | 38 | ||||
| -rw-r--r-- | drivers/gpu/drm/sti/sti_hdmi.h | 17 | ||||
| -rw-r--r-- | drivers/gpu/drm/sti/sti_hqvdp.c | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/sti/sti_mixer.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/sti/sti_vtg.c | 58 |
9 files changed, 95 insertions, 250 deletions
diff --git a/drivers/gpu/drm/sti/sti_crtc.c b/drivers/gpu/drm/sti/sti_crtc.c index e992bed98dcb..d45a4335df5d 100644 --- a/drivers/gpu/drm/sti/sti_crtc.c +++ b/drivers/gpu/drm/sti/sti_crtc.c | |||
| @@ -134,21 +134,6 @@ sti_crtc_mode_set_nofb(struct drm_crtc *crtc) | |||
| 134 | sti_crtc_mode_set(crtc, &crtc->state->adjusted_mode); | 134 | sti_crtc_mode_set(crtc, &crtc->state->adjusted_mode); |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | static void sti_crtc_atomic_begin(struct drm_crtc *crtc, | ||
| 138 | struct drm_crtc_state *old_crtc_state) | ||
| 139 | { | ||
| 140 | struct sti_mixer *mixer = to_sti_mixer(crtc); | ||
| 141 | |||
| 142 | if (crtc->state->event) { | ||
| 143 | crtc->state->event->pipe = drm_crtc_index(crtc); | ||
| 144 | |||
| 145 | WARN_ON(drm_crtc_vblank_get(crtc) != 0); | ||
| 146 | |||
| 147 | mixer->pending_event = crtc->state->event; | ||
| 148 | crtc->state->event = NULL; | ||
| 149 | } | ||
| 150 | } | ||
| 151 | |||
| 152 | static void sti_crtc_atomic_flush(struct drm_crtc *crtc, | 137 | static void sti_crtc_atomic_flush(struct drm_crtc *crtc, |
| 153 | struct drm_crtc_state *old_crtc_state) | 138 | struct drm_crtc_state *old_crtc_state) |
| 154 | { | 139 | { |
| @@ -156,6 +141,8 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc, | |||
| 156 | struct sti_mixer *mixer = to_sti_mixer(crtc); | 141 | struct sti_mixer *mixer = to_sti_mixer(crtc); |
| 157 | struct sti_compositor *compo = dev_get_drvdata(mixer->dev); | 142 | struct sti_compositor *compo = dev_get_drvdata(mixer->dev); |
| 158 | struct drm_plane *p; | 143 | struct drm_plane *p; |
| 144 | struct drm_pending_vblank_event *event; | ||
| 145 | unsigned long flags; | ||
| 159 | 146 | ||
| 160 | DRM_DEBUG_DRIVER("\n"); | 147 | DRM_DEBUG_DRIVER("\n"); |
| 161 | 148 | ||
| @@ -220,13 +207,24 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc, | |||
| 220 | break; | 207 | break; |
| 221 | } | 208 | } |
| 222 | } | 209 | } |
| 210 | |||
| 211 | event = crtc->state->event; | ||
| 212 | if (event) { | ||
| 213 | crtc->state->event = NULL; | ||
| 214 | |||
| 215 | spin_lock_irqsave(&crtc->dev->event_lock, flags); | ||
| 216 | if (drm_crtc_vblank_get(crtc) == 0) | ||
| 217 | drm_crtc_arm_vblank_event(crtc, event); | ||
| 218 | else | ||
| 219 | drm_crtc_send_vblank_event(crtc, event); | ||
| 220 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); | ||
| 221 | } | ||
| 223 | } | 222 | } |
| 224 | 223 | ||
| 225 | static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = { | 224 | static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = { |
| 226 | .enable = sti_crtc_enable, | 225 | .enable = sti_crtc_enable, |
| 227 | .disable = sti_crtc_disabling, | 226 | .disable = sti_crtc_disabling, |
| 228 | .mode_set_nofb = sti_crtc_mode_set_nofb, | 227 | .mode_set_nofb = sti_crtc_mode_set_nofb, |
| 229 | .atomic_begin = sti_crtc_atomic_begin, | ||
| 230 | .atomic_flush = sti_crtc_atomic_flush, | 228 | .atomic_flush = sti_crtc_atomic_flush, |
| 231 | }; | 229 | }; |
| 232 | 230 | ||
| @@ -250,7 +248,6 @@ int sti_crtc_vblank_cb(struct notifier_block *nb, | |||
| 250 | struct sti_compositor *compo; | 248 | struct sti_compositor *compo; |
| 251 | struct drm_crtc *crtc = data; | 249 | struct drm_crtc *crtc = data; |
| 252 | struct sti_mixer *mixer; | 250 | struct sti_mixer *mixer; |
| 253 | unsigned long flags; | ||
| 254 | struct sti_private *priv; | 251 | struct sti_private *priv; |
| 255 | unsigned int pipe; | 252 | unsigned int pipe; |
| 256 | 253 | ||
| @@ -267,14 +264,6 @@ int sti_crtc_vblank_cb(struct notifier_block *nb, | |||
| 267 | 264 | ||
| 268 | drm_crtc_handle_vblank(crtc); | 265 | drm_crtc_handle_vblank(crtc); |
| 269 | 266 | ||
| 270 | spin_lock_irqsave(&crtc->dev->event_lock, flags); | ||
| 271 | if (mixer->pending_event) { | ||
| 272 | drm_crtc_send_vblank_event(crtc, mixer->pending_event); | ||
| 273 | drm_crtc_vblank_put(crtc); | ||
| 274 | mixer->pending_event = NULL; | ||
| 275 | } | ||
| 276 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); | ||
| 277 | |||
| 278 | if (mixer->status == STI_MIXER_DISABLING) { | 267 | if (mixer->status == STI_MIXER_DISABLING) { |
| 279 | struct drm_plane *p; | 268 | struct drm_plane *p; |
| 280 | 269 | ||
| @@ -317,19 +306,12 @@ void sti_crtc_disable_vblank(struct drm_device *drm_dev, unsigned int pipe) | |||
| 317 | struct sti_private *priv = drm_dev->dev_private; | 306 | struct sti_private *priv = drm_dev->dev_private; |
| 318 | struct sti_compositor *compo = priv->compo; | 307 | struct sti_compositor *compo = priv->compo; |
| 319 | struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb[pipe]; | 308 | struct notifier_block *vtg_vblank_nb = &compo->vtg_vblank_nb[pipe]; |
| 320 | struct drm_crtc *crtc = &compo->mixer[pipe]->drm_crtc; | ||
| 321 | struct sti_vtg *vtg = compo->vtg[pipe]; | 309 | struct sti_vtg *vtg = compo->vtg[pipe]; |
| 322 | 310 | ||
| 323 | DRM_DEBUG_DRIVER("\n"); | 311 | DRM_DEBUG_DRIVER("\n"); |
| 324 | 312 | ||
| 325 | if (sti_vtg_unregister_client(vtg, vtg_vblank_nb)) | 313 | if (sti_vtg_unregister_client(vtg, vtg_vblank_nb)) |
| 326 | DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n"); | 314 | DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n"); |
| 327 | |||
| 328 | /* free the resources of the pending requests */ | ||
| 329 | if (compo->mixer[pipe]->pending_event) { | ||
| 330 | drm_crtc_vblank_put(crtc); | ||
| 331 | compo->mixer[pipe]->pending_event = NULL; | ||
| 332 | } | ||
| 333 | } | 315 | } |
| 334 | 316 | ||
| 335 | static int sti_crtc_late_register(struct drm_crtc *crtc) | 317 | static int sti_crtc_late_register(struct drm_crtc *crtc) |
diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index 788feed208d7..e6c1646b9c53 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c | |||
| @@ -58,7 +58,9 @@ static int sti_drm_fps_set(void *data, u64 val) | |||
| 58 | list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) { | 58 | list_for_each_entry(p, &drm_dev->mode_config.plane_list, head) { |
| 59 | struct sti_plane *plane = to_sti_plane(p); | 59 | struct sti_plane *plane = to_sti_plane(p); |
| 60 | 60 | ||
| 61 | memset(&plane->fps_info, 0, sizeof(plane->fps_info)); | ||
| 61 | plane->fps_info.output = (val >> i) & 1; | 62 | plane->fps_info.output = (val >> i) & 1; |
| 63 | |||
| 62 | i++; | 64 | i++; |
| 63 | } | 65 | } |
| 64 | 66 | ||
| @@ -115,50 +117,13 @@ err: | |||
| 115 | return ret; | 117 | return ret; |
| 116 | } | 118 | } |
| 117 | 119 | ||
| 118 | static void sti_atomic_schedule(struct sti_private *private, | 120 | static void sti_drm_dbg_cleanup(struct drm_minor *minor) |
| 119 | struct drm_atomic_state *state) | ||
| 120 | { | ||
| 121 | private->commit.state = state; | ||
| 122 | schedule_work(&private->commit.work); | ||
| 123 | } | ||
| 124 | |||
| 125 | static void sti_atomic_complete(struct sti_private *private, | ||
| 126 | struct drm_atomic_state *state) | ||
| 127 | { | ||
| 128 | struct drm_device *drm = private->drm_dev; | ||
| 129 | |||
| 130 | /* | ||
| 131 | * Everything below can be run asynchronously without the need to grab | ||
| 132 | * any modeset locks at all under one condition: It must be guaranteed | ||
| 133 | * that the asynchronous work has either been cancelled (if the driver | ||
| 134 | * supports it, which at least requires that the framebuffers get | ||
| 135 | * cleaned up with drm_atomic_helper_cleanup_planes()) or completed | ||
| 136 | * before the new state gets committed on the software side with | ||
| 137 | * drm_atomic_helper_swap_state(). | ||
| 138 | * | ||
| 139 | * This scheme allows new atomic state updates to be prepared and | ||
| 140 | * checked in parallel to the asynchronous completion of the previous | ||
| 141 | * update. Which is important since compositors need to figure out the | ||
| 142 | * composition of the next frame right after having submitted the | ||
| 143 | * current layout. | ||
| 144 | */ | ||
| 145 | |||
| 146 | drm_atomic_helper_commit_modeset_disables(drm, state); | ||
| 147 | drm_atomic_helper_commit_planes(drm, state, 0); | ||
| 148 | drm_atomic_helper_commit_modeset_enables(drm, state); | ||
| 149 | |||
| 150 | drm_atomic_helper_wait_for_vblanks(drm, state); | ||
| 151 | |||
| 152 | drm_atomic_helper_cleanup_planes(drm, state); | ||
| 153 | drm_atomic_state_put(state); | ||
| 154 | } | ||
| 155 | |||
| 156 | static void sti_atomic_work(struct work_struct *work) | ||
| 157 | { | 121 | { |
| 158 | struct sti_private *private = container_of(work, | 122 | drm_debugfs_remove_files(sti_drm_dbg_list, |
| 159 | struct sti_private, commit.work); | 123 | ARRAY_SIZE(sti_drm_dbg_list), minor); |
| 160 | 124 | ||
| 161 | sti_atomic_complete(private, private->commit.state); | 125 | drm_debugfs_remove_files((struct drm_info_list *)&sti_drm_fps_fops, |
| 126 | 1, minor); | ||
| 162 | } | 127 | } |
| 163 | 128 | ||
| 164 | static int sti_atomic_check(struct drm_device *dev, | 129 | static int sti_atomic_check(struct drm_device *dev, |
| @@ -181,38 +146,6 @@ static int sti_atomic_check(struct drm_device *dev, | |||
| 181 | return ret; | 146 | return ret; |
| 182 | } | 147 | } |
| 183 | 148 | ||
| 184 | static int sti_atomic_commit(struct drm_device *drm, | ||
| 185 | struct drm_atomic_state *state, bool nonblock) | ||
| 186 | { | ||
| 187 | struct sti_private *private = drm->dev_private; | ||
| 188 | int err; | ||
| 189 | |||
| 190 | err = drm_atomic_helper_prepare_planes(drm, state); | ||
| 191 | if (err) | ||
| 192 | return err; | ||
| 193 | |||
| 194 | /* serialize outstanding nonblocking commits */ | ||
| 195 | mutex_lock(&private->commit.lock); | ||
| 196 | flush_work(&private->commit.work); | ||
| 197 | |||
| 198 | /* | ||
| 199 | * This is the point of no return - everything below never fails except | ||
| 200 | * when the hw goes bonghits. Which means we can commit the new state on | ||
| 201 | * the software side now. | ||
| 202 | */ | ||
| 203 | |||
| 204 | drm_atomic_helper_swap_state(state, true); | ||
| 205 | |||
| 206 | drm_atomic_state_get(state); | ||
| 207 | if (nonblock) | ||
| 208 | sti_atomic_schedule(private, state); | ||
| 209 | else | ||
| 210 | sti_atomic_complete(private, state); | ||
| 211 | |||
| 212 | mutex_unlock(&private->commit.lock); | ||
| 213 | return 0; | ||
| 214 | } | ||
| 215 | |||
| 216 | static void sti_output_poll_changed(struct drm_device *ddev) | 149 | static void sti_output_poll_changed(struct drm_device *ddev) |
| 217 | { | 150 | { |
| 218 | struct sti_private *private = ddev->dev_private; | 151 | struct sti_private *private = ddev->dev_private; |
| @@ -224,7 +157,7 @@ static const struct drm_mode_config_funcs sti_mode_config_funcs = { | |||
| 224 | .fb_create = drm_fb_cma_create, | 157 | .fb_create = drm_fb_cma_create, |
| 225 | .output_poll_changed = sti_output_poll_changed, | 158 | .output_poll_changed = sti_output_poll_changed, |
| 226 | .atomic_check = sti_atomic_check, | 159 | .atomic_check = sti_atomic_check, |
| 227 | .atomic_commit = sti_atomic_commit, | 160 | .atomic_commit = drm_atomic_helper_commit, |
| 228 | }; | 161 | }; |
| 229 | 162 | ||
| 230 | static void sti_mode_config_init(struct drm_device *dev) | 163 | static void sti_mode_config_init(struct drm_device *dev) |
| @@ -304,9 +237,6 @@ static int sti_init(struct drm_device *ddev) | |||
| 304 | dev_set_drvdata(ddev->dev, ddev); | 237 | dev_set_drvdata(ddev->dev, ddev); |
| 305 | private->drm_dev = ddev; | 238 | private->drm_dev = ddev; |
| 306 | 239 | ||
| 307 | mutex_init(&private->commit.lock); | ||
| 308 | INIT_WORK(&private->commit.work, sti_atomic_work); | ||
| 309 | |||
| 310 | drm_mode_config_init(ddev); | 240 | drm_mode_config_init(ddev); |
| 311 | 241 | ||
| 312 | sti_mode_config_init(ddev); | 242 | sti_mode_config_init(ddev); |
| @@ -327,6 +257,7 @@ static void sti_cleanup(struct drm_device *ddev) | |||
| 327 | 257 | ||
| 328 | drm_kms_helper_poll_fini(ddev); | 258 | drm_kms_helper_poll_fini(ddev); |
| 329 | drm_vblank_cleanup(ddev); | 259 | drm_vblank_cleanup(ddev); |
| 260 | component_unbind_all(ddev->dev, ddev); | ||
| 330 | kfree(private); | 261 | kfree(private); |
| 331 | ddev->dev_private = NULL; | 262 | ddev->dev_private = NULL; |
| 332 | } | 263 | } |
diff --git a/drivers/gpu/drm/sti/sti_drv.h b/drivers/gpu/drm/sti/sti_drv.h index 4c75845cc9ab..6502ed2d3351 100644 --- a/drivers/gpu/drm/sti/sti_drv.h +++ b/drivers/gpu/drm/sti/sti_drv.h | |||
| @@ -25,12 +25,6 @@ struct sti_private { | |||
| 25 | struct drm_property *plane_zorder_property; | 25 | struct drm_property *plane_zorder_property; |
| 26 | struct drm_device *drm_dev; | 26 | struct drm_device *drm_dev; |
| 27 | struct drm_fbdev_cma *fbdev; | 27 | struct drm_fbdev_cma *fbdev; |
| 28 | |||
| 29 | struct { | ||
| 30 | struct drm_atomic_state *state; | ||
| 31 | struct work_struct work; | ||
| 32 | struct mutex lock; | ||
| 33 | } commit; | ||
| 34 | }; | 28 | }; |
| 35 | 29 | ||
| 36 | extern struct platform_driver sti_tvout_driver; | 30 | extern struct platform_driver sti_tvout_driver; |
diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index 877d053d86f4..86279f5022c2 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c | |||
| @@ -610,7 +610,6 @@ static int sti_gdp_atomic_check(struct drm_plane *drm_plane, | |||
| 610 | struct sti_plane *plane = to_sti_plane(drm_plane); | 610 | struct sti_plane *plane = to_sti_plane(drm_plane); |
| 611 | struct sti_gdp *gdp = to_sti_gdp(plane); | 611 | struct sti_gdp *gdp = to_sti_gdp(plane); |
| 612 | struct drm_crtc *crtc = state->crtc; | 612 | struct drm_crtc *crtc = state->crtc; |
| 613 | struct sti_compositor *compo = dev_get_drvdata(gdp->dev); | ||
| 614 | struct drm_framebuffer *fb = state->fb; | 613 | struct drm_framebuffer *fb = state->fb; |
| 615 | struct drm_crtc_state *crtc_state; | 614 | struct drm_crtc_state *crtc_state; |
| 616 | struct sti_mixer *mixer; | 615 | struct sti_mixer *mixer; |
| @@ -648,45 +647,30 @@ static int sti_gdp_atomic_check(struct drm_plane *drm_plane, | |||
| 648 | return -EINVAL; | 647 | return -EINVAL; |
| 649 | } | 648 | } |
| 650 | 649 | ||
| 651 | if (!gdp->vtg) { | 650 | /* Set gdp clock */ |
| 652 | /* Register gdp callback */ | 651 | if (mode->clock && gdp->clk_pix) { |
| 653 | gdp->vtg = compo->vtg[mixer->id]; | 652 | struct clk *clkp; |
| 654 | if (sti_vtg_register_client(gdp->vtg, | 653 | int rate = mode->clock * 1000; |
| 655 | &gdp->vtg_field_nb, crtc)) { | 654 | int res; |
| 656 | DRM_ERROR("Cannot register VTG notifier\n"); | 655 | |
| 656 | /* | ||
| 657 | * According to the mixer used, the gdp pixel clock | ||
| 658 | * should have a different parent clock. | ||
| 659 | */ | ||
| 660 | if (mixer->id == STI_MIXER_MAIN) | ||
| 661 | clkp = gdp->clk_main_parent; | ||
| 662 | else | ||
| 663 | clkp = gdp->clk_aux_parent; | ||
| 664 | |||
| 665 | if (clkp) | ||
| 666 | clk_set_parent(gdp->clk_pix, clkp); | ||
| 667 | |||
| 668 | res = clk_set_rate(gdp->clk_pix, rate); | ||
| 669 | if (res < 0) { | ||
| 670 | DRM_ERROR("Cannot set rate (%dHz) for gdp\n", | ||
| 671 | rate); | ||
| 657 | return -EINVAL; | 672 | return -EINVAL; |
| 658 | } | 673 | } |
| 659 | |||
| 660 | /* Set and enable gdp clock */ | ||
| 661 | if (gdp->clk_pix) { | ||
| 662 | struct clk *clkp; | ||
| 663 | int rate = mode->clock * 1000; | ||
| 664 | int res; | ||
| 665 | |||
| 666 | /* | ||
| 667 | * According to the mixer used, the gdp pixel clock | ||
| 668 | * should have a different parent clock. | ||
| 669 | */ | ||
| 670 | if (mixer->id == STI_MIXER_MAIN) | ||
| 671 | clkp = gdp->clk_main_parent; | ||
| 672 | else | ||
| 673 | clkp = gdp->clk_aux_parent; | ||
| 674 | |||
| 675 | if (clkp) | ||
| 676 | clk_set_parent(gdp->clk_pix, clkp); | ||
| 677 | |||
| 678 | res = clk_set_rate(gdp->clk_pix, rate); | ||
| 679 | if (res < 0) { | ||
| 680 | DRM_ERROR("Cannot set rate (%dHz) for gdp\n", | ||
| 681 | rate); | ||
| 682 | return -EINVAL; | ||
| 683 | } | ||
| 684 | |||
| 685 | if (clk_prepare_enable(gdp->clk_pix)) { | ||
| 686 | DRM_ERROR("Failed to prepare/enable gdp\n"); | ||
| 687 | return -EINVAL; | ||
| 688 | } | ||
| 689 | } | ||
| 690 | } | 674 | } |
| 691 | 675 | ||
| 692 | DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n", | 676 | DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n", |
| @@ -724,6 +708,31 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, | |||
| 724 | if (!crtc || !fb) | 708 | if (!crtc || !fb) |
| 725 | return; | 709 | return; |
| 726 | 710 | ||
| 711 | if ((oldstate->fb == state->fb) && | ||
| 712 | (oldstate->crtc_x == state->crtc_x) && | ||
| 713 | (oldstate->crtc_y == state->crtc_y) && | ||
| 714 | (oldstate->crtc_w == state->crtc_w) && | ||
| 715 | (oldstate->crtc_h == state->crtc_h) && | ||
| 716 | (oldstate->src_x == state->src_x) && | ||
| 717 | (oldstate->src_y == state->src_y) && | ||
| 718 | (oldstate->src_w == state->src_w) && | ||
| 719 | (oldstate->src_h == state->src_h)) { | ||
| 720 | /* No change since last update, do not post cmd */ | ||
| 721 | DRM_DEBUG_DRIVER("No change, not posting cmd\n"); | ||
| 722 | plane->status = STI_PLANE_UPDATED; | ||
| 723 | return; | ||
| 724 | } | ||
| 725 | |||
| 726 | if (!gdp->vtg) { | ||
| 727 | struct sti_compositor *compo = dev_get_drvdata(gdp->dev); | ||
| 728 | struct sti_mixer *mixer = to_sti_mixer(crtc); | ||
| 729 | |||
| 730 | /* Register gdp callback */ | ||
| 731 | gdp->vtg = compo->vtg[mixer->id]; | ||
| 732 | sti_vtg_register_client(gdp->vtg, &gdp->vtg_field_nb, crtc); | ||
| 733 | clk_prepare_enable(gdp->clk_pix); | ||
| 734 | } | ||
| 735 | |||
| 727 | mode = &crtc->mode; | 736 | mode = &crtc->mode; |
| 728 | dst_x = state->crtc_x; | 737 | dst_x = state->crtc_x; |
| 729 | dst_y = state->crtc_y; | 738 | dst_y = state->crtc_y; |
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index c9151849d604..ce2dcba679d5 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c | |||
| @@ -95,7 +95,6 @@ | |||
| 95 | #define HDMI_CFG_HDCP_EN BIT(2) | 95 | #define HDMI_CFG_HDCP_EN BIT(2) |
| 96 | #define HDMI_CFG_ESS_NOT_OESS BIT(3) | 96 | #define HDMI_CFG_ESS_NOT_OESS BIT(3) |
| 97 | #define HDMI_CFG_H_SYNC_POL_NEG BIT(4) | 97 | #define HDMI_CFG_H_SYNC_POL_NEG BIT(4) |
| 98 | #define HDMI_CFG_SINK_TERM_DET_EN BIT(5) | ||
| 99 | #define HDMI_CFG_V_SYNC_POL_NEG BIT(6) | 98 | #define HDMI_CFG_V_SYNC_POL_NEG BIT(6) |
| 100 | #define HDMI_CFG_422_EN BIT(8) | 99 | #define HDMI_CFG_422_EN BIT(8) |
| 101 | #define HDMI_CFG_FIFO_OVERRUN_CLR BIT(12) | 100 | #define HDMI_CFG_FIFO_OVERRUN_CLR BIT(12) |
| @@ -159,7 +158,6 @@ struct sti_hdmi_connector { | |||
| 159 | struct drm_encoder *encoder; | 158 | struct drm_encoder *encoder; |
| 160 | struct sti_hdmi *hdmi; | 159 | struct sti_hdmi *hdmi; |
| 161 | struct drm_property *colorspace_property; | 160 | struct drm_property *colorspace_property; |
| 162 | struct drm_property *hdmi_mode_property; | ||
| 163 | }; | 161 | }; |
| 164 | 162 | ||
| 165 | #define to_sti_hdmi_connector(x) \ | 163 | #define to_sti_hdmi_connector(x) \ |
| @@ -266,12 +264,9 @@ static void hdmi_config(struct sti_hdmi *hdmi) | |||
| 266 | 264 | ||
| 267 | /* Select encryption type and the framing mode */ | 265 | /* Select encryption type and the framing mode */ |
| 268 | conf |= HDMI_CFG_ESS_NOT_OESS; | 266 | conf |= HDMI_CFG_ESS_NOT_OESS; |
| 269 | if (hdmi->hdmi_mode == HDMI_MODE_HDMI) | 267 | if (hdmi->hdmi_monitor) |
| 270 | conf |= HDMI_CFG_HDMI_NOT_DVI; | 268 | conf |= HDMI_CFG_HDMI_NOT_DVI; |
| 271 | 269 | ||
| 272 | /* Enable sink term detection */ | ||
| 273 | conf |= HDMI_CFG_SINK_TERM_DET_EN; | ||
| 274 | |||
| 275 | /* Set Hsync polarity */ | 270 | /* Set Hsync polarity */ |
| 276 | if (hdmi->mode.flags & DRM_MODE_FLAG_NHSYNC) { | 271 | if (hdmi->mode.flags & DRM_MODE_FLAG_NHSYNC) { |
| 277 | DRM_DEBUG_DRIVER("H Sync Negative\n"); | 272 | DRM_DEBUG_DRIVER("H Sync Negative\n"); |
| @@ -607,9 +602,6 @@ static void hdmi_dbg_cfg(struct seq_file *s, int val) | |||
| 607 | tmp = val & HDMI_CFG_ESS_NOT_OESS; | 602 | tmp = val & HDMI_CFG_ESS_NOT_OESS; |
| 608 | DBGFS_PRINT_STR("HDCP mode:", tmp ? "ESS enable" : "OESS enable"); | 603 | DBGFS_PRINT_STR("HDCP mode:", tmp ? "ESS enable" : "OESS enable"); |
| 609 | seq_puts(s, "\t\t\t\t\t"); | 604 | seq_puts(s, "\t\t\t\t\t"); |
| 610 | tmp = val & HDMI_CFG_SINK_TERM_DET_EN; | ||
| 611 | DBGFS_PRINT_STR("Sink term detection:", tmp ? "enable" : "disable"); | ||
| 612 | seq_puts(s, "\t\t\t\t\t"); | ||
| 613 | tmp = val & HDMI_CFG_H_SYNC_POL_NEG; | 605 | tmp = val & HDMI_CFG_H_SYNC_POL_NEG; |
| 614 | DBGFS_PRINT_STR("Hsync polarity:", tmp ? "inverted" : "normal"); | 606 | DBGFS_PRINT_STR("Hsync polarity:", tmp ? "inverted" : "normal"); |
| 615 | seq_puts(s, "\t\t\t\t\t"); | 607 | seq_puts(s, "\t\t\t\t\t"); |
| @@ -977,6 +969,11 @@ static int sti_hdmi_connector_get_modes(struct drm_connector *connector) | |||
| 977 | if (!edid) | 969 | if (!edid) |
| 978 | goto fail; | 970 | goto fail; |
| 979 | 971 | ||
| 972 | hdmi->hdmi_monitor = drm_detect_hdmi_monitor(edid); | ||
| 973 | DRM_DEBUG_KMS("%s : %dx%d cm\n", | ||
| 974 | (hdmi->hdmi_monitor ? "hdmi monitor" : "dvi monitor"), | ||
| 975 | edid->width_cm, edid->height_cm); | ||
| 976 | |||
| 980 | count = drm_add_edid_modes(connector, edid); | 977 | count = drm_add_edid_modes(connector, edid); |
| 981 | drm_mode_connector_update_edid_property(connector, edid); | 978 | drm_mode_connector_update_edid_property(connector, edid); |
| 982 | drm_edid_to_eld(connector, edid); | 979 | drm_edid_to_eld(connector, edid); |
| @@ -1060,19 +1057,6 @@ static void sti_hdmi_connector_init_property(struct drm_device *drm_dev, | |||
| 1060 | } | 1057 | } |
| 1061 | hdmi_connector->colorspace_property = prop; | 1058 | hdmi_connector->colorspace_property = prop; |
| 1062 | drm_object_attach_property(&connector->base, prop, hdmi->colorspace); | 1059 | drm_object_attach_property(&connector->base, prop, hdmi->colorspace); |
| 1063 | |||
| 1064 | /* hdmi_mode property */ | ||
| 1065 | hdmi->hdmi_mode = DEFAULT_HDMI_MODE; | ||
| 1066 | prop = drm_property_create_enum(drm_dev, 0, "hdmi_mode", | ||
| 1067 | hdmi_mode_names, | ||
| 1068 | ARRAY_SIZE(hdmi_mode_names)); | ||
| 1069 | if (!prop) { | ||
| 1070 | DRM_ERROR("fails to create colorspace property\n"); | ||
| 1071 | return; | ||
| 1072 | } | ||
| 1073 | hdmi_connector->hdmi_mode_property = prop; | ||
| 1074 | drm_object_attach_property(&connector->base, prop, hdmi->hdmi_mode); | ||
| 1075 | |||
| 1076 | } | 1060 | } |
| 1077 | 1061 | ||
| 1078 | static int | 1062 | static int |
| @@ -1090,11 +1074,6 @@ sti_hdmi_connector_set_property(struct drm_connector *connector, | |||
| 1090 | return 0; | 1074 | return 0; |
| 1091 | } | 1075 | } |
| 1092 | 1076 | ||
| 1093 | if (property == hdmi_connector->hdmi_mode_property) { | ||
| 1094 | hdmi->hdmi_mode = val; | ||
| 1095 | return 0; | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | DRM_ERROR("failed to set hdmi connector property\n"); | 1077 | DRM_ERROR("failed to set hdmi connector property\n"); |
| 1099 | return -EINVAL; | 1078 | return -EINVAL; |
| 1100 | } | 1079 | } |
| @@ -1114,11 +1093,6 @@ sti_hdmi_connector_get_property(struct drm_connector *connector, | |||
| 1114 | return 0; | 1093 | return 0; |
| 1115 | } | 1094 | } |
| 1116 | 1095 | ||
| 1117 | if (property == hdmi_connector->hdmi_mode_property) { | ||
| 1118 | *val = hdmi->hdmi_mode; | ||
| 1119 | return 0; | ||
| 1120 | } | ||
| 1121 | |||
| 1122 | DRM_ERROR("failed to get hdmi connector property\n"); | 1096 | DRM_ERROR("failed to get hdmi connector property\n"); |
| 1123 | return -EINVAL; | 1097 | return -EINVAL; |
| 1124 | } | 1098 | } |
diff --git a/drivers/gpu/drm/sti/sti_hdmi.h b/drivers/gpu/drm/sti/sti_hdmi.h index 119bc3582ac7..407012350f1a 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.h +++ b/drivers/gpu/drm/sti/sti_hdmi.h | |||
| @@ -30,19 +30,6 @@ struct hdmi_audio_params { | |||
| 30 | struct hdmi_audio_infoframe cea; | 30 | struct hdmi_audio_infoframe cea; |
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| 33 | /* values for the framing mode property */ | ||
| 34 | enum sti_hdmi_modes { | ||
| 35 | HDMI_MODE_HDMI, | ||
| 36 | HDMI_MODE_DVI, | ||
| 37 | }; | ||
| 38 | |||
| 39 | static const struct drm_prop_enum_list hdmi_mode_names[] = { | ||
| 40 | { HDMI_MODE_HDMI, "hdmi" }, | ||
| 41 | { HDMI_MODE_DVI, "dvi" }, | ||
| 42 | }; | ||
| 43 | |||
| 44 | #define DEFAULT_HDMI_MODE HDMI_MODE_HDMI | ||
| 45 | |||
| 46 | static const struct drm_prop_enum_list colorspace_mode_names[] = { | 33 | static const struct drm_prop_enum_list colorspace_mode_names[] = { |
| 47 | { HDMI_COLORSPACE_RGB, "rgb" }, | 34 | { HDMI_COLORSPACE_RGB, "rgb" }, |
| 48 | { HDMI_COLORSPACE_YUV422, "yuv422" }, | 35 | { HDMI_COLORSPACE_YUV422, "yuv422" }, |
| @@ -73,7 +60,7 @@ static const struct drm_prop_enum_list colorspace_mode_names[] = { | |||
| 73 | * @reset: reset control of the hdmi phy | 60 | * @reset: reset control of the hdmi phy |
| 74 | * @ddc_adapt: i2c ddc adapter | 61 | * @ddc_adapt: i2c ddc adapter |
| 75 | * @colorspace: current colorspace selected | 62 | * @colorspace: current colorspace selected |
| 76 | * @hdmi_mode: select framing for HDMI or DVI | 63 | * @hdmi_monitor: true if HDMI monitor detected else DVI monitor assumed |
| 77 | * @audio_pdev: ASoC hdmi-codec platform device | 64 | * @audio_pdev: ASoC hdmi-codec platform device |
| 78 | * @audio: hdmi audio parameters. | 65 | * @audio: hdmi audio parameters. |
| 79 | * @drm_connector: hdmi connector | 66 | * @drm_connector: hdmi connector |
| @@ -98,7 +85,7 @@ struct sti_hdmi { | |||
| 98 | struct reset_control *reset; | 85 | struct reset_control *reset; |
| 99 | struct i2c_adapter *ddc_adapt; | 86 | struct i2c_adapter *ddc_adapt; |
| 100 | enum hdmi_colorspace colorspace; | 87 | enum hdmi_colorspace colorspace; |
| 101 | enum sti_hdmi_modes hdmi_mode; | 88 | bool hdmi_monitor; |
| 102 | struct platform_device *audio_pdev; | 89 | struct platform_device *audio_pdev; |
| 103 | struct hdmi_audio_params audio; | 90 | struct hdmi_audio_params audio; |
| 104 | struct drm_connector *drm_connector; | 91 | struct drm_connector *drm_connector; |
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c index 4376fd8a8e52..66f843148ef7 100644 --- a/drivers/gpu/drm/sti/sti_hqvdp.c +++ b/drivers/gpu/drm/sti/sti_hqvdp.c | |||
| @@ -1037,9 +1037,9 @@ static int sti_hqvdp_atomic_check(struct drm_plane *drm_plane, | |||
| 1037 | src_w = state->src_w >> 16; | 1037 | src_w = state->src_w >> 16; |
| 1038 | src_h = state->src_h >> 16; | 1038 | src_h = state->src_h >> 16; |
| 1039 | 1039 | ||
| 1040 | if (!sti_hqvdp_check_hw_scaling(hqvdp, mode, | 1040 | if (mode->clock && !sti_hqvdp_check_hw_scaling(hqvdp, mode, |
| 1041 | src_w, src_h, | 1041 | src_w, src_h, |
| 1042 | dst_w, dst_h)) { | 1042 | dst_w, dst_h)) { |
| 1043 | DRM_ERROR("Scaling beyond HW capabilities\n"); | 1043 | DRM_ERROR("Scaling beyond HW capabilities\n"); |
| 1044 | return -EINVAL; | 1044 | return -EINVAL; |
| 1045 | } | 1045 | } |
diff --git a/drivers/gpu/drm/sti/sti_mixer.h b/drivers/gpu/drm/sti/sti_mixer.h index 830a3c42d886..e64a00e61049 100644 --- a/drivers/gpu/drm/sti/sti_mixer.h +++ b/drivers/gpu/drm/sti/sti_mixer.h | |||
| @@ -28,7 +28,6 @@ enum sti_mixer_status { | |||
| 28 | * @regs: mixer registers | 28 | * @regs: mixer registers |
| 29 | * @id: id of the mixer | 29 | * @id: id of the mixer |
| 30 | * @drm_crtc: crtc object link to the mixer | 30 | * @drm_crtc: crtc object link to the mixer |
| 31 | * @pending_event: set if a flip event is pending on crtc | ||
| 32 | * @status: to know the status of the mixer | 31 | * @status: to know the status of the mixer |
| 33 | */ | 32 | */ |
| 34 | struct sti_mixer { | 33 | struct sti_mixer { |
| @@ -36,7 +35,6 @@ struct sti_mixer { | |||
| 36 | void __iomem *regs; | 35 | void __iomem *regs; |
| 37 | int id; | 36 | int id; |
| 38 | struct drm_crtc drm_crtc; | 37 | struct drm_crtc drm_crtc; |
| 39 | struct drm_pending_vblank_event *pending_event; | ||
| 40 | enum sti_mixer_status status; | 38 | enum sti_mixer_status status; |
| 41 | }; | 39 | }; |
| 42 | 40 | ||
diff --git a/drivers/gpu/drm/sti/sti_vtg.c b/drivers/gpu/drm/sti/sti_vtg.c index c3d9c8ae14af..943bce56692e 100644 --- a/drivers/gpu/drm/sti/sti_vtg.c +++ b/drivers/gpu/drm/sti/sti_vtg.c | |||
| @@ -17,7 +17,6 @@ | |||
| 17 | #include "sti_vtg.h" | 17 | #include "sti_vtg.h" |
| 18 | 18 | ||
| 19 | #define VTG_MODE_MASTER 0 | 19 | #define VTG_MODE_MASTER 0 |
| 20 | #define VTG_MODE_SLAVE_BY_EXT0 1 | ||
| 21 | 20 | ||
| 22 | /* registers offset */ | 21 | /* registers offset */ |
| 23 | #define VTG_MODE 0x0000 | 22 | #define VTG_MODE 0x0000 |
| @@ -132,7 +131,6 @@ struct sti_vtg_sync_params { | |||
| 132 | * @irq_status: store the IRQ status value | 131 | * @irq_status: store the IRQ status value |
| 133 | * @notifier_list: notifier callback | 132 | * @notifier_list: notifier callback |
| 134 | * @crtc: the CRTC for vblank event | 133 | * @crtc: the CRTC for vblank event |
| 135 | * @slave: slave vtg | ||
| 136 | * @link: List node to link the structure in lookup list | 134 | * @link: List node to link the structure in lookup list |
| 137 | */ | 135 | */ |
| 138 | struct sti_vtg { | 136 | struct sti_vtg { |
| @@ -144,7 +142,6 @@ struct sti_vtg { | |||
| 144 | u32 irq_status; | 142 | u32 irq_status; |
| 145 | struct raw_notifier_head notifier_list; | 143 | struct raw_notifier_head notifier_list; |
| 146 | struct drm_crtc *crtc; | 144 | struct drm_crtc *crtc; |
| 147 | struct sti_vtg *slave; | ||
| 148 | struct list_head link; | 145 | struct list_head link; |
| 149 | }; | 146 | }; |
| 150 | 147 | ||
| @@ -166,10 +163,6 @@ struct sti_vtg *of_vtg_find(struct device_node *np) | |||
| 166 | 163 | ||
| 167 | static void vtg_reset(struct sti_vtg *vtg) | 164 | static void vtg_reset(struct sti_vtg *vtg) |
| 168 | { | 165 | { |
| 169 | /* reset slave and then master */ | ||
| 170 | if (vtg->slave) | ||
| 171 | vtg_reset(vtg->slave); | ||
| 172 | |||
| 173 | writel(1, vtg->regs + VTG_DRST_AUTOC); | 166 | writel(1, vtg->regs + VTG_DRST_AUTOC); |
| 174 | } | 167 | } |
| 175 | 168 | ||
| @@ -259,10 +252,6 @@ static void vtg_set_mode(struct sti_vtg *vtg, | |||
| 259 | { | 252 | { |
| 260 | unsigned int i; | 253 | unsigned int i; |
| 261 | 254 | ||
| 262 | if (vtg->slave) | ||
| 263 | vtg_set_mode(vtg->slave, VTG_MODE_SLAVE_BY_EXT0, | ||
| 264 | vtg->sync_params, mode); | ||
| 265 | |||
| 266 | /* Set the number of clock cycles per line */ | 255 | /* Set the number of clock cycles per line */ |
| 267 | writel(mode->htotal, vtg->regs + VTG_CLKLN); | 256 | writel(mode->htotal, vtg->regs + VTG_CLKLN); |
| 268 | 257 | ||
| @@ -318,11 +307,7 @@ void sti_vtg_set_config(struct sti_vtg *vtg, | |||
| 318 | 307 | ||
| 319 | vtg_reset(vtg); | 308 | vtg_reset(vtg); |
| 320 | 309 | ||
| 321 | /* enable irq for the vtg vblank synchro */ | 310 | vtg_enable_irq(vtg); |
| 322 | if (vtg->slave) | ||
| 323 | vtg_enable_irq(vtg->slave); | ||
| 324 | else | ||
| 325 | vtg_enable_irq(vtg); | ||
| 326 | } | 311 | } |
| 327 | 312 | ||
| 328 | /** | 313 | /** |
| @@ -365,18 +350,12 @@ u32 sti_vtg_get_pixel_number(struct drm_display_mode mode, int x) | |||
| 365 | int sti_vtg_register_client(struct sti_vtg *vtg, struct notifier_block *nb, | 350 | int sti_vtg_register_client(struct sti_vtg *vtg, struct notifier_block *nb, |
| 366 | struct drm_crtc *crtc) | 351 | struct drm_crtc *crtc) |
| 367 | { | 352 | { |
| 368 | if (vtg->slave) | ||
| 369 | return sti_vtg_register_client(vtg->slave, nb, crtc); | ||
| 370 | |||
| 371 | vtg->crtc = crtc; | 353 | vtg->crtc = crtc; |
| 372 | return raw_notifier_chain_register(&vtg->notifier_list, nb); | 354 | return raw_notifier_chain_register(&vtg->notifier_list, nb); |
| 373 | } | 355 | } |
| 374 | 356 | ||
| 375 | int sti_vtg_unregister_client(struct sti_vtg *vtg, struct notifier_block *nb) | 357 | int sti_vtg_unregister_client(struct sti_vtg *vtg, struct notifier_block *nb) |
| 376 | { | 358 | { |
| 377 | if (vtg->slave) | ||
| 378 | return sti_vtg_unregister_client(vtg->slave, nb); | ||
| 379 | |||
| 380 | return raw_notifier_chain_unregister(&vtg->notifier_list, nb); | 359 | return raw_notifier_chain_unregister(&vtg->notifier_list, nb); |
| 381 | } | 360 | } |
| 382 | 361 | ||
| @@ -434,29 +413,20 @@ static int vtg_probe(struct platform_device *pdev) | |||
| 434 | return -ENOMEM; | 413 | return -ENOMEM; |
| 435 | } | 414 | } |
| 436 | 415 | ||
| 437 | np = of_parse_phandle(pdev->dev.of_node, "st,slave", 0); | 416 | vtg->irq = platform_get_irq(pdev, 0); |
| 438 | if (np) { | 417 | if (vtg->irq < 0) { |
| 439 | vtg->slave = of_vtg_find(np); | 418 | DRM_ERROR("Failed to get VTG interrupt\n"); |
| 440 | of_node_put(np); | 419 | return vtg->irq; |
| 420 | } | ||
| 441 | 421 | ||
| 442 | if (!vtg->slave) | 422 | RAW_INIT_NOTIFIER_HEAD(&vtg->notifier_list); |
| 443 | return -EPROBE_DEFER; | 423 | |
| 444 | } else { | 424 | ret = devm_request_threaded_irq(dev, vtg->irq, vtg_irq, |
| 445 | vtg->irq = platform_get_irq(pdev, 0); | 425 | vtg_irq_thread, IRQF_ONESHOT, |
| 446 | if (vtg->irq < 0) { | 426 | dev_name(dev), vtg); |
| 447 | DRM_ERROR("Failed to get VTG interrupt\n"); | 427 | if (ret < 0) { |
| 448 | return vtg->irq; | 428 | DRM_ERROR("Failed to register VTG interrupt\n"); |
| 449 | } | 429 | return ret; |
| 450 | |||
| 451 | RAW_INIT_NOTIFIER_HEAD(&vtg->notifier_list); | ||
| 452 | |||
| 453 | ret = devm_request_threaded_irq(dev, vtg->irq, vtg_irq, | ||
| 454 | vtg_irq_thread, IRQF_ONESHOT, | ||
| 455 | dev_name(dev), vtg); | ||
| 456 | if (ret < 0) { | ||
| 457 | DRM_ERROR("Failed to register VTG interrupt\n"); | ||
| 458 | return ret; | ||
| 459 | } | ||
| 460 | } | 430 | } |
| 461 | 431 | ||
| 462 | vtg_register(vtg); | 432 | vtg_register(vtg); |
