1 // SPDX-License-Identifier: GPL-2.0-only
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>
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>
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
32 * Assume a monitor resolution of 96 dpi to
33 * get a somewhat reasonable screen size.
36 (((d) * 254ul) / (96ul * 10ul))
38 #define SIMPLEDRM_MODE(hd, vd) \
39 DRM_SIMPLE_MODE(hd, vd, RES_MM(hd), RES_MM(vd))
42 * Helpers for simplefb
46 simplefb_get_validated_int(struct drm_device
*dev
, const char *name
,
49 if (value
> INT_MAX
) {
50 drm_err(dev
, "simplefb: invalid framebuffer %s of %u\n",
58 simplefb_get_validated_int0(struct drm_device
*dev
, const char *name
,
62 drm_err(dev
, "simplefb: invalid framebuffer %s of %u\n",
66 return simplefb_get_validated_int(dev
, name
, value
);
69 static const struct drm_format_info
*
70 simplefb_get_validated_format(struct drm_device
*dev
, const char *format_name
)
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
;
78 drm_err(dev
, "simplefb: missing framebuffer format\n");
79 return ERR_PTR(-EINVAL
);
83 if (!strcmp(format_name
, fmt
->name
)) {
84 info
= drm_format_info(fmt
->fourcc
);
86 return ERR_PTR(-EINVAL
);
92 drm_err(dev
, "simplefb: unknown framebuffer format %s\n",
95 return ERR_PTR(-EINVAL
);
99 simplefb_get_width_pd(struct drm_device
*dev
,
100 const struct simplefb_platform_data
*pd
)
102 return simplefb_get_validated_int0(dev
, "width", pd
->width
);
106 simplefb_get_height_pd(struct drm_device
*dev
,
107 const struct simplefb_platform_data
*pd
)
109 return simplefb_get_validated_int0(dev
, "height", pd
->height
);
113 simplefb_get_stride_pd(struct drm_device
*dev
,
114 const struct simplefb_platform_data
*pd
)
116 return simplefb_get_validated_int(dev
, "stride", pd
->stride
);
119 static const struct drm_format_info
*
120 simplefb_get_format_pd(struct drm_device
*dev
,
121 const struct simplefb_platform_data
*pd
)
123 return simplefb_get_validated_format(dev
, pd
->format
);
127 simplefb_read_u32_of(struct drm_device
*dev
, struct device_node
*of_node
,
128 const char *name
, u32
*value
)
130 int ret
= of_property_read_u32(of_node
, name
, value
);
133 drm_err(dev
, "simplefb: cannot parse framebuffer %s: error %d\n",
139 simplefb_read_string_of(struct drm_device
*dev
, struct device_node
*of_node
,
140 const char *name
, const char **value
)
142 int ret
= of_property_read_string(of_node
, name
, value
);
145 drm_err(dev
, "simplefb: cannot parse framebuffer %s: error %d\n",
151 simplefb_get_width_of(struct drm_device
*dev
, struct device_node
*of_node
)
154 int ret
= simplefb_read_u32_of(dev
, of_node
, "width", &width
);
158 return simplefb_get_validated_int0(dev
, "width", width
);
162 simplefb_get_height_of(struct drm_device
*dev
, struct device_node
*of_node
)
165 int ret
= simplefb_read_u32_of(dev
, of_node
, "height", &height
);
169 return simplefb_get_validated_int0(dev
, "height", height
);
173 simplefb_get_stride_of(struct drm_device
*dev
, struct device_node
*of_node
)
176 int ret
= simplefb_read_u32_of(dev
, of_node
, "stride", &stride
);
180 return simplefb_get_validated_int(dev
, "stride", stride
);
183 static const struct drm_format_info
*
184 simplefb_get_format_of(struct drm_device
*dev
, struct device_node
*of_node
)
187 int ret
= simplefb_read_string_of(dev
, of_node
, "format", &format
);
191 return simplefb_get_validated_format(dev
, format
);
195 * Simple Framebuffer device
198 struct simpledrm_device
{
199 struct drm_device dev
;
200 struct platform_device
*pdev
;
203 #if defined CONFIG_OF && defined CONFIG_COMMON_CLK
204 unsigned int clk_count
;
208 #if defined CONFIG_OF && defined CONFIG_REGULATOR
209 unsigned int regulator_count
;
210 struct regulator
**regulators
;
213 /* simplefb settings */
214 struct drm_display_mode mode
;
215 const struct drm_format_info
*format
;
218 /* memory management */
219 struct resource
*mem
;
220 void __iomem
*screen_base
;
225 struct drm_connector connector
;
226 struct drm_simple_display_pipe pipe
;
229 static struct simpledrm_device
*simpledrm_device_of_dev(struct drm_device
*dev
)
231 return container_of(dev
, struct simpledrm_device
, dev
);
238 #if defined CONFIG_OF && defined CONFIG_COMMON_CLK
240 * Clock handling code.
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
248 * When the driver unloads, we cleanly disable, and then release the clocks.
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.
258 static void simpledrm_device_release_clocks(void *res
)
260 struct simpledrm_device
*sdev
= simpledrm_device_of_dev(res
);
263 for (i
= 0; i
< sdev
->clk_count
; ++i
) {
265 clk_disable_unprepare(sdev
->clks
[i
]);
266 clk_put(sdev
->clks
[i
]);
271 static int simpledrm_device_init_clocks(struct simpledrm_device
*sdev
)
273 struct drm_device
*dev
= &sdev
->dev
;
274 struct platform_device
*pdev
= sdev
->pdev
;
275 struct device_node
*of_node
= pdev
->dev
.of_node
;
280 if (dev_get_platdata(&pdev
->dev
) || !of_node
)
283 sdev
->clk_count
= of_clk_get_parent_count(of_node
);
284 if (!sdev
->clk_count
)
287 sdev
->clks
= drmm_kzalloc(dev
, sdev
->clk_count
* sizeof(sdev
->clks
[0]),
292 for (i
= 0; i
< sdev
->clk_count
; ++i
) {
293 clock
= of_clk_get(of_node
, i
);
295 ret
= PTR_ERR(clock
);
296 if (ret
== -EPROBE_DEFER
)
298 drm_err(dev
, "clock %u not found: %d\n", i
, ret
);
301 ret
= clk_prepare_enable(clock
);
303 drm_err(dev
, "failed to enable clock %u: %d\n",
308 sdev
->clks
[i
] = clock
;
311 return devm_add_action_or_reset(&pdev
->dev
,
312 simpledrm_device_release_clocks
,
319 clk_disable_unprepare(sdev
->clks
[i
]);
320 clk_put(sdev
->clks
[i
]);
326 static int simpledrm_device_init_clocks(struct simpledrm_device
*sdev
)
332 #if defined CONFIG_OF && defined CONFIG_REGULATOR
334 #define SUPPLY_SUFFIX "-supply"
337 * Regulator handling code.
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.
345 * When the driver unloads, we cleanly disable, and then release the
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.
356 static void simpledrm_device_release_regulators(void *res
)
358 struct simpledrm_device
*sdev
= simpledrm_device_of_dev(res
);
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
]);
369 static int simpledrm_device_init_regulators(struct simpledrm_device
*sdev
)
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
;
377 unsigned int count
= 0, i
= 0;
380 if (dev_get_platdata(&pdev
->dev
) || !of_node
)
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
)
393 sdev
->regulators
= drmm_kzalloc(dev
,
394 count
* sizeof(sdev
->regulators
[0]),
396 if (!sdev
->regulators
)
399 for_each_property_of_node(of_node
, prop
) {
400 char name
[32]; /* 32 is max size of property name */
403 p
= strstr(prop
->name
, SUPPLY_SUFFIX
);
404 if (!p
|| p
== prop
->name
)
406 len
= strlen(prop
->name
) - strlen(SUPPLY_SUFFIX
) + 1;
407 strscpy(name
, prop
->name
, min(sizeof(name
), len
));
409 regulator
= regulator_get_optional(&pdev
->dev
, name
);
410 if (IS_ERR(regulator
)) {
411 ret
= PTR_ERR(regulator
);
412 if (ret
== -EPROBE_DEFER
)
414 drm_err(dev
, "regulator %s not found: %d\n",
419 ret
= regulator_enable(regulator
);
421 drm_err(dev
, "failed to enable regulator %u: %d\n",
423 regulator_put(regulator
);
427 sdev
->regulators
[i
++] = regulator
;
429 sdev
->regulator_count
= i
;
431 return devm_add_action_or_reset(&pdev
->dev
,
432 simpledrm_device_release_regulators
,
438 if (sdev
->regulators
[i
]) {
439 regulator_disable(sdev
->regulators
[i
]);
440 regulator_put(sdev
->regulators
[i
]);
446 static int simpledrm_device_init_regulators(struct simpledrm_device
*sdev
)
456 static struct drm_display_mode
simpledrm_mode(unsigned int width
,
459 struct drm_display_mode mode
= { SIMPLEDRM_MODE(width
, height
) };
461 mode
.clock
= 60 /* Hz */ * mode
.hdisplay
* mode
.vdisplay
;
462 drm_mode_set_name(&mode
);
467 static int simpledrm_device_init_fb(struct simpledrm_device
*sdev
)
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
;
477 width
= simplefb_get_width_pd(dev
, pd
);
480 height
= simplefb_get_height_pd(dev
, pd
);
483 stride
= simplefb_get_stride_pd(dev
, pd
);
486 format
= simplefb_get_format_pd(dev
, pd
);
488 return PTR_ERR(format
);
489 } else if (of_node
) {
490 width
= simplefb_get_width_of(dev
, of_node
);
493 height
= simplefb_get_height_of(dev
, of_node
);
496 stride
= simplefb_get_stride_of(dev
, of_node
);
499 format
= simplefb_get_format_of(dev
, of_node
);
501 return PTR_ERR(format
);
503 drm_err(dev
, "no simplefb configuration found\n");
507 sdev
->mode
= simpledrm_mode(width
, height
);
508 sdev
->format
= format
;
509 sdev
->pitch
= stride
;
511 drm_dbg_kms(dev
, "display mode={" DRM_MODE_FMT
"}\n",
512 DRM_MODE_ARG(&sdev
->mode
));
514 "framebuffer format=%p4cc, size=%dx%d, stride=%d byte\n",
515 &format
->format
, width
, height
, stride
);
524 static int simpledrm_device_init_mm(struct simpledrm_device
*sdev
)
526 struct drm_device
*dev
= &sdev
->dev
;
527 struct platform_device
*pdev
= sdev
->pdev
;
528 struct resource
*mem
;
529 void __iomem
*screen_base
;
532 mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
536 ret
= devm_aperture_acquire_from_firmware(dev
, mem
->start
, resource_size(mem
));
538 drm_err(dev
, "could not acquire memory range %pr: error %d\n",
543 screen_base
= devm_ioremap_wc(&pdev
->dev
, mem
->start
,
549 sdev
->screen_base
= screen_base
;
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.
563 * TODO: Add blit helpers for remaining formats and uncomment
566 static const uint32_t simpledrm_default_formats
[] = {
570 //DRM_FORMAT_XRGB1555,
571 //DRM_FORMAT_ARGB1555,
573 //DRM_FORMAT_XRGB2101010,
574 //DRM_FORMAT_ARGB2101010,
577 static const uint64_t simpledrm_format_modifiers
[] = {
578 DRM_FORMAT_MOD_LINEAR
,
579 DRM_FORMAT_MOD_INVALID
582 static int simpledrm_connector_helper_get_modes(struct drm_connector
*connector
)
584 struct simpledrm_device
*sdev
= simpledrm_device_of_dev(connector
->dev
);
585 struct drm_display_mode
*mode
;
587 mode
= drm_mode_duplicate(connector
->dev
, &sdev
->mode
);
591 if (mode
->name
[0] == '\0')
592 drm_mode_set_name(mode
);
594 mode
->type
|= DRM_MODE_TYPE_PREFERRED
;
595 drm_mode_probed_add(connector
, mode
);
598 connector
->display_info
.width_mm
= mode
->width_mm
;
600 connector
->display_info
.height_mm
= mode
->height_mm
;
605 static const struct drm_connector_helper_funcs simpledrm_connector_helper_funcs
= {
606 .get_modes
= simpledrm_connector_helper_get_modes
,
609 static 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
,
618 simpledrm_simple_display_pipe_mode_valid(struct drm_simple_display_pipe
*pipe
,
619 const struct drm_display_mode
*mode
)
621 struct simpledrm_device
*sdev
= simpledrm_device_of_dev(pipe
->crtc
.dev
);
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
;
635 simpledrm_simple_display_pipe_enable(struct drm_simple_display_pipe
*pipe
,
636 struct drm_crtc_state
*crtc_state
,
637 struct drm_plane_state
*plane_state
)
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
;
649 if (!drm_dev_enter(dev
, &idx
))
652 drm_fb_blit_dstclip(sdev
->screen_base
, sdev
->pitch
,
653 sdev
->format
->format
, vmap
, fb
);
658 simpledrm_simple_display_pipe_disable(struct drm_simple_display_pipe
*pipe
)
660 struct simpledrm_device
*sdev
= simpledrm_device_of_dev(pipe
->crtc
.dev
);
661 struct drm_device
*dev
= &sdev
->dev
;
664 if (!drm_dev_enter(dev
, &idx
))
667 /* Clear screen to black if disabled */
668 memset_io(sdev
->screen_base
, 0, sdev
->pitch
* sdev
->mode
.vdisplay
);
674 simpledrm_simple_display_pipe_update(struct drm_simple_display_pipe
*pipe
,
675 struct drm_plane_state
*old_plane_state
)
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
;
689 if (!drm_atomic_helper_damage_merged(old_plane_state
, plane_state
, &clip
))
692 if (!drm_dev_enter(dev
, &idx
))
695 drm_fb_blit_rect_dstclip(sdev
->screen_base
, sdev
->pitch
,
696 sdev
->format
->format
, vmap
, fb
, &clip
);
701 static const struct drm_simple_display_pipe_funcs
702 simpledrm_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
,
710 static 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
,
716 static const uint32_t *simpledrm_device_formats(struct simpledrm_device
*sdev
,
717 size_t *nformats_out
)
719 struct drm_device
*dev
= &sdev
->dev
;
723 goto out
; /* don't rebuild list on recurring calls */
725 /* native format goes first */
726 sdev
->formats
[0] = sdev
->format
->format
;
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
];
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.
744 if (drm_WARN_ONCE(dev
, i
!= sdev
->nformats
,
745 "format conversion helpers required for %p4cc",
746 &sdev
->format
->format
)) {
751 *nformats_out
= sdev
->nformats
;
752 return sdev
->formats
;
755 static int simpledrm_device_init_modeset(struct simpledrm_device
*sdev
)
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
;
765 ret
= drmm_mode_config_init(dev
);
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
;
777 ret
= drm_connector_init(dev
, connector
, &simpledrm_connector_funcs
,
778 DRM_MODE_CONNECTOR_Unknown
);
781 drm_connector_helper_add(connector
, &simpledrm_connector_helper_funcs
);
783 formats
= simpledrm_device_formats(sdev
, &nformats
);
785 ret
= drm_simple_display_pipe_init(dev
, pipe
, &simpledrm_simple_display_pipe_funcs
,
786 formats
, nformats
, simpledrm_format_modifiers
,
791 drm_mode_config_reset(dev
);
800 static struct simpledrm_device
*
801 simpledrm_device_create(struct drm_driver
*drv
, struct platform_device
*pdev
)
803 struct simpledrm_device
*sdev
;
806 sdev
= devm_drm_dev_alloc(&pdev
->dev
, drv
, struct simpledrm_device
,
809 return ERR_CAST(sdev
);
811 platform_set_drvdata(pdev
, sdev
);
813 ret
= simpledrm_device_init_clocks(sdev
);
816 ret
= simpledrm_device_init_regulators(sdev
);
819 ret
= simpledrm_device_init_fb(sdev
);
822 ret
= simpledrm_device_init_mm(sdev
);
825 ret
= simpledrm_device_init_modeset(sdev
);
836 DEFINE_DRM_GEM_FOPS(simpledrm_fops
);
838 static struct drm_driver simpledrm_driver
= {
839 DRM_GEM_SHMEM_DRIVER_OPS
,
843 .major
= DRIVER_MAJOR
,
844 .minor
= DRIVER_MINOR
,
845 .driver_features
= DRIVER_ATOMIC
| DRIVER_GEM
| DRIVER_MODESET
,
846 .fops
= &simpledrm_fops
,
853 static int simpledrm_probe(struct platform_device
*pdev
)
855 struct simpledrm_device
*sdev
;
856 struct drm_device
*dev
;
859 sdev
= simpledrm_device_create(&simpledrm_driver
, pdev
);
861 return PTR_ERR(sdev
);
864 ret
= drm_dev_register(dev
, 0);
868 drm_fbdev_generic_setup(dev
, 0);
873 static int simpledrm_remove(struct platform_device
*pdev
)
875 struct simpledrm_device
*sdev
= platform_get_drvdata(pdev
);
876 struct drm_device
*dev
= &sdev
->dev
;
883 static const struct of_device_id simpledrm_of_match_table
[] = {
884 { .compatible
= "simple-framebuffer", },
887 MODULE_DEVICE_TABLE(of
, simpledrm_of_match_table
);
889 static struct platform_driver simpledrm_platform_driver
= {
891 .name
= "simple-framebuffer", /* connect to sysfb */
892 .of_match_table
= simpledrm_of_match_table
,
894 .probe
= simpledrm_probe
,
895 .remove
= simpledrm_remove
,
898 module_platform_driver(simpledrm_platform_driver
);
900 MODULE_DESCRIPTION(DRIVER_DESC
);
901 MODULE_LICENSE("GPL v2");