aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-03-31 23:14:24 -0400
committerDave Airlie <airlied@redhat.com>2016-03-31 23:14:24 -0400
commit5456248d6647c61d333961ab919cec0350cdcb83 (patch)
treeb9aade6af8b9ead843e4480f9deef7a18841907b
parent90516d89cd02cbd18e87b9add68c448cd54579a8 (diff)
parent06b898ec84139b9d5957ec0e275fa0a6a1825df3 (diff)
Merge branch 'drm-rockchip-next-fixes-2016-03-28' of https://github.com/markyzq/kernel-drm-rockchip into drm-fixes
bunch of rockchip fixes. * 'drm-rockchip-next-fixes-2016-03-28' of https://github.com/markyzq/kernel-drm-rockchip: drm/rockchip: dw_hdmi: Don't call platform_set_drvdata() drm/rockchip: vop: Fix vop crtc cleanup drm/rockchip: dw_hdmi: Call drm_encoder_cleanup() in error path drm/rockchip: vop: Disable planes when disabling CRTC drm/rockchip: vop: Don't reject empty modesets drm/rockchip: cancel pending vblanks on close drm/rockchip: vop: fix crtc size in plane check
-rw-r--r--drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c13
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c22
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.h1
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c79
4 files changed, 100 insertions, 15 deletions
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 3d3cf2f8891e..d5cfef75fc80 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -271,8 +271,6 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
271 if (!iores) 271 if (!iores)
272 return -ENXIO; 272 return -ENXIO;
273 273
274 platform_set_drvdata(pdev, hdmi);
275
276 encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); 274 encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
277 /* 275 /*
278 * If we failed to find the CRTC(s) which this encoder is 276 * If we failed to find the CRTC(s) which this encoder is
@@ -293,7 +291,16 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
293 drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs, 291 drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs,
294 DRM_MODE_ENCODER_TMDS, NULL); 292 DRM_MODE_ENCODER_TMDS, NULL);
295 293
296 return dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data); 294 ret = dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data);
295
296 /*
297 * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
298 * which would have called the encoder cleanup. Do it manually.
299 */
300 if (ret)
301 drm_encoder_cleanup(encoder);
302
303 return ret;
297} 304}
298 305
299static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, 306static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 896da09e49ee..f556a8f4fde6 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -251,6 +251,27 @@ static int rockchip_drm_unload(struct drm_device *drm_dev)
251 return 0; 251 return 0;
252} 252}
253 253
254static void rockchip_drm_crtc_cancel_pending_vblank(struct drm_crtc *crtc,
255 struct drm_file *file_priv)
256{
257 struct rockchip_drm_private *priv = crtc->dev->dev_private;
258 int pipe = drm_crtc_index(crtc);
259
260 if (pipe < ROCKCHIP_MAX_CRTC &&
261 priv->crtc_funcs[pipe] &&
262 priv->crtc_funcs[pipe]->cancel_pending_vblank)
263 priv->crtc_funcs[pipe]->cancel_pending_vblank(crtc, file_priv);
264}
265
266static void rockchip_drm_preclose(struct drm_device *dev,
267 struct drm_file *file_priv)
268{
269 struct drm_crtc *crtc;
270
271 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
272 rockchip_drm_crtc_cancel_pending_vblank(crtc, file_priv);
273}
274
254void rockchip_drm_lastclose(struct drm_device *dev) 275void rockchip_drm_lastclose(struct drm_device *dev)
255{ 276{
256 struct rockchip_drm_private *priv = dev->dev_private; 277 struct rockchip_drm_private *priv = dev->dev_private;
@@ -281,6 +302,7 @@ static struct drm_driver rockchip_drm_driver = {
281 DRIVER_PRIME | DRIVER_ATOMIC, 302 DRIVER_PRIME | DRIVER_ATOMIC,
282 .load = rockchip_drm_load, 303 .load = rockchip_drm_load,
283 .unload = rockchip_drm_unload, 304 .unload = rockchip_drm_unload,
305 .preclose = rockchip_drm_preclose,
284 .lastclose = rockchip_drm_lastclose, 306 .lastclose = rockchip_drm_lastclose,
285 .get_vblank_counter = drm_vblank_no_hw_counter, 307 .get_vblank_counter = drm_vblank_no_hw_counter,
286 .enable_vblank = rockchip_drm_crtc_enable_vblank, 308 .enable_vblank = rockchip_drm_crtc_enable_vblank,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 3529f692edb8..00d17d71aa4c 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -40,6 +40,7 @@ struct rockchip_crtc_funcs {
40 int (*enable_vblank)(struct drm_crtc *crtc); 40 int (*enable_vblank)(struct drm_crtc *crtc);
41 void (*disable_vblank)(struct drm_crtc *crtc); 41 void (*disable_vblank)(struct drm_crtc *crtc);
42 void (*wait_for_update)(struct drm_crtc *crtc); 42 void (*wait_for_update)(struct drm_crtc *crtc);
43 void (*cancel_pending_vblank)(struct drm_crtc *crtc, struct drm_file *file_priv);
43}; 44};
44 45
45struct rockchip_atomic_commit { 46struct rockchip_atomic_commit {
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index fd370548d7d7..a619f120f801 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -499,10 +499,25 @@ err_disable_hclk:
499static void vop_crtc_disable(struct drm_crtc *crtc) 499static void vop_crtc_disable(struct drm_crtc *crtc)
500{ 500{
501 struct vop *vop = to_vop(crtc); 501 struct vop *vop = to_vop(crtc);
502 int i;
502 503
503 if (!vop->is_enabled) 504 if (!vop->is_enabled)
504 return; 505 return;
505 506
507 /*
508 * We need to make sure that all windows are disabled before we
509 * disable that crtc. Otherwise we might try to scan from a destroyed
510 * buffer later.
511 */
512 for (i = 0; i < vop->data->win_size; i++) {
513 struct vop_win *vop_win = &vop->win[i];
514 const struct vop_win_data *win = vop_win->data;
515
516 spin_lock(&vop->reg_lock);
517 VOP_WIN_SET(vop, win, enable, 0);
518 spin_unlock(&vop->reg_lock);
519 }
520
506 drm_crtc_vblank_off(crtc); 521 drm_crtc_vblank_off(crtc);
507 522
508 /* 523 /*
@@ -549,6 +564,7 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
549 struct drm_plane_state *state) 564 struct drm_plane_state *state)
550{ 565{
551 struct drm_crtc *crtc = state->crtc; 566 struct drm_crtc *crtc = state->crtc;
567 struct drm_crtc_state *crtc_state;
552 struct drm_framebuffer *fb = state->fb; 568 struct drm_framebuffer *fb = state->fb;
553 struct vop_win *vop_win = to_vop_win(plane); 569 struct vop_win *vop_win = to_vop_win(plane);
554 struct vop_plane_state *vop_plane_state = to_vop_plane_state(state); 570 struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
@@ -563,12 +579,13 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
563 int max_scale = win->phy->scl ? FRAC_16_16(8, 1) : 579 int max_scale = win->phy->scl ? FRAC_16_16(8, 1) :
564 DRM_PLANE_HELPER_NO_SCALING; 580 DRM_PLANE_HELPER_NO_SCALING;
565 581
566 crtc = crtc ? crtc : plane->state->crtc;
567 /*
568 * Both crtc or plane->state->crtc can be null.
569 */
570 if (!crtc || !fb) 582 if (!crtc || !fb)
571 goto out_disable; 583 goto out_disable;
584
585 crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
586 if (WARN_ON(!crtc_state))
587 return -EINVAL;
588
572 src->x1 = state->src_x; 589 src->x1 = state->src_x;
573 src->y1 = state->src_y; 590 src->y1 = state->src_y;
574 src->x2 = state->src_x + state->src_w; 591 src->x2 = state->src_x + state->src_w;
@@ -580,8 +597,8 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
580 597
581 clip.x1 = 0; 598 clip.x1 = 0;
582 clip.y1 = 0; 599 clip.y1 = 0;
583 clip.x2 = crtc->mode.hdisplay; 600 clip.x2 = crtc_state->adjusted_mode.hdisplay;
584 clip.y2 = crtc->mode.vdisplay; 601 clip.y2 = crtc_state->adjusted_mode.vdisplay;
585 602
586 ret = drm_plane_helper_check_update(plane, crtc, state->fb, 603 ret = drm_plane_helper_check_update(plane, crtc, state->fb,
587 src, dest, &clip, 604 src, dest, &clip,
@@ -873,10 +890,30 @@ static void vop_crtc_wait_for_update(struct drm_crtc *crtc)
873 WARN_ON(!wait_for_completion_timeout(&vop->wait_update_complete, 100)); 890 WARN_ON(!wait_for_completion_timeout(&vop->wait_update_complete, 100));
874} 891}
875 892
893static void vop_crtc_cancel_pending_vblank(struct drm_crtc *crtc,
894 struct drm_file *file_priv)
895{
896 struct drm_device *drm = crtc->dev;
897 struct vop *vop = to_vop(crtc);
898 struct drm_pending_vblank_event *e;
899 unsigned long flags;
900
901 spin_lock_irqsave(&drm->event_lock, flags);
902 e = vop->event;
903 if (e && e->base.file_priv == file_priv) {
904 vop->event = NULL;
905
906 e->base.destroy(&e->base);
907 file_priv->event_space += sizeof(e->event);
908 }
909 spin_unlock_irqrestore(&drm->event_lock, flags);
910}
911
876static const struct rockchip_crtc_funcs private_crtc_funcs = { 912static const struct rockchip_crtc_funcs private_crtc_funcs = {
877 .enable_vblank = vop_crtc_enable_vblank, 913 .enable_vblank = vop_crtc_enable_vblank,
878 .disable_vblank = vop_crtc_disable_vblank, 914 .disable_vblank = vop_crtc_disable_vblank,
879 .wait_for_update = vop_crtc_wait_for_update, 915 .wait_for_update = vop_crtc_wait_for_update,
916 .cancel_pending_vblank = vop_crtc_cancel_pending_vblank,
880}; 917};
881 918
882static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, 919static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
@@ -885,9 +922,6 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
885{ 922{
886 struct vop *vop = to_vop(crtc); 923 struct vop *vop = to_vop(crtc);
887 924
888 if (adjusted_mode->htotal == 0 || adjusted_mode->vtotal == 0)
889 return false;
890
891 adjusted_mode->clock = 925 adjusted_mode->clock =
892 clk_round_rate(vop->dclk, mode->clock * 1000) / 1000; 926 clk_round_rate(vop->dclk, mode->clock * 1000) / 1000;
893 927
@@ -1108,7 +1142,7 @@ static int vop_create_crtc(struct vop *vop)
1108 const struct vop_data *vop_data = vop->data; 1142 const struct vop_data *vop_data = vop->data;
1109 struct device *dev = vop->dev; 1143 struct device *dev = vop->dev;
1110 struct drm_device *drm_dev = vop->drm_dev; 1144 struct drm_device *drm_dev = vop->drm_dev;
1111 struct drm_plane *primary = NULL, *cursor = NULL, *plane; 1145 struct drm_plane *primary = NULL, *cursor = NULL, *plane, *tmp;
1112 struct drm_crtc *crtc = &vop->crtc; 1146 struct drm_crtc *crtc = &vop->crtc;
1113 struct device_node *port; 1147 struct device_node *port;
1114 int ret; 1148 int ret;
@@ -1148,7 +1182,7 @@ static int vop_create_crtc(struct vop *vop)
1148 ret = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor, 1182 ret = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor,
1149 &vop_crtc_funcs, NULL); 1183 &vop_crtc_funcs, NULL);
1150 if (ret) 1184 if (ret)
1151 return ret; 1185 goto err_cleanup_planes;
1152 1186
1153 drm_crtc_helper_add(crtc, &vop_crtc_helper_funcs); 1187 drm_crtc_helper_add(crtc, &vop_crtc_helper_funcs);
1154 1188
@@ -1181,6 +1215,7 @@ static int vop_create_crtc(struct vop *vop)
1181 if (!port) { 1215 if (!port) {
1182 DRM_ERROR("no port node found in %s\n", 1216 DRM_ERROR("no port node found in %s\n",
1183 dev->of_node->full_name); 1217 dev->of_node->full_name);
1218 ret = -ENOENT;
1184 goto err_cleanup_crtc; 1219 goto err_cleanup_crtc;
1185 } 1220 }
1186 1221
@@ -1194,7 +1229,8 @@ static int vop_create_crtc(struct vop *vop)
1194err_cleanup_crtc: 1229err_cleanup_crtc:
1195 drm_crtc_cleanup(crtc); 1230 drm_crtc_cleanup(crtc);
1196err_cleanup_planes: 1231err_cleanup_planes:
1197 list_for_each_entry(plane, &drm_dev->mode_config.plane_list, head) 1232 list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list,
1233 head)
1198 drm_plane_cleanup(plane); 1234 drm_plane_cleanup(plane);
1199 return ret; 1235 return ret;
1200} 1236}
@@ -1202,9 +1238,28 @@ err_cleanup_planes:
1202static void vop_destroy_crtc(struct vop *vop) 1238static void vop_destroy_crtc(struct vop *vop)
1203{ 1239{
1204 struct drm_crtc *crtc = &vop->crtc; 1240 struct drm_crtc *crtc = &vop->crtc;
1241 struct drm_device *drm_dev = vop->drm_dev;
1242 struct drm_plane *plane, *tmp;
1205 1243
1206 rockchip_unregister_crtc_funcs(crtc); 1244 rockchip_unregister_crtc_funcs(crtc);
1207 of_node_put(crtc->port); 1245 of_node_put(crtc->port);
1246
1247 /*
1248 * We need to cleanup the planes now. Why?
1249 *
1250 * The planes are "&vop->win[i].base". That means the memory is
1251 * all part of the big "struct vop" chunk of memory. That memory
1252 * was devm allocated and associated with this component. We need to
1253 * free it ourselves before vop_unbind() finishes.
1254 */
1255 list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list,
1256 head)
1257 vop_plane_destroy(plane);
1258
1259 /*
1260 * Destroy CRTC after vop_plane_destroy() since vop_disable_plane()
1261 * references the CRTC.
1262 */
1208 drm_crtc_cleanup(crtc); 1263 drm_crtc_cleanup(crtc);
1209} 1264}
1210 1265