Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Simplest possible simple frame-buffer driver, as a platform device
0004  *
0005  * Copyright (c) 2013, Stephen Warren
0006  *
0007  * Based on q40fb.c, which was:
0008  * Copyright (C) 2001 Richard Zidlicky <rz@linux-m68k.org>
0009  *
0010  * Also based on offb.c, which was:
0011  * Copyright (C) 1997 Geert Uytterhoeven
0012  * Copyright (C) 1996 Paul Mackerras
0013  */
0014 
0015 #include <linux/errno.h>
0016 #include <linux/fb.h>
0017 #include <linux/io.h>
0018 #include <linux/module.h>
0019 #include <linux/platform_data/simplefb.h>
0020 #include <linux/platform_device.h>
0021 #include <linux/clk.h>
0022 #include <linux/of.h>
0023 #include <linux/of_clk.h>
0024 #include <linux/of_platform.h>
0025 #include <linux/parser.h>
0026 #include <linux/regulator/consumer.h>
0027 
0028 static const struct fb_fix_screeninfo simplefb_fix = {
0029     .id     = "simple",
0030     .type       = FB_TYPE_PACKED_PIXELS,
0031     .visual     = FB_VISUAL_TRUECOLOR,
0032     .accel      = FB_ACCEL_NONE,
0033 };
0034 
0035 static const struct fb_var_screeninfo simplefb_var = {
0036     .height     = -1,
0037     .width      = -1,
0038     .activate   = FB_ACTIVATE_NOW,
0039     .vmode      = FB_VMODE_NONINTERLACED,
0040 };
0041 
0042 #define PSEUDO_PALETTE_SIZE 16
0043 
0044 static int simplefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
0045                   u_int transp, struct fb_info *info)
0046 {
0047     u32 *pal = info->pseudo_palette;
0048     u32 cr = red >> (16 - info->var.red.length);
0049     u32 cg = green >> (16 - info->var.green.length);
0050     u32 cb = blue >> (16 - info->var.blue.length);
0051     u32 value;
0052 
0053     if (regno >= PSEUDO_PALETTE_SIZE)
0054         return -EINVAL;
0055 
0056     value = (cr << info->var.red.offset) |
0057         (cg << info->var.green.offset) |
0058         (cb << info->var.blue.offset);
0059     if (info->var.transp.length > 0) {
0060         u32 mask = (1 << info->var.transp.length) - 1;
0061         mask <<= info->var.transp.offset;
0062         value |= mask;
0063     }
0064     pal[regno] = value;
0065 
0066     return 0;
0067 }
0068 
0069 struct simplefb_par {
0070     u32 palette[PSEUDO_PALETTE_SIZE];
0071     struct resource *mem;
0072 #if defined CONFIG_OF && defined CONFIG_COMMON_CLK
0073     bool clks_enabled;
0074     unsigned int clk_count;
0075     struct clk **clks;
0076 #endif
0077 #if defined CONFIG_OF && defined CONFIG_REGULATOR
0078     bool regulators_enabled;
0079     u32 regulator_count;
0080     struct regulator **regulators;
0081 #endif
0082 };
0083 
0084 static void simplefb_clocks_destroy(struct simplefb_par *par);
0085 static void simplefb_regulators_destroy(struct simplefb_par *par);
0086 
0087 /*
0088  * fb_ops.fb_destroy is called by the last put_fb_info() call at the end
0089  * of unregister_framebuffer() or fb_release(). Do any cleanup here.
0090  */
0091 static void simplefb_destroy(struct fb_info *info)
0092 {
0093     struct simplefb_par *par = info->par;
0094     struct resource *mem = par->mem;
0095 
0096     simplefb_regulators_destroy(info->par);
0097     simplefb_clocks_destroy(info->par);
0098     if (info->screen_base)
0099         iounmap(info->screen_base);
0100 
0101     framebuffer_release(info);
0102 
0103     if (mem)
0104         release_mem_region(mem->start, resource_size(mem));
0105 }
0106 
0107 static const struct fb_ops simplefb_ops = {
0108     .owner      = THIS_MODULE,
0109     .fb_destroy = simplefb_destroy,
0110     .fb_setcolreg   = simplefb_setcolreg,
0111     .fb_fillrect    = cfb_fillrect,
0112     .fb_copyarea    = cfb_copyarea,
0113     .fb_imageblit   = cfb_imageblit,
0114 };
0115 
0116 static struct simplefb_format simplefb_formats[] = SIMPLEFB_FORMATS;
0117 
0118 struct simplefb_params {
0119     u32 width;
0120     u32 height;
0121     u32 stride;
0122     struct simplefb_format *format;
0123 };
0124 
0125 static int simplefb_parse_dt(struct platform_device *pdev,
0126                struct simplefb_params *params)
0127 {
0128     struct device_node *np = pdev->dev.of_node;
0129     int ret;
0130     const char *format;
0131     int i;
0132 
0133     ret = of_property_read_u32(np, "width", &params->width);
0134     if (ret) {
0135         dev_err(&pdev->dev, "Can't parse width property\n");
0136         return ret;
0137     }
0138 
0139     ret = of_property_read_u32(np, "height", &params->height);
0140     if (ret) {
0141         dev_err(&pdev->dev, "Can't parse height property\n");
0142         return ret;
0143     }
0144 
0145     ret = of_property_read_u32(np, "stride", &params->stride);
0146     if (ret) {
0147         dev_err(&pdev->dev, "Can't parse stride property\n");
0148         return ret;
0149     }
0150 
0151     ret = of_property_read_string(np, "format", &format);
0152     if (ret) {
0153         dev_err(&pdev->dev, "Can't parse format property\n");
0154         return ret;
0155     }
0156     params->format = NULL;
0157     for (i = 0; i < ARRAY_SIZE(simplefb_formats); i++) {
0158         if (strcmp(format, simplefb_formats[i].name))
0159             continue;
0160         params->format = &simplefb_formats[i];
0161         break;
0162     }
0163     if (!params->format) {
0164         dev_err(&pdev->dev, "Invalid format value\n");
0165         return -EINVAL;
0166     }
0167 
0168     return 0;
0169 }
0170 
0171 static int simplefb_parse_pd(struct platform_device *pdev,
0172                  struct simplefb_params *params)
0173 {
0174     struct simplefb_platform_data *pd = dev_get_platdata(&pdev->dev);
0175     int i;
0176 
0177     params->width = pd->width;
0178     params->height = pd->height;
0179     params->stride = pd->stride;
0180 
0181     params->format = NULL;
0182     for (i = 0; i < ARRAY_SIZE(simplefb_formats); i++) {
0183         if (strcmp(pd->format, simplefb_formats[i].name))
0184             continue;
0185 
0186         params->format = &simplefb_formats[i];
0187         break;
0188     }
0189 
0190     if (!params->format) {
0191         dev_err(&pdev->dev, "Invalid format value\n");
0192         return -EINVAL;
0193     }
0194 
0195     return 0;
0196 }
0197 
0198 #if defined CONFIG_OF && defined CONFIG_COMMON_CLK
0199 /*
0200  * Clock handling code.
0201  *
0202  * Here we handle the clocks property of our "simple-framebuffer" dt node.
0203  * This is necessary so that we can make sure that any clocks needed by
0204  * the display engine that the bootloader set up for us (and for which it
0205  * provided a simplefb dt node), stay up, for the life of the simplefb
0206  * driver.
0207  *
0208  * When the driver unloads, we cleanly disable, and then release the clocks.
0209  *
0210  * We only complain about errors here, no action is taken as the most likely
0211  * error can only happen due to a mismatch between the bootloader which set
0212  * up simplefb, and the clock definitions in the device tree. Chances are
0213  * that there are no adverse effects, and if there are, a clean teardown of
0214  * the fb probe will not help us much either. So just complain and carry on,
0215  * and hope that the user actually gets a working fb at the end of things.
0216  */
0217 static int simplefb_clocks_get(struct simplefb_par *par,
0218                    struct platform_device *pdev)
0219 {
0220     struct device_node *np = pdev->dev.of_node;
0221     struct clk *clock;
0222     int i;
0223 
0224     if (dev_get_platdata(&pdev->dev) || !np)
0225         return 0;
0226 
0227     par->clk_count = of_clk_get_parent_count(np);
0228     if (!par->clk_count)
0229         return 0;
0230 
0231     par->clks = kcalloc(par->clk_count, sizeof(struct clk *), GFP_KERNEL);
0232     if (!par->clks)
0233         return -ENOMEM;
0234 
0235     for (i = 0; i < par->clk_count; i++) {
0236         clock = of_clk_get(np, i);
0237         if (IS_ERR(clock)) {
0238             if (PTR_ERR(clock) == -EPROBE_DEFER) {
0239                 while (--i >= 0) {
0240                     clk_put(par->clks[i]);
0241                 }
0242                 kfree(par->clks);
0243                 return -EPROBE_DEFER;
0244             }
0245             dev_err(&pdev->dev, "%s: clock %d not found: %ld\n",
0246                 __func__, i, PTR_ERR(clock));
0247             continue;
0248         }
0249         par->clks[i] = clock;
0250     }
0251 
0252     return 0;
0253 }
0254 
0255 static void simplefb_clocks_enable(struct simplefb_par *par,
0256                    struct platform_device *pdev)
0257 {
0258     int i, ret;
0259 
0260     for (i = 0; i < par->clk_count; i++) {
0261         if (par->clks[i]) {
0262             ret = clk_prepare_enable(par->clks[i]);
0263             if (ret) {
0264                 dev_err(&pdev->dev,
0265                     "%s: failed to enable clock %d: %d\n",
0266                     __func__, i, ret);
0267                 clk_put(par->clks[i]);
0268                 par->clks[i] = NULL;
0269             }
0270         }
0271     }
0272     par->clks_enabled = true;
0273 }
0274 
0275 static void simplefb_clocks_destroy(struct simplefb_par *par)
0276 {
0277     int i;
0278 
0279     if (!par->clks)
0280         return;
0281 
0282     for (i = 0; i < par->clk_count; i++) {
0283         if (par->clks[i]) {
0284             if (par->clks_enabled)
0285                 clk_disable_unprepare(par->clks[i]);
0286             clk_put(par->clks[i]);
0287         }
0288     }
0289 
0290     kfree(par->clks);
0291 }
0292 #else
0293 static int simplefb_clocks_get(struct simplefb_par *par,
0294     struct platform_device *pdev) { return 0; }
0295 static void simplefb_clocks_enable(struct simplefb_par *par,
0296     struct platform_device *pdev) { }
0297 static void simplefb_clocks_destroy(struct simplefb_par *par) { }
0298 #endif
0299 
0300 #if defined CONFIG_OF && defined CONFIG_REGULATOR
0301 
0302 #define SUPPLY_SUFFIX "-supply"
0303 
0304 /*
0305  * Regulator handling code.
0306  *
0307  * Here we handle the num-supplies and vin*-supply properties of our
0308  * "simple-framebuffer" dt node. This is necessary so that we can make sure
0309  * that any regulators needed by the display hardware that the bootloader
0310  * set up for us (and for which it provided a simplefb dt node), stay up,
0311  * for the life of the simplefb driver.
0312  *
0313  * When the driver unloads, we cleanly disable, and then release the
0314  * regulators.
0315  *
0316  * We only complain about errors here, no action is taken as the most likely
0317  * error can only happen due to a mismatch between the bootloader which set
0318  * up simplefb, and the regulator definitions in the device tree. Chances are
0319  * that there are no adverse effects, and if there are, a clean teardown of
0320  * the fb probe will not help us much either. So just complain and carry on,
0321  * and hope that the user actually gets a working fb at the end of things.
0322  */
0323 static int simplefb_regulators_get(struct simplefb_par *par,
0324                    struct platform_device *pdev)
0325 {
0326     struct device_node *np = pdev->dev.of_node;
0327     struct property *prop;
0328     struct regulator *regulator;
0329     const char *p;
0330     int count = 0, i = 0;
0331 
0332     if (dev_get_platdata(&pdev->dev) || !np)
0333         return 0;
0334 
0335     /* Count the number of regulator supplies */
0336     for_each_property_of_node(np, prop) {
0337         p = strstr(prop->name, SUPPLY_SUFFIX);
0338         if (p && p != prop->name)
0339             count++;
0340     }
0341 
0342     if (!count)
0343         return 0;
0344 
0345     par->regulators = devm_kcalloc(&pdev->dev, count,
0346                        sizeof(struct regulator *), GFP_KERNEL);
0347     if (!par->regulators)
0348         return -ENOMEM;
0349 
0350     /* Get all the regulators */
0351     for_each_property_of_node(np, prop) {
0352         char name[32]; /* 32 is max size of property name */
0353 
0354         p = strstr(prop->name, SUPPLY_SUFFIX);
0355         if (!p || p == prop->name)
0356             continue;
0357 
0358         strscpy(name, prop->name,
0359             strlen(prop->name) - strlen(SUPPLY_SUFFIX) + 1);
0360         regulator = devm_regulator_get_optional(&pdev->dev, name);
0361         if (IS_ERR(regulator)) {
0362             if (PTR_ERR(regulator) == -EPROBE_DEFER)
0363                 return -EPROBE_DEFER;
0364             dev_err(&pdev->dev, "regulator %s not found: %ld\n",
0365                 name, PTR_ERR(regulator));
0366             continue;
0367         }
0368         par->regulators[i++] = regulator;
0369     }
0370     par->regulator_count = i;
0371 
0372     return 0;
0373 }
0374 
0375 static void simplefb_regulators_enable(struct simplefb_par *par,
0376                        struct platform_device *pdev)
0377 {
0378     int i, ret;
0379 
0380     /* Enable all the regulators */
0381     for (i = 0; i < par->regulator_count; i++) {
0382         ret = regulator_enable(par->regulators[i]);
0383         if (ret) {
0384             dev_err(&pdev->dev,
0385                 "failed to enable regulator %d: %d\n",
0386                 i, ret);
0387             devm_regulator_put(par->regulators[i]);
0388             par->regulators[i] = NULL;
0389         }
0390     }
0391     par->regulators_enabled = true;
0392 }
0393 
0394 static void simplefb_regulators_destroy(struct simplefb_par *par)
0395 {
0396     int i;
0397 
0398     if (!par->regulators || !par->regulators_enabled)
0399         return;
0400 
0401     for (i = 0; i < par->regulator_count; i++)
0402         if (par->regulators[i])
0403             regulator_disable(par->regulators[i]);
0404 }
0405 #else
0406 static int simplefb_regulators_get(struct simplefb_par *par,
0407     struct platform_device *pdev) { return 0; }
0408 static void simplefb_regulators_enable(struct simplefb_par *par,
0409     struct platform_device *pdev) { }
0410 static void simplefb_regulators_destroy(struct simplefb_par *par) { }
0411 #endif
0412 
0413 static int simplefb_probe(struct platform_device *pdev)
0414 {
0415     int ret;
0416     struct simplefb_params params;
0417     struct fb_info *info;
0418     struct simplefb_par *par;
0419     struct resource *res, *mem;
0420 
0421     if (fb_get_options("simplefb", NULL))
0422         return -ENODEV;
0423 
0424     ret = -ENODEV;
0425     if (dev_get_platdata(&pdev->dev))
0426         ret = simplefb_parse_pd(pdev, &params);
0427     else if (pdev->dev.of_node)
0428         ret = simplefb_parse_dt(pdev, &params);
0429 
0430     if (ret)
0431         return ret;
0432 
0433     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0434     if (!res) {
0435         dev_err(&pdev->dev, "No memory resource\n");
0436         return -EINVAL;
0437     }
0438 
0439     mem = request_mem_region(res->start, resource_size(res), "simplefb");
0440     if (!mem) {
0441         /*
0442          * We cannot make this fatal. Sometimes this comes from magic
0443          * spaces our resource handlers simply don't know about. Use
0444          * the I/O-memory resource as-is and try to map that instead.
0445          */
0446         dev_warn(&pdev->dev, "simplefb: cannot reserve video memory at %pR\n", res);
0447         mem = res;
0448     }
0449 
0450     info = framebuffer_alloc(sizeof(struct simplefb_par), &pdev->dev);
0451     if (!info) {
0452         ret = -ENOMEM;
0453         goto error_release_mem_region;
0454     }
0455     platform_set_drvdata(pdev, info);
0456 
0457     par = info->par;
0458 
0459     info->fix = simplefb_fix;
0460     info->fix.smem_start = mem->start;
0461     info->fix.smem_len = resource_size(mem);
0462     info->fix.line_length = params.stride;
0463 
0464     info->var = simplefb_var;
0465     info->var.xres = params.width;
0466     info->var.yres = params.height;
0467     info->var.xres_virtual = params.width;
0468     info->var.yres_virtual = params.height;
0469     info->var.bits_per_pixel = params.format->bits_per_pixel;
0470     info->var.red = params.format->red;
0471     info->var.green = params.format->green;
0472     info->var.blue = params.format->blue;
0473     info->var.transp = params.format->transp;
0474 
0475     info->apertures = alloc_apertures(1);
0476     if (!info->apertures) {
0477         ret = -ENOMEM;
0478         goto error_fb_release;
0479     }
0480     info->apertures->ranges[0].base = info->fix.smem_start;
0481     info->apertures->ranges[0].size = info->fix.smem_len;
0482 
0483     info->fbops = &simplefb_ops;
0484     info->flags = FBINFO_DEFAULT | FBINFO_MISC_FIRMWARE;
0485     info->screen_base = ioremap_wc(info->fix.smem_start,
0486                        info->fix.smem_len);
0487     if (!info->screen_base) {
0488         ret = -ENOMEM;
0489         goto error_fb_release;
0490     }
0491     info->pseudo_palette = par->palette;
0492 
0493     ret = simplefb_clocks_get(par, pdev);
0494     if (ret < 0)
0495         goto error_unmap;
0496 
0497     ret = simplefb_regulators_get(par, pdev);
0498     if (ret < 0)
0499         goto error_clocks;
0500 
0501     simplefb_clocks_enable(par, pdev);
0502     simplefb_regulators_enable(par, pdev);
0503 
0504     dev_info(&pdev->dev, "framebuffer at 0x%lx, 0x%x bytes\n",
0505                  info->fix.smem_start, info->fix.smem_len);
0506     dev_info(&pdev->dev, "format=%s, mode=%dx%dx%d, linelength=%d\n",
0507                  params.format->name,
0508                  info->var.xres, info->var.yres,
0509                  info->var.bits_per_pixel, info->fix.line_length);
0510 
0511     if (mem != res)
0512         par->mem = mem; /* release in clean-up handler */
0513 
0514     ret = register_framebuffer(info);
0515     if (ret < 0) {
0516         dev_err(&pdev->dev, "Unable to register simplefb: %d\n", ret);
0517         goto error_regulators;
0518     }
0519 
0520     dev_info(&pdev->dev, "fb%d: simplefb registered!\n", info->node);
0521 
0522     return 0;
0523 
0524 error_regulators:
0525     simplefb_regulators_destroy(par);
0526 error_clocks:
0527     simplefb_clocks_destroy(par);
0528 error_unmap:
0529     iounmap(info->screen_base);
0530 error_fb_release:
0531     framebuffer_release(info);
0532 error_release_mem_region:
0533     if (mem != res)
0534         release_mem_region(mem->start, resource_size(mem));
0535     return ret;
0536 }
0537 
0538 static int simplefb_remove(struct platform_device *pdev)
0539 {
0540     struct fb_info *info = platform_get_drvdata(pdev);
0541 
0542     /* simplefb_destroy takes care of info cleanup */
0543     unregister_framebuffer(info);
0544 
0545     return 0;
0546 }
0547 
0548 static const struct of_device_id simplefb_of_match[] = {
0549     { .compatible = "simple-framebuffer", },
0550     { },
0551 };
0552 MODULE_DEVICE_TABLE(of, simplefb_of_match);
0553 
0554 static struct platform_driver simplefb_driver = {
0555     .driver = {
0556         .name = "simple-framebuffer",
0557         .of_match_table = simplefb_of_match,
0558     },
0559     .probe = simplefb_probe,
0560     .remove = simplefb_remove,
0561 };
0562 
0563 module_platform_driver(simplefb_driver);
0564 
0565 MODULE_AUTHOR("Stephen Warren <swarren@wwwdotorg.org>");
0566 MODULE_DESCRIPTION("Simple framebuffer driver");
0567 MODULE_LICENSE("GPL v2");