Merge tag 'trace-v5.1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / rockchip / rockchip_drm_psr.c
1 /*
2  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
3  * Author: Yakir Yang <ykk@rock-chips.com>
4  *
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.
8  *
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.
13  */
14
15 #include <drm/drmP.h>
16 #include <drm/drm_atomic.h>
17 #include <drm/drm_probe_helper.h>
18
19 #include "rockchip_drm_drv.h"
20 #include "rockchip_drm_psr.h"
21
22 #define PSR_FLUSH_TIMEOUT_MS    100
23
24 struct psr_drv {
25         struct list_head        list;
26         struct drm_encoder      *encoder;
27
28         struct mutex            lock;
29         int                     inhibit_count;
30         bool                    enabled;
31
32         struct delayed_work     flush_work;
33
34         int (*set)(struct drm_encoder *encoder, bool enable);
35 };
36
37 static struct psr_drv *find_psr_by_encoder(struct drm_encoder *encoder)
38 {
39         struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
40         struct psr_drv *psr;
41
42         mutex_lock(&drm_drv->psr_list_lock);
43         list_for_each_entry(psr, &drm_drv->psr_list, list) {
44                 if (psr->encoder == encoder)
45                         goto out;
46         }
47         psr = ERR_PTR(-ENODEV);
48
49 out:
50         mutex_unlock(&drm_drv->psr_list_lock);
51         return psr;
52 }
53
54 static int psr_set_state_locked(struct psr_drv *psr, bool enable)
55 {
56         int ret;
57
58         if (psr->inhibit_count > 0)
59                 return -EINVAL;
60
61         if (enable == psr->enabled)
62                 return 0;
63
64         ret = psr->set(psr->encoder, enable);
65         if (ret)
66                 return ret;
67
68         psr->enabled = enable;
69         return 0;
70 }
71
72 static void psr_flush_handler(struct work_struct *work)
73 {
74         struct psr_drv *psr = container_of(to_delayed_work(work),
75                                            struct psr_drv, flush_work);
76
77         mutex_lock(&psr->lock);
78         psr_set_state_locked(psr, true);
79         mutex_unlock(&psr->lock);
80 }
81
82 /**
83  * rockchip_drm_psr_inhibit_put - release PSR inhibit on given encoder
84  * @encoder: encoder to obtain the PSR encoder
85  *
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.
90  *
91  * Returns:
92  * Zero on success, negative errno on failure.
93  */
94 int rockchip_drm_psr_inhibit_put(struct drm_encoder *encoder)
95 {
96         struct psr_drv *psr = find_psr_by_encoder(encoder);
97
98         if (IS_ERR(psr))
99                 return PTR_ERR(psr);
100
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);
108
109         return 0;
110 }
111 EXPORT_SYMBOL(rockchip_drm_psr_inhibit_put);
112
113 void rockchip_drm_psr_inhibit_get_state(struct drm_atomic_state *state)
114 {
115         struct drm_crtc *crtc;
116         struct drm_crtc_state *crtc_state;
117         struct drm_encoder *encoder;
118         u32 encoder_mask = 0;
119         int i;
120
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;
124         }
125
126         drm_for_each_encoder_mask(encoder, state->dev, encoder_mask)
127                 rockchip_drm_psr_inhibit_get(encoder);
128 }
129 EXPORT_SYMBOL(rockchip_drm_psr_inhibit_get_state);
130
131 void rockchip_drm_psr_inhibit_put_state(struct drm_atomic_state *state)
132 {
133         struct drm_crtc *crtc;
134         struct drm_crtc_state *crtc_state;
135         struct drm_encoder *encoder;
136         u32 encoder_mask = 0;
137         int i;
138
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;
142         }
143
144         drm_for_each_encoder_mask(encoder, state->dev, encoder_mask)
145                 rockchip_drm_psr_inhibit_put(encoder);
146 }
147 EXPORT_SYMBOL(rockchip_drm_psr_inhibit_put_state);
148
149 /**
150  * rockchip_drm_psr_inhibit_get - acquire PSR inhibit on given encoder
151  * @encoder: encoder to obtain the PSR encoder
152  *
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.
157  *
158  * Returns:
159  * Zero on success, negative errno on failure.
160  */
161 int rockchip_drm_psr_inhibit_get(struct drm_encoder *encoder)
162 {
163         struct psr_drv *psr = find_psr_by_encoder(encoder);
164
165         if (IS_ERR(psr))
166                 return PTR_ERR(psr);
167
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);
173
174         return 0;
175 }
176 EXPORT_SYMBOL(rockchip_drm_psr_inhibit_get);
177
178 static void rockchip_drm_do_flush(struct psr_drv *psr)
179 {
180         cancel_delayed_work_sync(&psr->flush_work);
181
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);
187 }
188
189 /**
190  * rockchip_drm_psr_flush_all - force to flush all registered PSR encoders
191  * @dev: drm device
192  *
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
196  * timeout.
197  *
198  * Returns:
199  * Zero on success, negative errno on failure.
200  */
201 void rockchip_drm_psr_flush_all(struct drm_device *dev)
202 {
203         struct rockchip_drm_private *drm_drv = dev->dev_private;
204         struct psr_drv *psr;
205
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);
210 }
211 EXPORT_SYMBOL(rockchip_drm_psr_flush_all);
212
213 /**
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
217  *
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
221  * enable request.
222  *
223  * Returns:
224  * Zero on success, negative errno on failure.
225  */
226 int rockchip_drm_psr_register(struct drm_encoder *encoder,
227                         int (*psr_set)(struct drm_encoder *, bool enable))
228 {
229         struct rockchip_drm_private *drm_drv;
230         struct psr_drv *psr;
231
232         if (!encoder || !psr_set)
233                 return -EINVAL;
234
235         drm_drv = encoder->dev->dev_private;
236
237         psr = kzalloc(sizeof(struct psr_drv), GFP_KERNEL);
238         if (!psr)
239                 return -ENOMEM;
240
241         INIT_DELAYED_WORK(&psr->flush_work, psr_flush_handler);
242         mutex_init(&psr->lock);
243
244         psr->inhibit_count = 1;
245         psr->enabled = false;
246         psr->encoder = encoder;
247         psr->set = psr_set;
248
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);
252
253         return 0;
254 }
255 EXPORT_SYMBOL(rockchip_drm_psr_register);
256
257 /**
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
261  *
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.
266  *
267  * Returns:
268  * Zero on success, negative errno on failure.
269  */
270 void rockchip_drm_psr_unregister(struct drm_encoder *encoder)
271 {
272         struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
273         struct psr_drv *psr, *n;
274
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) {
278                         /*
279                          * Any other value would mean that the encoder
280                          * is still in use.
281                          */
282                         WARN_ON(psr->inhibit_count != 1);
283
284                         list_del(&psr->list);
285                         kfree(psr);
286                 }
287         }
288         mutex_unlock(&drm_drv->psr_list_lock);
289 }
290 EXPORT_SYMBOL(rockchip_drm_psr_unregister);