1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright 2021 Google Inc. |
4 | * |
5 | * Panel driver for the Samsung ATNA33XC20 panel. This panel can't be handled |
6 | * by the DRM_PANEL_SIMPLE driver because its power sequencing is non-standard. |
7 | */ |
8 | |
9 | #include <linux/backlight.h> |
10 | #include <linux/delay.h> |
11 | #include <linux/gpio/consumer.h> |
12 | #include <linux/iopoll.h> |
13 | #include <linux/module.h> |
14 | #include <linux/pm_runtime.h> |
15 | #include <linux/regulator/consumer.h> |
16 | |
17 | #include <drm/display/drm_dp_aux_bus.h> |
18 | #include <drm/display/drm_dp_helper.h> |
19 | #include <drm/drm_edid.h> |
20 | #include <drm/drm_panel.h> |
21 | |
22 | /* T3 VCC to HPD high is max 200 ms */ |
23 | #define HPD_MAX_MS 200 |
24 | #define HPD_MAX_US (HPD_MAX_MS * 1000) |
25 | |
26 | struct atana33xc20_panel { |
27 | struct drm_panel base; |
28 | bool prepared; |
29 | bool enabled; |
30 | bool el3_was_on; |
31 | |
32 | bool no_hpd; |
33 | struct gpio_desc *hpd_gpio; |
34 | |
35 | struct regulator *supply; |
36 | struct gpio_desc *el_on3_gpio; |
37 | struct drm_dp_aux *aux; |
38 | |
39 | struct edid *edid; |
40 | |
41 | ktime_t powered_off_time; |
42 | ktime_t powered_on_time; |
43 | ktime_t el_on3_off_time; |
44 | }; |
45 | |
46 | static inline struct atana33xc20_panel *to_atana33xc20(struct drm_panel *panel) |
47 | { |
48 | return container_of(panel, struct atana33xc20_panel, base); |
49 | } |
50 | |
51 | static void atana33xc20_wait(ktime_t start_ktime, unsigned int min_ms) |
52 | { |
53 | ktime_t now_ktime, min_ktime; |
54 | |
55 | min_ktime = ktime_add(start_ktime, ms_to_ktime(min_ms)); |
56 | now_ktime = ktime_get_boottime(); |
57 | |
58 | if (ktime_before(cmp1: now_ktime, cmp2: min_ktime)) |
59 | msleep(msecs: ktime_to_ms(ktime_sub(min_ktime, now_ktime)) + 1); |
60 | } |
61 | |
62 | static int atana33xc20_suspend(struct device *dev) |
63 | { |
64 | struct atana33xc20_panel *p = dev_get_drvdata(dev); |
65 | int ret; |
66 | |
67 | /* |
68 | * Note 3 (Example of power off sequence in detail) in spec |
69 | * specifies to wait 150 ms after deasserting EL3_ON before |
70 | * powering off. |
71 | */ |
72 | if (p->el3_was_on) |
73 | atana33xc20_wait(start_ktime: p->el_on3_off_time, min_ms: 150); |
74 | |
75 | drm_dp_dpcd_set_powered(aux: p->aux, powered: false); |
76 | ret = regulator_disable(regulator: p->supply); |
77 | if (ret) |
78 | return ret; |
79 | p->powered_off_time = ktime_get_boottime(); |
80 | p->el3_was_on = false; |
81 | |
82 | return 0; |
83 | } |
84 | |
85 | static int atana33xc20_resume(struct device *dev) |
86 | { |
87 | struct atana33xc20_panel *p = dev_get_drvdata(dev); |
88 | int hpd_asserted; |
89 | int ret; |
90 | |
91 | /* T12 (Power off time) is min 500 ms */ |
92 | atana33xc20_wait(start_ktime: p->powered_off_time, min_ms: 500); |
93 | |
94 | ret = regulator_enable(regulator: p->supply); |
95 | if (ret) |
96 | return ret; |
97 | drm_dp_dpcd_set_powered(aux: p->aux, powered: true); |
98 | p->powered_on_time = ktime_get_boottime(); |
99 | |
100 | if (p->no_hpd) { |
101 | msleep(HPD_MAX_MS); |
102 | return 0; |
103 | } |
104 | |
105 | if (p->hpd_gpio) { |
106 | ret = readx_poll_timeout(gpiod_get_value_cansleep, p->hpd_gpio, |
107 | hpd_asserted, hpd_asserted, |
108 | 1000, HPD_MAX_US); |
109 | if (hpd_asserted < 0) |
110 | ret = hpd_asserted; |
111 | |
112 | if (ret) |
113 | dev_warn(dev, "Error waiting for HPD GPIO: %d\n" , ret); |
114 | |
115 | return ret; |
116 | } |
117 | |
118 | if (p->aux->wait_hpd_asserted) { |
119 | ret = p->aux->wait_hpd_asserted(p->aux, HPD_MAX_US); |
120 | |
121 | if (ret) |
122 | dev_warn(dev, "Controller error waiting for HPD: %d\n" , ret); |
123 | |
124 | return ret; |
125 | } |
126 | |
127 | /* |
128 | * Note that it's possible that no_hpd is false, hpd_gpio is |
129 | * NULL, and wait_hpd_asserted is NULL. This is because |
130 | * wait_hpd_asserted() is optional even if HPD is hooked up to |
131 | * a dedicated pin on the eDP controller. In this case we just |
132 | * assume that the controller driver will wait for HPD at the |
133 | * right times. |
134 | */ |
135 | return 0; |
136 | } |
137 | |
138 | static int atana33xc20_disable(struct drm_panel *panel) |
139 | { |
140 | struct atana33xc20_panel *p = to_atana33xc20(panel); |
141 | |
142 | /* Disabling when already disabled is a no-op */ |
143 | if (!p->enabled) |
144 | return 0; |
145 | |
146 | gpiod_set_value_cansleep(desc: p->el_on3_gpio, value: 0); |
147 | p->el_on3_off_time = ktime_get_boottime(); |
148 | p->enabled = false; |
149 | |
150 | /* |
151 | * Keep track of the fact that EL_ON3 was on but we haven't power |
152 | * cycled yet. This lets us know that "el_on3_off_time" is recent (we |
153 | * don't need to worry about ktime wraparounds) and also makes it |
154 | * obvious if we try to enable again without a power cycle (see the |
155 | * warning in atana33xc20_enable()). |
156 | */ |
157 | p->el3_was_on = true; |
158 | |
159 | /* |
160 | * Sleeping 20 ms here (after setting the GPIO) avoids a glitch when |
161 | * powering off. |
162 | */ |
163 | msleep(msecs: 20); |
164 | |
165 | return 0; |
166 | } |
167 | |
168 | static int atana33xc20_enable(struct drm_panel *panel) |
169 | { |
170 | struct atana33xc20_panel *p = to_atana33xc20(panel); |
171 | |
172 | /* Enabling when already enabled is a no-op */ |
173 | if (p->enabled) |
174 | return 0; |
175 | |
176 | /* |
177 | * Once EL_ON3 drops we absolutely need a power cycle before the next |
178 | * enable or the backlight will never come on again. The code ensures |
179 | * this because disable() is _always_ followed by unprepare() and |
180 | * unprepare() forces a suspend with pm_runtime_put_sync_suspend(), |
181 | * but let's track just to make sure since the requirement is so |
182 | * non-obvious. |
183 | */ |
184 | if (WARN_ON(p->el3_was_on)) |
185 | return -EIO; |
186 | |
187 | /* |
188 | * Note 2 (Example of power on sequence in detail) in spec specifies |
189 | * to wait 400 ms after powering on before asserting EL3_on. |
190 | */ |
191 | atana33xc20_wait(start_ktime: p->powered_on_time, min_ms: 400); |
192 | |
193 | gpiod_set_value_cansleep(desc: p->el_on3_gpio, value: 1); |
194 | p->enabled = true; |
195 | |
196 | return 0; |
197 | } |
198 | |
199 | static int atana33xc20_unprepare(struct drm_panel *panel) |
200 | { |
201 | struct atana33xc20_panel *p = to_atana33xc20(panel); |
202 | int ret; |
203 | |
204 | /* Unpreparing when already unprepared is a no-op */ |
205 | if (!p->prepared) |
206 | return 0; |
207 | |
208 | /* |
209 | * Purposely do a put_sync, don't use autosuspend. The panel's tcon |
210 | * seems to sometimes crash when you stop giving it data and this is |
211 | * the best way to ensure it will come back. |
212 | * |
213 | * NOTE: we still want autosuspend for cases where we only turn on |
214 | * to get the EDID or otherwise send DP AUX commands to the panel. |
215 | */ |
216 | ret = pm_runtime_put_sync_suspend(dev: panel->dev); |
217 | if (ret < 0) |
218 | return ret; |
219 | p->prepared = false; |
220 | |
221 | return 0; |
222 | } |
223 | |
224 | static int atana33xc20_prepare(struct drm_panel *panel) |
225 | { |
226 | struct atana33xc20_panel *p = to_atana33xc20(panel); |
227 | int ret; |
228 | |
229 | /* Preparing when already prepared is a no-op */ |
230 | if (p->prepared) |
231 | return 0; |
232 | |
233 | ret = pm_runtime_get_sync(dev: panel->dev); |
234 | if (ret < 0) { |
235 | pm_runtime_put_autosuspend(dev: panel->dev); |
236 | return ret; |
237 | } |
238 | p->prepared = true; |
239 | |
240 | return 0; |
241 | } |
242 | |
243 | static int atana33xc20_get_modes(struct drm_panel *panel, |
244 | struct drm_connector *connector) |
245 | { |
246 | struct atana33xc20_panel *p = to_atana33xc20(panel); |
247 | struct dp_aux_ep_device *aux_ep = to_dp_aux_ep_dev(dev: panel->dev); |
248 | int num = 0; |
249 | |
250 | pm_runtime_get_sync(dev: panel->dev); |
251 | |
252 | if (!p->edid) |
253 | p->edid = drm_get_edid(connector, adapter: &aux_ep->aux->ddc); |
254 | num = drm_add_edid_modes(connector, edid: p->edid); |
255 | |
256 | pm_runtime_mark_last_busy(dev: panel->dev); |
257 | pm_runtime_put_autosuspend(dev: panel->dev); |
258 | |
259 | return num; |
260 | } |
261 | |
262 | static const struct drm_panel_funcs atana33xc20_funcs = { |
263 | .disable = atana33xc20_disable, |
264 | .enable = atana33xc20_enable, |
265 | .unprepare = atana33xc20_unprepare, |
266 | .prepare = atana33xc20_prepare, |
267 | .get_modes = atana33xc20_get_modes, |
268 | }; |
269 | |
270 | static void atana33xc20_runtime_disable(void *data) |
271 | { |
272 | pm_runtime_disable(dev: data); |
273 | } |
274 | |
275 | static void atana33xc20_dont_use_autosuspend(void *data) |
276 | { |
277 | pm_runtime_dont_use_autosuspend(dev: data); |
278 | } |
279 | |
280 | static int atana33xc20_probe(struct dp_aux_ep_device *aux_ep) |
281 | { |
282 | struct atana33xc20_panel *panel; |
283 | struct device *dev = &aux_ep->dev; |
284 | int ret; |
285 | |
286 | panel = devm_kzalloc(dev, size: sizeof(*panel), GFP_KERNEL); |
287 | if (!panel) |
288 | return -ENOMEM; |
289 | dev_set_drvdata(dev, data: panel); |
290 | |
291 | panel->aux = aux_ep->aux; |
292 | |
293 | panel->supply = devm_regulator_get(dev, id: "power" ); |
294 | if (IS_ERR(ptr: panel->supply)) |
295 | return dev_err_probe(dev, err: PTR_ERR(ptr: panel->supply), |
296 | fmt: "Failed to get power supply\n" ); |
297 | |
298 | panel->el_on3_gpio = devm_gpiod_get(dev, con_id: "enable" , flags: GPIOD_OUT_LOW); |
299 | if (IS_ERR(ptr: panel->el_on3_gpio)) |
300 | return dev_err_probe(dev, err: PTR_ERR(ptr: panel->el_on3_gpio), |
301 | fmt: "Failed to get enable GPIO\n" ); |
302 | |
303 | panel->no_hpd = of_property_read_bool(np: dev->of_node, propname: "no-hpd" ); |
304 | if (!panel->no_hpd) { |
305 | panel->hpd_gpio = devm_gpiod_get_optional(dev, con_id: "hpd" , flags: GPIOD_IN); |
306 | if (IS_ERR(ptr: panel->hpd_gpio)) |
307 | return dev_err_probe(dev, err: PTR_ERR(ptr: panel->hpd_gpio), |
308 | fmt: "Failed to get HPD GPIO\n" ); |
309 | } |
310 | |
311 | pm_runtime_enable(dev); |
312 | ret = devm_add_action_or_reset(dev, atana33xc20_runtime_disable, dev); |
313 | if (ret) |
314 | return ret; |
315 | pm_runtime_set_autosuspend_delay(dev, delay: 2000); |
316 | pm_runtime_use_autosuspend(dev); |
317 | ret = devm_add_action_or_reset(dev, atana33xc20_dont_use_autosuspend, dev); |
318 | if (ret) |
319 | return ret; |
320 | |
321 | drm_panel_init(panel: &panel->base, dev, funcs: &atana33xc20_funcs, DRM_MODE_CONNECTOR_eDP); |
322 | |
323 | pm_runtime_get_sync(dev); |
324 | ret = drm_panel_dp_aux_backlight(panel: &panel->base, aux: aux_ep->aux); |
325 | pm_runtime_mark_last_busy(dev); |
326 | pm_runtime_put_autosuspend(dev); |
327 | if (ret) |
328 | return dev_err_probe(dev, err: ret, |
329 | fmt: "failed to register dp aux backlight\n" ); |
330 | |
331 | drm_panel_add(panel: &panel->base); |
332 | |
333 | return 0; |
334 | } |
335 | |
336 | static void atana33xc20_remove(struct dp_aux_ep_device *aux_ep) |
337 | { |
338 | struct device *dev = &aux_ep->dev; |
339 | struct atana33xc20_panel *panel = dev_get_drvdata(dev); |
340 | |
341 | drm_panel_remove(panel: &panel->base); |
342 | drm_panel_disable(panel: &panel->base); |
343 | drm_panel_unprepare(panel: &panel->base); |
344 | |
345 | kfree(objp: panel->edid); |
346 | } |
347 | |
348 | static void atana33xc20_shutdown(struct dp_aux_ep_device *aux_ep) |
349 | { |
350 | struct device *dev = &aux_ep->dev; |
351 | struct atana33xc20_panel *panel = dev_get_drvdata(dev); |
352 | |
353 | drm_panel_disable(panel: &panel->base); |
354 | drm_panel_unprepare(panel: &panel->base); |
355 | } |
356 | |
357 | static const struct of_device_id atana33xc20_dt_match[] = { |
358 | { .compatible = "samsung,atna33xc20" , }, |
359 | { /* sentinal */ } |
360 | }; |
361 | MODULE_DEVICE_TABLE(of, atana33xc20_dt_match); |
362 | |
363 | static const struct dev_pm_ops atana33xc20_pm_ops = { |
364 | SET_RUNTIME_PM_OPS(atana33xc20_suspend, atana33xc20_resume, NULL) |
365 | SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, |
366 | pm_runtime_force_resume) |
367 | }; |
368 | |
369 | static struct dp_aux_ep_driver atana33xc20_driver = { |
370 | .driver = { |
371 | .name = "samsung_atana33xc20" , |
372 | .of_match_table = atana33xc20_dt_match, |
373 | .pm = &atana33xc20_pm_ops, |
374 | }, |
375 | .probe = atana33xc20_probe, |
376 | .remove = atana33xc20_remove, |
377 | .shutdown = atana33xc20_shutdown, |
378 | }; |
379 | |
380 | static int __init atana33xc20_init(void) |
381 | { |
382 | return dp_aux_dp_driver_register(&atana33xc20_driver); |
383 | } |
384 | module_init(atana33xc20_init); |
385 | |
386 | static void __exit atana33xc20_exit(void) |
387 | { |
388 | dp_aux_dp_driver_unregister(aux_ep_drv: &atana33xc20_driver); |
389 | } |
390 | module_exit(atana33xc20_exit); |
391 | |
392 | MODULE_DESCRIPTION("Samsung ATANA33XC20 Panel Driver" ); |
393 | MODULE_LICENSE("GPL v2" ); |
394 | |