aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-09-27 21:22:27 -0400
committerDave Airlie <airlied@redhat.com>2016-09-27 21:22:27 -0400
commit378db830c3cc5c05e2c176274b0d2fcee0b133f3 (patch)
tree74664de990ece01ba3360973e8e3adc3debb2436
parent662d5c957161802e2f26317bfe02108fdb215706 (diff)
parent8c763c9b1072c91aac90e5bc0a2ac2220a6980d7 (diff)
Merge branch 'for-next' of ssh://people.freedesktop.org/~seanpaul/dogwood into drm-next
I've included some improvements to PSR from myself, as well as a great series from Tomasz to clean up and tighten up vblank/flip handling. The last patch is one from Tomeu that has been floating around for a while, and since rockchip is one of the beneficiaries, I figured this would be a good place to pick it up. * 'for-next' of ssh://people.freedesktop.org/~seanpaul/dogwood: drm/rockchip: Balance irq refcount on failure drm/rockchip: Kill vop_plane_state drm/rockchip: Always signal event in next vblank after cfg_done drm/rockchip: Do not enable vblank without event drm/rockchip: Replace custom wait_for_vblanks with helper drm/rockchip: Unreference framebuffers from flip work drm/rockchip: Avoid race with vblank count increment drm/rockchip: Get rid of some unnecessary code drm/rockchip: Clear interrupt status bits before enabling drm/rockchip: Fix up bug in psr state machine drm/bridge: analogix_dp: Remove duplicated code drm/rockchip: Reduce psr flush time to 100ms drm/rockchip: Don't key off vblank for psr
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.h1
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_fb.c66
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_psr.c80
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_psr.h8
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c259
5 files changed, 165 insertions, 249 deletions
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 5c698456aa1c..fb6226cf84b7 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -39,7 +39,6 @@ struct drm_connector;
39struct rockchip_crtc_funcs { 39struct 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);
43}; 42};
44 43
45struct rockchip_crtc_state { 44struct rockchip_crtc_state {
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 60bcc48f84b9..0f6eda023bd0 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -70,7 +70,7 @@ static int rockchip_drm_fb_dirty(struct drm_framebuffer *fb,
70 struct drm_clip_rect *clips, 70 struct drm_clip_rect *clips,
71 unsigned int num_clips) 71 unsigned int num_clips)
72{ 72{
73 rockchip_drm_psr_flush(fb->dev); 73 rockchip_drm_psr_flush_all(fb->dev);
74 return 0; 74 return 0;
75} 75}
76 76
@@ -174,68 +174,6 @@ static void rockchip_drm_output_poll_changed(struct drm_device *dev)
174 drm_fb_helper_hotplug_event(fb_helper); 174 drm_fb_helper_hotplug_event(fb_helper);
175} 175}
176 176
177static void rockchip_crtc_wait_for_update(struct drm_crtc *crtc)
178{
179 struct rockchip_drm_private *priv = crtc->dev->dev_private;
180 int pipe = drm_crtc_index(crtc);
181 const struct rockchip_crtc_funcs *crtc_funcs = priv->crtc_funcs[pipe];
182
183 if (crtc_funcs && crtc_funcs->wait_for_update)
184 crtc_funcs->wait_for_update(crtc);
185}
186
187/*
188 * We can't use drm_atomic_helper_wait_for_vblanks() because rk3288 and rk3066
189 * have hardware counters for neither vblanks nor scanlines, which results in
190 * a race where:
191 * | <-- HW vsync irq and reg take effect
192 * plane_commit --> |
193 * get_vblank and wait --> |
194 * | <-- handle_vblank, vblank->count + 1
195 * cleanup_fb --> |
196 * iommu crash --> |
197 * | <-- HW vsync irq and reg take effect
198 *
199 * This function is equivalent but uses rockchip_crtc_wait_for_update() instead
200 * of waiting for vblank_count to change.
201 */
202static void
203rockchip_atomic_wait_for_complete(struct drm_device *dev, struct drm_atomic_state *old_state)
204{
205 struct drm_crtc_state *old_crtc_state;
206 struct drm_crtc *crtc;
207 int i, ret;
208
209 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
210 /* No one cares about the old state, so abuse it for tracking
211 * and store whether we hold a vblank reference (and should do a
212 * vblank wait) in the ->enable boolean.
213 */
214 old_crtc_state->enable = false;
215
216 if (!crtc->state->active)
217 continue;
218
219 if (!drm_atomic_helper_framebuffer_changed(dev,
220 old_state, crtc))
221 continue;
222
223 ret = drm_crtc_vblank_get(crtc);
224 if (ret != 0)
225 continue;
226
227 old_crtc_state->enable = true;
228 }
229
230 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
231 if (!old_crtc_state->enable)
232 continue;
233
234 rockchip_crtc_wait_for_update(crtc);
235 drm_crtc_vblank_put(crtc);
236 }
237}
238
239static void 177static void
240rockchip_atomic_commit_tail(struct drm_atomic_state *state) 178rockchip_atomic_commit_tail(struct drm_atomic_state *state)
241{ 179{
@@ -250,7 +188,7 @@ rockchip_atomic_commit_tail(struct drm_atomic_state *state)
250 188
251 drm_atomic_helper_commit_hw_done(state); 189 drm_atomic_helper_commit_hw_done(state);
252 190
253 rockchip_atomic_wait_for_complete(dev, state); 191 drm_atomic_helper_wait_for_vblanks(dev, state);
254 192
255 drm_atomic_helper_cleanup_planes(dev, state); 193 drm_atomic_helper_cleanup_planes(dev, state);
256} 194}
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
index c6ac5d01c8e4..a553e182ff53 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
@@ -18,7 +18,7 @@
18#include "rockchip_drm_drv.h" 18#include "rockchip_drm_drv.h"
19#include "rockchip_drm_psr.h" 19#include "rockchip_drm_psr.h"
20 20
21#define PSR_FLUSH_TIMEOUT msecs_to_jiffies(3000) /* 3 seconds */ 21#define PSR_FLUSH_TIMEOUT msecs_to_jiffies(100)
22 22
23enum psr_state { 23enum psr_state {
24 PSR_FLUSH, 24 PSR_FLUSH,
@@ -31,6 +31,7 @@ struct psr_drv {
31 struct drm_encoder *encoder; 31 struct drm_encoder *encoder;
32 32
33 spinlock_t lock; 33 spinlock_t lock;
34 bool active;
34 enum psr_state state; 35 enum psr_state state;
35 36
36 struct timer_list flush_timer; 37 struct timer_list flush_timer;
@@ -67,19 +68,17 @@ static void psr_set_state_locked(struct psr_drv *psr, enum psr_state state)
67 * v | | 68 * v | |
68 * PSR_DISABLE < - - - - - - - - - 69 * PSR_DISABLE < - - - - - - - - -
69 */ 70 */
70 if (state == psr->state) 71 if (state == psr->state || !psr->active)
71 return; 72 return;
72 73
73 /* Requesting a flush when disabled is a noop */ 74 /* Already disabled in flush, change the state, but not the hardware */
74 if (state == PSR_FLUSH && psr->state == PSR_DISABLE) 75 if (state == PSR_DISABLE && psr->state == PSR_FLUSH) {
76 psr->state = state;
75 return; 77 return;
78 }
76 79
77 psr->state = state; 80 psr->state = state;
78 81
79 /* Already disabled in flush, change the state, but not the hardware */
80 if (state == PSR_DISABLE && psr->state == PSR_FLUSH)
81 return;
82
83 /* Actually commit the state change to hardware */ 82 /* Actually commit the state change to hardware */
84 switch (psr->state) { 83 switch (psr->state) {
85 case PSR_ENABLE: 84 case PSR_ENABLE:
@@ -115,45 +114,79 @@ static void psr_flush_handler(unsigned long data)
115} 114}
116 115
117/** 116/**
118 * rockchip_drm_psr_enable - enable the encoder PSR which bind to given CRTC 117 * rockchip_drm_psr_activate - activate PSR on the given pipe
119 * @crtc: CRTC to obtain the PSR encoder 118 * @crtc: CRTC to obtain the PSR encoder
120 * 119 *
121 * Returns: 120 * Returns:
122 * Zero on success, negative errno on failure. 121 * Zero on success, negative errno on failure.
123 */ 122 */
124int rockchip_drm_psr_enable(struct drm_crtc *crtc) 123int rockchip_drm_psr_activate(struct drm_crtc *crtc)
125{ 124{
126 struct psr_drv *psr = find_psr_by_crtc(crtc); 125 struct psr_drv *psr = find_psr_by_crtc(crtc);
126 unsigned long flags;
127 127
128 if (IS_ERR(psr)) 128 if (IS_ERR(psr))
129 return PTR_ERR(psr); 129 return PTR_ERR(psr);
130 130
131 psr_set_state(psr, PSR_ENABLE); 131 spin_lock_irqsave(&psr->lock, flags);
132 psr->active = true;
133 spin_unlock_irqrestore(&psr->lock, flags);
134
132 return 0; 135 return 0;
133} 136}
134EXPORT_SYMBOL(rockchip_drm_psr_enable); 137EXPORT_SYMBOL(rockchip_drm_psr_activate);
135 138
136/** 139/**
137 * rockchip_drm_psr_disable - disable the encoder PSR which bind to given CRTC 140 * rockchip_drm_psr_deactivate - deactivate PSR on the given pipe
138 * @crtc: CRTC to obtain the PSR encoder 141 * @crtc: CRTC to obtain the PSR encoder
139 * 142 *
140 * Returns: 143 * Returns:
141 * Zero on success, negative errno on failure. 144 * Zero on success, negative errno on failure.
142 */ 145 */
143int rockchip_drm_psr_disable(struct drm_crtc *crtc) 146int rockchip_drm_psr_deactivate(struct drm_crtc *crtc)
144{ 147{
145 struct psr_drv *psr = find_psr_by_crtc(crtc); 148 struct psr_drv *psr = find_psr_by_crtc(crtc);
149 unsigned long flags;
146 150
147 if (IS_ERR(psr)) 151 if (IS_ERR(psr))
148 return PTR_ERR(psr); 152 return PTR_ERR(psr);
149 153
150 psr_set_state(psr, PSR_DISABLE); 154 spin_lock_irqsave(&psr->lock, flags);
155 psr->active = false;
156 spin_unlock_irqrestore(&psr->lock, flags);
157 del_timer_sync(&psr->flush_timer);
158
151 return 0; 159 return 0;
152} 160}
153EXPORT_SYMBOL(rockchip_drm_psr_disable); 161EXPORT_SYMBOL(rockchip_drm_psr_deactivate);
162
163static void rockchip_drm_do_flush(struct psr_drv *psr)
164{
165 mod_timer(&psr->flush_timer,
166 round_jiffies_up(jiffies + PSR_FLUSH_TIMEOUT));
167 psr_set_state(psr, PSR_FLUSH);
168}
154 169
155/** 170/**
156 * rockchip_drm_psr_flush - force to flush all registered PSR encoders 171 * rockchip_drm_psr_flush - flush a single pipe
172 * @crtc: CRTC of the pipe to flush
173 *
174 * Returns:
175 * 0 on success, -errno on fail
176 */
177int rockchip_drm_psr_flush(struct drm_crtc *crtc)
178{
179 struct psr_drv *psr = find_psr_by_crtc(crtc);
180 if (IS_ERR(psr))
181 return PTR_ERR(psr);
182
183 rockchip_drm_do_flush(psr);
184 return 0;
185}
186EXPORT_SYMBOL(rockchip_drm_psr_flush);
187
188/**
189 * rockchip_drm_psr_flush_all - force to flush all registered PSR encoders
157 * @dev: drm device 190 * @dev: drm device
158 * 191 *
159 * Disable the PSR function for all registered encoders, and then enable the 192 * Disable the PSR function for all registered encoders, and then enable the
@@ -164,22 +197,18 @@ EXPORT_SYMBOL(rockchip_drm_psr_disable);
164 * Returns: 197 * Returns:
165 * Zero on success, negative errno on failure. 198 * Zero on success, negative errno on failure.
166 */ 199 */
167void rockchip_drm_psr_flush(struct drm_device *dev) 200void rockchip_drm_psr_flush_all(struct drm_device *dev)
168{ 201{
169 struct rockchip_drm_private *drm_drv = dev->dev_private; 202 struct rockchip_drm_private *drm_drv = dev->dev_private;
170 struct psr_drv *psr; 203 struct psr_drv *psr;
171 unsigned long flags; 204 unsigned long flags;
172 205
173 spin_lock_irqsave(&drm_drv->psr_list_lock, flags); 206 spin_lock_irqsave(&drm_drv->psr_list_lock, flags);
174 list_for_each_entry(psr, &drm_drv->psr_list, list) { 207 list_for_each_entry(psr, &drm_drv->psr_list, list)
175 mod_timer(&psr->flush_timer, 208 rockchip_drm_do_flush(psr);
176 round_jiffies_up(jiffies + PSR_FLUSH_TIMEOUT));
177
178 psr_set_state(psr, PSR_FLUSH);
179 }
180 spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags); 209 spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags);
181} 210}
182EXPORT_SYMBOL(rockchip_drm_psr_flush); 211EXPORT_SYMBOL(rockchip_drm_psr_flush_all);
183 212
184/** 213/**
185 * rockchip_drm_psr_register - register encoder to psr driver 214 * rockchip_drm_psr_register - register encoder to psr driver
@@ -206,6 +235,7 @@ int rockchip_drm_psr_register(struct drm_encoder *encoder,
206 setup_timer(&psr->flush_timer, psr_flush_handler, (unsigned long)psr); 235 setup_timer(&psr->flush_timer, psr_flush_handler, (unsigned long)psr);
207 spin_lock_init(&psr->lock); 236 spin_lock_init(&psr->lock);
208 237
238 psr->active = true;
209 psr->state = PSR_DISABLE; 239 psr->state = PSR_DISABLE;
210 psr->encoder = encoder; 240 psr->encoder = encoder;
211 psr->set = psr_set; 241 psr->set = psr_set;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
index c35b68873a30..b420cf1bf902 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
@@ -15,9 +15,11 @@
15#ifndef __ROCKCHIP_DRM_PSR___ 15#ifndef __ROCKCHIP_DRM_PSR___
16#define __ROCKCHIP_DRM_PSR___ 16#define __ROCKCHIP_DRM_PSR___
17 17
18void rockchip_drm_psr_flush(struct drm_device *dev); 18void rockchip_drm_psr_flush_all(struct drm_device *dev);
19int rockchip_drm_psr_enable(struct drm_crtc *crtc); 19int rockchip_drm_psr_flush(struct drm_crtc *crtc);
20int rockchip_drm_psr_disable(struct drm_crtc *crtc); 20
21int rockchip_drm_psr_activate(struct drm_crtc *crtc);
22int rockchip_drm_psr_deactivate(struct drm_crtc *crtc);
21 23
22int rockchip_drm_psr_register(struct drm_encoder *encoder, 24int rockchip_drm_psr_register(struct drm_encoder *encoder,
23 void (*psr_set)(struct drm_encoder *, bool enable)); 25 void (*psr_set)(struct drm_encoder *, bool enable));
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index d486049f9722..c7eba305c488 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -17,12 +17,14 @@
17#include <drm/drm_atomic.h> 17#include <drm/drm_atomic.h>
18#include <drm/drm_crtc.h> 18#include <drm/drm_crtc.h>
19#include <drm/drm_crtc_helper.h> 19#include <drm/drm_crtc_helper.h>
20#include <drm/drm_flip_work.h>
20#include <drm/drm_plane_helper.h> 21#include <drm/drm_plane_helper.h>
21 22
22#include <linux/kernel.h> 23#include <linux/kernel.h>
23#include <linux/module.h> 24#include <linux/module.h>
24#include <linux/platform_device.h> 25#include <linux/platform_device.h>
25#include <linux/clk.h> 26#include <linux/clk.h>
27#include <linux/iopoll.h>
26#include <linux/of.h> 28#include <linux/of.h>
27#include <linux/of_device.h> 29#include <linux/of_device.h>
28#include <linux/pm_runtime.h> 30#include <linux/pm_runtime.h>
@@ -86,23 +88,15 @@
86 88
87#define to_vop(x) container_of(x, struct vop, crtc) 89#define to_vop(x) container_of(x, struct vop, crtc)
88#define to_vop_win(x) container_of(x, struct vop_win, base) 90#define to_vop_win(x) container_of(x, struct vop_win, base)
89#define to_vop_plane_state(x) container_of(x, struct vop_plane_state, base)
90 91
91struct vop_plane_state { 92enum vop_pending {
92 struct drm_plane_state base; 93 VOP_PENDING_FB_UNREF,
93 int format;
94 dma_addr_t yrgb_mst;
95 bool enable;
96}; 94};
97 95
98struct vop_win { 96struct vop_win {
99 struct drm_plane base; 97 struct drm_plane base;
100 const struct vop_win_data *data; 98 const struct vop_win_data *data;
101 struct vop *vop; 99 struct vop *vop;
102
103 /* protected by dev->event_lock */
104 bool enable;
105 dma_addr_t yrgb_mst;
106}; 100};
107 101
108struct vop { 102struct vop {
@@ -110,17 +104,18 @@ struct vop {
110 struct device *dev; 104 struct device *dev;
111 struct drm_device *drm_dev; 105 struct drm_device *drm_dev;
112 bool is_enabled; 106 bool is_enabled;
113 bool vblank_active;
114 107
115 /* mutex vsync_ work */ 108 /* mutex vsync_ work */
116 struct mutex vsync_mutex; 109 struct mutex vsync_mutex;
117 bool vsync_work_pending; 110 bool vsync_work_pending;
118 struct completion dsp_hold_completion; 111 struct completion dsp_hold_completion;
119 struct completion wait_update_complete;
120 112
121 /* protected by dev->event_lock */ 113 /* protected by dev->event_lock */
122 struct drm_pending_vblank_event *event; 114 struct drm_pending_vblank_event *event;
123 115
116 struct drm_flip_work fb_unref_work;
117 unsigned long pending;
118
124 struct completion line_flag_completion; 119 struct completion line_flag_completion;
125 120
126 const struct vop_data *data; 121 const struct vop_data *data;
@@ -414,6 +409,7 @@ static void vop_dsp_hold_valid_irq_enable(struct vop *vop)
414 409
415 spin_lock_irqsave(&vop->irq_lock, flags); 410 spin_lock_irqsave(&vop->irq_lock, flags);
416 411
412 VOP_INTR_SET_TYPE(vop, clear, DSP_HOLD_VALID_INTR, 1);
417 VOP_INTR_SET_TYPE(vop, enable, DSP_HOLD_VALID_INTR, 1); 413 VOP_INTR_SET_TYPE(vop, enable, DSP_HOLD_VALID_INTR, 1);
418 414
419 spin_unlock_irqrestore(&vop->irq_lock, flags); 415 spin_unlock_irqrestore(&vop->irq_lock, flags);
@@ -479,6 +475,7 @@ static void vop_line_flag_irq_enable(struct vop *vop, int line_num)
479 spin_lock_irqsave(&vop->irq_lock, flags); 475 spin_lock_irqsave(&vop->irq_lock, flags);
480 476
481 VOP_CTRL_SET(vop, line_flag_num[0], line_num); 477 VOP_CTRL_SET(vop, line_flag_num[0], line_num);
478 VOP_INTR_SET_TYPE(vop, clear, LINE_FLAG_INTR, 1);
482 VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 1); 479 VOP_INTR_SET_TYPE(vop, enable, LINE_FLAG_INTR, 1);
483 480
484 spin_unlock_irqrestore(&vop->irq_lock, flags); 481 spin_unlock_irqrestore(&vop->irq_lock, flags);
@@ -569,6 +566,8 @@ static void vop_crtc_disable(struct drm_crtc *crtc)
569 566
570 WARN_ON(vop->event); 567 WARN_ON(vop->event);
571 568
569 rockchip_drm_psr_deactivate(&vop->crtc);
570
572 /* 571 /*
573 * We need to make sure that all windows are disabled before we 572 * We need to make sure that all windows are disabled before we
574 * disable that crtc. Otherwise we might try to scan from a destroyed 573 * disable that crtc. Otherwise we might try to scan from a destroyed
@@ -633,22 +632,6 @@ static void vop_plane_destroy(struct drm_plane *plane)
633 drm_plane_cleanup(plane); 632 drm_plane_cleanup(plane);
634} 633}
635 634
636static int vop_plane_prepare_fb(struct drm_plane *plane,
637 struct drm_plane_state *new_state)
638{
639 if (plane->state->fb)
640 drm_framebuffer_reference(plane->state->fb);
641
642 return 0;
643}
644
645static void vop_plane_cleanup_fb(struct drm_plane *plane,
646 struct drm_plane_state *old_state)
647{
648 if (old_state->fb)
649 drm_framebuffer_unreference(old_state->fb);
650}
651
652static int vop_plane_atomic_check(struct drm_plane *plane, 635static int vop_plane_atomic_check(struct drm_plane *plane,
653 struct drm_plane_state *state) 636 struct drm_plane_state *state)
654{ 637{
@@ -656,7 +639,6 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
656 struct drm_crtc_state *crtc_state; 639 struct drm_crtc_state *crtc_state;
657 struct drm_framebuffer *fb = state->fb; 640 struct drm_framebuffer *fb = state->fb;
658 struct vop_win *vop_win = to_vop_win(plane); 641 struct vop_win *vop_win = to_vop_win(plane);
659 struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
660 const struct vop_win_data *win = vop_win->data; 642 const struct vop_win_data *win = vop_win->data;
661 int ret; 643 int ret;
662 struct drm_rect clip; 644 struct drm_rect clip;
@@ -666,7 +648,7 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
666 DRM_PLANE_HELPER_NO_SCALING; 648 DRM_PLANE_HELPER_NO_SCALING;
667 649
668 if (!crtc || !fb) 650 if (!crtc || !fb)
669 goto out_disable; 651 return 0;
670 652
671 crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc); 653 crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
672 if (WARN_ON(!crtc_state)) 654 if (WARN_ON(!crtc_state))
@@ -684,11 +666,11 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
684 return ret; 666 return ret;
685 667
686 if (!state->visible) 668 if (!state->visible)
687 goto out_disable; 669 return 0;
688 670
689 vop_plane_state->format = vop_convert_format(fb->pixel_format); 671 ret = vop_convert_format(fb->pixel_format);
690 if (vop_plane_state->format < 0) 672 if (ret < 0)
691 return vop_plane_state->format; 673 return ret;
692 674
693 /* 675 /*
694 * Src.x1 can be odd when do clip, but yuv plane start point 676 * Src.x1 can be odd when do clip, but yuv plane start point
@@ -697,19 +679,12 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
697 if (is_yuv_support(fb->pixel_format) && ((state->src.x1 >> 16) % 2)) 679 if (is_yuv_support(fb->pixel_format) && ((state->src.x1 >> 16) % 2))
698 return -EINVAL; 680 return -EINVAL;
699 681
700 vop_plane_state->enable = true;
701
702 return 0;
703
704out_disable:
705 vop_plane_state->enable = false;
706 return 0; 682 return 0;
707} 683}
708 684
709static void vop_plane_atomic_disable(struct drm_plane *plane, 685static void vop_plane_atomic_disable(struct drm_plane *plane,
710 struct drm_plane_state *old_state) 686 struct drm_plane_state *old_state)
711{ 687{
712 struct vop_plane_state *vop_plane_state = to_vop_plane_state(old_state);
713 struct vop_win *vop_win = to_vop_win(plane); 688 struct vop_win *vop_win = to_vop_win(plane);
714 const struct vop_win_data *win = vop_win->data; 689 const struct vop_win_data *win = vop_win->data;
715 struct vop *vop = to_vop(old_state->crtc); 690 struct vop *vop = to_vop(old_state->crtc);
@@ -717,18 +692,11 @@ static void vop_plane_atomic_disable(struct drm_plane *plane,
717 if (!old_state->crtc) 692 if (!old_state->crtc)
718 return; 693 return;
719 694
720 spin_lock_irq(&plane->dev->event_lock);
721 vop_win->enable = false;
722 vop_win->yrgb_mst = 0;
723 spin_unlock_irq(&plane->dev->event_lock);
724
725 spin_lock(&vop->reg_lock); 695 spin_lock(&vop->reg_lock);
726 696
727 VOP_WIN_SET(vop, win, enable, 0); 697 VOP_WIN_SET(vop, win, enable, 0);
728 698
729 spin_unlock(&vop->reg_lock); 699 spin_unlock(&vop->reg_lock);
730
731 vop_plane_state->enable = false;
732} 700}
733 701
734static void vop_plane_atomic_update(struct drm_plane *plane, 702static void vop_plane_atomic_update(struct drm_plane *plane,
@@ -737,7 +705,6 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
737 struct drm_plane_state *state = plane->state; 705 struct drm_plane_state *state = plane->state;
738 struct drm_crtc *crtc = state->crtc; 706 struct drm_crtc *crtc = state->crtc;
739 struct vop_win *vop_win = to_vop_win(plane); 707 struct vop_win *vop_win = to_vop_win(plane);
740 struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
741 const struct vop_win_data *win = vop_win->data; 708 const struct vop_win_data *win = vop_win->data;
742 struct vop *vop = to_vop(state->crtc); 709 struct vop *vop = to_vop(state->crtc);
743 struct drm_framebuffer *fb = state->fb; 710 struct drm_framebuffer *fb = state->fb;
@@ -752,6 +719,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
752 dma_addr_t dma_addr; 719 dma_addr_t dma_addr;
753 uint32_t val; 720 uint32_t val;
754 bool rb_swap; 721 bool rb_swap;
722 int format;
755 723
756 /* 724 /*
757 * can't update plane when vop is disabled. 725 * can't update plane when vop is disabled.
@@ -762,7 +730,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
762 if (WARN_ON(!vop->is_enabled)) 730 if (WARN_ON(!vop->is_enabled))
763 return; 731 return;
764 732
765 if (!vop_plane_state->enable) { 733 if (!state->visible) {
766 vop_plane_atomic_disable(plane, old_state); 734 vop_plane_atomic_disable(plane, old_state);
767 return; 735 return;
768 } 736 }
@@ -783,18 +751,15 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
783 751
784 offset = (src->x1 >> 16) * drm_format_plane_cpp(fb->pixel_format, 0); 752 offset = (src->x1 >> 16) * drm_format_plane_cpp(fb->pixel_format, 0);
785 offset += (src->y1 >> 16) * fb->pitches[0]; 753 offset += (src->y1 >> 16) * fb->pitches[0];
786 vop_plane_state->yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0]; 754 dma_addr = rk_obj->dma_addr + offset + fb->offsets[0];
787 755
788 spin_lock_irq(&plane->dev->event_lock); 756 format = vop_convert_format(fb->pixel_format);
789 vop_win->enable = true;
790 vop_win->yrgb_mst = vop_plane_state->yrgb_mst;
791 spin_unlock_irq(&plane->dev->event_lock);
792 757
793 spin_lock(&vop->reg_lock); 758 spin_lock(&vop->reg_lock);
794 759
795 VOP_WIN_SET(vop, win, format, vop_plane_state->format); 760 VOP_WIN_SET(vop, win, format, format);
796 VOP_WIN_SET(vop, win, yrgb_vir, fb->pitches[0] >> 2); 761 VOP_WIN_SET(vop, win, yrgb_vir, fb->pitches[0] >> 2);
797 VOP_WIN_SET(vop, win, yrgb_mst, vop_plane_state->yrgb_mst); 762 VOP_WIN_SET(vop, win, yrgb_mst, dma_addr);
798 if (is_yuv_support(fb->pixel_format)) { 763 if (is_yuv_support(fb->pixel_format)) {
799 int hsub = drm_format_horz_chroma_subsampling(fb->pixel_format); 764 int hsub = drm_format_horz_chroma_subsampling(fb->pixel_format);
800 int vsub = drm_format_vert_chroma_subsampling(fb->pixel_format); 765 int vsub = drm_format_vert_chroma_subsampling(fb->pixel_format);
@@ -841,68 +806,18 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
841} 806}
842 807
843static const struct drm_plane_helper_funcs plane_helper_funcs = { 808static const struct drm_plane_helper_funcs plane_helper_funcs = {
844 .prepare_fb = vop_plane_prepare_fb,
845 .cleanup_fb = vop_plane_cleanup_fb,
846 .atomic_check = vop_plane_atomic_check, 809 .atomic_check = vop_plane_atomic_check,
847 .atomic_update = vop_plane_atomic_update, 810 .atomic_update = vop_plane_atomic_update,
848 .atomic_disable = vop_plane_atomic_disable, 811 .atomic_disable = vop_plane_atomic_disable,
849}; 812};
850 813
851static void vop_atomic_plane_reset(struct drm_plane *plane)
852{
853 struct vop_plane_state *vop_plane_state =
854 to_vop_plane_state(plane->state);
855
856 if (plane->state && plane->state->fb)
857 drm_framebuffer_unreference(plane->state->fb);
858
859 kfree(vop_plane_state);
860 vop_plane_state = kzalloc(sizeof(*vop_plane_state), GFP_KERNEL);
861 if (!vop_plane_state)
862 return;
863
864 plane->state = &vop_plane_state->base;
865 plane->state->plane = plane;
866}
867
868static struct drm_plane_state *
869vop_atomic_plane_duplicate_state(struct drm_plane *plane)
870{
871 struct vop_plane_state *old_vop_plane_state;
872 struct vop_plane_state *vop_plane_state;
873
874 if (WARN_ON(!plane->state))
875 return NULL;
876
877 old_vop_plane_state = to_vop_plane_state(plane->state);
878 vop_plane_state = kmemdup(old_vop_plane_state,
879 sizeof(*vop_plane_state), GFP_KERNEL);
880 if (!vop_plane_state)
881 return NULL;
882
883 __drm_atomic_helper_plane_duplicate_state(plane,
884 &vop_plane_state->base);
885
886 return &vop_plane_state->base;
887}
888
889static void vop_atomic_plane_destroy_state(struct drm_plane *plane,
890 struct drm_plane_state *state)
891{
892 struct vop_plane_state *vop_state = to_vop_plane_state(state);
893
894 __drm_atomic_helper_plane_destroy_state(state);
895
896 kfree(vop_state);
897}
898
899static const struct drm_plane_funcs vop_plane_funcs = { 814static const struct drm_plane_funcs vop_plane_funcs = {
900 .update_plane = drm_atomic_helper_update_plane, 815 .update_plane = drm_atomic_helper_update_plane,
901 .disable_plane = drm_atomic_helper_disable_plane, 816 .disable_plane = drm_atomic_helper_disable_plane,
902 .destroy = vop_plane_destroy, 817 .destroy = vop_plane_destroy,
903 .reset = vop_atomic_plane_reset, 818 .reset = drm_atomic_helper_plane_reset,
904 .atomic_duplicate_state = vop_atomic_plane_duplicate_state, 819 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
905 .atomic_destroy_state = vop_atomic_plane_destroy_state, 820 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
906}; 821};
907 822
908static int vop_crtc_enable_vblank(struct drm_crtc *crtc) 823static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
@@ -915,12 +830,11 @@ static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
915 830
916 spin_lock_irqsave(&vop->irq_lock, flags); 831 spin_lock_irqsave(&vop->irq_lock, flags);
917 832
833 VOP_INTR_SET_TYPE(vop, clear, FS_INTR, 1);
918 VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 1); 834 VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 1);
919 835
920 spin_unlock_irqrestore(&vop->irq_lock, flags); 836 spin_unlock_irqrestore(&vop->irq_lock, flags);
921 837
922 rockchip_drm_psr_disable(&vop->crtc);
923
924 return 0; 838 return 0;
925} 839}
926 840
@@ -937,22 +851,11 @@ static void vop_crtc_disable_vblank(struct drm_crtc *crtc)
937 VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 0); 851 VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 0);
938 852
939 spin_unlock_irqrestore(&vop->irq_lock, flags); 853 spin_unlock_irqrestore(&vop->irq_lock, flags);
940
941 rockchip_drm_psr_enable(&vop->crtc);
942}
943
944static void vop_crtc_wait_for_update(struct drm_crtc *crtc)
945{
946 struct vop *vop = to_vop(crtc);
947
948 reinit_completion(&vop->wait_update_complete);
949 WARN_ON(!wait_for_completion_timeout(&vop->wait_update_complete, 100));
950} 854}
951 855
952static const struct rockchip_crtc_funcs private_crtc_funcs = { 856static const struct rockchip_crtc_funcs private_crtc_funcs = {
953 .enable_vblank = vop_crtc_enable_vblank, 857 .enable_vblank = vop_crtc_enable_vblank,
954 .disable_vblank = vop_crtc_disable_vblank, 858 .disable_vblank = vop_crtc_disable_vblank,
955 .wait_for_update = vop_crtc_wait_for_update,
956}; 859};
957 860
958static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, 861static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
@@ -1072,12 +975,44 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
1072 clk_set_rate(vop->dclk, adjusted_mode->clock * 1000); 975 clk_set_rate(vop->dclk, adjusted_mode->clock * 1000);
1073 976
1074 VOP_CTRL_SET(vop, standby, 0); 977 VOP_CTRL_SET(vop, standby, 0);
978
979 rockchip_drm_psr_activate(&vop->crtc);
980}
981
982static bool vop_fs_irq_is_pending(struct vop *vop)
983{
984 return VOP_INTR_GET_TYPE(vop, status, FS_INTR);
985}
986
987static void vop_wait_for_irq_handler(struct vop *vop)
988{
989 bool pending;
990 int ret;
991
992 /*
993 * Spin until frame start interrupt status bit goes low, which means
994 * that interrupt handler was invoked and cleared it. The timeout of
995 * 10 msecs is really too long, but it is just a safety measure if
996 * something goes really wrong. The wait will only happen in the very
997 * unlikely case of a vblank happening exactly at the same time and
998 * shouldn't exceed microseconds range.
999 */
1000 ret = readx_poll_timeout_atomic(vop_fs_irq_is_pending, vop, pending,
1001 !pending, 0, 10 * 1000);
1002 if (ret)
1003 DRM_DEV_ERROR(vop->dev, "VOP vblank IRQ stuck for 10 ms\n");
1004
1005 synchronize_irq(vop->irq);
1075} 1006}
1076 1007
1077static void vop_crtc_atomic_flush(struct drm_crtc *crtc, 1008static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
1078 struct drm_crtc_state *old_crtc_state) 1009 struct drm_crtc_state *old_crtc_state)
1079{ 1010{
1011 struct drm_atomic_state *old_state = old_crtc_state->state;
1012 struct drm_plane_state *old_plane_state;
1080 struct vop *vop = to_vop(crtc); 1013 struct vop *vop = to_vop(crtc);
1014 struct drm_plane *plane;
1015 int i;
1081 1016
1082 if (WARN_ON(!vop->is_enabled)) 1017 if (WARN_ON(!vop->is_enabled))
1083 return; 1018 return;
@@ -1087,23 +1022,42 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
1087 vop_cfg_done(vop); 1022 vop_cfg_done(vop);
1088 1023
1089 spin_unlock(&vop->reg_lock); 1024 spin_unlock(&vop->reg_lock);
1090}
1091 1025
1092static void vop_crtc_atomic_begin(struct drm_crtc *crtc, 1026 /*
1093 struct drm_crtc_state *old_crtc_state) 1027 * There is a (rather unlikely) possiblity that a vblank interrupt
1094{ 1028 * fired before we set the cfg_done bit. To avoid spuriously
1095 struct vop *vop = to_vop(crtc); 1029 * signalling flip completion we need to wait for it to finish.
1030 */
1031 vop_wait_for_irq_handler(vop);
1096 1032
1097 spin_lock_irq(&crtc->dev->event_lock); 1033 spin_lock_irq(&crtc->dev->event_lock);
1098 vop->vblank_active = true;
1099 WARN_ON(drm_crtc_vblank_get(crtc) != 0);
1100 WARN_ON(vop->event);
1101
1102 if (crtc->state->event) { 1034 if (crtc->state->event) {
1035 WARN_ON(drm_crtc_vblank_get(crtc) != 0);
1036 WARN_ON(vop->event);
1037
1103 vop->event = crtc->state->event; 1038 vop->event = crtc->state->event;
1104 crtc->state->event = NULL; 1039 crtc->state->event = NULL;
1105 } 1040 }
1106 spin_unlock_irq(&crtc->dev->event_lock); 1041 spin_unlock_irq(&crtc->dev->event_lock);
1042
1043 for_each_plane_in_state(old_state, plane, old_plane_state, i) {
1044 if (!old_plane_state->fb)
1045 continue;
1046
1047 if (old_plane_state->fb == plane->state->fb)
1048 continue;
1049
1050 drm_framebuffer_reference(old_plane_state->fb);
1051 drm_flip_work_queue(&vop->fb_unref_work, old_plane_state->fb);
1052 set_bit(VOP_PENDING_FB_UNREF, &vop->pending);
1053 WARN_ON(drm_crtc_vblank_get(crtc) != 0);
1054 }
1055}
1056
1057static void vop_crtc_atomic_begin(struct drm_crtc *crtc,
1058 struct drm_crtc_state *old_crtc_state)
1059{
1060 rockchip_drm_psr_flush(crtc);
1107} 1061}
1108 1062
1109static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = { 1063static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = {
@@ -1160,16 +1114,13 @@ static const struct drm_crtc_funcs vop_crtc_funcs = {
1160 .atomic_destroy_state = vop_crtc_destroy_state, 1114 .atomic_destroy_state = vop_crtc_destroy_state,
1161}; 1115};
1162 1116
1163static bool vop_win_pending_is_complete(struct vop_win *vop_win) 1117static void vop_fb_unref_worker(struct drm_flip_work *work, void *val)
1164{ 1118{
1165 dma_addr_t yrgb_mst; 1119 struct vop *vop = container_of(work, struct vop, fb_unref_work);
1120 struct drm_framebuffer *fb = val;
1166 1121
1167 if (!vop_win->enable) 1122 drm_crtc_vblank_put(&vop->crtc);
1168 return VOP_WIN_GET(vop_win->vop, vop_win->data, enable) == 0; 1123 drm_framebuffer_unreference(fb);
1169
1170 yrgb_mst = VOP_WIN_GET_YRGBADDR(vop_win->vop, vop_win->data);
1171
1172 return yrgb_mst == vop_win->yrgb_mst;
1173} 1124}
1174 1125
1175static void vop_handle_vblank(struct vop *vop) 1126static void vop_handle_vblank(struct vop *vop)
@@ -1177,27 +1128,17 @@ static void vop_handle_vblank(struct vop *vop)
1177 struct drm_device *drm = vop->drm_dev; 1128 struct drm_device *drm = vop->drm_dev;
1178 struct drm_crtc *crtc = &vop->crtc; 1129 struct drm_crtc *crtc = &vop->crtc;
1179 unsigned long flags; 1130 unsigned long flags;
1180 int i;
1181
1182 for (i = 0; i < vop->data->win_size; i++) {
1183 if (!vop_win_pending_is_complete(&vop->win[i]))
1184 return;
1185 }
1186 1131
1187 spin_lock_irqsave(&drm->event_lock, flags); 1132 spin_lock_irqsave(&drm->event_lock, flags);
1188 if (vop->event) { 1133 if (vop->event) {
1189 drm_crtc_send_vblank_event(crtc, vop->event); 1134 drm_crtc_send_vblank_event(crtc, vop->event);
1190 vop->event = NULL;
1191
1192 }
1193 if (vop->vblank_active) {
1194 vop->vblank_active = false;
1195 drm_crtc_vblank_put(crtc); 1135 drm_crtc_vblank_put(crtc);
1136 vop->event = NULL;
1196 } 1137 }
1197 spin_unlock_irqrestore(&drm->event_lock, flags); 1138 spin_unlock_irqrestore(&drm->event_lock, flags);
1198 1139
1199 if (!completion_done(&vop->wait_update_complete)) 1140 if (test_and_clear_bit(VOP_PENDING_FB_UNREF, &vop->pending))
1200 complete(&vop->wait_update_complete); 1141 drm_flip_work_commit(&vop->fb_unref_work, system_unbound_wq);
1201} 1142}
1202 1143
1203static irqreturn_t vop_isr(int irq, void *data) 1144static irqreturn_t vop_isr(int irq, void *data)
@@ -1336,8 +1277,10 @@ static int vop_create_crtc(struct vop *vop)
1336 goto err_cleanup_crtc; 1277 goto err_cleanup_crtc;
1337 } 1278 }
1338 1279
1280 drm_flip_work_init(&vop->fb_unref_work, "fb_unref",
1281 vop_fb_unref_worker);
1282
1339 init_completion(&vop->dsp_hold_completion); 1283 init_completion(&vop->dsp_hold_completion);
1340 init_completion(&vop->wait_update_complete);
1341 init_completion(&vop->line_flag_completion); 1284 init_completion(&vop->line_flag_completion);
1342 crtc->port = port; 1285 crtc->port = port;
1343 rockchip_register_crtc_funcs(crtc, &private_crtc_funcs); 1286 rockchip_register_crtc_funcs(crtc, &private_crtc_funcs);
@@ -1379,6 +1322,7 @@ static void vop_destroy_crtc(struct vop *vop)
1379 * references the CRTC. 1322 * references the CRTC.
1380 */ 1323 */
1381 drm_crtc_cleanup(crtc); 1324 drm_crtc_cleanup(crtc);
1325 drm_flip_work_cleanup(&vop->fb_unref_work);
1382} 1326}
1383 1327
1384static int vop_initial(struct vop *vop) 1328static int vop_initial(struct vop *vop)
@@ -1466,7 +1410,6 @@ static int vop_initial(struct vop *vop)
1466 clk_disable(vop->aclk); 1410 clk_disable(vop->aclk);
1467 1411
1468 vop->is_enabled = false; 1412 vop->is_enabled = false;
1469 vop->vblank_active = false;
1470 1413
1471 return 0; 1414 return 0;
1472 1415
@@ -1604,11 +1547,15 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
1604 1547
1605 ret = vop_create_crtc(vop); 1548 ret = vop_create_crtc(vop);
1606 if (ret) 1549 if (ret)
1607 return ret; 1550 goto err_enable_irq;
1608 1551
1609 pm_runtime_enable(&pdev->dev); 1552 pm_runtime_enable(&pdev->dev);
1610 1553
1611 return 0; 1554 return 0;
1555
1556err_enable_irq:
1557 enable_irq(vop->irq); /* To balance out the disable_irq above */
1558 return ret;
1612} 1559}
1613 1560
1614static void vop_unbind(struct device *dev, struct device *master, void *data) 1561static void vop_unbind(struct device *dev, struct device *master, void *data)