2 * Freescale i.MX drm driver
4 * Copyright (C) 2011 Sascha Hauer, Pengutronix
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <linux/component.h>
17 #include <linux/device.h>
18 #include <linux/platform_device.h>
20 #include <drm/drm_fb_helper.h>
21 #include <drm/drm_crtc_helper.h>
23 #include <linux/module.h>
24 #include <drm/drm_gem_cma_helper.h>
25 #include <drm/drm_fb_cma_helper.h>
34 struct list_head list
;
39 struct imx_drm_device
{
40 struct drm_device
*drm
;
42 struct imx_drm_crtc
*crtc
[MAX_CRTC
];
43 struct list_head encoder_list
;
44 struct list_head connector_list
;
47 struct drm_fbdev_cma
*fbhelper
;
51 struct drm_crtc
*crtc
;
52 struct imx_drm_device
*imxdrm
;
54 struct imx_drm_crtc_helper_funcs imx_drm_helper_funcs
;
56 struct crtc_cookie cookie
;
60 struct imx_drm_encoder
{
61 struct drm_encoder
*encoder
;
62 struct list_head list
;
64 struct list_head possible_crtcs
;
67 struct imx_drm_connector
{
68 struct drm_connector
*connector
;
69 struct list_head list
;
73 static struct imx_drm_device
*__imx_drm_device(void);
75 int imx_drm_crtc_id(struct imx_drm_crtc
*crtc
)
79 EXPORT_SYMBOL_GPL(imx_drm_crtc_id
);
81 static void imx_drm_driver_lastclose(struct drm_device
*drm
)
83 struct imx_drm_device
*imxdrm
= drm
->dev_private
;
86 drm_fbdev_cma_restore_mode(imxdrm
->fbhelper
);
89 static int imx_drm_driver_unload(struct drm_device
*drm
)
91 struct imx_drm_device
*imxdrm
= drm
->dev_private
;
93 component_unbind_all(drm
->dev
, drm
);
97 drm_vblank_cleanup(drm
);
98 drm_kms_helper_poll_fini(drm
);
99 drm_mode_config_cleanup(drm
);
104 struct imx_drm_crtc
*imx_drm_find_crtc(struct drm_crtc
*crtc
)
106 struct imx_drm_device
*imxdrm
= __imx_drm_device();
109 for (i
= 0; i
< MAX_CRTC
; i
++)
110 if (imxdrm
->crtc
[i
] && imxdrm
->crtc
[i
]->crtc
== crtc
)
111 return imxdrm
->crtc
[i
];
116 int imx_drm_panel_format_pins(struct drm_encoder
*encoder
,
117 u32 interface_pix_fmt
, int hsync_pin
, int vsync_pin
)
119 struct imx_drm_crtc_helper_funcs
*helper
;
120 struct imx_drm_crtc
*imx_crtc
;
122 imx_crtc
= imx_drm_find_crtc(encoder
->crtc
);
126 helper
= &imx_crtc
->imx_drm_helper_funcs
;
127 if (helper
->set_interface_pix_fmt
)
128 return helper
->set_interface_pix_fmt(encoder
->crtc
,
129 encoder
->encoder_type
, interface_pix_fmt
,
130 hsync_pin
, vsync_pin
);
133 EXPORT_SYMBOL_GPL(imx_drm_panel_format_pins
);
135 int imx_drm_panel_format(struct drm_encoder
*encoder
, u32 interface_pix_fmt
)
137 return imx_drm_panel_format_pins(encoder
, interface_pix_fmt
, 2, 3);
139 EXPORT_SYMBOL_GPL(imx_drm_panel_format
);
141 int imx_drm_crtc_vblank_get(struct imx_drm_crtc
*imx_drm_crtc
)
143 return drm_vblank_get(imx_drm_crtc
->crtc
->dev
, imx_drm_crtc
->pipe
);
145 EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_get
);
147 void imx_drm_crtc_vblank_put(struct imx_drm_crtc
*imx_drm_crtc
)
149 drm_vblank_put(imx_drm_crtc
->crtc
->dev
, imx_drm_crtc
->pipe
);
151 EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_put
);
153 void imx_drm_handle_vblank(struct imx_drm_crtc
*imx_drm_crtc
)
155 drm_handle_vblank(imx_drm_crtc
->crtc
->dev
, imx_drm_crtc
->pipe
);
157 EXPORT_SYMBOL_GPL(imx_drm_handle_vblank
);
159 static int imx_drm_enable_vblank(struct drm_device
*drm
, int crtc
)
161 struct imx_drm_device
*imxdrm
= drm
->dev_private
;
162 struct imx_drm_crtc
*imx_drm_crtc
= imxdrm
->crtc
[crtc
];
168 if (!imx_drm_crtc
->imx_drm_helper_funcs
.enable_vblank
)
171 ret
= imx_drm_crtc
->imx_drm_helper_funcs
.enable_vblank(
177 static void imx_drm_disable_vblank(struct drm_device
*drm
, int crtc
)
179 struct imx_drm_device
*imxdrm
= drm
->dev_private
;
180 struct imx_drm_crtc
*imx_drm_crtc
= imxdrm
->crtc
[crtc
];
185 if (!imx_drm_crtc
->imx_drm_helper_funcs
.disable_vblank
)
188 imx_drm_crtc
->imx_drm_helper_funcs
.disable_vblank(imx_drm_crtc
->crtc
);
191 static void imx_drm_driver_preclose(struct drm_device
*drm
,
192 struct drm_file
*file
)
196 if (!file
->is_master
)
199 for (i
= 0; i
< MAX_CRTC
; i
++)
200 imx_drm_disable_vblank(drm
, i
);
203 static const struct file_operations imx_drm_driver_fops
= {
204 .owner
= THIS_MODULE
,
206 .release
= drm_release
,
207 .unlocked_ioctl
= drm_ioctl
,
208 .mmap
= drm_gem_cma_mmap
,
211 .llseek
= noop_llseek
,
214 int imx_drm_connector_mode_valid(struct drm_connector
*connector
,
215 struct drm_display_mode
*mode
)
219 EXPORT_SYMBOL(imx_drm_connector_mode_valid
);
221 static struct imx_drm_device
*imx_drm_device
;
223 static struct imx_drm_device
*__imx_drm_device(void)
225 return imx_drm_device
;
228 struct drm_device
*imx_drm_device_get(void)
230 struct imx_drm_device
*imxdrm
= __imx_drm_device();
231 struct imx_drm_encoder
*enc
;
232 struct imx_drm_connector
*con
;
233 struct imx_drm_crtc
*crtc
;
235 list_for_each_entry(enc
, &imxdrm
->encoder_list
, list
) {
236 if (!try_module_get(enc
->owner
)) {
237 dev_err(imxdrm
->dev
, "could not get module %s\n",
238 module_name(enc
->owner
));
243 list_for_each_entry(con
, &imxdrm
->connector_list
, list
) {
244 if (!try_module_get(con
->owner
)) {
245 dev_err(imxdrm
->dev
, "could not get module %s\n",
246 module_name(con
->owner
));
251 list_for_each_entry(crtc
, &imxdrm
->crtc_list
, list
) {
252 if (!try_module_get(crtc
->owner
)) {
253 dev_err(imxdrm
->dev
, "could not get module %s\n",
254 module_name(crtc
->owner
));
262 list_for_each_entry_continue_reverse(crtc
, &imxdrm
->crtc_list
, list
)
263 module_put(crtc
->owner
);
265 list_for_each_entry_continue_reverse(con
, &imxdrm
->connector_list
, list
)
266 module_put(con
->owner
);
268 list_for_each_entry_continue_reverse(enc
, &imxdrm
->encoder_list
, list
)
269 module_put(enc
->owner
);
271 mutex_unlock(&imxdrm
->mutex
);
276 EXPORT_SYMBOL_GPL(imx_drm_device_get
);
278 void imx_drm_device_put(void)
280 struct imx_drm_device
*imxdrm
= __imx_drm_device();
281 struct imx_drm_encoder
*enc
;
282 struct imx_drm_connector
*con
;
283 struct imx_drm_crtc
*crtc
;
285 mutex_lock(&imxdrm
->mutex
);
287 list_for_each_entry(crtc
, &imxdrm
->crtc_list
, list
)
288 module_put(crtc
->owner
);
290 list_for_each_entry(con
, &imxdrm
->connector_list
, list
)
291 module_put(con
->owner
);
293 list_for_each_entry(enc
, &imxdrm
->encoder_list
, list
)
294 module_put(enc
->owner
);
296 mutex_unlock(&imxdrm
->mutex
);
298 EXPORT_SYMBOL_GPL(imx_drm_device_put
);
300 static int drm_mode_group_reinit(struct drm_device
*dev
)
302 struct drm_mode_group
*group
= &dev
->primary
->mode_group
;
303 uint32_t *id_list
= group
->id_list
;
306 ret
= drm_mode_group_init_legacy_group(dev
, group
);
315 * register an encoder to the drm core
317 static int imx_drm_encoder_register(struct imx_drm_encoder
*imx_drm_encoder
)
319 struct imx_drm_device
*imxdrm
= __imx_drm_device();
321 INIT_LIST_HEAD(&imx_drm_encoder
->possible_crtcs
);
323 drm_encoder_init(imxdrm
->drm
, imx_drm_encoder
->encoder
,
324 imx_drm_encoder
->encoder
->funcs
,
325 imx_drm_encoder
->encoder
->encoder_type
);
327 drm_mode_group_reinit(imxdrm
->drm
);
333 * unregister an encoder from the drm core
335 static void imx_drm_encoder_unregister(struct imx_drm_encoder
338 struct imx_drm_device
*imxdrm
= __imx_drm_device();
340 drm_encoder_cleanup(imx_drm_encoder
->encoder
);
342 drm_mode_group_reinit(imxdrm
->drm
);
346 * register a connector to the drm core
348 static int imx_drm_connector_register(
349 struct imx_drm_connector
*imx_drm_connector
)
351 struct imx_drm_device
*imxdrm
= __imx_drm_device();
353 drm_connector_init(imxdrm
->drm
, imx_drm_connector
->connector
,
354 imx_drm_connector
->connector
->funcs
,
355 imx_drm_connector
->connector
->connector_type
);
356 drm_mode_group_reinit(imxdrm
->drm
);
358 return drm_sysfs_connector_add(imx_drm_connector
->connector
);
362 * unregister a connector from the drm core
364 static void imx_drm_connector_unregister(
365 struct imx_drm_connector
*imx_drm_connector
)
367 struct imx_drm_device
*imxdrm
= __imx_drm_device();
369 drm_sysfs_connector_remove(imx_drm_connector
->connector
);
370 drm_connector_cleanup(imx_drm_connector
->connector
);
372 drm_mode_group_reinit(imxdrm
->drm
);
376 * Main DRM initialisation. This binds, initialises and registers
377 * with DRM the subcomponents of the driver.
379 static int imx_drm_driver_load(struct drm_device
*drm
, unsigned long flags
)
381 struct imx_drm_device
*imxdrm
= __imx_drm_device();
386 drm
->dev_private
= imxdrm
;
389 * enable drm irq mode.
390 * - with irq_enabled = true, we can use the vblank feature.
392 * P.S. note that we wouldn't use drm irq handler but
393 * just specific driver own one instead because
394 * drm framework supports only one irq handler and
395 * drivers can well take care of their interrupts
397 drm
->irq_enabled
= true;
399 drm_mode_config_init(drm
);
400 imx_drm_mode_config_init(drm
);
402 mutex_lock(&imxdrm
->mutex
);
404 drm_kms_helper_poll_init(drm
);
406 /* setup the grouping for the legacy output */
407 ret
= drm_mode_group_init_legacy_group(drm
,
408 &drm
->primary
->mode_group
);
412 ret
= drm_vblank_init(drm
, MAX_CRTC
);
417 * with vblank_disable_allowed = true, vblank interrupt will be disabled
418 * by drm timer once a current process gives up ownership of
419 * vblank event.(after drm_vblank_put function is called)
421 drm
->vblank_disable_allowed
= true;
423 if (!imx_drm_device_get()) {
428 platform_set_drvdata(drm
->platformdev
, drm
);
429 mutex_unlock(&imxdrm
->mutex
);
431 /* Now try and bind all our sub-components */
432 ret
= component_bind_all(drm
->dev
, drm
);
438 mutex_lock(&imxdrm
->mutex
);
440 drm_vblank_cleanup(drm
);
442 drm_kms_helper_poll_fini(drm
);
443 drm_mode_config_cleanup(drm
);
444 mutex_unlock(&imxdrm
->mutex
);
449 static void imx_drm_update_possible_crtcs(void)
451 struct imx_drm_device
*imxdrm
= __imx_drm_device();
452 struct imx_drm_crtc
*imx_drm_crtc
;
453 struct imx_drm_encoder
*enc
;
454 struct crtc_cookie
*cookie
;
456 list_for_each_entry(enc
, &imxdrm
->encoder_list
, list
) {
457 u32 possible_crtcs
= 0;
459 list_for_each_entry(cookie
, &enc
->possible_crtcs
, list
) {
460 list_for_each_entry(imx_drm_crtc
, &imxdrm
->crtc_list
, list
) {
461 if (imx_drm_crtc
->cookie
.cookie
== cookie
->cookie
&&
462 imx_drm_crtc
->cookie
.id
== cookie
->id
) {
463 possible_crtcs
|= 1 << imx_drm_crtc
->pipe
;
467 enc
->encoder
->possible_crtcs
= possible_crtcs
;
468 enc
->encoder
->possible_clones
= possible_crtcs
;
473 * imx_drm_add_crtc - add a new crtc
475 * The return value if !NULL is a cookie for the caller to pass to
476 * imx_drm_remove_crtc later.
478 int imx_drm_add_crtc(struct drm_crtc
*crtc
,
479 struct imx_drm_crtc
**new_crtc
,
480 const struct imx_drm_crtc_helper_funcs
*imx_drm_helper_funcs
,
481 struct module
*owner
, void *cookie
, int id
)
483 struct imx_drm_device
*imxdrm
= __imx_drm_device();
484 struct imx_drm_crtc
*imx_drm_crtc
;
487 mutex_lock(&imxdrm
->mutex
);
490 * The vblank arrays are dimensioned by MAX_CRTC - we can't
491 * pass IDs greater than this to those functions.
493 if (imxdrm
->pipes
>= MAX_CRTC
) {
498 if (imxdrm
->drm
->open_count
) {
503 imx_drm_crtc
= kzalloc(sizeof(*imx_drm_crtc
), GFP_KERNEL
);
509 imx_drm_crtc
->imx_drm_helper_funcs
= *imx_drm_helper_funcs
;
510 imx_drm_crtc
->pipe
= imxdrm
->pipes
++;
511 imx_drm_crtc
->cookie
.cookie
= cookie
;
512 imx_drm_crtc
->cookie
.id
= id
;
513 imx_drm_crtc
->mux_id
= imx_drm_crtc
->pipe
;
514 imx_drm_crtc
->crtc
= crtc
;
515 imx_drm_crtc
->imxdrm
= imxdrm
;
517 imx_drm_crtc
->owner
= owner
;
519 imxdrm
->crtc
[imx_drm_crtc
->pipe
] = imx_drm_crtc
;
521 *new_crtc
= imx_drm_crtc
;
523 ret
= drm_mode_crtc_set_gamma_size(imx_drm_crtc
->crtc
, 256);
527 drm_crtc_helper_add(crtc
,
528 imx_drm_crtc
->imx_drm_helper_funcs
.crtc_helper_funcs
);
530 drm_crtc_init(imxdrm
->drm
, crtc
,
531 imx_drm_crtc
->imx_drm_helper_funcs
.crtc_funcs
);
533 drm_mode_group_reinit(imxdrm
->drm
);
535 imx_drm_update_possible_crtcs();
537 mutex_unlock(&imxdrm
->mutex
);
542 imxdrm
->crtc
[imx_drm_crtc
->pipe
] = NULL
;
546 mutex_unlock(&imxdrm
->mutex
);
549 EXPORT_SYMBOL_GPL(imx_drm_add_crtc
);
552 * imx_drm_remove_crtc - remove a crtc
554 int imx_drm_remove_crtc(struct imx_drm_crtc
*imx_drm_crtc
)
556 struct imx_drm_device
*imxdrm
= imx_drm_crtc
->imxdrm
;
558 mutex_lock(&imxdrm
->mutex
);
560 drm_crtc_cleanup(imx_drm_crtc
->crtc
);
562 imxdrm
->crtc
[imx_drm_crtc
->pipe
] = NULL
;
564 drm_mode_group_reinit(imxdrm
->drm
);
566 mutex_unlock(&imxdrm
->mutex
);
572 EXPORT_SYMBOL_GPL(imx_drm_remove_crtc
);
575 * imx_drm_add_encoder - add a new encoder
577 int imx_drm_add_encoder(struct drm_encoder
*encoder
,
578 struct imx_drm_encoder
**newenc
, struct module
*owner
)
580 struct imx_drm_device
*imxdrm
= __imx_drm_device();
581 struct imx_drm_encoder
*imx_drm_encoder
;
584 mutex_lock(&imxdrm
->mutex
);
586 if (imxdrm
->drm
->open_count
) {
591 imx_drm_encoder
= kzalloc(sizeof(*imx_drm_encoder
), GFP_KERNEL
);
592 if (!imx_drm_encoder
) {
597 imx_drm_encoder
->encoder
= encoder
;
598 imx_drm_encoder
->owner
= owner
;
600 ret
= imx_drm_encoder_register(imx_drm_encoder
);
606 list_add_tail(&imx_drm_encoder
->list
, &imxdrm
->encoder_list
);
608 *newenc
= imx_drm_encoder
;
610 mutex_unlock(&imxdrm
->mutex
);
615 kfree(imx_drm_encoder
);
618 mutex_unlock(&imxdrm
->mutex
);
622 EXPORT_SYMBOL_GPL(imx_drm_add_encoder
);
624 int imx_drm_encoder_add_possible_crtcs(
625 struct imx_drm_encoder
*imx_drm_encoder
,
626 struct device_node
*np
)
628 struct imx_drm_device
*imxdrm
= __imx_drm_device();
629 struct of_phandle_args args
;
630 struct crtc_cookie
*c
;
634 if (!list_empty(&imx_drm_encoder
->possible_crtcs
))
637 for (i
= 0; !ret
; i
++) {
638 ret
= of_parse_phandle_with_args(np
, "crtcs",
639 "#crtc-cells", i
, &args
);
643 c
= kzalloc(sizeof(*c
), GFP_KERNEL
);
645 of_node_put(args
.np
);
650 c
->id
= args
.args_count
> 0 ? args
.args
[0] : 0;
652 of_node_put(args
.np
);
654 mutex_lock(&imxdrm
->mutex
);
656 list_add_tail(&c
->list
, &imx_drm_encoder
->possible_crtcs
);
658 mutex_unlock(&imxdrm
->mutex
);
661 imx_drm_update_possible_crtcs();
665 EXPORT_SYMBOL_GPL(imx_drm_encoder_add_possible_crtcs
);
667 int imx_drm_encoder_get_mux_id(struct drm_encoder
*encoder
)
669 struct imx_drm_crtc
*imx_crtc
= imx_drm_find_crtc(encoder
->crtc
);
671 return imx_crtc
? imx_crtc
->mux_id
: -EINVAL
;
673 EXPORT_SYMBOL_GPL(imx_drm_encoder_get_mux_id
);
676 * imx_drm_remove_encoder - remove an encoder
678 int imx_drm_remove_encoder(struct imx_drm_encoder
*imx_drm_encoder
)
680 struct imx_drm_device
*imxdrm
= __imx_drm_device();
681 struct crtc_cookie
*c
, *tmp
;
683 mutex_lock(&imxdrm
->mutex
);
685 imx_drm_encoder_unregister(imx_drm_encoder
);
687 list_del(&imx_drm_encoder
->list
);
689 list_for_each_entry_safe(c
, tmp
, &imx_drm_encoder
->possible_crtcs
,
693 mutex_unlock(&imxdrm
->mutex
);
695 kfree(imx_drm_encoder
);
699 EXPORT_SYMBOL_GPL(imx_drm_remove_encoder
);
702 * imx_drm_add_connector - add a connector
704 int imx_drm_add_connector(struct drm_connector
*connector
,
705 struct imx_drm_connector
**new_con
,
706 struct module
*owner
)
708 struct imx_drm_device
*imxdrm
= __imx_drm_device();
709 struct imx_drm_connector
*imx_drm_connector
;
712 mutex_lock(&imxdrm
->mutex
);
714 if (imxdrm
->drm
->open_count
) {
719 imx_drm_connector
= kzalloc(sizeof(*imx_drm_connector
), GFP_KERNEL
);
720 if (!imx_drm_connector
) {
725 imx_drm_connector
->connector
= connector
;
726 imx_drm_connector
->owner
= owner
;
728 ret
= imx_drm_connector_register(imx_drm_connector
);
732 list_add_tail(&imx_drm_connector
->list
, &imxdrm
->connector_list
);
734 *new_con
= imx_drm_connector
;
736 mutex_unlock(&imxdrm
->mutex
);
741 kfree(imx_drm_connector
);
744 mutex_unlock(&imxdrm
->mutex
);
748 EXPORT_SYMBOL_GPL(imx_drm_add_connector
);
750 void imx_drm_fb_helper_set(struct drm_fbdev_cma
*fbdev_helper
)
752 struct imx_drm_device
*imxdrm
= __imx_drm_device();
754 imxdrm
->fbhelper
= fbdev_helper
;
756 EXPORT_SYMBOL_GPL(imx_drm_fb_helper_set
);
759 * imx_drm_remove_connector - remove a connector
761 int imx_drm_remove_connector(struct imx_drm_connector
*imx_drm_connector
)
763 struct imx_drm_device
*imxdrm
= __imx_drm_device();
765 mutex_lock(&imxdrm
->mutex
);
767 imx_drm_connector_unregister(imx_drm_connector
);
769 list_del(&imx_drm_connector
->list
);
771 mutex_unlock(&imxdrm
->mutex
);
773 kfree(imx_drm_connector
);
777 EXPORT_SYMBOL_GPL(imx_drm_remove_connector
);
779 static const struct drm_ioctl_desc imx_drm_ioctls
[] = {
783 static struct drm_driver imx_drm_driver
= {
784 .driver_features
= DRIVER_MODESET
| DRIVER_GEM
| DRIVER_PRIME
,
785 .load
= imx_drm_driver_load
,
786 .unload
= imx_drm_driver_unload
,
787 .lastclose
= imx_drm_driver_lastclose
,
788 .preclose
= imx_drm_driver_preclose
,
789 .gem_free_object
= drm_gem_cma_free_object
,
790 .gem_vm_ops
= &drm_gem_cma_vm_ops
,
791 .dumb_create
= drm_gem_cma_dumb_create
,
792 .dumb_map_offset
= drm_gem_cma_dumb_map_offset
,
793 .dumb_destroy
= drm_gem_dumb_destroy
,
795 .prime_handle_to_fd
= drm_gem_prime_handle_to_fd
,
796 .prime_fd_to_handle
= drm_gem_prime_fd_to_handle
,
797 .gem_prime_import
= drm_gem_prime_import
,
798 .gem_prime_export
= drm_gem_prime_export
,
799 .gem_prime_get_sg_table
= drm_gem_cma_prime_get_sg_table
,
800 .gem_prime_import_sg_table
= drm_gem_cma_prime_import_sg_table
,
801 .gem_prime_vmap
= drm_gem_cma_prime_vmap
,
802 .gem_prime_vunmap
= drm_gem_cma_prime_vunmap
,
803 .gem_prime_mmap
= drm_gem_cma_prime_mmap
,
804 .get_vblank_counter
= drm_vblank_count
,
805 .enable_vblank
= imx_drm_enable_vblank
,
806 .disable_vblank
= imx_drm_disable_vblank
,
807 .ioctls
= imx_drm_ioctls
,
808 .num_ioctls
= ARRAY_SIZE(imx_drm_ioctls
),
809 .fops
= &imx_drm_driver_fops
,
811 .desc
= "i.MX DRM graphics",
818 static int compare_parent_of(struct device
*dev
, void *data
)
820 struct of_phandle_args
*args
= data
;
821 return dev
->parent
&& dev
->parent
->of_node
== args
->np
;
824 static int compare_of(struct device
*dev
, void *data
)
826 return dev
->of_node
== data
;
829 static int imx_drm_add_components(struct device
*master
, struct master
*m
)
831 struct device_node
*np
= master
->of_node
;
836 struct of_phandle_args args
;
838 ret
= of_parse_phandle_with_fixed_args(np
, "crtcs", 1,
843 ret
= component_master_add_child(m
, compare_parent_of
, &args
);
844 of_node_put(args
.np
);
851 struct device_node
*node
;
853 node
= of_parse_phandle(np
, "connectors", i
);
857 ret
= component_master_add_child(m
, compare_of
, node
);
866 static int imx_drm_bind(struct device
*dev
)
868 return drm_platform_init(&imx_drm_driver
, to_platform_device(dev
));
871 static void imx_drm_unbind(struct device
*dev
)
873 drm_put_dev(dev_get_drvdata(dev
));
876 static const struct component_master_ops imx_drm_ops
= {
877 .add_components
= imx_drm_add_components
,
878 .bind
= imx_drm_bind
,
879 .unbind
= imx_drm_unbind
,
882 static int imx_drm_platform_probe(struct platform_device
*pdev
)
886 ret
= dma_set_coherent_mask(&pdev
->dev
, DMA_BIT_MASK(32));
890 imx_drm_device
->dev
= &pdev
->dev
;
892 return component_master_add(&pdev
->dev
, &imx_drm_ops
);
895 static int imx_drm_platform_remove(struct platform_device
*pdev
)
897 component_master_del(&pdev
->dev
, &imx_drm_ops
);
901 static const struct of_device_id imx_drm_dt_ids
[] = {
902 { .compatible
= "fsl,imx-drm", },
905 MODULE_DEVICE_TABLE(of
, imx_drm_dt_ids
);
907 static struct platform_driver imx_drm_pdrv
= {
908 .probe
= imx_drm_platform_probe
,
909 .remove
= imx_drm_platform_remove
,
911 .owner
= THIS_MODULE
,
913 .of_match_table
= imx_drm_dt_ids
,
917 static int __init
imx_drm_init(void)
921 imx_drm_device
= kzalloc(sizeof(*imx_drm_device
), GFP_KERNEL
);
925 mutex_init(&imx_drm_device
->mutex
);
926 INIT_LIST_HEAD(&imx_drm_device
->connector_list
);
927 INIT_LIST_HEAD(&imx_drm_device
->encoder_list
);
929 ret
= platform_driver_register(&imx_drm_pdrv
);
936 kfree(imx_drm_device
);
941 static void __exit
imx_drm_exit(void)
943 platform_driver_unregister(&imx_drm_pdrv
);
945 kfree(imx_drm_device
);
948 module_init(imx_drm_init
);
949 module_exit(imx_drm_exit
);
951 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
952 MODULE_DESCRIPTION("i.MX drm driver core");
953 MODULE_LICENSE("GPL");