1 // SPDX-License-Identifier: GPL-2.0-only
4 #include <linux/of_clk.h>
5 #include <linux/minmax.h>
6 #include <linux/of_address.h>
7 #include <linux/platform_data/simplefb.h>
8 #include <linux/platform_device.h>
9 #include <linux/regulator/consumer.h>
11 #include <drm/drm_aperture.h>
12 #include <drm/drm_atomic.h>
13 #include <drm/drm_atomic_state_helper.h>
14 #include <drm/drm_connector.h>
15 #include <drm/drm_crtc_helper.h>
16 #include <drm/drm_damage_helper.h>
17 #include <drm/drm_device.h>
18 #include <drm/drm_drv.h>
19 #include <drm/drm_fbdev_generic.h>
20 #include <drm/drm_format_helper.h>
21 #include <drm/drm_gem_atomic_helper.h>
22 #include <drm/drm_gem_framebuffer_helper.h>
23 #include <drm/drm_gem_shmem_helper.h>
24 #include <drm/drm_managed.h>
25 #include <drm/drm_modeset_helper_vtables.h>
26 #include <drm/drm_plane_helper.h>
27 #include <drm/drm_probe_helper.h>
29 #define DRIVER_NAME "simpledrm"
30 #define DRIVER_DESC "DRM driver for simple-framebuffer platform devices"
31 #define DRIVER_DATE "20200625"
32 #define DRIVER_MAJOR 1
33 #define DRIVER_MINOR 0
36 * Helpers for simplefb
40 simplefb_get_validated_int(struct drm_device
*dev
, const char *name
,
43 if (value
> INT_MAX
) {
44 drm_err(dev
, "simplefb: invalid framebuffer %s of %u\n",
52 simplefb_get_validated_int0(struct drm_device
*dev
, const char *name
,
56 drm_err(dev
, "simplefb: invalid framebuffer %s of %u\n",
60 return simplefb_get_validated_int(dev
, name
, value
);
63 static const struct drm_format_info
*
64 simplefb_get_validated_format(struct drm_device
*dev
, const char *format_name
)
66 static const struct simplefb_format formats
[] = SIMPLEFB_FORMATS
;
67 const struct simplefb_format
*fmt
= formats
;
68 const struct simplefb_format
*end
= fmt
+ ARRAY_SIZE(formats
);
69 const struct drm_format_info
*info
;
72 drm_err(dev
, "simplefb: missing framebuffer format\n");
73 return ERR_PTR(-EINVAL
);
77 if (!strcmp(format_name
, fmt
->name
)) {
78 info
= drm_format_info(fmt
->fourcc
);
80 return ERR_PTR(-EINVAL
);
86 drm_err(dev
, "simplefb: unknown framebuffer format %s\n",
89 return ERR_PTR(-EINVAL
);
93 simplefb_get_width_pd(struct drm_device
*dev
,
94 const struct simplefb_platform_data
*pd
)
96 return simplefb_get_validated_int0(dev
, "width", pd
->width
);
100 simplefb_get_height_pd(struct drm_device
*dev
,
101 const struct simplefb_platform_data
*pd
)
103 return simplefb_get_validated_int0(dev
, "height", pd
->height
);
107 simplefb_get_stride_pd(struct drm_device
*dev
,
108 const struct simplefb_platform_data
*pd
)
110 return simplefb_get_validated_int(dev
, "stride", pd
->stride
);
113 static const struct drm_format_info
*
114 simplefb_get_format_pd(struct drm_device
*dev
,
115 const struct simplefb_platform_data
*pd
)
117 return simplefb_get_validated_format(dev
, pd
->format
);
121 simplefb_read_u32_of(struct drm_device
*dev
, struct device_node
*of_node
,
122 const char *name
, u32
*value
)
124 int ret
= of_property_read_u32(of_node
, name
, value
);
127 drm_err(dev
, "simplefb: cannot parse framebuffer %s: error %d\n",
133 simplefb_read_string_of(struct drm_device
*dev
, struct device_node
*of_node
,
134 const char *name
, const char **value
)
136 int ret
= of_property_read_string(of_node
, name
, value
);
139 drm_err(dev
, "simplefb: cannot parse framebuffer %s: error %d\n",
145 simplefb_get_width_of(struct drm_device
*dev
, struct device_node
*of_node
)
148 int ret
= simplefb_read_u32_of(dev
, of_node
, "width", &width
);
152 return simplefb_get_validated_int0(dev
, "width", width
);
156 simplefb_get_height_of(struct drm_device
*dev
, struct device_node
*of_node
)
159 int ret
= simplefb_read_u32_of(dev
, of_node
, "height", &height
);
163 return simplefb_get_validated_int0(dev
, "height", height
);
167 simplefb_get_stride_of(struct drm_device
*dev
, struct device_node
*of_node
)
170 int ret
= simplefb_read_u32_of(dev
, of_node
, "stride", &stride
);
174 return simplefb_get_validated_int(dev
, "stride", stride
);
177 static const struct drm_format_info
*
178 simplefb_get_format_of(struct drm_device
*dev
, struct device_node
*of_node
)
181 int ret
= simplefb_read_string_of(dev
, of_node
, "format", &format
);
185 return simplefb_get_validated_format(dev
, format
);
188 static struct resource
*
189 simplefb_get_memory_of(struct drm_device
*dev
, struct device_node
*of_node
)
191 struct device_node
*np
;
192 struct resource
*res
;
195 np
= of_parse_phandle(of_node
, "memory-region", 0);
199 res
= devm_kzalloc(dev
->dev
, sizeof(*res
), GFP_KERNEL
);
201 return ERR_PTR(-ENOMEM
);
203 err
= of_address_to_resource(np
, 0, res
);
207 if (of_property_present(of_node
, "reg"))
208 drm_warn(dev
, "preferring \"memory-region\" over \"reg\" property\n");
214 * Simple Framebuffer device
217 struct simpledrm_device
{
218 struct drm_device dev
;
221 #if defined CONFIG_OF && defined CONFIG_COMMON_CLK
222 unsigned int clk_count
;
226 #if defined CONFIG_OF && defined CONFIG_REGULATOR
227 unsigned int regulator_count
;
228 struct regulator
**regulators
;
231 /* simplefb settings */
232 struct drm_display_mode mode
;
233 const struct drm_format_info
*format
;
236 /* memory management */
237 struct iosys_map screen_base
;
242 struct drm_plane primary_plane
;
243 struct drm_crtc crtc
;
244 struct drm_encoder encoder
;
245 struct drm_connector connector
;
248 static struct simpledrm_device
*simpledrm_device_of_dev(struct drm_device
*dev
)
250 return container_of(dev
, struct simpledrm_device
, dev
);
257 #if defined CONFIG_OF && defined CONFIG_COMMON_CLK
259 * Clock handling code.
261 * Here we handle the clocks property of our "simple-framebuffer" dt node.
262 * This is necessary so that we can make sure that any clocks needed by
263 * the display engine that the bootloader set up for us (and for which it
264 * provided a simplefb dt node), stay up, for the life of the simplefb
267 * When the driver unloads, we cleanly disable, and then release the clocks.
269 * We only complain about errors here, no action is taken as the most likely
270 * error can only happen due to a mismatch between the bootloader which set
271 * up simplefb, and the clock definitions in the device tree. Chances are
272 * that there are no adverse effects, and if there are, a clean teardown of
273 * the fb probe will not help us much either. So just complain and carry on,
274 * and hope that the user actually gets a working fb at the end of things.
277 static void simpledrm_device_release_clocks(void *res
)
279 struct simpledrm_device
*sdev
= simpledrm_device_of_dev(res
);
282 for (i
= 0; i
< sdev
->clk_count
; ++i
) {
284 clk_disable_unprepare(sdev
->clks
[i
]);
285 clk_put(sdev
->clks
[i
]);
290 static int simpledrm_device_init_clocks(struct simpledrm_device
*sdev
)
292 struct drm_device
*dev
= &sdev
->dev
;
293 struct platform_device
*pdev
= to_platform_device(dev
->dev
);
294 struct device_node
*of_node
= pdev
->dev
.of_node
;
299 if (dev_get_platdata(&pdev
->dev
) || !of_node
)
302 sdev
->clk_count
= of_clk_get_parent_count(of_node
);
303 if (!sdev
->clk_count
)
306 sdev
->clks
= drmm_kzalloc(dev
, sdev
->clk_count
* sizeof(sdev
->clks
[0]),
311 for (i
= 0; i
< sdev
->clk_count
; ++i
) {
312 clock
= of_clk_get(of_node
, i
);
314 ret
= PTR_ERR(clock
);
315 if (ret
== -EPROBE_DEFER
)
317 drm_err(dev
, "clock %u not found: %d\n", i
, ret
);
320 ret
= clk_prepare_enable(clock
);
322 drm_err(dev
, "failed to enable clock %u: %d\n",
327 sdev
->clks
[i
] = clock
;
330 return devm_add_action_or_reset(&pdev
->dev
,
331 simpledrm_device_release_clocks
,
338 clk_disable_unprepare(sdev
->clks
[i
]);
339 clk_put(sdev
->clks
[i
]);
345 static int simpledrm_device_init_clocks(struct simpledrm_device
*sdev
)
351 #if defined CONFIG_OF && defined CONFIG_REGULATOR
353 #define SUPPLY_SUFFIX "-supply"
356 * Regulator handling code.
358 * Here we handle the num-supplies and vin*-supply properties of our
359 * "simple-framebuffer" dt node. This is necessary so that we can make sure
360 * that any regulators needed by the display hardware that the bootloader
361 * set up for us (and for which it provided a simplefb dt node), stay up,
362 * for the life of the simplefb driver.
364 * When the driver unloads, we cleanly disable, and then release the
367 * We only complain about errors here, no action is taken as the most likely
368 * error can only happen due to a mismatch between the bootloader which set
369 * up simplefb, and the regulator definitions in the device tree. Chances are
370 * that there are no adverse effects, and if there are, a clean teardown of
371 * the fb probe will not help us much either. So just complain and carry on,
372 * and hope that the user actually gets a working fb at the end of things.
375 static void simpledrm_device_release_regulators(void *res
)
377 struct simpledrm_device
*sdev
= simpledrm_device_of_dev(res
);
380 for (i
= 0; i
< sdev
->regulator_count
; ++i
) {
381 if (sdev
->regulators
[i
]) {
382 regulator_disable(sdev
->regulators
[i
]);
383 regulator_put(sdev
->regulators
[i
]);
388 static int simpledrm_device_init_regulators(struct simpledrm_device
*sdev
)
390 struct drm_device
*dev
= &sdev
->dev
;
391 struct platform_device
*pdev
= to_platform_device(dev
->dev
);
392 struct device_node
*of_node
= pdev
->dev
.of_node
;
393 struct property
*prop
;
394 struct regulator
*regulator
;
396 unsigned int count
= 0, i
= 0;
399 if (dev_get_platdata(&pdev
->dev
) || !of_node
)
402 /* Count the number of regulator supplies */
403 for_each_property_of_node(of_node
, prop
) {
404 p
= strstr(prop
->name
, SUPPLY_SUFFIX
);
405 if (p
&& p
!= prop
->name
)
412 sdev
->regulators
= drmm_kzalloc(dev
,
413 count
* sizeof(sdev
->regulators
[0]),
415 if (!sdev
->regulators
)
418 for_each_property_of_node(of_node
, prop
) {
419 char name
[32]; /* 32 is max size of property name */
422 p
= strstr(prop
->name
, SUPPLY_SUFFIX
);
423 if (!p
|| p
== prop
->name
)
425 len
= strlen(prop
->name
) - strlen(SUPPLY_SUFFIX
) + 1;
426 strscpy(name
, prop
->name
, min(sizeof(name
), len
));
428 regulator
= regulator_get_optional(&pdev
->dev
, name
);
429 if (IS_ERR(regulator
)) {
430 ret
= PTR_ERR(regulator
);
431 if (ret
== -EPROBE_DEFER
)
433 drm_err(dev
, "regulator %s not found: %d\n",
438 ret
= regulator_enable(regulator
);
440 drm_err(dev
, "failed to enable regulator %u: %d\n",
442 regulator_put(regulator
);
446 sdev
->regulators
[i
++] = regulator
;
448 sdev
->regulator_count
= i
;
450 return devm_add_action_or_reset(&pdev
->dev
,
451 simpledrm_device_release_regulators
,
457 if (sdev
->regulators
[i
]) {
458 regulator_disable(sdev
->regulators
[i
]);
459 regulator_put(sdev
->regulators
[i
]);
465 static int simpledrm_device_init_regulators(struct simpledrm_device
*sdev
)
475 static const uint64_t simpledrm_primary_plane_format_modifiers
[] = {
476 DRM_FORMAT_MOD_LINEAR
,
477 DRM_FORMAT_MOD_INVALID
480 static void simpledrm_primary_plane_helper_atomic_update(struct drm_plane
*plane
,
481 struct drm_atomic_state
*state
)
483 struct drm_plane_state
*plane_state
= drm_atomic_get_new_plane_state(state
, plane
);
484 struct drm_plane_state
*old_plane_state
= drm_atomic_get_old_plane_state(state
, plane
);
485 struct drm_shadow_plane_state
*shadow_plane_state
= to_drm_shadow_plane_state(plane_state
);
486 struct drm_framebuffer
*fb
= plane_state
->fb
;
487 struct drm_device
*dev
= plane
->dev
;
488 struct simpledrm_device
*sdev
= simpledrm_device_of_dev(dev
);
489 struct drm_atomic_helper_damage_iter iter
;
490 struct drm_rect damage
;
493 ret
= drm_gem_fb_begin_cpu_access(fb
, DMA_FROM_DEVICE
);
497 if (!drm_dev_enter(dev
, &idx
))
498 goto out_drm_gem_fb_end_cpu_access
;
500 drm_atomic_helper_damage_iter_init(&iter
, old_plane_state
, plane_state
);
501 drm_atomic_for_each_plane_damage(&iter
, &damage
) {
502 struct drm_rect dst_clip
= plane_state
->dst
;
503 struct iosys_map dst
= sdev
->screen_base
;
505 if (!drm_rect_intersect(&dst_clip
, &damage
))
508 iosys_map_incr(&dst
, drm_fb_clip_offset(sdev
->pitch
, sdev
->format
, &dst_clip
));
509 drm_fb_blit(&dst
, &sdev
->pitch
, sdev
->format
->format
, shadow_plane_state
->data
,
514 out_drm_gem_fb_end_cpu_access
:
515 drm_gem_fb_end_cpu_access(fb
, DMA_FROM_DEVICE
);
518 static void simpledrm_primary_plane_helper_atomic_disable(struct drm_plane
*plane
,
519 struct drm_atomic_state
*state
)
521 struct drm_device
*dev
= plane
->dev
;
522 struct simpledrm_device
*sdev
= simpledrm_device_of_dev(dev
);
525 if (!drm_dev_enter(dev
, &idx
))
528 /* Clear screen to black if disabled */
529 iosys_map_memset(&sdev
->screen_base
, 0, 0, sdev
->pitch
* sdev
->mode
.vdisplay
);
534 static const struct drm_plane_helper_funcs simpledrm_primary_plane_helper_funcs
= {
535 DRM_GEM_SHADOW_PLANE_HELPER_FUNCS
,
536 .atomic_check
= drm_plane_helper_atomic_check
,
537 .atomic_update
= simpledrm_primary_plane_helper_atomic_update
,
538 .atomic_disable
= simpledrm_primary_plane_helper_atomic_disable
,
541 static const struct drm_plane_funcs simpledrm_primary_plane_funcs
= {
542 .update_plane
= drm_atomic_helper_update_plane
,
543 .disable_plane
= drm_atomic_helper_disable_plane
,
544 .destroy
= drm_plane_cleanup
,
545 DRM_GEM_SHADOW_PLANE_FUNCS
,
548 static enum drm_mode_status
simpledrm_crtc_helper_mode_valid(struct drm_crtc
*crtc
,
549 const struct drm_display_mode
*mode
)
551 struct simpledrm_device
*sdev
= simpledrm_device_of_dev(crtc
->dev
);
553 return drm_crtc_helper_mode_valid_fixed(crtc
, mode
, &sdev
->mode
);
557 * The CRTC is always enabled. Screen updates are performed by
558 * the primary plane's atomic_update function. Disabling clears
559 * the screen in the primary plane's atomic_disable function.
561 static const struct drm_crtc_helper_funcs simpledrm_crtc_helper_funcs
= {
562 .mode_valid
= simpledrm_crtc_helper_mode_valid
,
563 .atomic_check
= drm_crtc_helper_atomic_check
,
566 static const struct drm_crtc_funcs simpledrm_crtc_funcs
= {
567 .reset
= drm_atomic_helper_crtc_reset
,
568 .destroy
= drm_crtc_cleanup
,
569 .set_config
= drm_atomic_helper_set_config
,
570 .page_flip
= drm_atomic_helper_page_flip
,
571 .atomic_duplicate_state
= drm_atomic_helper_crtc_duplicate_state
,
572 .atomic_destroy_state
= drm_atomic_helper_crtc_destroy_state
,
575 static const struct drm_encoder_funcs simpledrm_encoder_funcs
= {
576 .destroy
= drm_encoder_cleanup
,
579 static int simpledrm_connector_helper_get_modes(struct drm_connector
*connector
)
581 struct simpledrm_device
*sdev
= simpledrm_device_of_dev(connector
->dev
);
583 return drm_connector_helper_get_modes_fixed(connector
, &sdev
->mode
);
586 static const struct drm_connector_helper_funcs simpledrm_connector_helper_funcs
= {
587 .get_modes
= simpledrm_connector_helper_get_modes
,
590 static const struct drm_connector_funcs simpledrm_connector_funcs
= {
591 .reset
= drm_atomic_helper_connector_reset
,
592 .fill_modes
= drm_helper_probe_single_connector_modes
,
593 .destroy
= drm_connector_cleanup
,
594 .atomic_duplicate_state
= drm_atomic_helper_connector_duplicate_state
,
595 .atomic_destroy_state
= drm_atomic_helper_connector_destroy_state
,
598 static const struct drm_mode_config_funcs simpledrm_mode_config_funcs
= {
599 .fb_create
= drm_gem_fb_create_with_dirty
,
600 .atomic_check
= drm_atomic_helper_check
,
601 .atomic_commit
= drm_atomic_helper_commit
,
608 static struct drm_display_mode
simpledrm_mode(unsigned int width
,
610 unsigned int width_mm
,
611 unsigned int height_mm
)
613 const struct drm_display_mode mode
= {
614 DRM_MODE_INIT(60, width
, height
, width_mm
, height_mm
)
620 static struct simpledrm_device
*simpledrm_device_create(struct drm_driver
*drv
,
621 struct platform_device
*pdev
)
623 const struct simplefb_platform_data
*pd
= dev_get_platdata(&pdev
->dev
);
624 struct device_node
*of_node
= pdev
->dev
.of_node
;
625 struct simpledrm_device
*sdev
;
626 struct drm_device
*dev
;
627 int width
, height
, stride
;
628 int width_mm
= 0, height_mm
= 0;
629 struct device_node
*panel_node
;
630 const struct drm_format_info
*format
;
631 struct resource
*res
, *mem
= NULL
;
632 struct drm_plane
*primary_plane
;
633 struct drm_crtc
*crtc
;
634 struct drm_encoder
*encoder
;
635 struct drm_connector
*connector
;
636 unsigned long max_width
, max_height
;
640 sdev
= devm_drm_dev_alloc(&pdev
->dev
, drv
, struct simpledrm_device
, dev
);
642 return ERR_CAST(sdev
);
644 platform_set_drvdata(pdev
, sdev
);
650 ret
= simpledrm_device_init_clocks(sdev
);
653 ret
= simpledrm_device_init_regulators(sdev
);
658 width
= simplefb_get_width_pd(dev
, pd
);
660 return ERR_PTR(width
);
661 height
= simplefb_get_height_pd(dev
, pd
);
663 return ERR_PTR(height
);
664 stride
= simplefb_get_stride_pd(dev
, pd
);
666 return ERR_PTR(stride
);
667 format
= simplefb_get_format_pd(dev
, pd
);
669 return ERR_CAST(format
);
670 } else if (of_node
) {
671 width
= simplefb_get_width_of(dev
, of_node
);
673 return ERR_PTR(width
);
674 height
= simplefb_get_height_of(dev
, of_node
);
676 return ERR_PTR(height
);
677 stride
= simplefb_get_stride_of(dev
, of_node
);
679 return ERR_PTR(stride
);
680 format
= simplefb_get_format_of(dev
, of_node
);
682 return ERR_CAST(format
);
683 mem
= simplefb_get_memory_of(dev
, of_node
);
685 return ERR_CAST(mem
);
686 panel_node
= of_parse_phandle(of_node
, "panel", 0);
688 simplefb_read_u32_of(dev
, panel_node
, "width-mm", &width_mm
);
689 simplefb_read_u32_of(dev
, panel_node
, "height-mm", &height_mm
);
690 of_node_put(panel_node
);
693 drm_err(dev
, "no simplefb configuration found\n");
694 return ERR_PTR(-ENODEV
);
697 stride
= drm_format_info_min_pitch(format
, 0, width
);
698 if (drm_WARN_ON(dev
, !stride
))
699 return ERR_PTR(-EINVAL
);
703 * Assume a monitor resolution of 96 dpi if physical dimensions
704 * are not specified to get a somewhat reasonable screen size.
707 width_mm
= DRM_MODE_RES_MM(width
, 96ul);
709 height_mm
= DRM_MODE_RES_MM(height
, 96ul);
711 sdev
->mode
= simpledrm_mode(width
, height
, width_mm
, height_mm
);
712 sdev
->format
= format
;
713 sdev
->pitch
= stride
;
715 drm_dbg(dev
, "display mode={" DRM_MODE_FMT
"}\n", DRM_MODE_ARG(&sdev
->mode
));
716 drm_dbg(dev
, "framebuffer format=%p4cc, size=%dx%d, stride=%d byte\n",
717 &format
->format
, width
, height
, stride
);
726 ret
= devm_aperture_acquire_from_firmware(dev
, mem
->start
, resource_size(mem
));
728 drm_err(dev
, "could not acquire memory range %pr: %d\n", mem
, ret
);
732 drm_dbg(dev
, "using system memory framebuffer at %pr\n", mem
);
734 screen_base
= devm_memremap(dev
->dev
, mem
->start
, resource_size(mem
), MEMREMAP_WC
);
735 if (IS_ERR(screen_base
))
738 iosys_map_set_vaddr(&sdev
->screen_base
, screen_base
);
740 void __iomem
*screen_base
;
742 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
744 return ERR_PTR(-EINVAL
);
746 ret
= devm_aperture_acquire_from_firmware(dev
, res
->start
, resource_size(res
));
748 drm_err(dev
, "could not acquire memory range %pr: %d\n", &res
, ret
);
752 drm_dbg(dev
, "using I/O memory framebuffer at %pr\n", res
);
754 mem
= devm_request_mem_region(&pdev
->dev
, res
->start
, resource_size(res
),
758 * We cannot make this fatal. Sometimes this comes from magic
759 * spaces our resource handlers simply don't know about. Use
760 * the I/O-memory resource as-is and try to map that instead.
762 drm_warn(dev
, "could not acquire memory region %pr\n", res
);
766 screen_base
= devm_ioremap_wc(&pdev
->dev
, mem
->start
, resource_size(mem
));
768 return ERR_PTR(-ENOMEM
);
770 iosys_map_set_vaddr_iomem(&sdev
->screen_base
, screen_base
);
777 ret
= drmm_mode_config_init(dev
);
781 max_width
= max_t(unsigned long, width
, DRM_SHADOW_PLANE_MAX_WIDTH
);
782 max_height
= max_t(unsigned long, height
, DRM_SHADOW_PLANE_MAX_HEIGHT
);
784 dev
->mode_config
.min_width
= width
;
785 dev
->mode_config
.max_width
= max_width
;
786 dev
->mode_config
.min_height
= height
;
787 dev
->mode_config
.max_height
= max_height
;
788 dev
->mode_config
.preferred_depth
= format
->depth
;
789 dev
->mode_config
.funcs
= &simpledrm_mode_config_funcs
;
793 nformats
= drm_fb_build_fourcc_list(dev
, &format
->format
, 1,
794 sdev
->formats
, ARRAY_SIZE(sdev
->formats
));
796 primary_plane
= &sdev
->primary_plane
;
797 ret
= drm_universal_plane_init(dev
, primary_plane
, 0, &simpledrm_primary_plane_funcs
,
798 sdev
->formats
, nformats
,
799 simpledrm_primary_plane_format_modifiers
,
800 DRM_PLANE_TYPE_PRIMARY
, NULL
);
803 drm_plane_helper_add(primary_plane
, &simpledrm_primary_plane_helper_funcs
);
804 drm_plane_enable_fb_damage_clips(primary_plane
);
809 ret
= drm_crtc_init_with_planes(dev
, crtc
, primary_plane
, NULL
,
810 &simpledrm_crtc_funcs
, NULL
);
813 drm_crtc_helper_add(crtc
, &simpledrm_crtc_helper_funcs
);
817 encoder
= &sdev
->encoder
;
818 ret
= drm_encoder_init(dev
, encoder
, &simpledrm_encoder_funcs
,
819 DRM_MODE_ENCODER_NONE
, NULL
);
822 encoder
->possible_crtcs
= drm_crtc_mask(crtc
);
826 connector
= &sdev
->connector
;
827 ret
= drm_connector_init(dev
, connector
, &simpledrm_connector_funcs
,
828 DRM_MODE_CONNECTOR_Unknown
);
831 drm_connector_helper_add(connector
, &simpledrm_connector_helper_funcs
);
832 drm_connector_set_panel_orientation_with_quirk(connector
,
833 DRM_MODE_PANEL_ORIENTATION_UNKNOWN
,
836 ret
= drm_connector_attach_encoder(connector
, encoder
);
840 drm_mode_config_reset(dev
);
849 DEFINE_DRM_GEM_FOPS(simpledrm_fops
);
851 static struct drm_driver simpledrm_driver
= {
852 DRM_GEM_SHMEM_DRIVER_OPS
,
856 .major
= DRIVER_MAJOR
,
857 .minor
= DRIVER_MINOR
,
858 .driver_features
= DRIVER_ATOMIC
| DRIVER_GEM
| DRIVER_MODESET
,
859 .fops
= &simpledrm_fops
,
866 static int simpledrm_probe(struct platform_device
*pdev
)
868 struct simpledrm_device
*sdev
;
869 struct drm_device
*dev
;
870 unsigned int color_mode
;
873 sdev
= simpledrm_device_create(&simpledrm_driver
, pdev
);
875 return PTR_ERR(sdev
);
878 ret
= drm_dev_register(dev
, 0);
882 color_mode
= drm_format_info_bpp(sdev
->format
, 0);
883 if (color_mode
== 16)
884 color_mode
= sdev
->format
->depth
; // can be 15 or 16
886 drm_fbdev_generic_setup(dev
, color_mode
);
891 static void simpledrm_remove(struct platform_device
*pdev
)
893 struct simpledrm_device
*sdev
= platform_get_drvdata(pdev
);
894 struct drm_device
*dev
= &sdev
->dev
;
899 static const struct of_device_id simpledrm_of_match_table
[] = {
900 { .compatible
= "simple-framebuffer", },
903 MODULE_DEVICE_TABLE(of
, simpledrm_of_match_table
);
905 static struct platform_driver simpledrm_platform_driver
= {
907 .name
= "simple-framebuffer", /* connect to sysfb */
908 .of_match_table
= simpledrm_of_match_table
,
910 .probe
= simpledrm_probe
,
911 .remove_new
= simpledrm_remove
,
914 module_platform_driver(simpledrm_platform_driver
);
916 MODULE_DESCRIPTION(DRIVER_DESC
);
917 MODULE_LICENSE("GPL v2");