0001
0002
0003 #include <linux/clk.h>
0004 #include <linux/of_clk.h>
0005 #include <linux/minmax.h>
0006 #include <linux/platform_data/simplefb.h>
0007 #include <linux/platform_device.h>
0008 #include <linux/regulator/consumer.h>
0009
0010 #include <drm/drm_aperture.h>
0011 #include <drm/drm_atomic_state_helper.h>
0012 #include <drm/drm_connector.h>
0013 #include <drm/drm_damage_helper.h>
0014 #include <drm/drm_device.h>
0015 #include <drm/drm_drv.h>
0016 #include <drm/drm_fb_helper.h>
0017 #include <drm/drm_format_helper.h>
0018 #include <drm/drm_gem_atomic_helper.h>
0019 #include <drm/drm_gem_framebuffer_helper.h>
0020 #include <drm/drm_gem_shmem_helper.h>
0021 #include <drm/drm_managed.h>
0022 #include <drm/drm_modeset_helper_vtables.h>
0023 #include <drm/drm_probe_helper.h>
0024 #include <drm/drm_simple_kms_helper.h>
0025
0026 #define DRIVER_NAME "simpledrm"
0027 #define DRIVER_DESC "DRM driver for simple-framebuffer platform devices"
0028 #define DRIVER_DATE "20200625"
0029 #define DRIVER_MAJOR 1
0030 #define DRIVER_MINOR 0
0031
0032
0033
0034
0035
0036 #define RES_MM(d) \
0037 (((d) * 254ul) / (96ul * 10ul))
0038
0039 #define SIMPLEDRM_MODE(hd, vd) \
0040 DRM_SIMPLE_MODE(hd, vd, RES_MM(hd), RES_MM(vd))
0041
0042
0043
0044
0045
0046 static int
0047 simplefb_get_validated_int(struct drm_device *dev, const char *name,
0048 uint32_t value)
0049 {
0050 if (value > INT_MAX) {
0051 drm_err(dev, "simplefb: invalid framebuffer %s of %u\n",
0052 name, value);
0053 return -EINVAL;
0054 }
0055 return (int)value;
0056 }
0057
0058 static int
0059 simplefb_get_validated_int0(struct drm_device *dev, const char *name,
0060 uint32_t value)
0061 {
0062 if (!value) {
0063 drm_err(dev, "simplefb: invalid framebuffer %s of %u\n",
0064 name, value);
0065 return -EINVAL;
0066 }
0067 return simplefb_get_validated_int(dev, name, value);
0068 }
0069
0070 static const struct drm_format_info *
0071 simplefb_get_validated_format(struct drm_device *dev, const char *format_name)
0072 {
0073 static const struct simplefb_format formats[] = SIMPLEFB_FORMATS;
0074 const struct simplefb_format *fmt = formats;
0075 const struct simplefb_format *end = fmt + ARRAY_SIZE(formats);
0076 const struct drm_format_info *info;
0077
0078 if (!format_name) {
0079 drm_err(dev, "simplefb: missing framebuffer format\n");
0080 return ERR_PTR(-EINVAL);
0081 }
0082
0083 while (fmt < end) {
0084 if (!strcmp(format_name, fmt->name)) {
0085 info = drm_format_info(fmt->fourcc);
0086 if (!info)
0087 return ERR_PTR(-EINVAL);
0088 return info;
0089 }
0090 ++fmt;
0091 }
0092
0093 drm_err(dev, "simplefb: unknown framebuffer format %s\n",
0094 format_name);
0095
0096 return ERR_PTR(-EINVAL);
0097 }
0098
0099 static int
0100 simplefb_get_width_pd(struct drm_device *dev,
0101 const struct simplefb_platform_data *pd)
0102 {
0103 return simplefb_get_validated_int0(dev, "width", pd->width);
0104 }
0105
0106 static int
0107 simplefb_get_height_pd(struct drm_device *dev,
0108 const struct simplefb_platform_data *pd)
0109 {
0110 return simplefb_get_validated_int0(dev, "height", pd->height);
0111 }
0112
0113 static int
0114 simplefb_get_stride_pd(struct drm_device *dev,
0115 const struct simplefb_platform_data *pd)
0116 {
0117 return simplefb_get_validated_int(dev, "stride", pd->stride);
0118 }
0119
0120 static const struct drm_format_info *
0121 simplefb_get_format_pd(struct drm_device *dev,
0122 const struct simplefb_platform_data *pd)
0123 {
0124 return simplefb_get_validated_format(dev, pd->format);
0125 }
0126
0127 static int
0128 simplefb_read_u32_of(struct drm_device *dev, struct device_node *of_node,
0129 const char *name, u32 *value)
0130 {
0131 int ret = of_property_read_u32(of_node, name, value);
0132
0133 if (ret)
0134 drm_err(dev, "simplefb: cannot parse framebuffer %s: error %d\n",
0135 name, ret);
0136 return ret;
0137 }
0138
0139 static int
0140 simplefb_read_string_of(struct drm_device *dev, struct device_node *of_node,
0141 const char *name, const char **value)
0142 {
0143 int ret = of_property_read_string(of_node, name, value);
0144
0145 if (ret)
0146 drm_err(dev, "simplefb: cannot parse framebuffer %s: error %d\n",
0147 name, ret);
0148 return ret;
0149 }
0150
0151 static int
0152 simplefb_get_width_of(struct drm_device *dev, struct device_node *of_node)
0153 {
0154 u32 width;
0155 int ret = simplefb_read_u32_of(dev, of_node, "width", &width);
0156
0157 if (ret)
0158 return ret;
0159 return simplefb_get_validated_int0(dev, "width", width);
0160 }
0161
0162 static int
0163 simplefb_get_height_of(struct drm_device *dev, struct device_node *of_node)
0164 {
0165 u32 height;
0166 int ret = simplefb_read_u32_of(dev, of_node, "height", &height);
0167
0168 if (ret)
0169 return ret;
0170 return simplefb_get_validated_int0(dev, "height", height);
0171 }
0172
0173 static int
0174 simplefb_get_stride_of(struct drm_device *dev, struct device_node *of_node)
0175 {
0176 u32 stride;
0177 int ret = simplefb_read_u32_of(dev, of_node, "stride", &stride);
0178
0179 if (ret)
0180 return ret;
0181 return simplefb_get_validated_int(dev, "stride", stride);
0182 }
0183
0184 static const struct drm_format_info *
0185 simplefb_get_format_of(struct drm_device *dev, struct device_node *of_node)
0186 {
0187 const char *format;
0188 int ret = simplefb_read_string_of(dev, of_node, "format", &format);
0189
0190 if (ret)
0191 return ERR_PTR(ret);
0192 return simplefb_get_validated_format(dev, format);
0193 }
0194
0195
0196
0197
0198
0199 struct simpledrm_device {
0200 struct drm_device dev;
0201 struct platform_device *pdev;
0202
0203
0204 #if defined CONFIG_OF && defined CONFIG_COMMON_CLK
0205 unsigned int clk_count;
0206 struct clk **clks;
0207 #endif
0208
0209 #if defined CONFIG_OF && defined CONFIG_REGULATOR
0210 unsigned int regulator_count;
0211 struct regulator **regulators;
0212 #endif
0213
0214
0215 struct drm_display_mode mode;
0216 const struct drm_format_info *format;
0217 unsigned int pitch;
0218
0219
0220 struct resource *mem;
0221 void __iomem *screen_base;
0222
0223
0224 uint32_t formats[8];
0225 size_t nformats;
0226 struct drm_connector connector;
0227 struct drm_simple_display_pipe pipe;
0228 };
0229
0230 static struct simpledrm_device *simpledrm_device_of_dev(struct drm_device *dev)
0231 {
0232 return container_of(dev, struct simpledrm_device, dev);
0233 }
0234
0235
0236
0237
0238
0239 #if defined CONFIG_OF && defined CONFIG_COMMON_CLK
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259 static void simpledrm_device_release_clocks(void *res)
0260 {
0261 struct simpledrm_device *sdev = simpledrm_device_of_dev(res);
0262 unsigned int i;
0263
0264 for (i = 0; i < sdev->clk_count; ++i) {
0265 if (sdev->clks[i]) {
0266 clk_disable_unprepare(sdev->clks[i]);
0267 clk_put(sdev->clks[i]);
0268 }
0269 }
0270 }
0271
0272 static int simpledrm_device_init_clocks(struct simpledrm_device *sdev)
0273 {
0274 struct drm_device *dev = &sdev->dev;
0275 struct platform_device *pdev = sdev->pdev;
0276 struct device_node *of_node = pdev->dev.of_node;
0277 struct clk *clock;
0278 unsigned int i;
0279 int ret;
0280
0281 if (dev_get_platdata(&pdev->dev) || !of_node)
0282 return 0;
0283
0284 sdev->clk_count = of_clk_get_parent_count(of_node);
0285 if (!sdev->clk_count)
0286 return 0;
0287
0288 sdev->clks = drmm_kzalloc(dev, sdev->clk_count * sizeof(sdev->clks[0]),
0289 GFP_KERNEL);
0290 if (!sdev->clks)
0291 return -ENOMEM;
0292
0293 for (i = 0; i < sdev->clk_count; ++i) {
0294 clock = of_clk_get(of_node, i);
0295 if (IS_ERR(clock)) {
0296 ret = PTR_ERR(clock);
0297 if (ret == -EPROBE_DEFER)
0298 goto err;
0299 drm_err(dev, "clock %u not found: %d\n", i, ret);
0300 continue;
0301 }
0302 ret = clk_prepare_enable(clock);
0303 if (ret) {
0304 drm_err(dev, "failed to enable clock %u: %d\n",
0305 i, ret);
0306 clk_put(clock);
0307 continue;
0308 }
0309 sdev->clks[i] = clock;
0310 }
0311
0312 return devm_add_action_or_reset(&pdev->dev,
0313 simpledrm_device_release_clocks,
0314 sdev);
0315
0316 err:
0317 while (i) {
0318 --i;
0319 if (sdev->clks[i]) {
0320 clk_disable_unprepare(sdev->clks[i]);
0321 clk_put(sdev->clks[i]);
0322 }
0323 }
0324 return ret;
0325 }
0326 #else
0327 static int simpledrm_device_init_clocks(struct simpledrm_device *sdev)
0328 {
0329 return 0;
0330 }
0331 #endif
0332
0333 #if defined CONFIG_OF && defined CONFIG_REGULATOR
0334
0335 #define SUPPLY_SUFFIX "-supply"
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357 static void simpledrm_device_release_regulators(void *res)
0358 {
0359 struct simpledrm_device *sdev = simpledrm_device_of_dev(res);
0360 unsigned int i;
0361
0362 for (i = 0; i < sdev->regulator_count; ++i) {
0363 if (sdev->regulators[i]) {
0364 regulator_disable(sdev->regulators[i]);
0365 regulator_put(sdev->regulators[i]);
0366 }
0367 }
0368 }
0369
0370 static int simpledrm_device_init_regulators(struct simpledrm_device *sdev)
0371 {
0372 struct drm_device *dev = &sdev->dev;
0373 struct platform_device *pdev = sdev->pdev;
0374 struct device_node *of_node = pdev->dev.of_node;
0375 struct property *prop;
0376 struct regulator *regulator;
0377 const char *p;
0378 unsigned int count = 0, i = 0;
0379 int ret;
0380
0381 if (dev_get_platdata(&pdev->dev) || !of_node)
0382 return 0;
0383
0384
0385 for_each_property_of_node(of_node, prop) {
0386 p = strstr(prop->name, SUPPLY_SUFFIX);
0387 if (p && p != prop->name)
0388 ++count;
0389 }
0390
0391 if (!count)
0392 return 0;
0393
0394 sdev->regulators = drmm_kzalloc(dev,
0395 count * sizeof(sdev->regulators[0]),
0396 GFP_KERNEL);
0397 if (!sdev->regulators)
0398 return -ENOMEM;
0399
0400 for_each_property_of_node(of_node, prop) {
0401 char name[32];
0402 size_t len;
0403
0404 p = strstr(prop->name, SUPPLY_SUFFIX);
0405 if (!p || p == prop->name)
0406 continue;
0407 len = strlen(prop->name) - strlen(SUPPLY_SUFFIX) + 1;
0408 strscpy(name, prop->name, min(sizeof(name), len));
0409
0410 regulator = regulator_get_optional(&pdev->dev, name);
0411 if (IS_ERR(regulator)) {
0412 ret = PTR_ERR(regulator);
0413 if (ret == -EPROBE_DEFER)
0414 goto err;
0415 drm_err(dev, "regulator %s not found: %d\n",
0416 name, ret);
0417 continue;
0418 }
0419
0420 ret = regulator_enable(regulator);
0421 if (ret) {
0422 drm_err(dev, "failed to enable regulator %u: %d\n",
0423 i, ret);
0424 regulator_put(regulator);
0425 continue;
0426 }
0427
0428 sdev->regulators[i++] = regulator;
0429 }
0430 sdev->regulator_count = i;
0431
0432 return devm_add_action_or_reset(&pdev->dev,
0433 simpledrm_device_release_regulators,
0434 sdev);
0435
0436 err:
0437 while (i) {
0438 --i;
0439 if (sdev->regulators[i]) {
0440 regulator_disable(sdev->regulators[i]);
0441 regulator_put(sdev->regulators[i]);
0442 }
0443 }
0444 return ret;
0445 }
0446 #else
0447 static int simpledrm_device_init_regulators(struct simpledrm_device *sdev)
0448 {
0449 return 0;
0450 }
0451 #endif
0452
0453
0454
0455
0456
0457 static struct drm_display_mode simpledrm_mode(unsigned int width,
0458 unsigned int height)
0459 {
0460 struct drm_display_mode mode = { SIMPLEDRM_MODE(width, height) };
0461
0462 mode.clock = mode.hdisplay * mode.vdisplay * 60 / 1000 ;
0463 drm_mode_set_name(&mode);
0464
0465 return mode;
0466 }
0467
0468 static int simpledrm_device_init_fb(struct simpledrm_device *sdev)
0469 {
0470 int width, height, stride;
0471 const struct drm_format_info *format;
0472 struct drm_device *dev = &sdev->dev;
0473 struct platform_device *pdev = sdev->pdev;
0474 const struct simplefb_platform_data *pd = dev_get_platdata(&pdev->dev);
0475 struct device_node *of_node = pdev->dev.of_node;
0476
0477 if (pd) {
0478 width = simplefb_get_width_pd(dev, pd);
0479 if (width < 0)
0480 return width;
0481 height = simplefb_get_height_pd(dev, pd);
0482 if (height < 0)
0483 return height;
0484 stride = simplefb_get_stride_pd(dev, pd);
0485 if (stride < 0)
0486 return stride;
0487 format = simplefb_get_format_pd(dev, pd);
0488 if (IS_ERR(format))
0489 return PTR_ERR(format);
0490 } else if (of_node) {
0491 width = simplefb_get_width_of(dev, of_node);
0492 if (width < 0)
0493 return width;
0494 height = simplefb_get_height_of(dev, of_node);
0495 if (height < 0)
0496 return height;
0497 stride = simplefb_get_stride_of(dev, of_node);
0498 if (stride < 0)
0499 return stride;
0500 format = simplefb_get_format_of(dev, of_node);
0501 if (IS_ERR(format))
0502 return PTR_ERR(format);
0503 } else {
0504 drm_err(dev, "no simplefb configuration found\n");
0505 return -ENODEV;
0506 }
0507
0508 sdev->mode = simpledrm_mode(width, height);
0509 sdev->format = format;
0510 sdev->pitch = stride;
0511
0512 drm_dbg_kms(dev, "display mode={" DRM_MODE_FMT "}\n",
0513 DRM_MODE_ARG(&sdev->mode));
0514 drm_dbg_kms(dev,
0515 "framebuffer format=%p4cc, size=%dx%d, stride=%d byte\n",
0516 &format->format, width, height, stride);
0517
0518 return 0;
0519 }
0520
0521
0522
0523
0524
0525 static int simpledrm_device_init_mm(struct simpledrm_device *sdev)
0526 {
0527 struct drm_device *dev = &sdev->dev;
0528 struct platform_device *pdev = sdev->pdev;
0529 struct resource *res, *mem;
0530 void __iomem *screen_base;
0531 int ret;
0532
0533 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0534 if (!res)
0535 return -EINVAL;
0536
0537 ret = devm_aperture_acquire_from_firmware(dev, res->start, resource_size(res));
0538 if (ret) {
0539 drm_err(dev, "could not acquire memory range %pr: error %d\n",
0540 res, ret);
0541 return ret;
0542 }
0543
0544 mem = devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
0545 sdev->dev.driver->name);
0546 if (!mem) {
0547
0548
0549
0550
0551
0552 drm_warn(dev, "could not acquire memory region %pr\n", res);
0553 mem = res;
0554 }
0555
0556 screen_base = devm_ioremap_wc(&pdev->dev, mem->start,
0557 resource_size(mem));
0558 if (!screen_base)
0559 return -ENOMEM;
0560
0561 sdev->mem = mem;
0562 sdev->screen_base = screen_base;
0563
0564 return 0;
0565 }
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579 static const uint32_t simpledrm_default_formats[] = {
0580 DRM_FORMAT_XRGB8888,
0581 DRM_FORMAT_ARGB8888,
0582 DRM_FORMAT_RGB565,
0583
0584
0585 DRM_FORMAT_RGB888,
0586 DRM_FORMAT_XRGB2101010,
0587 DRM_FORMAT_ARGB2101010,
0588 };
0589
0590 static const uint64_t simpledrm_format_modifiers[] = {
0591 DRM_FORMAT_MOD_LINEAR,
0592 DRM_FORMAT_MOD_INVALID
0593 };
0594
0595 static int simpledrm_connector_helper_get_modes(struct drm_connector *connector)
0596 {
0597 struct simpledrm_device *sdev = simpledrm_device_of_dev(connector->dev);
0598 struct drm_display_mode *mode;
0599
0600 mode = drm_mode_duplicate(connector->dev, &sdev->mode);
0601 if (!mode)
0602 return 0;
0603
0604 if (mode->name[0] == '\0')
0605 drm_mode_set_name(mode);
0606
0607 mode->type |= DRM_MODE_TYPE_PREFERRED;
0608 drm_mode_probed_add(connector, mode);
0609
0610 if (mode->width_mm)
0611 connector->display_info.width_mm = mode->width_mm;
0612 if (mode->height_mm)
0613 connector->display_info.height_mm = mode->height_mm;
0614
0615 return 1;
0616 }
0617
0618 static const struct drm_connector_helper_funcs simpledrm_connector_helper_funcs = {
0619 .get_modes = simpledrm_connector_helper_get_modes,
0620 };
0621
0622 static const struct drm_connector_funcs simpledrm_connector_funcs = {
0623 .reset = drm_atomic_helper_connector_reset,
0624 .fill_modes = drm_helper_probe_single_connector_modes,
0625 .destroy = drm_connector_cleanup,
0626 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
0627 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
0628 };
0629
0630 static enum drm_mode_status
0631 simpledrm_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
0632 const struct drm_display_mode *mode)
0633 {
0634 struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev);
0635
0636 if (mode->hdisplay != sdev->mode.hdisplay &&
0637 mode->vdisplay != sdev->mode.vdisplay)
0638 return MODE_ONE_SIZE;
0639 else if (mode->hdisplay != sdev->mode.hdisplay)
0640 return MODE_ONE_WIDTH;
0641 else if (mode->vdisplay != sdev->mode.vdisplay)
0642 return MODE_ONE_HEIGHT;
0643
0644 return MODE_OK;
0645 }
0646
0647 static void
0648 simpledrm_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
0649 struct drm_crtc_state *crtc_state,
0650 struct drm_plane_state *plane_state)
0651 {
0652 struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev);
0653 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
0654 struct drm_framebuffer *fb = plane_state->fb;
0655 void *vmap = shadow_plane_state->data[0].vaddr;
0656 struct drm_device *dev = &sdev->dev;
0657 void __iomem *dst = sdev->screen_base;
0658 struct drm_rect src_clip, dst_clip;
0659 int idx;
0660
0661 if (!fb)
0662 return;
0663
0664 drm_rect_fp_to_int(&src_clip, &plane_state->src);
0665
0666 dst_clip = plane_state->dst;
0667 if (!drm_rect_intersect(&dst_clip, &src_clip))
0668 return;
0669
0670 if (!drm_dev_enter(dev, &idx))
0671 return;
0672
0673 dst += drm_fb_clip_offset(sdev->pitch, sdev->format, &dst_clip);
0674 drm_fb_blit_toio(dst, sdev->pitch, sdev->format->format, vmap, fb, &src_clip);
0675
0676 drm_dev_exit(idx);
0677 }
0678
0679 static void
0680 simpledrm_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe)
0681 {
0682 struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev);
0683 struct drm_device *dev = &sdev->dev;
0684 int idx;
0685
0686 if (!drm_dev_enter(dev, &idx))
0687 return;
0688
0689
0690 memset_io(sdev->screen_base, 0, sdev->pitch * sdev->mode.vdisplay);
0691
0692 drm_dev_exit(idx);
0693 }
0694
0695 static void
0696 simpledrm_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
0697 struct drm_plane_state *old_plane_state)
0698 {
0699 struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev);
0700 struct drm_plane_state *plane_state = pipe->plane.state;
0701 struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
0702 void *vmap = shadow_plane_state->data[0].vaddr;
0703 struct drm_framebuffer *fb = plane_state->fb;
0704 struct drm_device *dev = &sdev->dev;
0705 void __iomem *dst = sdev->screen_base;
0706 struct drm_rect src_clip, dst_clip;
0707 int idx;
0708
0709 if (!fb)
0710 return;
0711
0712 if (!drm_atomic_helper_damage_merged(old_plane_state, plane_state, &src_clip))
0713 return;
0714
0715 dst_clip = plane_state->dst;
0716 if (!drm_rect_intersect(&dst_clip, &src_clip))
0717 return;
0718
0719 if (!drm_dev_enter(dev, &idx))
0720 return;
0721
0722 dst += drm_fb_clip_offset(sdev->pitch, sdev->format, &dst_clip);
0723 drm_fb_blit_toio(dst, sdev->pitch, sdev->format->format, vmap, fb, &src_clip);
0724
0725 drm_dev_exit(idx);
0726 }
0727
0728 static const struct drm_simple_display_pipe_funcs
0729 simpledrm_simple_display_pipe_funcs = {
0730 .mode_valid = simpledrm_simple_display_pipe_mode_valid,
0731 .enable = simpledrm_simple_display_pipe_enable,
0732 .disable = simpledrm_simple_display_pipe_disable,
0733 .update = simpledrm_simple_display_pipe_update,
0734 DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
0735 };
0736
0737 static const struct drm_mode_config_funcs simpledrm_mode_config_funcs = {
0738 .fb_create = drm_gem_fb_create_with_dirty,
0739 .atomic_check = drm_atomic_helper_check,
0740 .atomic_commit = drm_atomic_helper_commit,
0741 };
0742
0743 static const uint32_t *simpledrm_device_formats(struct simpledrm_device *sdev,
0744 size_t *nformats_out)
0745 {
0746 struct drm_device *dev = &sdev->dev;
0747 size_t i;
0748
0749 if (sdev->nformats)
0750 goto out;
0751
0752
0753 sdev->formats[0] = sdev->format->format;
0754 sdev->nformats = 1;
0755
0756
0757 for (i = 0; i < ARRAY_SIZE(simpledrm_default_formats); ++i) {
0758 if (simpledrm_default_formats[i] == sdev->format->format)
0759 continue;
0760 sdev->formats[sdev->nformats] = simpledrm_default_formats[i];
0761 sdev->nformats++;
0762 }
0763
0764
0765
0766
0767
0768
0769
0770
0771 if (drm_WARN_ONCE(dev, i != sdev->nformats,
0772 "format conversion helpers required for %p4cc",
0773 &sdev->format->format)) {
0774 sdev->nformats = 1;
0775 }
0776
0777 out:
0778 *nformats_out = sdev->nformats;
0779 return sdev->formats;
0780 }
0781
0782 static int simpledrm_device_init_modeset(struct simpledrm_device *sdev)
0783 {
0784 struct drm_device *dev = &sdev->dev;
0785 struct drm_display_mode *mode = &sdev->mode;
0786 struct drm_connector *connector = &sdev->connector;
0787 struct drm_simple_display_pipe *pipe = &sdev->pipe;
0788 unsigned long max_width, max_height;
0789 const uint32_t *formats;
0790 size_t nformats;
0791 int ret;
0792
0793 ret = drmm_mode_config_init(dev);
0794 if (ret)
0795 return ret;
0796
0797 max_width = max_t(unsigned long, mode->hdisplay, DRM_SHADOW_PLANE_MAX_WIDTH);
0798 max_height = max_t(unsigned long, mode->vdisplay, DRM_SHADOW_PLANE_MAX_HEIGHT);
0799
0800 dev->mode_config.min_width = mode->hdisplay;
0801 dev->mode_config.max_width = max_width;
0802 dev->mode_config.min_height = mode->vdisplay;
0803 dev->mode_config.max_height = max_height;
0804 dev->mode_config.preferred_depth = sdev->format->cpp[0] * 8;
0805 dev->mode_config.funcs = &simpledrm_mode_config_funcs;
0806
0807 ret = drm_connector_init(dev, connector, &simpledrm_connector_funcs,
0808 DRM_MODE_CONNECTOR_Unknown);
0809 if (ret)
0810 return ret;
0811 drm_connector_helper_add(connector, &simpledrm_connector_helper_funcs);
0812 drm_connector_set_panel_orientation_with_quirk(connector,
0813 DRM_MODE_PANEL_ORIENTATION_UNKNOWN,
0814 mode->hdisplay, mode->vdisplay);
0815
0816 formats = simpledrm_device_formats(sdev, &nformats);
0817
0818 ret = drm_simple_display_pipe_init(dev, pipe, &simpledrm_simple_display_pipe_funcs,
0819 formats, nformats, simpledrm_format_modifiers,
0820 connector);
0821 if (ret)
0822 return ret;
0823
0824 drm_plane_enable_fb_damage_clips(&pipe->plane);
0825
0826 drm_mode_config_reset(dev);
0827
0828 return 0;
0829 }
0830
0831
0832
0833
0834
0835 static struct simpledrm_device *
0836 simpledrm_device_create(struct drm_driver *drv, struct platform_device *pdev)
0837 {
0838 struct simpledrm_device *sdev;
0839 int ret;
0840
0841 sdev = devm_drm_dev_alloc(&pdev->dev, drv, struct simpledrm_device,
0842 dev);
0843 if (IS_ERR(sdev))
0844 return ERR_CAST(sdev);
0845 sdev->pdev = pdev;
0846 platform_set_drvdata(pdev, sdev);
0847
0848 ret = simpledrm_device_init_clocks(sdev);
0849 if (ret)
0850 return ERR_PTR(ret);
0851 ret = simpledrm_device_init_regulators(sdev);
0852 if (ret)
0853 return ERR_PTR(ret);
0854 ret = simpledrm_device_init_fb(sdev);
0855 if (ret)
0856 return ERR_PTR(ret);
0857 ret = simpledrm_device_init_mm(sdev);
0858 if (ret)
0859 return ERR_PTR(ret);
0860 ret = simpledrm_device_init_modeset(sdev);
0861 if (ret)
0862 return ERR_PTR(ret);
0863
0864 return sdev;
0865 }
0866
0867
0868
0869
0870
0871 DEFINE_DRM_GEM_FOPS(simpledrm_fops);
0872
0873 static struct drm_driver simpledrm_driver = {
0874 DRM_GEM_SHMEM_DRIVER_OPS,
0875 .name = DRIVER_NAME,
0876 .desc = DRIVER_DESC,
0877 .date = DRIVER_DATE,
0878 .major = DRIVER_MAJOR,
0879 .minor = DRIVER_MINOR,
0880 .driver_features = DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET,
0881 .fops = &simpledrm_fops,
0882 };
0883
0884
0885
0886
0887
0888 static int simpledrm_probe(struct platform_device *pdev)
0889 {
0890 struct simpledrm_device *sdev;
0891 struct drm_device *dev;
0892 int ret;
0893
0894 sdev = simpledrm_device_create(&simpledrm_driver, pdev);
0895 if (IS_ERR(sdev))
0896 return PTR_ERR(sdev);
0897 dev = &sdev->dev;
0898
0899 ret = drm_dev_register(dev, 0);
0900 if (ret)
0901 return ret;
0902
0903 drm_fbdev_generic_setup(dev, 0);
0904
0905 return 0;
0906 }
0907
0908 static int simpledrm_remove(struct platform_device *pdev)
0909 {
0910 struct simpledrm_device *sdev = platform_get_drvdata(pdev);
0911 struct drm_device *dev = &sdev->dev;
0912
0913 drm_dev_unplug(dev);
0914
0915 return 0;
0916 }
0917
0918 static const struct of_device_id simpledrm_of_match_table[] = {
0919 { .compatible = "simple-framebuffer", },
0920 { },
0921 };
0922 MODULE_DEVICE_TABLE(of, simpledrm_of_match_table);
0923
0924 static struct platform_driver simpledrm_platform_driver = {
0925 .driver = {
0926 .name = "simple-framebuffer",
0927 .of_match_table = simpledrm_of_match_table,
0928 },
0929 .probe = simpledrm_probe,
0930 .remove = simpledrm_remove,
0931 };
0932
0933 module_platform_driver(simpledrm_platform_driver);
0934
0935 MODULE_DESCRIPTION(DRIVER_DESC);
0936 MODULE_LICENSE("GPL v2");