aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2015-03-19 00:05:53 -0400
committerDave Airlie <airlied@redhat.com>2015-03-19 00:05:53 -0400
commit6b94aea01d4f96235e947892f6c39f837045e741 (patch)
treef0597c10cae2e1102fad291336bc818214e98942
parentd79dc0a9baef6ba909ac9e8da095524046523d6a (diff)
parent1067219b27e29e925e7bdbb85b72c4c2bec0267e (diff)
Merge branch 'drm_next' of https://github.com/markyzq/kernel-drm-rockchip into drm-next
rockchip fixes. * 'drm_next' of https://github.com/markyzq/kernel-drm-rockchip: drm/rockchip: vop: power off until vop standby take effect drm/rockchip: vop: set vop enabled after enable iommu drm/rockchip: vop use is_enabled instead of dpms mode drm/rockchip: vop: fix vop vsync/hsync polarity drm/rockchip: Only alloc a kmap for fbdev gem object
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c2
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_gem.c17
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_gem.h3
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c118
4 files changed, 102 insertions, 38 deletions
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c
index ff04877e837c..d5c1248916b2 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c
@@ -71,7 +71,7 @@ static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper,
71 71
72 size = mode_cmd.pitches[0] * mode_cmd.height; 72 size = mode_cmd.pitches[0] * mode_cmd.height;
73 73
74 rk_obj = rockchip_gem_create_object(dev, size); 74 rk_obj = rockchip_gem_create_object(dev, size, true);
75 if (IS_ERR(rk_obj)) 75 if (IS_ERR(rk_obj))
76 return -ENOMEM; 76 return -ENOMEM;
77 77
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
index 7ca8799ef784..eb2282cc4a56 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
@@ -22,7 +22,8 @@
22#include "rockchip_drm_drv.h" 22#include "rockchip_drm_drv.h"
23#include "rockchip_drm_gem.h" 23#include "rockchip_drm_gem.h"
24 24
25static int rockchip_gem_alloc_buf(struct rockchip_gem_object *rk_obj) 25static int rockchip_gem_alloc_buf(struct rockchip_gem_object *rk_obj,
26 bool alloc_kmap)
26{ 27{
27 struct drm_gem_object *obj = &rk_obj->base; 28 struct drm_gem_object *obj = &rk_obj->base;
28 struct drm_device *drm = obj->dev; 29 struct drm_device *drm = obj->dev;
@@ -30,7 +31,9 @@ static int rockchip_gem_alloc_buf(struct rockchip_gem_object *rk_obj)
30 init_dma_attrs(&rk_obj->dma_attrs); 31 init_dma_attrs(&rk_obj->dma_attrs);
31 dma_set_attr(DMA_ATTR_WRITE_COMBINE, &rk_obj->dma_attrs); 32 dma_set_attr(DMA_ATTR_WRITE_COMBINE, &rk_obj->dma_attrs);
32 33
33 /* TODO(djkurtz): Use DMA_ATTR_NO_KERNEL_MAPPING except for fbdev */ 34 if (!alloc_kmap)
35 dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &rk_obj->dma_attrs);
36
34 rk_obj->kvaddr = dma_alloc_attrs(drm->dev, obj->size, 37 rk_obj->kvaddr = dma_alloc_attrs(drm->dev, obj->size,
35 &rk_obj->dma_addr, GFP_KERNEL, 38 &rk_obj->dma_addr, GFP_KERNEL,
36 &rk_obj->dma_attrs); 39 &rk_obj->dma_attrs);
@@ -103,7 +106,8 @@ int rockchip_gem_mmap(struct file *filp, struct vm_area_struct *vma)
103} 106}
104 107
105struct rockchip_gem_object * 108struct rockchip_gem_object *
106 rockchip_gem_create_object(struct drm_device *drm, unsigned int size) 109 rockchip_gem_create_object(struct drm_device *drm, unsigned int size,
110 bool alloc_kmap)
107{ 111{
108 struct rockchip_gem_object *rk_obj; 112 struct rockchip_gem_object *rk_obj;
109 struct drm_gem_object *obj; 113 struct drm_gem_object *obj;
@@ -119,7 +123,7 @@ struct rockchip_gem_object *
119 123
120 drm_gem_private_object_init(drm, obj, size); 124 drm_gem_private_object_init(drm, obj, size);
121 125
122 ret = rockchip_gem_alloc_buf(rk_obj); 126 ret = rockchip_gem_alloc_buf(rk_obj, alloc_kmap);
123 if (ret) 127 if (ret)
124 goto err_free_rk_obj; 128 goto err_free_rk_obj;
125 129
@@ -163,7 +167,7 @@ rockchip_gem_create_with_handle(struct drm_file *file_priv,
163 struct drm_gem_object *obj; 167 struct drm_gem_object *obj;
164 int ret; 168 int ret;
165 169
166 rk_obj = rockchip_gem_create_object(drm, size); 170 rk_obj = rockchip_gem_create_object(drm, size, false);
167 if (IS_ERR(rk_obj)) 171 if (IS_ERR(rk_obj))
168 return ERR_CAST(rk_obj); 172 return ERR_CAST(rk_obj);
169 173
@@ -282,6 +286,9 @@ void *rockchip_gem_prime_vmap(struct drm_gem_object *obj)
282{ 286{
283 struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj); 287 struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj);
284 288
289 if (dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, &rk_obj->dma_attrs))
290 return NULL;
291
285 return rk_obj->kvaddr; 292 return rk_obj->kvaddr;
286} 293}
287 294
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.h b/drivers/gpu/drm/rockchip/rockchip_drm_gem.h
index 67bcebe90003..ad22618473a4 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.h
@@ -41,7 +41,8 @@ int rockchip_gem_mmap_buf(struct drm_gem_object *obj,
41 struct vm_area_struct *vma); 41 struct vm_area_struct *vma);
42 42
43struct rockchip_gem_object * 43struct rockchip_gem_object *
44 rockchip_gem_create_object(struct drm_device *drm, unsigned int size); 44 rockchip_gem_create_object(struct drm_device *drm, unsigned int size,
45 bool alloc_kmap);
45 46
46void rockchip_gem_free_object(struct drm_gem_object *obj); 47void rockchip_gem_free_object(struct drm_gem_object *obj);
47 48
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 9a5c571b95fc..d041921b3bb9 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -81,7 +81,7 @@ struct vop {
81 struct drm_crtc crtc; 81 struct drm_crtc crtc;
82 struct device *dev; 82 struct device *dev;
83 struct drm_device *drm_dev; 83 struct drm_device *drm_dev;
84 unsigned int dpms; 84 bool is_enabled;
85 85
86 int connector_type; 86 int connector_type;
87 int connector_out_mode; 87 int connector_out_mode;
@@ -89,6 +89,7 @@ struct vop {
89 /* mutex vsync_ work */ 89 /* mutex vsync_ work */
90 struct mutex vsync_mutex; 90 struct mutex vsync_mutex;
91 bool vsync_work_pending; 91 bool vsync_work_pending;
92 struct completion dsp_hold_completion;
92 93
93 const struct vop_data *data; 94 const struct vop_data *data;
94 95
@@ -382,11 +383,44 @@ static bool is_alpha_support(uint32_t format)
382 } 383 }
383} 384}
384 385
386static void vop_dsp_hold_valid_irq_enable(struct vop *vop)
387{
388 unsigned long flags;
389
390 if (WARN_ON(!vop->is_enabled))
391 return;
392
393 spin_lock_irqsave(&vop->irq_lock, flags);
394
395 vop_mask_write(vop, INTR_CTRL0, DSP_HOLD_VALID_INTR_MASK,
396 DSP_HOLD_VALID_INTR_EN(1));
397
398 spin_unlock_irqrestore(&vop->irq_lock, flags);
399}
400
401static void vop_dsp_hold_valid_irq_disable(struct vop *vop)
402{
403 unsigned long flags;
404
405 if (WARN_ON(!vop->is_enabled))
406 return;
407
408 spin_lock_irqsave(&vop->irq_lock, flags);
409
410 vop_mask_write(vop, INTR_CTRL0, DSP_HOLD_VALID_INTR_MASK,
411 DSP_HOLD_VALID_INTR_EN(0));
412
413 spin_unlock_irqrestore(&vop->irq_lock, flags);
414}
415
385static void vop_enable(struct drm_crtc *crtc) 416static void vop_enable(struct drm_crtc *crtc)
386{ 417{
387 struct vop *vop = to_vop(crtc); 418 struct vop *vop = to_vop(crtc);
388 int ret; 419 int ret;
389 420
421 if (vop->is_enabled)
422 return;
423
390 ret = clk_enable(vop->hclk); 424 ret = clk_enable(vop->hclk);
391 if (ret < 0) { 425 if (ret < 0) {
392 dev_err(vop->dev, "failed to enable hclk - %d\n", ret); 426 dev_err(vop->dev, "failed to enable hclk - %d\n", ret);
@@ -417,6 +451,11 @@ static void vop_enable(struct drm_crtc *crtc)
417 goto err_disable_aclk; 451 goto err_disable_aclk;
418 } 452 }
419 453
454 /*
455 * At here, vop clock & iommu is enable, R/W vop regs would be safe.
456 */
457 vop->is_enabled = true;
458
420 spin_lock(&vop->reg_lock); 459 spin_lock(&vop->reg_lock);
421 460
422 VOP_CTRL_SET(vop, standby, 0); 461 VOP_CTRL_SET(vop, standby, 0);
@@ -441,26 +480,41 @@ static void vop_disable(struct drm_crtc *crtc)
441{ 480{
442 struct vop *vop = to_vop(crtc); 481 struct vop *vop = to_vop(crtc);
443 482
444 drm_vblank_off(crtc->dev, vop->pipe); 483 if (!vop->is_enabled)
484 return;
445 485
446 disable_irq(vop->irq); 486 drm_vblank_off(crtc->dev, vop->pipe);
447 487
448 /* 488 /*
449 * TODO: Since standby doesn't take effect until the next vblank, 489 * Vop standby will take effect at end of current frame,
450 * when we turn off dclk below, the vop is probably still active. 490 * if dsp hold valid irq happen, it means standby complete.
491 *
492 * we must wait standby complete when we want to disable aclk,
493 * if not, memory bus maybe dead.
451 */ 494 */
495 reinit_completion(&vop->dsp_hold_completion);
496 vop_dsp_hold_valid_irq_enable(vop);
497
452 spin_lock(&vop->reg_lock); 498 spin_lock(&vop->reg_lock);
453 499
454 VOP_CTRL_SET(vop, standby, 1); 500 VOP_CTRL_SET(vop, standby, 1);
455 501
456 spin_unlock(&vop->reg_lock); 502 spin_unlock(&vop->reg_lock);
503
504 wait_for_completion(&vop->dsp_hold_completion);
505
506 vop_dsp_hold_valid_irq_disable(vop);
507
508 disable_irq(vop->irq);
509
510 vop->is_enabled = false;
511
457 /* 512 /*
458 * disable dclk to stop frame scan, so we can safely detach iommu, 513 * vop standby complete, so iommu detach is safe.
459 */ 514 */
460 clk_disable(vop->dclk);
461
462 rockchip_drm_dma_detach_device(vop->drm_dev, vop->dev); 515 rockchip_drm_dma_detach_device(vop->drm_dev, vop->dev);
463 516
517 clk_disable(vop->dclk);
464 clk_disable(vop->aclk); 518 clk_disable(vop->aclk);
465 clk_disable(vop->hclk); 519 clk_disable(vop->hclk);
466} 520}
@@ -742,7 +796,7 @@ static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
742 struct vop *vop = to_vop(crtc); 796 struct vop *vop = to_vop(crtc);
743 unsigned long flags; 797 unsigned long flags;
744 798
745 if (vop->dpms != DRM_MODE_DPMS_ON) 799 if (!vop->is_enabled)
746 return -EPERM; 800 return -EPERM;
747 801
748 spin_lock_irqsave(&vop->irq_lock, flags); 802 spin_lock_irqsave(&vop->irq_lock, flags);
@@ -759,8 +813,9 @@ static void vop_crtc_disable_vblank(struct drm_crtc *crtc)
759 struct vop *vop = to_vop(crtc); 813 struct vop *vop = to_vop(crtc);
760 unsigned long flags; 814 unsigned long flags;
761 815
762 if (vop->dpms != DRM_MODE_DPMS_ON) 816 if (!vop->is_enabled)
763 return; 817 return;
818
764 spin_lock_irqsave(&vop->irq_lock, flags); 819 spin_lock_irqsave(&vop->irq_lock, flags);
765 vop_mask_write(vop, INTR_CTRL0, FS_INTR_MASK, FS_INTR_EN(0)); 820 vop_mask_write(vop, INTR_CTRL0, FS_INTR_MASK, FS_INTR_EN(0));
766 spin_unlock_irqrestore(&vop->irq_lock, flags); 821 spin_unlock_irqrestore(&vop->irq_lock, flags);
@@ -773,15 +828,8 @@ static const struct rockchip_crtc_funcs private_crtc_funcs = {
773 828
774static void vop_crtc_dpms(struct drm_crtc *crtc, int mode) 829static void vop_crtc_dpms(struct drm_crtc *crtc, int mode)
775{ 830{
776 struct vop *vop = to_vop(crtc);
777
778 DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode); 831 DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
779 832
780 if (vop->dpms == mode) {
781 DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
782 return;
783 }
784
785 switch (mode) { 833 switch (mode) {
786 case DRM_MODE_DPMS_ON: 834 case DRM_MODE_DPMS_ON:
787 vop_enable(crtc); 835 vop_enable(crtc);
@@ -795,8 +843,6 @@ static void vop_crtc_dpms(struct drm_crtc *crtc, int mode)
795 DRM_DEBUG_KMS("unspecified mode %d\n", mode); 843 DRM_DEBUG_KMS("unspecified mode %d\n", mode);
796 break; 844 break;
797 } 845 }
798
799 vop->dpms = mode;
800} 846}
801 847
802static void vop_crtc_prepare(struct drm_crtc *crtc) 848static void vop_crtc_prepare(struct drm_crtc *crtc)
@@ -874,8 +920,8 @@ static int vop_crtc_mode_set(struct drm_crtc *crtc,
874 VOP_CTRL_SET(vop, out_mode, vop->connector_out_mode); 920 VOP_CTRL_SET(vop, out_mode, vop->connector_out_mode);
875 921
876 val = 0x8; 922 val = 0x8;
877 val |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0; 923 val |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1;
878 val |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? (1 << 1) : 0; 924 val |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : (1 << 1);
879 VOP_CTRL_SET(vop, pin_pol, val); 925 VOP_CTRL_SET(vop, pin_pol, val);
880 926
881 VOP_CTRL_SET(vop, htotal_pw, (htotal << 16) | hsync_len); 927 VOP_CTRL_SET(vop, htotal_pw, (htotal << 16) | hsync_len);
@@ -934,9 +980,9 @@ static int vop_crtc_page_flip(struct drm_crtc *crtc,
934 struct drm_framebuffer *old_fb = crtc->primary->fb; 980 struct drm_framebuffer *old_fb = crtc->primary->fb;
935 int ret; 981 int ret;
936 982
937 /* when the page flip is requested, crtc's dpms should be on */ 983 /* when the page flip is requested, crtc should be on */
938 if (vop->dpms > DRM_MODE_DPMS_ON) { 984 if (!vop->is_enabled) {
939 DRM_DEBUG("failed page flip request at dpms[%d].\n", vop->dpms); 985 DRM_DEBUG("page flip request rejected because crtc is off.\n");
940 return 0; 986 return 0;
941 } 987 }
942 988
@@ -1081,6 +1127,7 @@ static irqreturn_t vop_isr(int irq, void *data)
1081 struct vop *vop = data; 1127 struct vop *vop = data;
1082 uint32_t intr0_reg, active_irqs; 1128 uint32_t intr0_reg, active_irqs;
1083 unsigned long flags; 1129 unsigned long flags;
1130 int ret = IRQ_NONE;
1084 1131
1085 /* 1132 /*
1086 * INTR_CTRL0 register has interrupt status, enable and clear bits, we 1133 * INTR_CTRL0 register has interrupt status, enable and clear bits, we
@@ -1099,15 +1146,23 @@ static irqreturn_t vop_isr(int irq, void *data)
1099 if (!active_irqs) 1146 if (!active_irqs)
1100 return IRQ_NONE; 1147 return IRQ_NONE;
1101 1148
1102 /* Only Frame Start Interrupt is enabled; other irqs are spurious. */ 1149 if (active_irqs & DSP_HOLD_VALID_INTR) {
1103 if (!(active_irqs & FS_INTR)) { 1150 complete(&vop->dsp_hold_completion);
1104 DRM_ERROR("Unknown VOP IRQs: %#02x\n", active_irqs); 1151 active_irqs &= ~DSP_HOLD_VALID_INTR;
1105 return IRQ_NONE; 1152 ret = IRQ_HANDLED;
1106 } 1153 }
1107 1154
1108 drm_handle_vblank(vop->drm_dev, vop->pipe); 1155 if (active_irqs & FS_INTR) {
1156 drm_handle_vblank(vop->drm_dev, vop->pipe);
1157 active_irqs &= ~FS_INTR;
1158 ret = (vop->vsync_work_pending) ? IRQ_WAKE_THREAD : IRQ_HANDLED;
1159 }
1109 1160
1110 return (vop->vsync_work_pending) ? IRQ_WAKE_THREAD : IRQ_HANDLED; 1161 /* Unhandled irqs are spurious. */
1162 if (active_irqs)
1163 DRM_ERROR("Unknown VOP IRQs: %#02x\n", active_irqs);
1164
1165 return ret;
1111} 1166}
1112 1167
1113static int vop_create_crtc(struct vop *vop) 1168static int vop_create_crtc(struct vop *vop)
@@ -1189,6 +1244,7 @@ static int vop_create_crtc(struct vop *vop)
1189 goto err_cleanup_crtc; 1244 goto err_cleanup_crtc;
1190 } 1245 }
1191 1246
1247 init_completion(&vop->dsp_hold_completion);
1192 crtc->port = port; 1248 crtc->port = port;
1193 vop->pipe = drm_crtc_index(crtc); 1249 vop->pipe = drm_crtc_index(crtc);
1194 rockchip_register_crtc_funcs(drm_dev, &private_crtc_funcs, vop->pipe); 1250 rockchip_register_crtc_funcs(drm_dev, &private_crtc_funcs, vop->pipe);
@@ -1302,7 +1358,7 @@ static int vop_initial(struct vop *vop)
1302 1358
1303 clk_disable(vop->hclk); 1359 clk_disable(vop->hclk);
1304 1360
1305 vop->dpms = DRM_MODE_DPMS_OFF; 1361 vop->is_enabled = false;
1306 1362
1307 return 0; 1363 return 0;
1308 1364