1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (C) 2017 NXP Semiconductors. |
4 | * Author: Marco Franchi <marco.franchi@nxp.com> |
5 | * |
6 | * Based on Panel Simple driver by Thierry Reding <treding@nvidia.com> |
7 | */ |
8 | |
9 | #include <linux/delay.h> |
10 | #include <linux/gpio/consumer.h> |
11 | #include <linux/media-bus-format.h> |
12 | #include <linux/module.h> |
13 | #include <linux/of.h> |
14 | #include <linux/platform_device.h> |
15 | #include <linux/regulator/consumer.h> |
16 | |
17 | #include <video/display_timing.h> |
18 | #include <video/videomode.h> |
19 | |
20 | #include <drm/drm_crtc.h> |
21 | #include <drm/drm_device.h> |
22 | #include <drm/drm_panel.h> |
23 | |
24 | struct seiko_panel_desc { |
25 | const struct drm_display_mode *modes; |
26 | unsigned int num_modes; |
27 | const struct display_timing *timings; |
28 | unsigned int num_timings; |
29 | |
30 | unsigned int bpc; |
31 | |
32 | /** |
33 | * @width: width (in millimeters) of the panel's active display area |
34 | * @height: height (in millimeters) of the panel's active display area |
35 | */ |
36 | struct { |
37 | unsigned int width; |
38 | unsigned int height; |
39 | } size; |
40 | |
41 | u32 bus_format; |
42 | u32 bus_flags; |
43 | }; |
44 | |
45 | struct seiko_panel { |
46 | struct drm_panel base; |
47 | bool prepared; |
48 | bool enabled; |
49 | const struct seiko_panel_desc *desc; |
50 | struct regulator *dvdd; |
51 | struct regulator *avdd; |
52 | struct gpio_desc *enable_gpio; |
53 | }; |
54 | |
55 | static inline struct seiko_panel *to_seiko_panel(struct drm_panel *panel) |
56 | { |
57 | return container_of(panel, struct seiko_panel, base); |
58 | } |
59 | |
60 | static int seiko_panel_get_fixed_modes(struct seiko_panel *panel, |
61 | struct drm_connector *connector) |
62 | { |
63 | struct drm_display_mode *mode; |
64 | unsigned int i, num = 0; |
65 | |
66 | if (!panel->desc) |
67 | return 0; |
68 | |
69 | for (i = 0; i < panel->desc->num_timings; i++) { |
70 | const struct display_timing *dt = &panel->desc->timings[i]; |
71 | struct videomode vm; |
72 | |
73 | videomode_from_timing(dt, vm: &vm); |
74 | mode = drm_mode_create(dev: connector->dev); |
75 | if (!mode) { |
76 | dev_err(panel->base.dev, "failed to add mode %ux%u\n" , |
77 | dt->hactive.typ, dt->vactive.typ); |
78 | continue; |
79 | } |
80 | |
81 | drm_display_mode_from_videomode(vm: &vm, dmode: mode); |
82 | |
83 | mode->type |= DRM_MODE_TYPE_DRIVER; |
84 | |
85 | if (panel->desc->num_timings == 1) |
86 | mode->type |= DRM_MODE_TYPE_PREFERRED; |
87 | |
88 | drm_mode_probed_add(connector, mode); |
89 | num++; |
90 | } |
91 | |
92 | for (i = 0; i < panel->desc->num_modes; i++) { |
93 | const struct drm_display_mode *m = &panel->desc->modes[i]; |
94 | |
95 | mode = drm_mode_duplicate(dev: connector->dev, mode: m); |
96 | if (!mode) { |
97 | dev_err(panel->base.dev, "failed to add mode %ux%u@%u\n" , |
98 | m->hdisplay, m->vdisplay, |
99 | drm_mode_vrefresh(m)); |
100 | continue; |
101 | } |
102 | |
103 | mode->type |= DRM_MODE_TYPE_DRIVER; |
104 | |
105 | if (panel->desc->num_modes == 1) |
106 | mode->type |= DRM_MODE_TYPE_PREFERRED; |
107 | |
108 | drm_mode_set_name(mode); |
109 | |
110 | drm_mode_probed_add(connector, mode); |
111 | num++; |
112 | } |
113 | |
114 | connector->display_info.bpc = panel->desc->bpc; |
115 | connector->display_info.width_mm = panel->desc->size.width; |
116 | connector->display_info.height_mm = panel->desc->size.height; |
117 | if (panel->desc->bus_format) |
118 | drm_display_info_set_bus_formats(info: &connector->display_info, |
119 | formats: &panel->desc->bus_format, num_formats: 1); |
120 | connector->display_info.bus_flags = panel->desc->bus_flags; |
121 | |
122 | return num; |
123 | } |
124 | |
125 | static int seiko_panel_disable(struct drm_panel *panel) |
126 | { |
127 | struct seiko_panel *p = to_seiko_panel(panel); |
128 | |
129 | if (!p->enabled) |
130 | return 0; |
131 | |
132 | p->enabled = false; |
133 | |
134 | return 0; |
135 | } |
136 | |
137 | static int seiko_panel_unprepare(struct drm_panel *panel) |
138 | { |
139 | struct seiko_panel *p = to_seiko_panel(panel); |
140 | |
141 | if (!p->prepared) |
142 | return 0; |
143 | |
144 | gpiod_set_value_cansleep(desc: p->enable_gpio, value: 0); |
145 | |
146 | regulator_disable(regulator: p->avdd); |
147 | |
148 | /* Add a 100ms delay as per the panel datasheet */ |
149 | msleep(msecs: 100); |
150 | |
151 | regulator_disable(regulator: p->dvdd); |
152 | |
153 | p->prepared = false; |
154 | |
155 | return 0; |
156 | } |
157 | |
158 | static int seiko_panel_prepare(struct drm_panel *panel) |
159 | { |
160 | struct seiko_panel *p = to_seiko_panel(panel); |
161 | int err; |
162 | |
163 | if (p->prepared) |
164 | return 0; |
165 | |
166 | err = regulator_enable(regulator: p->dvdd); |
167 | if (err < 0) { |
168 | dev_err(panel->dev, "failed to enable dvdd: %d\n" , err); |
169 | return err; |
170 | } |
171 | |
172 | /* Add a 100ms delay as per the panel datasheet */ |
173 | msleep(msecs: 100); |
174 | |
175 | err = regulator_enable(regulator: p->avdd); |
176 | if (err < 0) { |
177 | dev_err(panel->dev, "failed to enable avdd: %d\n" , err); |
178 | goto disable_dvdd; |
179 | } |
180 | |
181 | gpiod_set_value_cansleep(desc: p->enable_gpio, value: 1); |
182 | |
183 | p->prepared = true; |
184 | |
185 | return 0; |
186 | |
187 | disable_dvdd: |
188 | regulator_disable(regulator: p->dvdd); |
189 | return err; |
190 | } |
191 | |
192 | static int seiko_panel_enable(struct drm_panel *panel) |
193 | { |
194 | struct seiko_panel *p = to_seiko_panel(panel); |
195 | |
196 | if (p->enabled) |
197 | return 0; |
198 | |
199 | p->enabled = true; |
200 | |
201 | return 0; |
202 | } |
203 | |
204 | static int seiko_panel_get_modes(struct drm_panel *panel, |
205 | struct drm_connector *connector) |
206 | { |
207 | struct seiko_panel *p = to_seiko_panel(panel); |
208 | |
209 | /* add hard-coded panel modes */ |
210 | return seiko_panel_get_fixed_modes(panel: p, connector); |
211 | } |
212 | |
213 | static int seiko_panel_get_timings(struct drm_panel *panel, |
214 | unsigned int num_timings, |
215 | struct display_timing *timings) |
216 | { |
217 | struct seiko_panel *p = to_seiko_panel(panel); |
218 | unsigned int i; |
219 | |
220 | if (p->desc->num_timings < num_timings) |
221 | num_timings = p->desc->num_timings; |
222 | |
223 | if (timings) |
224 | for (i = 0; i < num_timings; i++) |
225 | timings[i] = p->desc->timings[i]; |
226 | |
227 | return p->desc->num_timings; |
228 | } |
229 | |
230 | static const struct drm_panel_funcs seiko_panel_funcs = { |
231 | .disable = seiko_panel_disable, |
232 | .unprepare = seiko_panel_unprepare, |
233 | .prepare = seiko_panel_prepare, |
234 | .enable = seiko_panel_enable, |
235 | .get_modes = seiko_panel_get_modes, |
236 | .get_timings = seiko_panel_get_timings, |
237 | }; |
238 | |
239 | static int seiko_panel_probe(struct device *dev, |
240 | const struct seiko_panel_desc *desc) |
241 | { |
242 | struct seiko_panel *panel; |
243 | int err; |
244 | |
245 | panel = devm_kzalloc(dev, size: sizeof(*panel), GFP_KERNEL); |
246 | if (!panel) |
247 | return -ENOMEM; |
248 | |
249 | panel->enabled = false; |
250 | panel->prepared = false; |
251 | panel->desc = desc; |
252 | |
253 | panel->dvdd = devm_regulator_get(dev, id: "dvdd" ); |
254 | if (IS_ERR(ptr: panel->dvdd)) |
255 | return PTR_ERR(ptr: panel->dvdd); |
256 | |
257 | panel->avdd = devm_regulator_get(dev, id: "avdd" ); |
258 | if (IS_ERR(ptr: panel->avdd)) |
259 | return PTR_ERR(ptr: panel->avdd); |
260 | |
261 | panel->enable_gpio = devm_gpiod_get_optional(dev, con_id: "enable" , |
262 | flags: GPIOD_OUT_LOW); |
263 | if (IS_ERR(ptr: panel->enable_gpio)) |
264 | return dev_err_probe(dev, err: PTR_ERR(ptr: panel->enable_gpio), |
265 | fmt: "failed to request GPIO\n" ); |
266 | |
267 | drm_panel_init(panel: &panel->base, dev, funcs: &seiko_panel_funcs, |
268 | DRM_MODE_CONNECTOR_DPI); |
269 | |
270 | err = drm_panel_of_backlight(panel: &panel->base); |
271 | if (err) |
272 | return err; |
273 | |
274 | drm_panel_add(panel: &panel->base); |
275 | |
276 | dev_set_drvdata(dev, data: panel); |
277 | |
278 | return 0; |
279 | } |
280 | |
281 | static void seiko_panel_remove(struct platform_device *pdev) |
282 | { |
283 | struct seiko_panel *panel = platform_get_drvdata(pdev); |
284 | |
285 | drm_panel_remove(panel: &panel->base); |
286 | drm_panel_disable(panel: &panel->base); |
287 | } |
288 | |
289 | static void seiko_panel_shutdown(struct platform_device *pdev) |
290 | { |
291 | struct seiko_panel *panel = platform_get_drvdata(pdev); |
292 | |
293 | drm_panel_disable(panel: &panel->base); |
294 | } |
295 | |
296 | static const struct display_timing seiko_43wvf1g_timing = { |
297 | .pixelclock = { 33500000, 33500000, 33500000 }, |
298 | .hactive = { 800, 800, 800 }, |
299 | .hfront_porch = { 164, 164, 164 }, |
300 | .hback_porch = { 89, 89, 89 }, |
301 | .hsync_len = { 10, 10, 10 }, |
302 | .vactive = { 480, 480, 480 }, |
303 | .vfront_porch = { 10, 10, 10 }, |
304 | .vback_porch = { 23, 23, 23 }, |
305 | .vsync_len = { 10, 10, 10 }, |
306 | .flags = DISPLAY_FLAGS_DE_LOW, |
307 | }; |
308 | |
309 | static const struct seiko_panel_desc seiko_43wvf1g = { |
310 | .timings = &seiko_43wvf1g_timing, |
311 | .num_timings = 1, |
312 | .bpc = 8, |
313 | .size = { |
314 | .width = 93, |
315 | .height = 57, |
316 | }, |
317 | .bus_format = MEDIA_BUS_FMT_RGB888_1X24, |
318 | .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE, |
319 | }; |
320 | |
321 | static const struct of_device_id platform_of_match[] = { |
322 | { |
323 | .compatible = "sii,43wvf1g" , |
324 | .data = &seiko_43wvf1g, |
325 | }, { |
326 | /* sentinel */ |
327 | } |
328 | }; |
329 | MODULE_DEVICE_TABLE(of, platform_of_match); |
330 | |
331 | static int seiko_panel_platform_probe(struct platform_device *pdev) |
332 | { |
333 | const struct of_device_id *id; |
334 | |
335 | id = of_match_node(matches: platform_of_match, node: pdev->dev.of_node); |
336 | if (!id) |
337 | return -ENODEV; |
338 | |
339 | return seiko_panel_probe(dev: &pdev->dev, desc: id->data); |
340 | } |
341 | |
342 | static struct platform_driver seiko_panel_platform_driver = { |
343 | .driver = { |
344 | .name = "seiko_panel" , |
345 | .of_match_table = platform_of_match, |
346 | }, |
347 | .probe = seiko_panel_platform_probe, |
348 | .remove_new = seiko_panel_remove, |
349 | .shutdown = seiko_panel_shutdown, |
350 | }; |
351 | module_platform_driver(seiko_panel_platform_driver); |
352 | |
353 | MODULE_AUTHOR("Marco Franchi <marco.franchi@nxp.com>" ); |
354 | MODULE_DESCRIPTION("Seiko 43WVF1G panel driver" ); |
355 | MODULE_LICENSE("GPL v2" ); |
356 | |