aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-11-06 18:41:10 -0500
committerDave Airlie <airlied@redhat.com>2016-11-06 18:41:10 -0500
commit020a0bbc0d89c15693e69ed2063584ef7ec2d811 (patch)
tree7ae26a678e3829475009e6263007e5b0ec043050
parent672c98915891285b04b97ea6112c7db507903595 (diff)
parent16976085a114ae293c6fa7a463d74600ffcfeb4b (diff)
Merge branch 'msm-fixes-4.9' of git://people.freedesktop.org/~robclark/linux into drm-fixes
Fixes for some msm issues * 'msm-fixes-4.9' of git://people.freedesktop.org/~robclark/linux: drm/msm: Fix error handling crashes seen when VRAM allocation fails drm/msm/mdp5: 8x16 actually has 8 mixer stages drm/msm/mdp5: no scaling support on RGBn pipes for 8x16 drm/msm/mdp5: handle non-fullscreen base plane case drm/msm: Set CLK_IGNORE_UNUSED flag for PLL clocks drm/msm/dsi: Queue HPD helper work in attach/detach callbacks
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c14
-rw-r--r--drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c1
-rw-r--r--drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c1
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c1
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c1
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c4
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c46
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c9
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c2
-rw-r--r--drivers/gpu/drm/msm/msm_gem_shrinker.c7
10 files changed, 55 insertions, 31 deletions
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index f05ed0e1f3d6..6f240021705b 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -139,6 +139,7 @@ struct msm_dsi_host {
139 139
140 u32 err_work_state; 140 u32 err_work_state;
141 struct work_struct err_work; 141 struct work_struct err_work;
142 struct work_struct hpd_work;
142 struct workqueue_struct *workqueue; 143 struct workqueue_struct *workqueue;
143 144
144 /* DSI 6G TX buffer*/ 145 /* DSI 6G TX buffer*/
@@ -1294,6 +1295,14 @@ static void dsi_sw_reset_restore(struct msm_dsi_host *msm_host)
1294 wmb(); /* make sure dsi controller enabled again */ 1295 wmb(); /* make sure dsi controller enabled again */
1295} 1296}
1296 1297
1298static void dsi_hpd_worker(struct work_struct *work)
1299{
1300 struct msm_dsi_host *msm_host =
1301 container_of(work, struct msm_dsi_host, hpd_work);
1302
1303 drm_helper_hpd_irq_event(msm_host->dev);
1304}
1305
1297static void dsi_err_worker(struct work_struct *work) 1306static void dsi_err_worker(struct work_struct *work)
1298{ 1307{
1299 struct msm_dsi_host *msm_host = 1308 struct msm_dsi_host *msm_host =
@@ -1480,7 +1489,7 @@ static int dsi_host_attach(struct mipi_dsi_host *host,
1480 1489
1481 DBG("id=%d", msm_host->id); 1490 DBG("id=%d", msm_host->id);
1482 if (msm_host->dev) 1491 if (msm_host->dev)
1483 drm_helper_hpd_irq_event(msm_host->dev); 1492 queue_work(msm_host->workqueue, &msm_host->hpd_work);
1484 1493
1485 return 0; 1494 return 0;
1486} 1495}
@@ -1494,7 +1503,7 @@ static int dsi_host_detach(struct mipi_dsi_host *host,
1494 1503
1495 DBG("id=%d", msm_host->id); 1504 DBG("id=%d", msm_host->id);
1496 if (msm_host->dev) 1505 if (msm_host->dev)
1497 drm_helper_hpd_irq_event(msm_host->dev); 1506 queue_work(msm_host->workqueue, &msm_host->hpd_work);
1498 1507
1499 return 0; 1508 return 0;
1500} 1509}
@@ -1748,6 +1757,7 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)
1748 /* setup workqueue */ 1757 /* setup workqueue */
1749 msm_host->workqueue = alloc_ordered_workqueue("dsi_drm_work", 0); 1758 msm_host->workqueue = alloc_ordered_workqueue("dsi_drm_work", 0);
1750 INIT_WORK(&msm_host->err_work, dsi_err_worker); 1759 INIT_WORK(&msm_host->err_work, dsi_err_worker);
1760 INIT_WORK(&msm_host->hpd_work, dsi_hpd_worker);
1751 1761
1752 msm_dsi->host = &msm_host->base; 1762 msm_dsi->host = &msm_host->base;
1753 msm_dsi->id = msm_host->id; 1763 msm_dsi->id = msm_host->id;
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c
index 598fdaff0a41..26e3a01a99c2 100644
--- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c
+++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c
@@ -521,6 +521,7 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm)
521 .parent_names = (const char *[]){ "xo" }, 521 .parent_names = (const char *[]){ "xo" },
522 .num_parents = 1, 522 .num_parents = 1,
523 .name = vco_name, 523 .name = vco_name,
524 .flags = CLK_IGNORE_UNUSED,
524 .ops = &clk_ops_dsi_pll_28nm_vco, 525 .ops = &clk_ops_dsi_pll_28nm_vco,
525 }; 526 };
526 struct device *dev = &pll_28nm->pdev->dev; 527 struct device *dev = &pll_28nm->pdev->dev;
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c
index 38c90e1eb002..49008451085b 100644
--- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c
+++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c
@@ -412,6 +412,7 @@ static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm)
412 struct clk_init_data vco_init = { 412 struct clk_init_data vco_init = {
413 .parent_names = (const char *[]){ "pxo" }, 413 .parent_names = (const char *[]){ "pxo" },
414 .num_parents = 1, 414 .num_parents = 1,
415 .flags = CLK_IGNORE_UNUSED,
415 .ops = &clk_ops_dsi_pll_28nm_vco, 416 .ops = &clk_ops_dsi_pll_28nm_vco,
416 }; 417 };
417 struct device *dev = &pll_28nm->pdev->dev; 418 struct device *dev = &pll_28nm->pdev->dev;
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c
index aa94a553794f..143eab46ba68 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c
@@ -702,6 +702,7 @@ static struct clk_init_data pll_init = {
702 .ops = &hdmi_8996_pll_ops, 702 .ops = &hdmi_8996_pll_ops,
703 .parent_names = hdmi_pll_parents, 703 .parent_names = hdmi_pll_parents,
704 .num_parents = ARRAY_SIZE(hdmi_pll_parents), 704 .num_parents = ARRAY_SIZE(hdmi_pll_parents),
705 .flags = CLK_IGNORE_UNUSED,
705}; 706};
706 707
707int msm_hdmi_pll_8996_init(struct platform_device *pdev) 708int msm_hdmi_pll_8996_init(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c b/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c
index 92da69aa6187..99590758c68b 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c
@@ -424,6 +424,7 @@ static struct clk_init_data pll_init = {
424 .ops = &hdmi_pll_ops, 424 .ops = &hdmi_pll_ops,
425 .parent_names = hdmi_pll_parents, 425 .parent_names = hdmi_pll_parents,
426 .num_parents = ARRAY_SIZE(hdmi_pll_parents), 426 .num_parents = ARRAY_SIZE(hdmi_pll_parents),
427 .flags = CLK_IGNORE_UNUSED,
427}; 428};
428 429
429int msm_hdmi_pll_8960_init(struct platform_device *pdev) 430int msm_hdmi_pll_8960_init(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
index ac9e4cde1380..8b4e3004f451 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
@@ -272,7 +272,7 @@ const struct mdp5_cfg_hw msm8x16_config = {
272 .count = 2, 272 .count = 2,
273 .base = { 0x14000, 0x16000 }, 273 .base = { 0x14000, 0x16000 },
274 .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP | 274 .caps = MDP_PIPE_CAP_HFLIP | MDP_PIPE_CAP_VFLIP |
275 MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_DECIMATION, 275 MDP_PIPE_CAP_DECIMATION,
276 }, 276 },
277 .pipe_dma = { 277 .pipe_dma = {
278 .count = 1, 278 .count = 1,
@@ -282,7 +282,7 @@ const struct mdp5_cfg_hw msm8x16_config = {
282 .lm = { 282 .lm = {
283 .count = 2, /* LM0 and LM3 */ 283 .count = 2, /* LM0 and LM3 */
284 .base = { 0x44000, 0x47000 }, 284 .base = { 0x44000, 0x47000 },
285 .nb_stages = 5, 285 .nb_stages = 8,
286 .max_width = 2048, 286 .max_width = 2048,
287 .max_height = 0xFFFF, 287 .max_height = 0xFFFF,
288 }, 288 },
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index fa2be7ce9468..c205c360e16d 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -223,12 +223,7 @@ static void blend_setup(struct drm_crtc *crtc)
223 plane_cnt++; 223 plane_cnt++;
224 } 224 }
225 225
226 /* 226 if (!pstates[STAGE_BASE]) {
227 * If there is no base layer, enable border color.
228 * Although it's not possbile in current blend logic,
229 * put it here as a reminder.
230 */
231 if (!pstates[STAGE_BASE] && plane_cnt) {
232 ctl_blend_flags |= MDP5_CTL_BLEND_OP_FLAG_BORDER_OUT; 227 ctl_blend_flags |= MDP5_CTL_BLEND_OP_FLAG_BORDER_OUT;
233 DBG("Border Color is enabled"); 228 DBG("Border Color is enabled");
234 } 229 }
@@ -365,6 +360,15 @@ static int pstate_cmp(const void *a, const void *b)
365 return pa->state->zpos - pb->state->zpos; 360 return pa->state->zpos - pb->state->zpos;
366} 361}
367 362
363/* is there a helper for this? */
364static bool is_fullscreen(struct drm_crtc_state *cstate,
365 struct drm_plane_state *pstate)
366{
367 return (pstate->crtc_x <= 0) && (pstate->crtc_y <= 0) &&
368 ((pstate->crtc_x + pstate->crtc_w) >= cstate->mode.hdisplay) &&
369 ((pstate->crtc_y + pstate->crtc_h) >= cstate->mode.vdisplay);
370}
371
368static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, 372static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
369 struct drm_crtc_state *state) 373 struct drm_crtc_state *state)
370{ 374{
@@ -375,21 +379,11 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
375 struct plane_state pstates[STAGE_MAX + 1]; 379 struct plane_state pstates[STAGE_MAX + 1];
376 const struct mdp5_cfg_hw *hw_cfg; 380 const struct mdp5_cfg_hw *hw_cfg;
377 const struct drm_plane_state *pstate; 381 const struct drm_plane_state *pstate;
378 int cnt = 0, i; 382 int cnt = 0, base = 0, i;
379 383
380 DBG("%s: check", mdp5_crtc->name); 384 DBG("%s: check", mdp5_crtc->name);
381 385
382 /* verify that there are not too many planes attached to crtc
383 * and that we don't have conflicting mixer stages:
384 */
385 hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
386 drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) { 386 drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
387 if (cnt >= (hw_cfg->lm.nb_stages)) {
388 dev_err(dev->dev, "too many planes!\n");
389 return -EINVAL;
390 }
391
392
393 pstates[cnt].plane = plane; 387 pstates[cnt].plane = plane;
394 pstates[cnt].state = to_mdp5_plane_state(pstate); 388 pstates[cnt].state = to_mdp5_plane_state(pstate);
395 389
@@ -399,8 +393,24 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
399 /* assign a stage based on sorted zpos property */ 393 /* assign a stage based on sorted zpos property */
400 sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL); 394 sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL);
401 395
396 /* if the bottom-most layer is not fullscreen, we need to use
397 * it for solid-color:
398 */
399 if ((cnt > 0) && !is_fullscreen(state, &pstates[0].state->base))
400 base++;
401
402 /* verify that there are not too many planes attached to crtc
403 * and that we don't have conflicting mixer stages:
404 */
405 hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
406
407 if ((cnt + base) >= hw_cfg->lm.nb_stages) {
408 dev_err(dev->dev, "too many planes!\n");
409 return -EINVAL;
410 }
411
402 for (i = 0; i < cnt; i++) { 412 for (i = 0; i < cnt; i++) {
403 pstates[i].state->stage = STAGE_BASE + i; 413 pstates[i].state->stage = STAGE_BASE + i + base;
404 DBG("%s: assign pipe %s on stage=%d", mdp5_crtc->name, 414 DBG("%s: assign pipe %s on stage=%d", mdp5_crtc->name,
405 pipe2name(mdp5_plane_pipe(pstates[i].plane)), 415 pipe2name(mdp5_plane_pipe(pstates[i].plane)),
406 pstates[i].state->stage); 416 pstates[i].state->stage);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 951c002b05df..83bf997dda03 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -292,8 +292,7 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
292 format = to_mdp_format(msm_framebuffer_format(state->fb)); 292 format = to_mdp_format(msm_framebuffer_format(state->fb));
293 if (MDP_FORMAT_IS_YUV(format) && 293 if (MDP_FORMAT_IS_YUV(format) &&
294 !pipe_supports_yuv(mdp5_plane->caps)) { 294 !pipe_supports_yuv(mdp5_plane->caps)) {
295 dev_err(plane->dev->dev, 295 DBG("Pipe doesn't support YUV\n");
296 "Pipe doesn't support YUV\n");
297 296
298 return -EINVAL; 297 return -EINVAL;
299 } 298 }
@@ -301,8 +300,7 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
301 if (!(mdp5_plane->caps & MDP_PIPE_CAP_SCALE) && 300 if (!(mdp5_plane->caps & MDP_PIPE_CAP_SCALE) &&
302 (((state->src_w >> 16) != state->crtc_w) || 301 (((state->src_w >> 16) != state->crtc_w) ||
303 ((state->src_h >> 16) != state->crtc_h))) { 302 ((state->src_h >> 16) != state->crtc_h))) {
304 dev_err(plane->dev->dev, 303 DBG("Pipe doesn't support scaling (%dx%d -> %dx%d)\n",
305 "Pipe doesn't support scaling (%dx%d -> %dx%d)\n",
306 state->src_w >> 16, state->src_h >> 16, 304 state->src_w >> 16, state->src_h >> 16,
307 state->crtc_w, state->crtc_h); 305 state->crtc_w, state->crtc_h);
308 306
@@ -313,8 +311,7 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
313 vflip = !!(state->rotation & DRM_REFLECT_Y); 311 vflip = !!(state->rotation & DRM_REFLECT_Y);
314 if ((vflip && !(mdp5_plane->caps & MDP_PIPE_CAP_VFLIP)) || 312 if ((vflip && !(mdp5_plane->caps & MDP_PIPE_CAP_VFLIP)) ||
315 (hflip && !(mdp5_plane->caps & MDP_PIPE_CAP_HFLIP))) { 313 (hflip && !(mdp5_plane->caps & MDP_PIPE_CAP_HFLIP))) {
316 dev_err(plane->dev->dev, 314 DBG("Pipe doesn't support flip\n");
317 "Pipe doesn't support flip\n");
318 315
319 return -EINVAL; 316 return -EINVAL;
320 } 317 }
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index fb5c0b0a7594..46568fc80848 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -228,7 +228,7 @@ static int msm_drm_uninit(struct device *dev)
228 flush_workqueue(priv->atomic_wq); 228 flush_workqueue(priv->atomic_wq);
229 destroy_workqueue(priv->atomic_wq); 229 destroy_workqueue(priv->atomic_wq);
230 230
231 if (kms) 231 if (kms && kms->funcs)
232 kms->funcs->destroy(kms); 232 kms->funcs->destroy(kms);
233 233
234 if (gpu) { 234 if (gpu) {
diff --git a/drivers/gpu/drm/msm/msm_gem_shrinker.c b/drivers/gpu/drm/msm/msm_gem_shrinker.c
index 283d2841ba58..192b2d3a79cb 100644
--- a/drivers/gpu/drm/msm/msm_gem_shrinker.c
+++ b/drivers/gpu/drm/msm/msm_gem_shrinker.c
@@ -163,6 +163,9 @@ void msm_gem_shrinker_init(struct drm_device *dev)
163void msm_gem_shrinker_cleanup(struct drm_device *dev) 163void msm_gem_shrinker_cleanup(struct drm_device *dev)
164{ 164{
165 struct msm_drm_private *priv = dev->dev_private; 165 struct msm_drm_private *priv = dev->dev_private;
166 WARN_ON(unregister_vmap_purge_notifier(&priv->vmap_notifier)); 166
167 unregister_shrinker(&priv->shrinker); 167 if (priv->shrinker.nr_deferred) {
168 WARN_ON(unregister_vmap_purge_notifier(&priv->vmap_notifier));
169 unregister_shrinker(&priv->shrinker);
170 }
168} 171}