1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Simplest possible simple frame-buffer driver, as a platform device
4 *
5 * Copyright (c) 2013, Stephen Warren
6 *
7 * Based on q40fb.c, which was:
8 * Copyright (C) 2001 Richard Zidlicky <rz@linux-m68k.org>
9 *
10 * Also based on offb.c, which was:
11 * Copyright (C) 1997 Geert Uytterhoeven
12 * Copyright (C) 1996 Paul Mackerras
13 */
14
15 #include <linux/aperture.h>
16 #include <linux/errno.h>
17 #include <linux/fb.h>
18 #include <linux/io.h>
19 #include <linux/module.h>
20 #include <linux/platform_data/simplefb.h>
21 #include <linux/platform_device.h>
22 #include <linux/clk.h>
23 #include <linux/of.h>
24 #include <linux/of_clk.h>
25 #include <linux/of_platform.h>
26 #include <linux/of_reserved_mem.h>
27 #include <linux/parser.h>
28 #include <linux/pm_domain.h>
29 #include <linux/regulator/consumer.h>
30
31 static const struct fb_fix_screeninfo simplefb_fix = {
32 .id = "simple",
33 .type = FB_TYPE_PACKED_PIXELS,
34 .visual = FB_VISUAL_TRUECOLOR,
35 .accel = FB_ACCEL_NONE,
36 };
37
38 static const struct fb_var_screeninfo simplefb_var = {
39 .height = -1,
40 .width = -1,
41 .activate = FB_ACTIVATE_NOW,
42 .vmode = FB_VMODE_NONINTERLACED,
43 };
44
45 #define PSEUDO_PALETTE_SIZE 16
46
simplefb_setcolreg(u_int regno,u_int red,u_int green,u_int blue,u_int transp,struct fb_info * info)47 static int simplefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
48 u_int transp, struct fb_info *info)
49 {
50 u32 *pal = info->pseudo_palette;
51 u32 cr = red >> (16 - info->var.red.length);
52 u32 cg = green >> (16 - info->var.green.length);
53 u32 cb = blue >> (16 - info->var.blue.length);
54 u32 value;
55
56 if (regno >= PSEUDO_PALETTE_SIZE)
57 return -EINVAL;
58
59 value = (cr << info->var.red.offset) |
60 (cg << info->var.green.offset) |
61 (cb << info->var.blue.offset);
62 if (info->var.transp.length > 0) {
63 u32 mask = (1 << info->var.transp.length) - 1;
64 mask <<= info->var.transp.offset;
65 value |= mask;
66 }
67 pal[regno] = value;
68
69 return 0;
70 }
71
72 struct simplefb_par {
73 u32 palette[PSEUDO_PALETTE_SIZE];
74 resource_size_t base;
75 resource_size_t size;
76 struct resource *mem;
77 #if defined CONFIG_OF && defined CONFIG_COMMON_CLK
78 bool clks_enabled;
79 unsigned int clk_count;
80 struct clk **clks;
81 #endif
82 #if defined CONFIG_OF && defined CONFIG_PM_GENERIC_DOMAINS
83 unsigned int num_genpds;
84 struct device **genpds;
85 struct device_link **genpd_links;
86 #endif
87 #if defined CONFIG_OF && defined CONFIG_REGULATOR
88 bool regulators_enabled;
89 u32 regulator_count;
90 struct regulator **regulators;
91 #endif
92 };
93
94 static void simplefb_clocks_destroy(struct simplefb_par *par);
95 static void simplefb_regulators_destroy(struct simplefb_par *par);
96
97 /*
98 * fb_ops.fb_destroy is called by the last put_fb_info() call at the end
99 * of unregister_framebuffer() or fb_release(). Do any cleanup here.
100 */
simplefb_destroy(struct fb_info * info)101 static void simplefb_destroy(struct fb_info *info)
102 {
103 struct simplefb_par *par = info->par;
104 struct resource *mem = par->mem;
105
106 simplefb_regulators_destroy(info->par);
107 simplefb_clocks_destroy(info->par);
108 if (info->screen_base)
109 iounmap(info->screen_base);
110
111 framebuffer_release(info);
112
113 if (mem)
114 release_mem_region(mem->start, resource_size(mem));
115 }
116
117 static const struct fb_ops simplefb_ops = {
118 .owner = THIS_MODULE,
119 FB_DEFAULT_IOMEM_OPS,
120 .fb_destroy = simplefb_destroy,
121 .fb_setcolreg = simplefb_setcolreg,
122 };
123
124 static struct simplefb_format simplefb_formats[] = SIMPLEFB_FORMATS;
125
126 struct simplefb_params {
127 u32 width;
128 u32 height;
129 u32 stride;
130 struct simplefb_format *format;
131 struct resource memory;
132 };
133
simplefb_parse_dt(struct platform_device * pdev,struct simplefb_params * params)134 static int simplefb_parse_dt(struct platform_device *pdev,
135 struct simplefb_params *params)
136 {
137 struct device_node *np = pdev->dev.of_node;
138 int ret;
139 const char *format;
140 int i;
141
142 ret = of_property_read_u32(np, "width", ¶ms->width);
143 if (ret) {
144 dev_err(&pdev->dev, "Can't parse width property\n");
145 return ret;
146 }
147
148 ret = of_property_read_u32(np, "height", ¶ms->height);
149 if (ret) {
150 dev_err(&pdev->dev, "Can't parse height property\n");
151 return ret;
152 }
153
154 ret = of_property_read_u32(np, "stride", ¶ms->stride);
155 if (ret) {
156 dev_err(&pdev->dev, "Can't parse stride property\n");
157 return ret;
158 }
159
160 ret = of_property_read_string(np, "format", &format);
161 if (ret) {
162 dev_err(&pdev->dev, "Can't parse format property\n");
163 return ret;
164 }
165 params->format = NULL;
166 for (i = 0; i < ARRAY_SIZE(simplefb_formats); i++) {
167 if (strcmp(format, simplefb_formats[i].name))
168 continue;
169 params->format = &simplefb_formats[i];
170 break;
171 }
172 if (!params->format) {
173 dev_err(&pdev->dev, "Invalid format value\n");
174 return -EINVAL;
175 }
176
177 ret = of_reserved_mem_region_to_resource(np, 0, ¶ms->memory);
178 if (!ret) {
179 if (of_property_present(np, "reg"))
180 dev_warn(&pdev->dev, "preferring \"memory-region\" over \"reg\" property\n");
181 } else {
182 memset(¶ms->memory, 0, sizeof(params->memory));
183 }
184
185 return 0;
186 }
187
simplefb_parse_pd(struct platform_device * pdev,struct simplefb_params * params)188 static int simplefb_parse_pd(struct platform_device *pdev,
189 struct simplefb_params *params)
190 {
191 struct simplefb_platform_data *pd = dev_get_platdata(&pdev->dev);
192 int i;
193
194 params->width = pd->width;
195 params->height = pd->height;
196 params->stride = pd->stride;
197
198 params->format = NULL;
199 for (i = 0; i < ARRAY_SIZE(simplefb_formats); i++) {
200 if (strcmp(pd->format, simplefb_formats[i].name))
201 continue;
202
203 params->format = &simplefb_formats[i];
204 break;
205 }
206
207 if (!params->format) {
208 dev_err(&pdev->dev, "Invalid format value\n");
209 return -EINVAL;
210 }
211
212 memset(¶ms->memory, 0, sizeof(params->memory));
213
214 return 0;
215 }
216
217 #if defined CONFIG_OF && defined CONFIG_COMMON_CLK
218 /*
219 * Clock handling code.
220 *
221 * Here we handle the clocks property of our "simple-framebuffer" dt node.
222 * This is necessary so that we can make sure that any clocks needed by
223 * the display engine that the bootloader set up for us (and for which it
224 * provided a simplefb dt node), stay up, for the life of the simplefb
225 * driver.
226 *
227 * When the driver unloads, we cleanly disable, and then release the clocks.
228 *
229 * We only complain about errors here, no action is taken as the most likely
230 * error can only happen due to a mismatch between the bootloader which set
231 * up simplefb, and the clock definitions in the device tree. Chances are
232 * that there are no adverse effects, and if there are, a clean teardown of
233 * the fb probe will not help us much either. So just complain and carry on,
234 * and hope that the user actually gets a working fb at the end of things.
235 */
simplefb_clocks_get(struct simplefb_par * par,struct platform_device * pdev)236 static int simplefb_clocks_get(struct simplefb_par *par,
237 struct platform_device *pdev)
238 {
239 struct device_node *np = pdev->dev.of_node;
240 struct clk *clock;
241 int i;
242
243 if (dev_get_platdata(&pdev->dev) || !np)
244 return 0;
245
246 par->clk_count = of_clk_get_parent_count(np);
247 if (!par->clk_count)
248 return 0;
249
250 par->clks = kcalloc(par->clk_count, sizeof(struct clk *), GFP_KERNEL);
251 if (!par->clks)
252 return -ENOMEM;
253
254 for (i = 0; i < par->clk_count; i++) {
255 clock = of_clk_get(np, i);
256 if (IS_ERR(clock)) {
257 if (PTR_ERR(clock) == -EPROBE_DEFER) {
258 while (--i >= 0) {
259 clk_put(par->clks[i]);
260 }
261 kfree(par->clks);
262 return -EPROBE_DEFER;
263 }
264 dev_err(&pdev->dev, "%s: clock %d not found: %ld\n",
265 __func__, i, PTR_ERR(clock));
266 continue;
267 }
268 par->clks[i] = clock;
269 }
270
271 return 0;
272 }
273
simplefb_clocks_enable(struct simplefb_par * par,struct platform_device * pdev)274 static void simplefb_clocks_enable(struct simplefb_par *par,
275 struct platform_device *pdev)
276 {
277 int i, ret;
278
279 for (i = 0; i < par->clk_count; i++) {
280 if (par->clks[i]) {
281 ret = clk_prepare_enable(par->clks[i]);
282 if (ret) {
283 dev_err(&pdev->dev,
284 "%s: failed to enable clock %d: %d\n",
285 __func__, i, ret);
286 clk_put(par->clks[i]);
287 par->clks[i] = NULL;
288 }
289 }
290 }
291 par->clks_enabled = true;
292 }
293
simplefb_clocks_destroy(struct simplefb_par * par)294 static void simplefb_clocks_destroy(struct simplefb_par *par)
295 {
296 int i;
297
298 if (!par->clks)
299 return;
300
301 for (i = 0; i < par->clk_count; i++) {
302 if (par->clks[i]) {
303 if (par->clks_enabled)
304 clk_disable_unprepare(par->clks[i]);
305 clk_put(par->clks[i]);
306 }
307 }
308
309 kfree(par->clks);
310 }
311 #else
simplefb_clocks_get(struct simplefb_par * par,struct platform_device * pdev)312 static int simplefb_clocks_get(struct simplefb_par *par,
313 struct platform_device *pdev) { return 0; }
simplefb_clocks_enable(struct simplefb_par * par,struct platform_device * pdev)314 static void simplefb_clocks_enable(struct simplefb_par *par,
315 struct platform_device *pdev) { }
simplefb_clocks_destroy(struct simplefb_par * par)316 static void simplefb_clocks_destroy(struct simplefb_par *par) { }
317 #endif
318
319 #if defined CONFIG_OF && defined CONFIG_REGULATOR
320
321 #define SUPPLY_SUFFIX "-supply"
322
323 /*
324 * Regulator handling code.
325 *
326 * Here we handle the num-supplies and vin*-supply properties of our
327 * "simple-framebuffer" dt node. This is necessary so that we can make sure
328 * that any regulators needed by the display hardware that the bootloader
329 * set up for us (and for which it provided a simplefb dt node), stay up,
330 * for the life of the simplefb driver.
331 *
332 * When the driver unloads, we cleanly disable, and then release the
333 * regulators.
334 *
335 * We only complain about errors here, no action is taken as the most likely
336 * error can only happen due to a mismatch between the bootloader which set
337 * up simplefb, and the regulator definitions in the device tree. Chances are
338 * that there are no adverse effects, and if there are, a clean teardown of
339 * the fb probe will not help us much either. So just complain and carry on,
340 * and hope that the user actually gets a working fb at the end of things.
341 */
simplefb_regulators_get(struct simplefb_par * par,struct platform_device * pdev)342 static int simplefb_regulators_get(struct simplefb_par *par,
343 struct platform_device *pdev)
344 {
345 struct device_node *np = pdev->dev.of_node;
346 struct property *prop;
347 struct regulator *regulator;
348 const char *p;
349 int count = 0, i = 0;
350
351 if (dev_get_platdata(&pdev->dev) || !np)
352 return 0;
353
354 /* Count the number of regulator supplies */
355 for_each_property_of_node(np, prop) {
356 p = strstr(prop->name, SUPPLY_SUFFIX);
357 if (p && p != prop->name)
358 count++;
359 }
360
361 if (!count)
362 return 0;
363
364 par->regulators = devm_kcalloc(&pdev->dev, count,
365 sizeof(struct regulator *), GFP_KERNEL);
366 if (!par->regulators)
367 return -ENOMEM;
368
369 /* Get all the regulators */
370 for_each_property_of_node(np, prop) {
371 char name[32]; /* 32 is max size of property name */
372
373 p = strstr(prop->name, SUPPLY_SUFFIX);
374 if (!p || p == prop->name)
375 continue;
376
377 strscpy(name, prop->name,
378 strlen(prop->name) - strlen(SUPPLY_SUFFIX) + 1);
379 regulator = devm_regulator_get_optional(&pdev->dev, name);
380 if (IS_ERR(regulator)) {
381 if (PTR_ERR(regulator) == -EPROBE_DEFER)
382 return -EPROBE_DEFER;
383 dev_err(&pdev->dev, "regulator %s not found: %ld\n",
384 name, PTR_ERR(regulator));
385 continue;
386 }
387 par->regulators[i++] = regulator;
388 }
389 par->regulator_count = i;
390
391 return 0;
392 }
393
simplefb_regulators_enable(struct simplefb_par * par,struct platform_device * pdev)394 static void simplefb_regulators_enable(struct simplefb_par *par,
395 struct platform_device *pdev)
396 {
397 int i, ret;
398
399 /* Enable all the regulators */
400 for (i = 0; i < par->regulator_count; i++) {
401 ret = regulator_enable(par->regulators[i]);
402 if (ret) {
403 dev_err(&pdev->dev,
404 "failed to enable regulator %d: %d\n",
405 i, ret);
406 devm_regulator_put(par->regulators[i]);
407 par->regulators[i] = NULL;
408 }
409 }
410 par->regulators_enabled = true;
411 }
412
simplefb_regulators_destroy(struct simplefb_par * par)413 static void simplefb_regulators_destroy(struct simplefb_par *par)
414 {
415 int i;
416
417 if (!par->regulators || !par->regulators_enabled)
418 return;
419
420 for (i = 0; i < par->regulator_count; i++)
421 if (par->regulators[i])
422 regulator_disable(par->regulators[i]);
423 }
424 #else
simplefb_regulators_get(struct simplefb_par * par,struct platform_device * pdev)425 static int simplefb_regulators_get(struct simplefb_par *par,
426 struct platform_device *pdev) { return 0; }
simplefb_regulators_enable(struct simplefb_par * par,struct platform_device * pdev)427 static void simplefb_regulators_enable(struct simplefb_par *par,
428 struct platform_device *pdev) { }
simplefb_regulators_destroy(struct simplefb_par * par)429 static void simplefb_regulators_destroy(struct simplefb_par *par) { }
430 #endif
431
432 #if defined CONFIG_OF && defined CONFIG_PM_GENERIC_DOMAINS
simplefb_detach_genpds(void * res)433 static void simplefb_detach_genpds(void *res)
434 {
435 struct simplefb_par *par = res;
436 unsigned int i = par->num_genpds;
437
438 if (par->num_genpds <= 1)
439 return;
440
441 while (i--) {
442 if (par->genpd_links[i])
443 device_link_del(par->genpd_links[i]);
444
445 if (!IS_ERR_OR_NULL(par->genpds[i]))
446 dev_pm_domain_detach(par->genpds[i], true);
447 }
448 }
449
simplefb_attach_genpds(struct simplefb_par * par,struct platform_device * pdev)450 static int simplefb_attach_genpds(struct simplefb_par *par,
451 struct platform_device *pdev)
452 {
453 struct device *dev = &pdev->dev;
454 unsigned int i;
455 int err;
456
457 err = of_count_phandle_with_args(dev->of_node, "power-domains",
458 "#power-domain-cells");
459 if (err < 0) {
460 /* Nothing wrong if optional PDs are missing */
461 if (err == -ENOENT)
462 return 0;
463
464 dev_err(dev, "failed to parse power-domains: %d\n", err);
465 return err;
466 }
467
468 par->num_genpds = err;
469
470 /*
471 * Single power-domain devices are handled by the driver core, so
472 * nothing to do here.
473 */
474 if (par->num_genpds <= 1)
475 return 0;
476
477 par->genpds = devm_kcalloc(dev, par->num_genpds, sizeof(*par->genpds),
478 GFP_KERNEL);
479 if (!par->genpds)
480 return -ENOMEM;
481
482 par->genpd_links = devm_kcalloc(dev, par->num_genpds,
483 sizeof(*par->genpd_links),
484 GFP_KERNEL);
485 if (!par->genpd_links)
486 return -ENOMEM;
487
488 for (i = 0; i < par->num_genpds; i++) {
489 par->genpds[i] = dev_pm_domain_attach_by_id(dev, i);
490 if (IS_ERR(par->genpds[i])) {
491 err = PTR_ERR(par->genpds[i]);
492 if (err == -EPROBE_DEFER) {
493 simplefb_detach_genpds(par);
494 return err;
495 }
496
497 dev_warn(dev, "failed to attach domain %u: %d\n", i, err);
498 continue;
499 }
500
501 par->genpd_links[i] = device_link_add(dev, par->genpds[i],
502 DL_FLAG_STATELESS |
503 DL_FLAG_PM_RUNTIME |
504 DL_FLAG_RPM_ACTIVE);
505 if (!par->genpd_links[i])
506 dev_warn(dev, "failed to link power-domain %u\n", i);
507 }
508
509 return devm_add_action_or_reset(dev, simplefb_detach_genpds, par);
510 }
511 #else
simplefb_attach_genpds(struct simplefb_par * par,struct platform_device * pdev)512 static int simplefb_attach_genpds(struct simplefb_par *par,
513 struct platform_device *pdev)
514 {
515 return 0;
516 }
517 #endif
518
simplefb_probe(struct platform_device * pdev)519 static int simplefb_probe(struct platform_device *pdev)
520 {
521 int ret;
522 struct simplefb_params params;
523 struct fb_info *info;
524 struct simplefb_par *par;
525 struct resource *res, *mem;
526
527 if (fb_get_options("simplefb", NULL))
528 return -ENODEV;
529
530 ret = -ENODEV;
531 if (dev_get_platdata(&pdev->dev))
532 ret = simplefb_parse_pd(pdev, ¶ms);
533 else if (pdev->dev.of_node)
534 ret = simplefb_parse_dt(pdev, ¶ms);
535
536 if (ret)
537 return ret;
538
539 if (params.memory.start == 0 && params.memory.end == 0) {
540 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
541 if (!res) {
542 dev_err(&pdev->dev, "No memory resource\n");
543 return -EINVAL;
544 }
545 } else {
546 res = ¶ms.memory;
547 }
548
549 mem = request_mem_region(res->start, resource_size(res), "simplefb");
550 if (!mem) {
551 /*
552 * We cannot make this fatal. Sometimes this comes from magic
553 * spaces our resource handlers simply don't know about. Use
554 * the I/O-memory resource as-is and try to map that instead.
555 */
556 dev_warn(&pdev->dev, "simplefb: cannot reserve video memory at %pR\n", res);
557 mem = res;
558 }
559
560 info = framebuffer_alloc(sizeof(struct simplefb_par), &pdev->dev);
561 if (!info) {
562 ret = -ENOMEM;
563 goto error_release_mem_region;
564 }
565 platform_set_drvdata(pdev, info);
566
567 par = info->par;
568
569 info->fix = simplefb_fix;
570 info->fix.smem_start = mem->start;
571 info->fix.smem_len = resource_size(mem);
572 info->fix.line_length = params.stride;
573
574 info->var = simplefb_var;
575 info->var.xres = params.width;
576 info->var.yres = params.height;
577 info->var.xres_virtual = params.width;
578 info->var.yres_virtual = params.height;
579 info->var.bits_per_pixel = params.format->bits_per_pixel;
580 info->var.red = params.format->red;
581 info->var.green = params.format->green;
582 info->var.blue = params.format->blue;
583 info->var.transp = params.format->transp;
584
585 par->base = info->fix.smem_start;
586 par->size = info->fix.smem_len;
587
588 info->fbops = &simplefb_ops;
589 info->screen_base = ioremap_wc(info->fix.smem_start,
590 info->fix.smem_len);
591 if (!info->screen_base) {
592 ret = -ENOMEM;
593 goto error_fb_release;
594 }
595 info->pseudo_palette = par->palette;
596
597 ret = simplefb_clocks_get(par, pdev);
598 if (ret < 0)
599 goto error_unmap;
600
601 ret = simplefb_regulators_get(par, pdev);
602 if (ret < 0)
603 goto error_clocks;
604
605 ret = simplefb_attach_genpds(par, pdev);
606 if (ret < 0)
607 goto error_regulators;
608
609 simplefb_clocks_enable(par, pdev);
610 simplefb_regulators_enable(par, pdev);
611
612 dev_info(&pdev->dev, "framebuffer at 0x%lx, 0x%x bytes\n",
613 info->fix.smem_start, info->fix.smem_len);
614 dev_info(&pdev->dev, "format=%s, mode=%dx%dx%d, linelength=%d\n",
615 params.format->name,
616 info->var.xres, info->var.yres,
617 info->var.bits_per_pixel, info->fix.line_length);
618
619 if (mem != res)
620 par->mem = mem; /* release in clean-up handler */
621
622 ret = devm_aperture_acquire_for_platform_device(pdev, par->base, par->size);
623 if (ret) {
624 dev_err(&pdev->dev, "Unable to acquire aperture: %d\n", ret);
625 goto error_regulators;
626 }
627 ret = register_framebuffer(info);
628 if (ret < 0) {
629 dev_err(&pdev->dev, "Unable to register simplefb: %d\n", ret);
630 goto error_regulators;
631 }
632
633 dev_info(&pdev->dev, "fb%d: simplefb registered!\n", info->node);
634
635 return 0;
636
637 error_regulators:
638 simplefb_regulators_destroy(par);
639 error_clocks:
640 simplefb_clocks_destroy(par);
641 error_unmap:
642 iounmap(info->screen_base);
643 error_fb_release:
644 framebuffer_release(info);
645 error_release_mem_region:
646 if (mem != res)
647 release_mem_region(mem->start, resource_size(mem));
648 return ret;
649 }
650
simplefb_remove(struct platform_device * pdev)651 static void simplefb_remove(struct platform_device *pdev)
652 {
653 struct fb_info *info = platform_get_drvdata(pdev);
654
655 /* simplefb_destroy takes care of info cleanup */
656 unregister_framebuffer(info);
657 }
658
659 static const struct of_device_id simplefb_of_match[] = {
660 { .compatible = "simple-framebuffer", },
661 { },
662 };
663 MODULE_DEVICE_TABLE(of, simplefb_of_match);
664
665 static struct platform_driver simplefb_driver = {
666 .driver = {
667 .name = "simple-framebuffer",
668 .of_match_table = simplefb_of_match,
669 },
670 .probe = simplefb_probe,
671 .remove = simplefb_remove,
672 };
673
674 module_platform_driver(simplefb_driver);
675
676 MODULE_AUTHOR("Stephen Warren <swarren@wwwdotorg.org>");
677 MODULE_DESCRIPTION("Simple framebuffer driver");
678 MODULE_LICENSE("GPL v2");
679