linux/drivers/gpu/drm/tiny/simpledrm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2
   3#include <linux/clk.h>
   4#include <linux/of_clk.h>
   5#include <linux/platform_data/simplefb.h>
   6#include <linux/platform_device.h>
   7#include <linux/regulator/consumer.h>
   8
   9#include <drm/drm_aperture.h>
  10#include <drm/drm_atomic_state_helper.h>
  11#include <drm/drm_connector.h>
  12#include <drm/drm_damage_helper.h>
  13#include <drm/drm_device.h>
  14#include <drm/drm_drv.h>
  15#include <drm/drm_fb_helper.h>
  16#include <drm/drm_format_helper.h>
  17#include <drm/drm_gem_atomic_helper.h>
  18#include <drm/drm_gem_framebuffer_helper.h>
  19#include <drm/drm_gem_shmem_helper.h>
  20#include <drm/drm_managed.h>
  21#include <drm/drm_modeset_helper_vtables.h>
  22#include <drm/drm_probe_helper.h>
  23#include <drm/drm_simple_kms_helper.h>
  24
  25#define DRIVER_NAME     "simpledrm"
  26#define DRIVER_DESC     "DRM driver for simple-framebuffer platform devices"
  27#define DRIVER_DATE     "20200625"
  28#define DRIVER_MAJOR    1
  29#define DRIVER_MINOR    0
  30
  31/*
  32 * Assume a monitor resolution of 96 dpi to
  33 * get a somewhat reasonable screen size.
  34 */
  35#define RES_MM(d)       \
  36        (((d) * 254ul) / (96ul * 10ul))
  37
  38#define SIMPLEDRM_MODE(hd, vd)  \
  39        DRM_SIMPLE_MODE(hd, vd, RES_MM(hd), RES_MM(vd))
  40
  41/*
  42 * Helpers for simplefb
  43 */
  44
  45static int
  46simplefb_get_validated_int(struct drm_device *dev, const char *name,
  47                           uint32_t value)
  48{
  49        if (value > INT_MAX) {
  50                drm_err(dev, "simplefb: invalid framebuffer %s of %u\n",
  51                        name, value);
  52                return -EINVAL;
  53        }
  54        return (int)value;
  55}
  56
  57static int
  58simplefb_get_validated_int0(struct drm_device *dev, const char *name,
  59                            uint32_t value)
  60{
  61        if (!value) {
  62                drm_err(dev, "simplefb: invalid framebuffer %s of %u\n",
  63                        name, value);
  64                return -EINVAL;
  65        }
  66        return simplefb_get_validated_int(dev, name, value);
  67}
  68
  69static const struct drm_format_info *
  70simplefb_get_validated_format(struct drm_device *dev, const char *format_name)
  71{
  72        static const struct simplefb_format formats[] = SIMPLEFB_FORMATS;
  73        const struct simplefb_format *fmt = formats;
  74        const struct simplefb_format *end = fmt + ARRAY_SIZE(formats);
  75        const struct drm_format_info *info;
  76
  77        if (!format_name) {
  78                drm_err(dev, "simplefb: missing framebuffer format\n");
  79                return ERR_PTR(-EINVAL);
  80        }
  81
  82        while (fmt < end) {
  83                if (!strcmp(format_name, fmt->name)) {
  84                        info = drm_format_info(fmt->fourcc);
  85                        if (!info)
  86                                return ERR_PTR(-EINVAL);
  87                        return info;
  88                }
  89                ++fmt;
  90        }
  91
  92        drm_err(dev, "simplefb: unknown framebuffer format %s\n",
  93                format_name);
  94
  95        return ERR_PTR(-EINVAL);
  96}
  97
  98static int
  99simplefb_get_width_pd(struct drm_device *dev,
 100                      const struct simplefb_platform_data *pd)
 101{
 102        return simplefb_get_validated_int0(dev, "width", pd->width);
 103}
 104
 105static int
 106simplefb_get_height_pd(struct drm_device *dev,
 107                       const struct simplefb_platform_data *pd)
 108{
 109        return simplefb_get_validated_int0(dev, "height", pd->height);
 110}
 111
 112static int
 113simplefb_get_stride_pd(struct drm_device *dev,
 114                       const struct simplefb_platform_data *pd)
 115{
 116        return simplefb_get_validated_int(dev, "stride", pd->stride);
 117}
 118
 119static const struct drm_format_info *
 120simplefb_get_format_pd(struct drm_device *dev,
 121                       const struct simplefb_platform_data *pd)
 122{
 123        return simplefb_get_validated_format(dev, pd->format);
 124}
 125
 126static int
 127simplefb_read_u32_of(struct drm_device *dev, struct device_node *of_node,
 128                     const char *name, u32 *value)
 129{
 130        int ret = of_property_read_u32(of_node, name, value);
 131
 132        if (ret)
 133                drm_err(dev, "simplefb: cannot parse framebuffer %s: error %d\n",
 134                        name, ret);
 135        return ret;
 136}
 137
 138static int
 139simplefb_read_string_of(struct drm_device *dev, struct device_node *of_node,
 140                        const char *name, const char **value)
 141{
 142        int ret = of_property_read_string(of_node, name, value);
 143
 144        if (ret)
 145                drm_err(dev, "simplefb: cannot parse framebuffer %s: error %d\n",
 146                        name, ret);
 147        return ret;
 148}
 149
 150static int
 151simplefb_get_width_of(struct drm_device *dev, struct device_node *of_node)
 152{
 153        u32 width;
 154        int ret = simplefb_read_u32_of(dev, of_node, "width", &width);
 155
 156        if (ret)
 157                return ret;
 158        return simplefb_get_validated_int0(dev, "width", width);
 159}
 160
 161static int
 162simplefb_get_height_of(struct drm_device *dev, struct device_node *of_node)
 163{
 164        u32 height;
 165        int ret = simplefb_read_u32_of(dev, of_node, "height", &height);
 166
 167        if (ret)
 168                return ret;
 169        return simplefb_get_validated_int0(dev, "height", height);
 170}
 171
 172static int
 173simplefb_get_stride_of(struct drm_device *dev, struct device_node *of_node)
 174{
 175        u32 stride;
 176        int ret = simplefb_read_u32_of(dev, of_node, "stride", &stride);
 177
 178        if (ret)
 179                return ret;
 180        return simplefb_get_validated_int(dev, "stride", stride);
 181}
 182
 183static const struct drm_format_info *
 184simplefb_get_format_of(struct drm_device *dev, struct device_node *of_node)
 185{
 186        const char *format;
 187        int ret = simplefb_read_string_of(dev, of_node, "format", &format);
 188
 189        if (ret)
 190                return ERR_PTR(ret);
 191        return simplefb_get_validated_format(dev, format);
 192}
 193
 194/*
 195 * Simple Framebuffer device
 196 */
 197
 198struct simpledrm_device {
 199        struct drm_device dev;
 200        struct platform_device *pdev;
 201
 202        /* clocks */
 203#if defined CONFIG_OF && defined CONFIG_COMMON_CLK
 204        unsigned int clk_count;
 205        struct clk **clks;
 206#endif
 207        /* regulators */
 208#if defined CONFIG_OF && defined CONFIG_REGULATOR
 209        unsigned int regulator_count;
 210        struct regulator **regulators;
 211#endif
 212
 213        /* simplefb settings */
 214        struct drm_display_mode mode;
 215        const struct drm_format_info *format;
 216        unsigned int pitch;
 217
 218        /* memory management */
 219        struct resource *mem;
 220        void __iomem *screen_base;
 221
 222        /* modesetting */
 223        uint32_t formats[8];
 224        size_t nformats;
 225        struct drm_connector connector;
 226        struct drm_simple_display_pipe pipe;
 227};
 228
 229static struct simpledrm_device *simpledrm_device_of_dev(struct drm_device *dev)
 230{
 231        return container_of(dev, struct simpledrm_device, dev);
 232}
 233
 234/*
 235 * Hardware
 236 */
 237
 238#if defined CONFIG_OF && defined CONFIG_COMMON_CLK
 239/*
 240 * Clock handling code.
 241 *
 242 * Here we handle the clocks property of our "simple-framebuffer" dt node.
 243 * This is necessary so that we can make sure that any clocks needed by
 244 * the display engine that the bootloader set up for us (and for which it
 245 * provided a simplefb dt node), stay up, for the life of the simplefb
 246 * driver.
 247 *
 248 * When the driver unloads, we cleanly disable, and then release the clocks.
 249 *
 250 * We only complain about errors here, no action is taken as the most likely
 251 * error can only happen due to a mismatch between the bootloader which set
 252 * up simplefb, and the clock definitions in the device tree. Chances are
 253 * that there are no adverse effects, and if there are, a clean teardown of
 254 * the fb probe will not help us much either. So just complain and carry on,
 255 * and hope that the user actually gets a working fb at the end of things.
 256 */
 257
 258static void simpledrm_device_release_clocks(void *res)
 259{
 260        struct simpledrm_device *sdev = simpledrm_device_of_dev(res);
 261        unsigned int i;
 262
 263        for (i = 0; i < sdev->clk_count; ++i) {
 264                if (sdev->clks[i]) {
 265                        clk_disable_unprepare(sdev->clks[i]);
 266                        clk_put(sdev->clks[i]);
 267                }
 268        }
 269}
 270
 271static int simpledrm_device_init_clocks(struct simpledrm_device *sdev)
 272{
 273        struct drm_device *dev = &sdev->dev;
 274        struct platform_device *pdev = sdev->pdev;
 275        struct device_node *of_node = pdev->dev.of_node;
 276        struct clk *clock;
 277        unsigned int i;
 278        int ret;
 279
 280        if (dev_get_platdata(&pdev->dev) || !of_node)
 281                return 0;
 282
 283        sdev->clk_count = of_clk_get_parent_count(of_node);
 284        if (!sdev->clk_count)
 285                return 0;
 286
 287        sdev->clks = drmm_kzalloc(dev, sdev->clk_count * sizeof(sdev->clks[0]),
 288                                  GFP_KERNEL);
 289        if (!sdev->clks)
 290                return -ENOMEM;
 291
 292        for (i = 0; i < sdev->clk_count; ++i) {
 293                clock = of_clk_get(of_node, i);
 294                if (IS_ERR(clock)) {
 295                        ret = PTR_ERR(clock);
 296                        if (ret == -EPROBE_DEFER)
 297                                goto err;
 298                        drm_err(dev, "clock %u not found: %d\n", i, ret);
 299                        continue;
 300                }
 301                ret = clk_prepare_enable(clock);
 302                if (ret) {
 303                        drm_err(dev, "failed to enable clock %u: %d\n",
 304                                i, ret);
 305                        clk_put(clock);
 306                        continue;
 307                }
 308                sdev->clks[i] = clock;
 309        }
 310
 311        return devm_add_action_or_reset(&pdev->dev,
 312                                        simpledrm_device_release_clocks,
 313                                        sdev);
 314
 315err:
 316        while (i) {
 317                --i;
 318                if (sdev->clks[i]) {
 319                        clk_disable_unprepare(sdev->clks[i]);
 320                        clk_put(sdev->clks[i]);
 321                }
 322        }
 323        return ret;
 324}
 325#else
 326static int simpledrm_device_init_clocks(struct simpledrm_device *sdev)
 327{
 328        return 0;
 329}
 330#endif
 331
 332#if defined CONFIG_OF && defined CONFIG_REGULATOR
 333
 334#define SUPPLY_SUFFIX "-supply"
 335
 336/*
 337 * Regulator handling code.
 338 *
 339 * Here we handle the num-supplies and vin*-supply properties of our
 340 * "simple-framebuffer" dt node. This is necessary so that we can make sure
 341 * that any regulators needed by the display hardware that the bootloader
 342 * set up for us (and for which it provided a simplefb dt node), stay up,
 343 * for the life of the simplefb driver.
 344 *
 345 * When the driver unloads, we cleanly disable, and then release the
 346 * regulators.
 347 *
 348 * We only complain about errors here, no action is taken as the most likely
 349 * error can only happen due to a mismatch between the bootloader which set
 350 * up simplefb, and the regulator definitions in the device tree. Chances are
 351 * that there are no adverse effects, and if there are, a clean teardown of
 352 * the fb probe will not help us much either. So just complain and carry on,
 353 * and hope that the user actually gets a working fb at the end of things.
 354 */
 355
 356static void simpledrm_device_release_regulators(void *res)
 357{
 358        struct simpledrm_device *sdev = simpledrm_device_of_dev(res);
 359        unsigned int i;
 360
 361        for (i = 0; i < sdev->regulator_count; ++i) {
 362                if (sdev->regulators[i]) {
 363                        regulator_disable(sdev->regulators[i]);
 364                        regulator_put(sdev->regulators[i]);
 365                }
 366        }
 367}
 368
 369static int simpledrm_device_init_regulators(struct simpledrm_device *sdev)
 370{
 371        struct drm_device *dev = &sdev->dev;
 372        struct platform_device *pdev = sdev->pdev;
 373        struct device_node *of_node = pdev->dev.of_node;
 374        struct property *prop;
 375        struct regulator *regulator;
 376        const char *p;
 377        unsigned int count = 0, i = 0;
 378        int ret;
 379
 380        if (dev_get_platdata(&pdev->dev) || !of_node)
 381                return 0;
 382
 383        /* Count the number of regulator supplies */
 384        for_each_property_of_node(of_node, prop) {
 385                p = strstr(prop->name, SUPPLY_SUFFIX);
 386                if (p && p != prop->name)
 387                        ++count;
 388        }
 389
 390        if (!count)
 391                return 0;
 392
 393        sdev->regulators = drmm_kzalloc(dev,
 394                                        count * sizeof(sdev->regulators[0]),
 395                                        GFP_KERNEL);
 396        if (!sdev->regulators)
 397                return -ENOMEM;
 398
 399        for_each_property_of_node(of_node, prop) {
 400                char name[32]; /* 32 is max size of property name */
 401                size_t len;
 402
 403                p = strstr(prop->name, SUPPLY_SUFFIX);
 404                if (!p || p == prop->name)
 405                        continue;
 406                len = strlen(prop->name) - strlen(SUPPLY_SUFFIX) + 1;
 407                strscpy(name, prop->name, min(sizeof(name), len));
 408
 409                regulator = regulator_get_optional(&pdev->dev, name);
 410                if (IS_ERR(regulator)) {
 411                        ret = PTR_ERR(regulator);
 412                        if (ret == -EPROBE_DEFER)
 413                                goto err;
 414                        drm_err(dev, "regulator %s not found: %d\n",
 415                                name, ret);
 416                        continue;
 417                }
 418
 419                ret = regulator_enable(regulator);
 420                if (ret) {
 421                        drm_err(dev, "failed to enable regulator %u: %d\n",
 422                                i, ret);
 423                        regulator_put(regulator);
 424                        continue;
 425                }
 426
 427                sdev->regulators[i++] = regulator;
 428        }
 429        sdev->regulator_count = i;
 430
 431        return devm_add_action_or_reset(&pdev->dev,
 432                                        simpledrm_device_release_regulators,
 433                                        sdev);
 434
 435err:
 436        while (i) {
 437                --i;
 438                if (sdev->regulators[i]) {
 439                        regulator_disable(sdev->regulators[i]);
 440                        regulator_put(sdev->regulators[i]);
 441                }
 442        }
 443        return ret;
 444}
 445#else
 446static int simpledrm_device_init_regulators(struct simpledrm_device *sdev)
 447{
 448        return 0;
 449}
 450#endif
 451
 452/*
 453 *  Simplefb settings
 454 */
 455
 456static struct drm_display_mode simpledrm_mode(unsigned int width,
 457                                              unsigned int height)
 458{
 459        struct drm_display_mode mode = { SIMPLEDRM_MODE(width, height) };
 460
 461        mode.clock = 60 /* Hz */ * mode.hdisplay * mode.vdisplay;
 462        drm_mode_set_name(&mode);
 463
 464        return mode;
 465}
 466
 467static int simpledrm_device_init_fb(struct simpledrm_device *sdev)
 468{
 469        int width, height, stride;
 470        const struct drm_format_info *format;
 471        struct drm_device *dev = &sdev->dev;
 472        struct platform_device *pdev = sdev->pdev;
 473        const struct simplefb_platform_data *pd = dev_get_platdata(&pdev->dev);
 474        struct device_node *of_node = pdev->dev.of_node;
 475
 476        if (pd) {
 477                width = simplefb_get_width_pd(dev, pd);
 478                if (width < 0)
 479                        return width;
 480                height = simplefb_get_height_pd(dev, pd);
 481                if (height < 0)
 482                        return height;
 483                stride = simplefb_get_stride_pd(dev, pd);
 484                if (stride < 0)
 485                        return stride;
 486                format = simplefb_get_format_pd(dev, pd);
 487                if (IS_ERR(format))
 488                        return PTR_ERR(format);
 489        } else if (of_node) {
 490                width = simplefb_get_width_of(dev, of_node);
 491                if (width < 0)
 492                        return width;
 493                height = simplefb_get_height_of(dev, of_node);
 494                if (height < 0)
 495                        return height;
 496                stride = simplefb_get_stride_of(dev, of_node);
 497                if (stride < 0)
 498                        return stride;
 499                format = simplefb_get_format_of(dev, of_node);
 500                if (IS_ERR(format))
 501                        return PTR_ERR(format);
 502        } else {
 503                drm_err(dev, "no simplefb configuration found\n");
 504                return -ENODEV;
 505        }
 506
 507        sdev->mode = simpledrm_mode(width, height);
 508        sdev->format = format;
 509        sdev->pitch = stride;
 510
 511        drm_dbg_kms(dev, "display mode={" DRM_MODE_FMT "}\n",
 512                    DRM_MODE_ARG(&sdev->mode));
 513        drm_dbg_kms(dev,
 514                    "framebuffer format=%p4cc, size=%dx%d, stride=%d byte\n",
 515                    &format->format, width, height, stride);
 516
 517        return 0;
 518}
 519
 520/*
 521 * Memory management
 522 */
 523
 524static int simpledrm_device_init_mm(struct simpledrm_device *sdev)
 525{
 526        struct drm_device *dev = &sdev->dev;
 527        struct platform_device *pdev = sdev->pdev;
 528        struct resource *mem;
 529        void __iomem *screen_base;
 530        int ret;
 531
 532        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 533        if (!mem)
 534                return -EINVAL;
 535
 536        ret = devm_aperture_acquire_from_firmware(dev, mem->start, resource_size(mem));
 537        if (ret) {
 538                drm_err(dev, "could not acquire memory range %pr: error %d\n",
 539                        mem, ret);
 540                return ret;
 541        }
 542
 543        screen_base = devm_ioremap_wc(&pdev->dev, mem->start,
 544                                      resource_size(mem));
 545        if (!screen_base)
 546                return -ENOMEM;
 547
 548        sdev->mem = mem;
 549        sdev->screen_base = screen_base;
 550
 551        return 0;
 552}
 553
 554/*
 555 * Modesetting
 556 */
 557
 558/*
 559 * Support all formats of simplefb and maybe more; in order
 560 * of preference. The display's update function will do any
 561 * conversion necessary.
 562 *
 563 * TODO: Add blit helpers for remaining formats and uncomment
 564 *       constants.
 565 */
 566static const uint32_t simpledrm_default_formats[] = {
 567        DRM_FORMAT_XRGB8888,
 568        DRM_FORMAT_ARGB8888,
 569        DRM_FORMAT_RGB565,
 570        //DRM_FORMAT_XRGB1555,
 571        //DRM_FORMAT_ARGB1555,
 572        DRM_FORMAT_RGB888,
 573        //DRM_FORMAT_XRGB2101010,
 574        //DRM_FORMAT_ARGB2101010,
 575};
 576
 577static const uint64_t simpledrm_format_modifiers[] = {
 578        DRM_FORMAT_MOD_LINEAR,
 579        DRM_FORMAT_MOD_INVALID
 580};
 581
 582static int simpledrm_connector_helper_get_modes(struct drm_connector *connector)
 583{
 584        struct simpledrm_device *sdev = simpledrm_device_of_dev(connector->dev);
 585        struct drm_display_mode *mode;
 586
 587        mode = drm_mode_duplicate(connector->dev, &sdev->mode);
 588        if (!mode)
 589                return 0;
 590
 591        if (mode->name[0] == '\0')
 592                drm_mode_set_name(mode);
 593
 594        mode->type |= DRM_MODE_TYPE_PREFERRED;
 595        drm_mode_probed_add(connector, mode);
 596
 597        if (mode->width_mm)
 598                connector->display_info.width_mm = mode->width_mm;
 599        if (mode->height_mm)
 600                connector->display_info.height_mm = mode->height_mm;
 601
 602        return 1;
 603}
 604
 605static const struct drm_connector_helper_funcs simpledrm_connector_helper_funcs = {
 606        .get_modes = simpledrm_connector_helper_get_modes,
 607};
 608
 609static const struct drm_connector_funcs simpledrm_connector_funcs = {
 610        .reset = drm_atomic_helper_connector_reset,
 611        .fill_modes = drm_helper_probe_single_connector_modes,
 612        .destroy = drm_connector_cleanup,
 613        .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 614        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 615};
 616
 617static int
 618simpledrm_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
 619                                    const struct drm_display_mode *mode)
 620{
 621        struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev);
 622
 623        if (mode->hdisplay != sdev->mode.hdisplay &&
 624            mode->vdisplay != sdev->mode.vdisplay)
 625                return MODE_ONE_SIZE;
 626        else if (mode->hdisplay != sdev->mode.hdisplay)
 627                return MODE_ONE_WIDTH;
 628        else if (mode->vdisplay != sdev->mode.vdisplay)
 629                return MODE_ONE_HEIGHT;
 630
 631        return MODE_OK;
 632}
 633
 634static void
 635simpledrm_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
 636                                     struct drm_crtc_state *crtc_state,
 637                                     struct drm_plane_state *plane_state)
 638{
 639        struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev);
 640        struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
 641        struct drm_framebuffer *fb = plane_state->fb;
 642        void *vmap = shadow_plane_state->data[0].vaddr; /* TODO: Use mapping abstraction */
 643        struct drm_device *dev = &sdev->dev;
 644        int idx;
 645
 646        if (!fb)
 647                return;
 648
 649        if (!drm_dev_enter(dev, &idx))
 650                return;
 651
 652        drm_fb_blit_dstclip(sdev->screen_base, sdev->pitch,
 653                            sdev->format->format, vmap, fb);
 654        drm_dev_exit(idx);
 655}
 656
 657static void
 658simpledrm_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe)
 659{
 660        struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev);
 661        struct drm_device *dev = &sdev->dev;
 662        int idx;
 663
 664        if (!drm_dev_enter(dev, &idx))
 665                return;
 666
 667        /* Clear screen to black if disabled */
 668        memset_io(sdev->screen_base, 0, sdev->pitch * sdev->mode.vdisplay);
 669
 670        drm_dev_exit(idx);
 671}
 672
 673static void
 674simpledrm_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
 675                                     struct drm_plane_state *old_plane_state)
 676{
 677        struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev);
 678        struct drm_plane_state *plane_state = pipe->plane.state;
 679        struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
 680        void *vmap = shadow_plane_state->data[0].vaddr; /* TODO: Use mapping abstraction */
 681        struct drm_framebuffer *fb = plane_state->fb;
 682        struct drm_device *dev = &sdev->dev;
 683        struct drm_rect clip;
 684        int idx;
 685
 686        if (!fb)
 687                return;
 688
 689        if (!drm_atomic_helper_damage_merged(old_plane_state, plane_state, &clip))
 690                return;
 691
 692        if (!drm_dev_enter(dev, &idx))
 693                return;
 694
 695        drm_fb_blit_rect_dstclip(sdev->screen_base, sdev->pitch,
 696                                 sdev->format->format, vmap, fb, &clip);
 697
 698        drm_dev_exit(idx);
 699}
 700
 701static const struct drm_simple_display_pipe_funcs
 702simpledrm_simple_display_pipe_funcs = {
 703        .mode_valid = simpledrm_simple_display_pipe_mode_valid,
 704        .enable = simpledrm_simple_display_pipe_enable,
 705        .disable = simpledrm_simple_display_pipe_disable,
 706        .update = simpledrm_simple_display_pipe_update,
 707        DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
 708};
 709
 710static const struct drm_mode_config_funcs simpledrm_mode_config_funcs = {
 711        .fb_create = drm_gem_fb_create_with_dirty,
 712        .atomic_check = drm_atomic_helper_check,
 713        .atomic_commit = drm_atomic_helper_commit,
 714};
 715
 716static const uint32_t *simpledrm_device_formats(struct simpledrm_device *sdev,
 717                                                size_t *nformats_out)
 718{
 719        struct drm_device *dev = &sdev->dev;
 720        size_t i;
 721
 722        if (sdev->nformats)
 723                goto out; /* don't rebuild list on recurring calls */
 724
 725        /* native format goes first */
 726        sdev->formats[0] = sdev->format->format;
 727        sdev->nformats = 1;
 728
 729        /* default formats go second */
 730        for (i = 0; i < ARRAY_SIZE(simpledrm_default_formats); ++i) {
 731                if (simpledrm_default_formats[i] == sdev->format->format)
 732                        continue; /* native format already went first */
 733                sdev->formats[sdev->nformats] = simpledrm_default_formats[i];
 734                sdev->nformats++;
 735        }
 736
 737        /*
 738         * TODO: The simpledrm driver converts framebuffers to the native
 739         * format when copying them to device memory. If there are more
 740         * formats listed than supported by the driver, the native format
 741         * is not supported by the conversion helpers. Therefore *only*
 742         * support the native format and add a conversion helper ASAP.
 743         */
 744        if (drm_WARN_ONCE(dev, i != sdev->nformats,
 745                          "format conversion helpers required for %p4cc",
 746                          &sdev->format->format)) {
 747                sdev->nformats = 1;
 748        }
 749
 750out:
 751        *nformats_out = sdev->nformats;
 752        return sdev->formats;
 753}
 754
 755static int simpledrm_device_init_modeset(struct simpledrm_device *sdev)
 756{
 757        struct drm_device *dev = &sdev->dev;
 758        struct drm_display_mode *mode = &sdev->mode;
 759        struct drm_connector *connector = &sdev->connector;
 760        struct drm_simple_display_pipe *pipe = &sdev->pipe;
 761        const uint32_t *formats;
 762        size_t nformats;
 763        int ret;
 764
 765        ret = drmm_mode_config_init(dev);
 766        if (ret)
 767                return ret;
 768
 769        dev->mode_config.min_width = mode->hdisplay;
 770        dev->mode_config.max_width = mode->hdisplay;
 771        dev->mode_config.min_height = mode->vdisplay;
 772        dev->mode_config.max_height = mode->vdisplay;
 773        dev->mode_config.prefer_shadow_fbdev = true;
 774        dev->mode_config.preferred_depth = sdev->format->cpp[0] * 8;
 775        dev->mode_config.funcs = &simpledrm_mode_config_funcs;
 776
 777        ret = drm_connector_init(dev, connector, &simpledrm_connector_funcs,
 778                                 DRM_MODE_CONNECTOR_Unknown);
 779        if (ret)
 780                return ret;
 781        drm_connector_helper_add(connector, &simpledrm_connector_helper_funcs);
 782
 783        formats = simpledrm_device_formats(sdev, &nformats);
 784
 785        ret = drm_simple_display_pipe_init(dev, pipe, &simpledrm_simple_display_pipe_funcs,
 786                                           formats, nformats, simpledrm_format_modifiers,
 787                                           connector);
 788        if (ret)
 789                return ret;
 790
 791        drm_mode_config_reset(dev);
 792
 793        return 0;
 794}
 795
 796/*
 797 * Init / Cleanup
 798 */
 799
 800static struct simpledrm_device *
 801simpledrm_device_create(struct drm_driver *drv, struct platform_device *pdev)
 802{
 803        struct simpledrm_device *sdev;
 804        int ret;
 805
 806        sdev = devm_drm_dev_alloc(&pdev->dev, drv, struct simpledrm_device,
 807                                  dev);
 808        if (IS_ERR(sdev))
 809                return ERR_CAST(sdev);
 810        sdev->pdev = pdev;
 811        platform_set_drvdata(pdev, sdev);
 812
 813        ret = simpledrm_device_init_clocks(sdev);
 814        if (ret)
 815                return ERR_PTR(ret);
 816        ret = simpledrm_device_init_regulators(sdev);
 817        if (ret)
 818                return ERR_PTR(ret);
 819        ret = simpledrm_device_init_fb(sdev);
 820        if (ret)
 821                return ERR_PTR(ret);
 822        ret = simpledrm_device_init_mm(sdev);
 823        if (ret)
 824                return ERR_PTR(ret);
 825        ret = simpledrm_device_init_modeset(sdev);
 826        if (ret)
 827                return ERR_PTR(ret);
 828
 829        return sdev;
 830}
 831
 832/*
 833 * DRM driver
 834 */
 835
 836DEFINE_DRM_GEM_FOPS(simpledrm_fops);
 837
 838static struct drm_driver simpledrm_driver = {
 839        DRM_GEM_SHMEM_DRIVER_OPS,
 840        .name                   = DRIVER_NAME,
 841        .desc                   = DRIVER_DESC,
 842        .date                   = DRIVER_DATE,
 843        .major                  = DRIVER_MAJOR,
 844        .minor                  = DRIVER_MINOR,
 845        .driver_features        = DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET,
 846        .fops                   = &simpledrm_fops,
 847};
 848
 849/*
 850 * Platform driver
 851 */
 852
 853static int simpledrm_probe(struct platform_device *pdev)
 854{
 855        struct simpledrm_device *sdev;
 856        struct drm_device *dev;
 857        int ret;
 858
 859        sdev = simpledrm_device_create(&simpledrm_driver, pdev);
 860        if (IS_ERR(sdev))
 861                return PTR_ERR(sdev);
 862        dev = &sdev->dev;
 863
 864        ret = drm_dev_register(dev, 0);
 865        if (ret)
 866                return ret;
 867
 868        drm_fbdev_generic_setup(dev, 0);
 869
 870        return 0;
 871}
 872
 873static int simpledrm_remove(struct platform_device *pdev)
 874{
 875        struct simpledrm_device *sdev = platform_get_drvdata(pdev);
 876        struct drm_device *dev = &sdev->dev;
 877
 878        drm_dev_unplug(dev);
 879
 880        return 0;
 881}
 882
 883static const struct of_device_id simpledrm_of_match_table[] = {
 884        { .compatible = "simple-framebuffer", },
 885        { },
 886};
 887MODULE_DEVICE_TABLE(of, simpledrm_of_match_table);
 888
 889static struct platform_driver simpledrm_platform_driver = {
 890        .driver = {
 891                .name = "simple-framebuffer", /* connect to sysfb */
 892                .of_match_table = simpledrm_of_match_table,
 893        },
 894        .probe = simpledrm_probe,
 895        .remove = simpledrm_remove,
 896};
 897
 898module_platform_driver(simpledrm_platform_driver);
 899
 900MODULE_DESCRIPTION(DRIVER_DESC);
 901MODULE_LICENSE("GPL v2");
 902