2 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
3 * Author: Yakir Yang <ykk@rock-chips.com>
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
16 #include <drm/drm_atomic.h>
17 #include <drm/drm_probe_helper.h>
19 #include "rockchip_drm_drv.h"
20 #include "rockchip_drm_psr.h"
22 #define PSR_FLUSH_TIMEOUT_MS 100
25 struct list_head list
;
26 struct drm_encoder
*encoder
;
32 struct delayed_work flush_work
;
34 int (*set
)(struct drm_encoder
*encoder
, bool enable
);
37 static struct psr_drv
*find_psr_by_encoder(struct drm_encoder
*encoder
)
39 struct rockchip_drm_private
*drm_drv
= encoder
->dev
->dev_private
;
42 mutex_lock(&drm_drv
->psr_list_lock
);
43 list_for_each_entry(psr
, &drm_drv
->psr_list
, list
) {
44 if (psr
->encoder
== encoder
)
47 psr
= ERR_PTR(-ENODEV
);
50 mutex_unlock(&drm_drv
->psr_list_lock
);
54 static int psr_set_state_locked(struct psr_drv
*psr
, bool enable
)
58 if (psr
->inhibit_count
> 0)
61 if (enable
== psr
->enabled
)
64 ret
= psr
->set(psr
->encoder
, enable
);
68 psr
->enabled
= enable
;
72 static void psr_flush_handler(struct work_struct
*work
)
74 struct psr_drv
*psr
= container_of(to_delayed_work(work
),
75 struct psr_drv
, flush_work
);
77 mutex_lock(&psr
->lock
);
78 psr_set_state_locked(psr
, true);
79 mutex_unlock(&psr
->lock
);
83 * rockchip_drm_psr_inhibit_put - release PSR inhibit on given encoder
84 * @encoder: encoder to obtain the PSR encoder
86 * Decrements PSR inhibit count on given encoder. Should be called only
87 * for a PSR inhibit count increment done before. If PSR inhibit counter
88 * reaches zero, PSR flush work is scheduled to make the hardware enter
89 * PSR mode in PSR_FLUSH_TIMEOUT_MS.
92 * Zero on success, negative errno on failure.
94 int rockchip_drm_psr_inhibit_put(struct drm_encoder
*encoder
)
96 struct psr_drv
*psr
= find_psr_by_encoder(encoder
);
101 mutex_lock(&psr
->lock
);
102 --psr
->inhibit_count
;
103 WARN_ON(psr
->inhibit_count
< 0);
104 if (!psr
->inhibit_count
)
105 mod_delayed_work(system_wq
, &psr
->flush_work
,
106 PSR_FLUSH_TIMEOUT_MS
);
107 mutex_unlock(&psr
->lock
);
111 EXPORT_SYMBOL(rockchip_drm_psr_inhibit_put
);
113 void rockchip_drm_psr_inhibit_get_state(struct drm_atomic_state
*state
)
115 struct drm_crtc
*crtc
;
116 struct drm_crtc_state
*crtc_state
;
117 struct drm_encoder
*encoder
;
118 u32 encoder_mask
= 0;
121 for_each_old_crtc_in_state(state
, crtc
, crtc_state
, i
) {
122 encoder_mask
|= crtc_state
->encoder_mask
;
123 encoder_mask
|= crtc
->state
->encoder_mask
;
126 drm_for_each_encoder_mask(encoder
, state
->dev
, encoder_mask
)
127 rockchip_drm_psr_inhibit_get(encoder
);
129 EXPORT_SYMBOL(rockchip_drm_psr_inhibit_get_state
);
131 void rockchip_drm_psr_inhibit_put_state(struct drm_atomic_state
*state
)
133 struct drm_crtc
*crtc
;
134 struct drm_crtc_state
*crtc_state
;
135 struct drm_encoder
*encoder
;
136 u32 encoder_mask
= 0;
139 for_each_old_crtc_in_state(state
, crtc
, crtc_state
, i
) {
140 encoder_mask
|= crtc_state
->encoder_mask
;
141 encoder_mask
|= crtc
->state
->encoder_mask
;
144 drm_for_each_encoder_mask(encoder
, state
->dev
, encoder_mask
)
145 rockchip_drm_psr_inhibit_put(encoder
);
147 EXPORT_SYMBOL(rockchip_drm_psr_inhibit_put_state
);
150 * rockchip_drm_psr_inhibit_get - acquire PSR inhibit on given encoder
151 * @encoder: encoder to obtain the PSR encoder
153 * Increments PSR inhibit count on given encoder. This function guarantees
154 * that after it returns PSR is turned off on given encoder and no PSR-related
155 * hardware state change occurs at least until a matching call to
156 * rockchip_drm_psr_inhibit_put() is done.
159 * Zero on success, negative errno on failure.
161 int rockchip_drm_psr_inhibit_get(struct drm_encoder
*encoder
)
163 struct psr_drv
*psr
= find_psr_by_encoder(encoder
);
168 mutex_lock(&psr
->lock
);
169 psr_set_state_locked(psr
, false);
170 ++psr
->inhibit_count
;
171 mutex_unlock(&psr
->lock
);
172 cancel_delayed_work_sync(&psr
->flush_work
);
176 EXPORT_SYMBOL(rockchip_drm_psr_inhibit_get
);
178 static void rockchip_drm_do_flush(struct psr_drv
*psr
)
180 cancel_delayed_work_sync(&psr
->flush_work
);
182 mutex_lock(&psr
->lock
);
183 if (!psr_set_state_locked(psr
, false))
184 mod_delayed_work(system_wq
, &psr
->flush_work
,
185 PSR_FLUSH_TIMEOUT_MS
);
186 mutex_unlock(&psr
->lock
);
190 * rockchip_drm_psr_flush_all - force to flush all registered PSR encoders
193 * Disable the PSR function for all registered encoders, and then enable the
194 * PSR function back after PSR_FLUSH_TIMEOUT. If encoder PSR state have been
195 * changed during flush time, then keep the state no change after flush
199 * Zero on success, negative errno on failure.
201 void rockchip_drm_psr_flush_all(struct drm_device
*dev
)
203 struct rockchip_drm_private
*drm_drv
= dev
->dev_private
;
206 mutex_lock(&drm_drv
->psr_list_lock
);
207 list_for_each_entry(psr
, &drm_drv
->psr_list
, list
)
208 rockchip_drm_do_flush(psr
);
209 mutex_unlock(&drm_drv
->psr_list_lock
);
211 EXPORT_SYMBOL(rockchip_drm_psr_flush_all
);
214 * rockchip_drm_psr_register - register encoder to psr driver
215 * @encoder: encoder that obtain the PSR function
216 * @psr_set: call back to set PSR state
218 * The function returns with PSR inhibit counter initialized with one
219 * and the caller (typically encoder driver) needs to call
220 * rockchip_drm_psr_inhibit_put() when it becomes ready to accept PSR
224 * Zero on success, negative errno on failure.
226 int rockchip_drm_psr_register(struct drm_encoder
*encoder
,
227 int (*psr_set
)(struct drm_encoder
*, bool enable
))
229 struct rockchip_drm_private
*drm_drv
;
232 if (!encoder
|| !psr_set
)
235 drm_drv
= encoder
->dev
->dev_private
;
237 psr
= kzalloc(sizeof(struct psr_drv
), GFP_KERNEL
);
241 INIT_DELAYED_WORK(&psr
->flush_work
, psr_flush_handler
);
242 mutex_init(&psr
->lock
);
244 psr
->inhibit_count
= 1;
245 psr
->enabled
= false;
246 psr
->encoder
= encoder
;
249 mutex_lock(&drm_drv
->psr_list_lock
);
250 list_add_tail(&psr
->list
, &drm_drv
->psr_list
);
251 mutex_unlock(&drm_drv
->psr_list_lock
);
255 EXPORT_SYMBOL(rockchip_drm_psr_register
);
258 * rockchip_drm_psr_unregister - unregister encoder to psr driver
259 * @encoder: encoder that obtain the PSR function
260 * @psr_set: call back to set PSR state
262 * It is expected that the PSR inhibit counter is 1 when this function is
263 * called, which corresponds to a state when related encoder has been
264 * disconnected from any CRTCs and its driver called
265 * rockchip_drm_psr_inhibit_get() to stop the PSR logic.
268 * Zero on success, negative errno on failure.
270 void rockchip_drm_psr_unregister(struct drm_encoder
*encoder
)
272 struct rockchip_drm_private
*drm_drv
= encoder
->dev
->dev_private
;
273 struct psr_drv
*psr
, *n
;
275 mutex_lock(&drm_drv
->psr_list_lock
);
276 list_for_each_entry_safe(psr
, n
, &drm_drv
->psr_list
, list
) {
277 if (psr
->encoder
== encoder
) {
279 * Any other value would mean that the encoder
282 WARN_ON(psr
->inhibit_count
!= 1);
284 list_del(&psr
->list
);
288 mutex_unlock(&drm_drv
->psr_list_lock
);
290 EXPORT_SYMBOL(rockchip_drm_psr_unregister
);