drm/msm/hdmi: Enable HPD after HDMI IRQ is set up
[linux/fpc-iii.git] / drivers / gpu / drm / rockchip / rockchip_drm_psr.c
blob79d00d861a31f701451d3387a6cc6e8fc8e71234
1 /*
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.
15 #include <drm/drmP.h>
16 #include <drm/drm_crtc_helper.h>
18 #include "rockchip_drm_drv.h"
19 #include "rockchip_drm_psr.h"
21 #define PSR_FLUSH_TIMEOUT_MS 100
23 struct psr_drv {
24 struct list_head list;
25 struct drm_encoder *encoder;
27 struct mutex lock;
28 int inhibit_count;
29 bool enabled;
31 struct delayed_work flush_work;
33 int (*set)(struct drm_encoder *encoder, bool enable);
36 static struct psr_drv *find_psr_by_encoder(struct drm_encoder *encoder)
38 struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
39 struct psr_drv *psr;
41 mutex_lock(&drm_drv->psr_list_lock);
42 list_for_each_entry(psr, &drm_drv->psr_list, list) {
43 if (psr->encoder == encoder)
44 goto out;
46 psr = ERR_PTR(-ENODEV);
48 out:
49 mutex_unlock(&drm_drv->psr_list_lock);
50 return psr;
53 static int psr_set_state_locked(struct psr_drv *psr, bool enable)
55 int ret;
57 if (psr->inhibit_count > 0)
58 return -EINVAL;
60 if (enable == psr->enabled)
61 return 0;
63 ret = psr->set(psr->encoder, enable);
64 if (ret)
65 return ret;
67 psr->enabled = enable;
68 return 0;
71 static void psr_flush_handler(struct work_struct *work)
73 struct psr_drv *psr = container_of(to_delayed_work(work),
74 struct psr_drv, flush_work);
76 mutex_lock(&psr->lock);
77 psr_set_state_locked(psr, true);
78 mutex_unlock(&psr->lock);
81 /**
82 * rockchip_drm_psr_inhibit_put - release PSR inhibit on given encoder
83 * @encoder: encoder to obtain the PSR encoder
85 * Decrements PSR inhibit count on given encoder. Should be called only
86 * for a PSR inhibit count increment done before. If PSR inhibit counter
87 * reaches zero, PSR flush work is scheduled to make the hardware enter
88 * PSR mode in PSR_FLUSH_TIMEOUT_MS.
90 * Returns:
91 * Zero on success, negative errno on failure.
93 int rockchip_drm_psr_inhibit_put(struct drm_encoder *encoder)
95 struct psr_drv *psr = find_psr_by_encoder(encoder);
97 if (IS_ERR(psr))
98 return PTR_ERR(psr);
100 mutex_lock(&psr->lock);
101 --psr->inhibit_count;
102 WARN_ON(psr->inhibit_count < 0);
103 if (!psr->inhibit_count)
104 mod_delayed_work(system_wq, &psr->flush_work,
105 PSR_FLUSH_TIMEOUT_MS);
106 mutex_unlock(&psr->lock);
108 return 0;
110 EXPORT_SYMBOL(rockchip_drm_psr_inhibit_put);
113 * rockchip_drm_psr_inhibit_get - acquire PSR inhibit on given encoder
114 * @encoder: encoder to obtain the PSR encoder
116 * Increments PSR inhibit count on given encoder. This function guarantees
117 * that after it returns PSR is turned off on given encoder and no PSR-related
118 * hardware state change occurs at least until a matching call to
119 * rockchip_drm_psr_inhibit_put() is done.
121 * Returns:
122 * Zero on success, negative errno on failure.
124 int rockchip_drm_psr_inhibit_get(struct drm_encoder *encoder)
126 struct psr_drv *psr = find_psr_by_encoder(encoder);
128 if (IS_ERR(psr))
129 return PTR_ERR(psr);
131 mutex_lock(&psr->lock);
132 psr_set_state_locked(psr, false);
133 ++psr->inhibit_count;
134 mutex_unlock(&psr->lock);
135 cancel_delayed_work_sync(&psr->flush_work);
137 return 0;
139 EXPORT_SYMBOL(rockchip_drm_psr_inhibit_get);
141 static void rockchip_drm_do_flush(struct psr_drv *psr)
143 cancel_delayed_work_sync(&psr->flush_work);
145 mutex_lock(&psr->lock);
146 if (!psr_set_state_locked(psr, false))
147 mod_delayed_work(system_wq, &psr->flush_work,
148 PSR_FLUSH_TIMEOUT_MS);
149 mutex_unlock(&psr->lock);
153 * rockchip_drm_psr_flush_all - force to flush all registered PSR encoders
154 * @dev: drm device
156 * Disable the PSR function for all registered encoders, and then enable the
157 * PSR function back after PSR_FLUSH_TIMEOUT. If encoder PSR state have been
158 * changed during flush time, then keep the state no change after flush
159 * timeout.
161 * Returns:
162 * Zero on success, negative errno on failure.
164 void rockchip_drm_psr_flush_all(struct drm_device *dev)
166 struct rockchip_drm_private *drm_drv = dev->dev_private;
167 struct psr_drv *psr;
169 mutex_lock(&drm_drv->psr_list_lock);
170 list_for_each_entry(psr, &drm_drv->psr_list, list)
171 rockchip_drm_do_flush(psr);
172 mutex_unlock(&drm_drv->psr_list_lock);
174 EXPORT_SYMBOL(rockchip_drm_psr_flush_all);
177 * rockchip_drm_psr_register - register encoder to psr driver
178 * @encoder: encoder that obtain the PSR function
179 * @psr_set: call back to set PSR state
181 * The function returns with PSR inhibit counter initialized with one
182 * and the caller (typically encoder driver) needs to call
183 * rockchip_drm_psr_inhibit_put() when it becomes ready to accept PSR
184 * enable request.
186 * Returns:
187 * Zero on success, negative errno on failure.
189 int rockchip_drm_psr_register(struct drm_encoder *encoder,
190 int (*psr_set)(struct drm_encoder *, bool enable))
192 struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
193 struct psr_drv *psr;
195 if (!encoder || !psr_set)
196 return -EINVAL;
198 psr = kzalloc(sizeof(struct psr_drv), GFP_KERNEL);
199 if (!psr)
200 return -ENOMEM;
202 INIT_DELAYED_WORK(&psr->flush_work, psr_flush_handler);
203 mutex_init(&psr->lock);
205 psr->inhibit_count = 1;
206 psr->enabled = false;
207 psr->encoder = encoder;
208 psr->set = psr_set;
210 mutex_lock(&drm_drv->psr_list_lock);
211 list_add_tail(&psr->list, &drm_drv->psr_list);
212 mutex_unlock(&drm_drv->psr_list_lock);
214 return 0;
216 EXPORT_SYMBOL(rockchip_drm_psr_register);
219 * rockchip_drm_psr_unregister - unregister encoder to psr driver
220 * @encoder: encoder that obtain the PSR function
221 * @psr_set: call back to set PSR state
223 * It is expected that the PSR inhibit counter is 1 when this function is
224 * called, which corresponds to a state when related encoder has been
225 * disconnected from any CRTCs and its driver called
226 * rockchip_drm_psr_inhibit_get() to stop the PSR logic.
228 * Returns:
229 * Zero on success, negative errno on failure.
231 void rockchip_drm_psr_unregister(struct drm_encoder *encoder)
233 struct rockchip_drm_private *drm_drv = encoder->dev->dev_private;
234 struct psr_drv *psr, *n;
236 mutex_lock(&drm_drv->psr_list_lock);
237 list_for_each_entry_safe(psr, n, &drm_drv->psr_list, list) {
238 if (psr->encoder == encoder) {
240 * Any other value would mean that the encoder
241 * is still in use.
243 WARN_ON(psr->inhibit_count != 1);
245 list_del(&psr->list);
246 kfree(psr);
249 mutex_unlock(&drm_drv->psr_list_lock);
251 EXPORT_SYMBOL(rockchip_drm_psr_unregister);