root/drivers/video/fbdev/simplefb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. simplefb_setcolreg
  2. simplefb_destroy
  3. simplefb_parse_dt
  4. simplefb_parse_pd
  5. simplefb_clocks_get
  6. simplefb_clocks_enable
  7. simplefb_clocks_destroy
  8. simplefb_clocks_get
  9. simplefb_clocks_enable
  10. simplefb_clocks_destroy
  11. simplefb_regulators_get
  12. simplefb_regulators_enable
  13. simplefb_regulators_destroy
  14. simplefb_regulators_get
  15. simplefb_regulators_enable
  16. simplefb_regulators_destroy
  17. simplefb_probe
  18. simplefb_remove
  19. simplefb_init

   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/errno.h>
  16 #include <linux/fb.h>
  17 #include <linux/io.h>
  18 #include <linux/module.h>
  19 #include <linux/platform_data/simplefb.h>
  20 #include <linux/platform_device.h>
  21 #include <linux/clk.h>
  22 #include <linux/of.h>
  23 #include <linux/of_clk.h>
  24 #include <linux/of_platform.h>
  25 #include <linux/parser.h>
  26 #include <linux/regulator/consumer.h>
  27 
  28 static const struct fb_fix_screeninfo simplefb_fix = {
  29         .id             = "simple",
  30         .type           = FB_TYPE_PACKED_PIXELS,
  31         .visual         = FB_VISUAL_TRUECOLOR,
  32         .accel          = FB_ACCEL_NONE,
  33 };
  34 
  35 static const struct fb_var_screeninfo simplefb_var = {
  36         .height         = -1,
  37         .width          = -1,
  38         .activate       = FB_ACTIVATE_NOW,
  39         .vmode          = FB_VMODE_NONINTERLACED,
  40 };
  41 
  42 #define PSEUDO_PALETTE_SIZE 16
  43 
  44 static int simplefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  45                               u_int transp, struct fb_info *info)
  46 {
  47         u32 *pal = info->pseudo_palette;
  48         u32 cr = red >> (16 - info->var.red.length);
  49         u32 cg = green >> (16 - info->var.green.length);
  50         u32 cb = blue >> (16 - info->var.blue.length);
  51         u32 value;
  52 
  53         if (regno >= PSEUDO_PALETTE_SIZE)
  54                 return -EINVAL;
  55 
  56         value = (cr << info->var.red.offset) |
  57                 (cg << info->var.green.offset) |
  58                 (cb << info->var.blue.offset);
  59         if (info->var.transp.length > 0) {
  60                 u32 mask = (1 << info->var.transp.length) - 1;
  61                 mask <<= info->var.transp.offset;
  62                 value |= mask;
  63         }
  64         pal[regno] = value;
  65 
  66         return 0;
  67 }
  68 
  69 struct simplefb_par;
  70 static void simplefb_clocks_destroy(struct simplefb_par *par);
  71 static void simplefb_regulators_destroy(struct simplefb_par *par);
  72 
  73 static void simplefb_destroy(struct fb_info *info)
  74 {
  75         simplefb_regulators_destroy(info->par);
  76         simplefb_clocks_destroy(info->par);
  77         if (info->screen_base)
  78                 iounmap(info->screen_base);
  79 }
  80 
  81 static struct fb_ops simplefb_ops = {
  82         .owner          = THIS_MODULE,
  83         .fb_destroy     = simplefb_destroy,
  84         .fb_setcolreg   = simplefb_setcolreg,
  85         .fb_fillrect    = cfb_fillrect,
  86         .fb_copyarea    = cfb_copyarea,
  87         .fb_imageblit   = cfb_imageblit,
  88 };
  89 
  90 static struct simplefb_format simplefb_formats[] = SIMPLEFB_FORMATS;
  91 
  92 struct simplefb_params {
  93         u32 width;
  94         u32 height;
  95         u32 stride;
  96         struct simplefb_format *format;
  97 };
  98 
  99 static int simplefb_parse_dt(struct platform_device *pdev,
 100                            struct simplefb_params *params)
 101 {
 102         struct device_node *np = pdev->dev.of_node;
 103         int ret;
 104         const char *format;
 105         int i;
 106 
 107         ret = of_property_read_u32(np, "width", &params->width);
 108         if (ret) {
 109                 dev_err(&pdev->dev, "Can't parse width property\n");
 110                 return ret;
 111         }
 112 
 113         ret = of_property_read_u32(np, "height", &params->height);
 114         if (ret) {
 115                 dev_err(&pdev->dev, "Can't parse height property\n");
 116                 return ret;
 117         }
 118 
 119         ret = of_property_read_u32(np, "stride", &params->stride);
 120         if (ret) {
 121                 dev_err(&pdev->dev, "Can't parse stride property\n");
 122                 return ret;
 123         }
 124 
 125         ret = of_property_read_string(np, "format", &format);
 126         if (ret) {
 127                 dev_err(&pdev->dev, "Can't parse format property\n");
 128                 return ret;
 129         }
 130         params->format = NULL;
 131         for (i = 0; i < ARRAY_SIZE(simplefb_formats); i++) {
 132                 if (strcmp(format, simplefb_formats[i].name))
 133                         continue;
 134                 params->format = &simplefb_formats[i];
 135                 break;
 136         }
 137         if (!params->format) {
 138                 dev_err(&pdev->dev, "Invalid format value\n");
 139                 return -EINVAL;
 140         }
 141 
 142         return 0;
 143 }
 144 
 145 static int simplefb_parse_pd(struct platform_device *pdev,
 146                              struct simplefb_params *params)
 147 {
 148         struct simplefb_platform_data *pd = dev_get_platdata(&pdev->dev);
 149         int i;
 150 
 151         params->width = pd->width;
 152         params->height = pd->height;
 153         params->stride = pd->stride;
 154 
 155         params->format = NULL;
 156         for (i = 0; i < ARRAY_SIZE(simplefb_formats); i++) {
 157                 if (strcmp(pd->format, simplefb_formats[i].name))
 158                         continue;
 159 
 160                 params->format = &simplefb_formats[i];
 161                 break;
 162         }
 163 
 164         if (!params->format) {
 165                 dev_err(&pdev->dev, "Invalid format value\n");
 166                 return -EINVAL;
 167         }
 168 
 169         return 0;
 170 }
 171 
 172 struct simplefb_par {
 173         u32 palette[PSEUDO_PALETTE_SIZE];
 174 #if defined CONFIG_OF && defined CONFIG_COMMON_CLK
 175         bool clks_enabled;
 176         unsigned int clk_count;
 177         struct clk **clks;
 178 #endif
 179 #if defined CONFIG_OF && defined CONFIG_REGULATOR
 180         bool regulators_enabled;
 181         u32 regulator_count;
 182         struct regulator **regulators;
 183 #endif
 184 };
 185 
 186 #if defined CONFIG_OF && defined CONFIG_COMMON_CLK
 187 /*
 188  * Clock handling code.
 189  *
 190  * Here we handle the clocks property of our "simple-framebuffer" dt node.
 191  * This is necessary so that we can make sure that any clocks needed by
 192  * the display engine that the bootloader set up for us (and for which it
 193  * provided a simplefb dt node), stay up, for the life of the simplefb
 194  * driver.
 195  *
 196  * When the driver unloads, we cleanly disable, and then release the clocks.
 197  *
 198  * We only complain about errors here, no action is taken as the most likely
 199  * error can only happen due to a mismatch between the bootloader which set
 200  * up simplefb, and the clock definitions in the device tree. Chances are
 201  * that there are no adverse effects, and if there are, a clean teardown of
 202  * the fb probe will not help us much either. So just complain and carry on,
 203  * and hope that the user actually gets a working fb at the end of things.
 204  */
 205 static int simplefb_clocks_get(struct simplefb_par *par,
 206                                struct platform_device *pdev)
 207 {
 208         struct device_node *np = pdev->dev.of_node;
 209         struct clk *clock;
 210         int i;
 211 
 212         if (dev_get_platdata(&pdev->dev) || !np)
 213                 return 0;
 214 
 215         par->clk_count = of_clk_get_parent_count(np);
 216         if (!par->clk_count)
 217                 return 0;
 218 
 219         par->clks = kcalloc(par->clk_count, sizeof(struct clk *), GFP_KERNEL);
 220         if (!par->clks)
 221                 return -ENOMEM;
 222 
 223         for (i = 0; i < par->clk_count; i++) {
 224                 clock = of_clk_get(np, i);
 225                 if (IS_ERR(clock)) {
 226                         if (PTR_ERR(clock) == -EPROBE_DEFER) {
 227                                 while (--i >= 0) {
 228                                         if (par->clks[i])
 229                                                 clk_put(par->clks[i]);
 230                                 }
 231                                 kfree(par->clks);
 232                                 return -EPROBE_DEFER;
 233                         }
 234                         dev_err(&pdev->dev, "%s: clock %d not found: %ld\n",
 235                                 __func__, i, PTR_ERR(clock));
 236                         continue;
 237                 }
 238                 par->clks[i] = clock;
 239         }
 240 
 241         return 0;
 242 }
 243 
 244 static void simplefb_clocks_enable(struct simplefb_par *par,
 245                                    struct platform_device *pdev)
 246 {
 247         int i, ret;
 248 
 249         for (i = 0; i < par->clk_count; i++) {
 250                 if (par->clks[i]) {
 251                         ret = clk_prepare_enable(par->clks[i]);
 252                         if (ret) {
 253                                 dev_err(&pdev->dev,
 254                                         "%s: failed to enable clock %d: %d\n",
 255                                         __func__, i, ret);
 256                                 clk_put(par->clks[i]);
 257                                 par->clks[i] = NULL;
 258                         }
 259                 }
 260         }
 261         par->clks_enabled = true;
 262 }
 263 
 264 static void simplefb_clocks_destroy(struct simplefb_par *par)
 265 {
 266         int i;
 267 
 268         if (!par->clks)
 269                 return;
 270 
 271         for (i = 0; i < par->clk_count; i++) {
 272                 if (par->clks[i]) {
 273                         if (par->clks_enabled)
 274                                 clk_disable_unprepare(par->clks[i]);
 275                         clk_put(par->clks[i]);
 276                 }
 277         }
 278 
 279         kfree(par->clks);
 280 }
 281 #else
 282 static int simplefb_clocks_get(struct simplefb_par *par,
 283         struct platform_device *pdev) { return 0; }
 284 static void simplefb_clocks_enable(struct simplefb_par *par,
 285         struct platform_device *pdev) { }
 286 static void simplefb_clocks_destroy(struct simplefb_par *par) { }
 287 #endif
 288 
 289 #if defined CONFIG_OF && defined CONFIG_REGULATOR
 290 
 291 #define SUPPLY_SUFFIX "-supply"
 292 
 293 /*
 294  * Regulator handling code.
 295  *
 296  * Here we handle the num-supplies and vin*-supply properties of our
 297  * "simple-framebuffer" dt node. This is necessary so that we can make sure
 298  * that any regulators needed by the display hardware that the bootloader
 299  * set up for us (and for which it provided a simplefb dt node), stay up,
 300  * for the life of the simplefb driver.
 301  *
 302  * When the driver unloads, we cleanly disable, and then release the
 303  * regulators.
 304  *
 305  * We only complain about errors here, no action is taken as the most likely
 306  * error can only happen due to a mismatch between the bootloader which set
 307  * up simplefb, and the regulator definitions in the device tree. Chances are
 308  * that there are no adverse effects, and if there are, a clean teardown of
 309  * the fb probe will not help us much either. So just complain and carry on,
 310  * and hope that the user actually gets a working fb at the end of things.
 311  */
 312 static int simplefb_regulators_get(struct simplefb_par *par,
 313                                    struct platform_device *pdev)
 314 {
 315         struct device_node *np = pdev->dev.of_node;
 316         struct property *prop;
 317         struct regulator *regulator;
 318         const char *p;
 319         int count = 0, i = 0;
 320 
 321         if (dev_get_platdata(&pdev->dev) || !np)
 322                 return 0;
 323 
 324         /* Count the number of regulator supplies */
 325         for_each_property_of_node(np, prop) {
 326                 p = strstr(prop->name, SUPPLY_SUFFIX);
 327                 if (p && p != prop->name)
 328                         count++;
 329         }
 330 
 331         if (!count)
 332                 return 0;
 333 
 334         par->regulators = devm_kcalloc(&pdev->dev, count,
 335                                        sizeof(struct regulator *), GFP_KERNEL);
 336         if (!par->regulators)
 337                 return -ENOMEM;
 338 
 339         /* Get all the regulators */
 340         for_each_property_of_node(np, prop) {
 341                 char name[32]; /* 32 is max size of property name */
 342 
 343                 p = strstr(prop->name, SUPPLY_SUFFIX);
 344                 if (!p || p == prop->name)
 345                         continue;
 346 
 347                 strlcpy(name, prop->name,
 348                         strlen(prop->name) - strlen(SUPPLY_SUFFIX) + 1);
 349                 regulator = devm_regulator_get_optional(&pdev->dev, name);
 350                 if (IS_ERR(regulator)) {
 351                         if (PTR_ERR(regulator) == -EPROBE_DEFER)
 352                                 return -EPROBE_DEFER;
 353                         dev_err(&pdev->dev, "regulator %s not found: %ld\n",
 354                                 name, PTR_ERR(regulator));
 355                         continue;
 356                 }
 357                 par->regulators[i++] = regulator;
 358         }
 359         par->regulator_count = i;
 360 
 361         return 0;
 362 }
 363 
 364 static void simplefb_regulators_enable(struct simplefb_par *par,
 365                                        struct platform_device *pdev)
 366 {
 367         int i, ret;
 368 
 369         /* Enable all the regulators */
 370         for (i = 0; i < par->regulator_count; i++) {
 371                 ret = regulator_enable(par->regulators[i]);
 372                 if (ret) {
 373                         dev_err(&pdev->dev,
 374                                 "failed to enable regulator %d: %d\n",
 375                                 i, ret);
 376                         devm_regulator_put(par->regulators[i]);
 377                         par->regulators[i] = NULL;
 378                 }
 379         }
 380         par->regulators_enabled = true;
 381 }
 382 
 383 static void simplefb_regulators_destroy(struct simplefb_par *par)
 384 {
 385         int i;
 386 
 387         if (!par->regulators || !par->regulators_enabled)
 388                 return;
 389 
 390         for (i = 0; i < par->regulator_count; i++)
 391                 if (par->regulators[i])
 392                         regulator_disable(par->regulators[i]);
 393 }
 394 #else
 395 static int simplefb_regulators_get(struct simplefb_par *par,
 396         struct platform_device *pdev) { return 0; }
 397 static void simplefb_regulators_enable(struct simplefb_par *par,
 398         struct platform_device *pdev) { }
 399 static void simplefb_regulators_destroy(struct simplefb_par *par) { }
 400 #endif
 401 
 402 static int simplefb_probe(struct platform_device *pdev)
 403 {
 404         int ret;
 405         struct simplefb_params params;
 406         struct fb_info *info;
 407         struct simplefb_par *par;
 408         struct resource *mem;
 409 
 410         if (fb_get_options("simplefb", NULL))
 411                 return -ENODEV;
 412 
 413         ret = -ENODEV;
 414         if (dev_get_platdata(&pdev->dev))
 415                 ret = simplefb_parse_pd(pdev, &params);
 416         else if (pdev->dev.of_node)
 417                 ret = simplefb_parse_dt(pdev, &params);
 418 
 419         if (ret)
 420                 return ret;
 421 
 422         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 423         if (!mem) {
 424                 dev_err(&pdev->dev, "No memory resource\n");
 425                 return -EINVAL;
 426         }
 427 
 428         info = framebuffer_alloc(sizeof(struct simplefb_par), &pdev->dev);
 429         if (!info)
 430                 return -ENOMEM;
 431         platform_set_drvdata(pdev, info);
 432 
 433         par = info->par;
 434 
 435         info->fix = simplefb_fix;
 436         info->fix.smem_start = mem->start;
 437         info->fix.smem_len = resource_size(mem);
 438         info->fix.line_length = params.stride;
 439 
 440         info->var = simplefb_var;
 441         info->var.xres = params.width;
 442         info->var.yres = params.height;
 443         info->var.xres_virtual = params.width;
 444         info->var.yres_virtual = params.height;
 445         info->var.bits_per_pixel = params.format->bits_per_pixel;
 446         info->var.red = params.format->red;
 447         info->var.green = params.format->green;
 448         info->var.blue = params.format->blue;
 449         info->var.transp = params.format->transp;
 450 
 451         info->apertures = alloc_apertures(1);
 452         if (!info->apertures) {
 453                 ret = -ENOMEM;
 454                 goto error_fb_release;
 455         }
 456         info->apertures->ranges[0].base = info->fix.smem_start;
 457         info->apertures->ranges[0].size = info->fix.smem_len;
 458 
 459         info->fbops = &simplefb_ops;
 460         info->flags = FBINFO_DEFAULT | FBINFO_MISC_FIRMWARE;
 461         info->screen_base = ioremap_wc(info->fix.smem_start,
 462                                        info->fix.smem_len);
 463         if (!info->screen_base) {
 464                 ret = -ENOMEM;
 465                 goto error_fb_release;
 466         }
 467         info->pseudo_palette = par->palette;
 468 
 469         ret = simplefb_clocks_get(par, pdev);
 470         if (ret < 0)
 471                 goto error_unmap;
 472 
 473         ret = simplefb_regulators_get(par, pdev);
 474         if (ret < 0)
 475                 goto error_clocks;
 476 
 477         simplefb_clocks_enable(par, pdev);
 478         simplefb_regulators_enable(par, pdev);
 479 
 480         dev_info(&pdev->dev, "framebuffer at 0x%lx, 0x%x bytes, mapped to 0x%p\n",
 481                              info->fix.smem_start, info->fix.smem_len,
 482                              info->screen_base);
 483         dev_info(&pdev->dev, "format=%s, mode=%dx%dx%d, linelength=%d\n",
 484                              params.format->name,
 485                              info->var.xres, info->var.yres,
 486                              info->var.bits_per_pixel, info->fix.line_length);
 487 
 488         ret = register_framebuffer(info);
 489         if (ret < 0) {
 490                 dev_err(&pdev->dev, "Unable to register simplefb: %d\n", ret);
 491                 goto error_regulators;
 492         }
 493 
 494         dev_info(&pdev->dev, "fb%d: simplefb registered!\n", info->node);
 495 
 496         return 0;
 497 
 498 error_regulators:
 499         simplefb_regulators_destroy(par);
 500 error_clocks:
 501         simplefb_clocks_destroy(par);
 502 error_unmap:
 503         iounmap(info->screen_base);
 504 error_fb_release:
 505         framebuffer_release(info);
 506         return ret;
 507 }
 508 
 509 static int simplefb_remove(struct platform_device *pdev)
 510 {
 511         struct fb_info *info = platform_get_drvdata(pdev);
 512 
 513         unregister_framebuffer(info);
 514         framebuffer_release(info);
 515 
 516         return 0;
 517 }
 518 
 519 static const struct of_device_id simplefb_of_match[] = {
 520         { .compatible = "simple-framebuffer", },
 521         { },
 522 };
 523 MODULE_DEVICE_TABLE(of, simplefb_of_match);
 524 
 525 static struct platform_driver simplefb_driver = {
 526         .driver = {
 527                 .name = "simple-framebuffer",
 528                 .of_match_table = simplefb_of_match,
 529         },
 530         .probe = simplefb_probe,
 531         .remove = simplefb_remove,
 532 };
 533 
 534 static int __init simplefb_init(void)
 535 {
 536         int ret;
 537         struct device_node *np;
 538 
 539         ret = platform_driver_register(&simplefb_driver);
 540         if (ret)
 541                 return ret;
 542 
 543         if (IS_ENABLED(CONFIG_OF_ADDRESS) && of_chosen) {
 544                 for_each_child_of_node(of_chosen, np) {
 545                         if (of_device_is_compatible(np, "simple-framebuffer"))
 546                                 of_platform_device_create(np, NULL, NULL);
 547                 }
 548         }
 549 
 550         return 0;
 551 }
 552 
 553 fs_initcall(simplefb_init);
 554 
 555 MODULE_AUTHOR("Stephen Warren <swarren@wwwdotorg.org>");
 556 MODULE_DESCRIPTION("Simple framebuffer driver");
 557 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */