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