imx-drm: remove separate imx-fbdev
[deliverable/linux.git] / drivers / staging / imx-drm / imx-drm-core.c
1 /*
2 * Freescale i.MX drm driver
3 *
4 * Copyright (C) 2011 Sascha Hauer, Pengutronix
5 *
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.
14 *
15 */
16 #include <linux/component.h>
17 #include <linux/device.h>
18 #include <linux/platform_device.h>
19 #include <drm/drmP.h>
20 #include <drm/drm_fb_helper.h>
21 #include <drm/drm_crtc_helper.h>
22 #include <linux/fb.h>
23 #include <linux/module.h>
24 #include <drm/drm_gem_cma_helper.h>
25 #include <drm/drm_fb_cma_helper.h>
26
27 #include "imx-drm.h"
28
29 #define MAX_CRTC 4
30
31 struct crtc_cookie {
32 void *cookie;
33 int id;
34 struct list_head list;
35 };
36
37 struct imx_drm_crtc;
38
39 struct imx_drm_device {
40 struct drm_device *drm;
41 struct device *dev;
42 struct imx_drm_crtc *crtc[MAX_CRTC];
43 struct list_head encoder_list;
44 struct list_head connector_list;
45 struct mutex mutex;
46 int pipes;
47 struct drm_fbdev_cma *fbhelper;
48 };
49
50 struct imx_drm_crtc {
51 struct drm_crtc *crtc;
52 struct imx_drm_device *imxdrm;
53 int pipe;
54 struct imx_drm_crtc_helper_funcs imx_drm_helper_funcs;
55 struct module *owner;
56 struct crtc_cookie cookie;
57 int mux_id;
58 };
59
60 struct imx_drm_encoder {
61 struct drm_encoder *encoder;
62 struct list_head list;
63 struct module *owner;
64 struct list_head possible_crtcs;
65 };
66
67 struct imx_drm_connector {
68 struct drm_connector *connector;
69 struct list_head list;
70 struct module *owner;
71 };
72
73 static int legacyfb_depth = 16;
74 module_param(legacyfb_depth, int, 0444);
75
76 static void imx_drm_device_put(void);
77 static struct imx_drm_device *__imx_drm_device(void);
78
79 int imx_drm_crtc_id(struct imx_drm_crtc *crtc)
80 {
81 return crtc->pipe;
82 }
83 EXPORT_SYMBOL_GPL(imx_drm_crtc_id);
84
85 static void imx_drm_driver_lastclose(struct drm_device *drm)
86 {
87 #if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
88 struct imx_drm_device *imxdrm = drm->dev_private;
89
90 if (imxdrm->fbhelper)
91 drm_fbdev_cma_restore_mode(imxdrm->fbhelper);
92 #endif
93 }
94
95 static int imx_drm_driver_unload(struct drm_device *drm)
96 {
97 #if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
98 struct imx_drm_device *imxdrm = drm->dev_private;
99
100 if (imxdrm->fbhelper)
101 drm_fbdev_cma_fini(imxdrm->fbhelper);
102 #endif
103
104 component_unbind_all(drm->dev, drm);
105
106 imx_drm_device_put();
107
108 drm_vblank_cleanup(drm);
109 drm_kms_helper_poll_fini(drm);
110 drm_mode_config_cleanup(drm);
111
112 return 0;
113 }
114
115 struct imx_drm_crtc *imx_drm_find_crtc(struct drm_crtc *crtc)
116 {
117 struct imx_drm_device *imxdrm = __imx_drm_device();
118 unsigned i;
119
120 for (i = 0; i < MAX_CRTC; i++)
121 if (imxdrm->crtc[i] && imxdrm->crtc[i]->crtc == crtc)
122 return imxdrm->crtc[i];
123
124 return NULL;
125 }
126
127 int imx_drm_panel_format_pins(struct drm_encoder *encoder,
128 u32 interface_pix_fmt, int hsync_pin, int vsync_pin)
129 {
130 struct imx_drm_crtc_helper_funcs *helper;
131 struct imx_drm_crtc *imx_crtc;
132
133 imx_crtc = imx_drm_find_crtc(encoder->crtc);
134 if (!imx_crtc)
135 return -EINVAL;
136
137 helper = &imx_crtc->imx_drm_helper_funcs;
138 if (helper->set_interface_pix_fmt)
139 return helper->set_interface_pix_fmt(encoder->crtc,
140 encoder->encoder_type, interface_pix_fmt,
141 hsync_pin, vsync_pin);
142 return 0;
143 }
144 EXPORT_SYMBOL_GPL(imx_drm_panel_format_pins);
145
146 int imx_drm_panel_format(struct drm_encoder *encoder, u32 interface_pix_fmt)
147 {
148 return imx_drm_panel_format_pins(encoder, interface_pix_fmt, 2, 3);
149 }
150 EXPORT_SYMBOL_GPL(imx_drm_panel_format);
151
152 int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc)
153 {
154 return drm_vblank_get(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe);
155 }
156 EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_get);
157
158 void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc)
159 {
160 drm_vblank_put(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe);
161 }
162 EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_put);
163
164 void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc)
165 {
166 drm_handle_vblank(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe);
167 }
168 EXPORT_SYMBOL_GPL(imx_drm_handle_vblank);
169
170 static int imx_drm_enable_vblank(struct drm_device *drm, int crtc)
171 {
172 struct imx_drm_device *imxdrm = drm->dev_private;
173 struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[crtc];
174 int ret;
175
176 if (!imx_drm_crtc)
177 return -EINVAL;
178
179 if (!imx_drm_crtc->imx_drm_helper_funcs.enable_vblank)
180 return -ENOSYS;
181
182 ret = imx_drm_crtc->imx_drm_helper_funcs.enable_vblank(
183 imx_drm_crtc->crtc);
184
185 return ret;
186 }
187
188 static void imx_drm_disable_vblank(struct drm_device *drm, int crtc)
189 {
190 struct imx_drm_device *imxdrm = drm->dev_private;
191 struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[crtc];
192
193 if (!imx_drm_crtc)
194 return;
195
196 if (!imx_drm_crtc->imx_drm_helper_funcs.disable_vblank)
197 return;
198
199 imx_drm_crtc->imx_drm_helper_funcs.disable_vblank(imx_drm_crtc->crtc);
200 }
201
202 static void imx_drm_driver_preclose(struct drm_device *drm,
203 struct drm_file *file)
204 {
205 int i;
206
207 if (!file->is_master)
208 return;
209
210 for (i = 0; i < MAX_CRTC; i++)
211 imx_drm_disable_vblank(drm, i);
212 }
213
214 static const struct file_operations imx_drm_driver_fops = {
215 .owner = THIS_MODULE,
216 .open = drm_open,
217 .release = drm_release,
218 .unlocked_ioctl = drm_ioctl,
219 .mmap = drm_gem_cma_mmap,
220 .poll = drm_poll,
221 .read = drm_read,
222 .llseek = noop_llseek,
223 };
224
225 int imx_drm_connector_mode_valid(struct drm_connector *connector,
226 struct drm_display_mode *mode)
227 {
228 return MODE_OK;
229 }
230 EXPORT_SYMBOL(imx_drm_connector_mode_valid);
231
232 static struct imx_drm_device *imx_drm_device;
233
234 static struct imx_drm_device *__imx_drm_device(void)
235 {
236 return imx_drm_device;
237 }
238
239 static struct drm_device *imx_drm_device_get(void)
240 {
241 struct imx_drm_device *imxdrm = __imx_drm_device();
242 struct imx_drm_encoder *enc;
243 struct imx_drm_connector *con;
244 struct imx_drm_crtc *crtc;
245
246 list_for_each_entry(enc, &imxdrm->encoder_list, list) {
247 if (!try_module_get(enc->owner)) {
248 dev_err(imxdrm->dev, "could not get module %s\n",
249 module_name(enc->owner));
250 goto unwind_enc;
251 }
252 }
253
254 list_for_each_entry(con, &imxdrm->connector_list, list) {
255 if (!try_module_get(con->owner)) {
256 dev_err(imxdrm->dev, "could not get module %s\n",
257 module_name(con->owner));
258 goto unwind_con;
259 }
260 }
261
262 list_for_each_entry(crtc, &imxdrm->crtc_list, list) {
263 if (!try_module_get(crtc->owner)) {
264 dev_err(imxdrm->dev, "could not get module %s\n",
265 module_name(crtc->owner));
266 goto unwind_crtc;
267 }
268 }
269
270 return imxdrm->drm;
271
272 unwind_crtc:
273 list_for_each_entry_continue_reverse(crtc, &imxdrm->crtc_list, list)
274 module_put(crtc->owner);
275 unwind_con:
276 list_for_each_entry_continue_reverse(con, &imxdrm->connector_list, list)
277 module_put(con->owner);
278 unwind_enc:
279 list_for_each_entry_continue_reverse(enc, &imxdrm->encoder_list, list)
280 module_put(enc->owner);
281
282 mutex_unlock(&imxdrm->mutex);
283
284 return NULL;
285
286 }
287
288 static void imx_drm_device_put(void)
289 {
290 struct imx_drm_device *imxdrm = __imx_drm_device();
291 struct imx_drm_encoder *enc;
292 struct imx_drm_connector *con;
293 struct imx_drm_crtc *crtc;
294
295 mutex_lock(&imxdrm->mutex);
296
297 list_for_each_entry(crtc, &imxdrm->crtc_list, list)
298 module_put(crtc->owner);
299
300 list_for_each_entry(con, &imxdrm->connector_list, list)
301 module_put(con->owner);
302
303 list_for_each_entry(enc, &imxdrm->encoder_list, list)
304 module_put(enc->owner);
305
306 mutex_unlock(&imxdrm->mutex);
307 }
308
309 static int drm_mode_group_reinit(struct drm_device *dev)
310 {
311 struct drm_mode_group *group = &dev->primary->mode_group;
312 uint32_t *id_list = group->id_list;
313 int ret;
314
315 ret = drm_mode_group_init_legacy_group(dev, group);
316 if (ret < 0)
317 return ret;
318
319 kfree(id_list);
320 return 0;
321 }
322
323 /*
324 * register an encoder to the drm core
325 */
326 static int imx_drm_encoder_register(struct imx_drm_encoder *imx_drm_encoder)
327 {
328 struct imx_drm_device *imxdrm = __imx_drm_device();
329
330 INIT_LIST_HEAD(&imx_drm_encoder->possible_crtcs);
331
332 drm_encoder_init(imxdrm->drm, imx_drm_encoder->encoder,
333 imx_drm_encoder->encoder->funcs,
334 imx_drm_encoder->encoder->encoder_type);
335
336 drm_mode_group_reinit(imxdrm->drm);
337
338 return 0;
339 }
340
341 /*
342 * unregister an encoder from the drm core
343 */
344 static void imx_drm_encoder_unregister(struct imx_drm_encoder
345 *imx_drm_encoder)
346 {
347 struct imx_drm_device *imxdrm = __imx_drm_device();
348
349 drm_encoder_cleanup(imx_drm_encoder->encoder);
350
351 drm_mode_group_reinit(imxdrm->drm);
352 }
353
354 /*
355 * register a connector to the drm core
356 */
357 static int imx_drm_connector_register(
358 struct imx_drm_connector *imx_drm_connector)
359 {
360 struct imx_drm_device *imxdrm = __imx_drm_device();
361
362 drm_connector_init(imxdrm->drm, imx_drm_connector->connector,
363 imx_drm_connector->connector->funcs,
364 imx_drm_connector->connector->connector_type);
365 drm_mode_group_reinit(imxdrm->drm);
366
367 return 0;
368 }
369
370 /*
371 * unregister a connector from the drm core
372 */
373 static void imx_drm_connector_unregister(
374 struct imx_drm_connector *imx_drm_connector)
375 {
376 struct imx_drm_device *imxdrm = __imx_drm_device();
377
378 drm_sysfs_connector_remove(imx_drm_connector->connector);
379 drm_connector_cleanup(imx_drm_connector->connector);
380
381 drm_mode_group_reinit(imxdrm->drm);
382 }
383
384 /*
385 * Main DRM initialisation. This binds, initialises and registers
386 * with DRM the subcomponents of the driver.
387 */
388 static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
389 {
390 struct imx_drm_device *imxdrm = __imx_drm_device();
391 struct drm_connector *connector;
392 int ret;
393
394 imxdrm->drm = drm;
395
396 drm->dev_private = imxdrm;
397
398 /*
399 * enable drm irq mode.
400 * - with irq_enabled = true, we can use the vblank feature.
401 *
402 * P.S. note that we wouldn't use drm irq handler but
403 * just specific driver own one instead because
404 * drm framework supports only one irq handler and
405 * drivers can well take care of their interrupts
406 */
407 drm->irq_enabled = true;
408
409 drm_mode_config_init(drm);
410 imx_drm_mode_config_init(drm);
411
412 mutex_lock(&imxdrm->mutex);
413
414 drm_kms_helper_poll_init(drm);
415
416 /* setup the grouping for the legacy output */
417 ret = drm_mode_group_init_legacy_group(drm,
418 &drm->primary->mode_group);
419 if (ret)
420 goto err_kms;
421
422 ret = drm_vblank_init(drm, MAX_CRTC);
423 if (ret)
424 goto err_kms;
425
426 /*
427 * with vblank_disable_allowed = true, vblank interrupt will be disabled
428 * by drm timer once a current process gives up ownership of
429 * vblank event.(after drm_vblank_put function is called)
430 */
431 drm->vblank_disable_allowed = true;
432
433 if (!imx_drm_device_get()) {
434 ret = -EINVAL;
435 goto err_vblank;
436 }
437
438 platform_set_drvdata(drm->platformdev, drm);
439 mutex_unlock(&imxdrm->mutex);
440
441 /* Now try and bind all our sub-components */
442 ret = component_bind_all(drm->dev, drm);
443 if (ret)
444 goto err_relock;
445
446 /*
447 * All components are now added, we can publish the connector sysfs
448 * entries to userspace. This will generate hotplug events and so
449 * userspace will expect to be able to access DRM at this point.
450 */
451 list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
452 ret = drm_sysfs_connector_add(connector);
453 if (ret) {
454 dev_err(drm->dev,
455 "[CONNECTOR:%d:%s] drm_sysfs_connector_add failed: %d\n",
456 connector->base.id,
457 drm_get_connector_name(connector), ret);
458 goto err_unbind;
459 }
460 }
461
462 /*
463 * All components are now initialised, so setup the fb helper.
464 * The fb helper takes copies of key hardware information, so the
465 * crtcs/connectors/encoders must not change after this point.
466 */
467 #if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER)
468 if (legacyfb_depth != 16 && legacyfb_depth != 32) {
469 dev_warn(drm->dev, "Invalid legacyfb_depth. Defaulting to 16bpp\n");
470 legacyfb_depth = 16;
471 }
472 imxdrm->fbhelper = drm_fbdev_cma_init(drm, legacyfb_depth,
473 drm->mode_config.num_crtc, MAX_CRTC);
474 if (IS_ERR(imxdrm->fbhelper)) {
475 ret = PTR_ERR(imxdrm->fbhelper);
476 imxdrm->fbhelper = NULL;
477 goto err_unbind;
478 }
479 #endif
480 return 0;
481
482 err_unbind:
483 component_unbind_all(drm->dev, drm);
484 err_relock:
485 mutex_lock(&imxdrm->mutex);
486 err_vblank:
487 drm_vblank_cleanup(drm);
488 err_kms:
489 drm_kms_helper_poll_fini(drm);
490 drm_mode_config_cleanup(drm);
491 mutex_unlock(&imxdrm->mutex);
492
493 return ret;
494 }
495
496 static void imx_drm_update_possible_crtcs(void)
497 {
498 struct imx_drm_device *imxdrm = __imx_drm_device();
499 struct imx_drm_crtc *imx_drm_crtc;
500 struct imx_drm_encoder *enc;
501 struct crtc_cookie *cookie;
502
503 list_for_each_entry(enc, &imxdrm->encoder_list, list) {
504 u32 possible_crtcs = 0;
505
506 list_for_each_entry(cookie, &enc->possible_crtcs, list) {
507 list_for_each_entry(imx_drm_crtc, &imxdrm->crtc_list, list) {
508 if (imx_drm_crtc->cookie.cookie == cookie->cookie &&
509 imx_drm_crtc->cookie.id == cookie->id) {
510 possible_crtcs |= 1 << imx_drm_crtc->pipe;
511 }
512 }
513 }
514 enc->encoder->possible_crtcs = possible_crtcs;
515 enc->encoder->possible_clones = possible_crtcs;
516 }
517 }
518
519 /*
520 * imx_drm_add_crtc - add a new crtc
521 *
522 * The return value if !NULL is a cookie for the caller to pass to
523 * imx_drm_remove_crtc later.
524 */
525 int imx_drm_add_crtc(struct drm_crtc *crtc,
526 struct imx_drm_crtc **new_crtc,
527 const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs,
528 struct module *owner, void *cookie, int id)
529 {
530 struct imx_drm_device *imxdrm = __imx_drm_device();
531 struct imx_drm_crtc *imx_drm_crtc;
532 int ret;
533
534 mutex_lock(&imxdrm->mutex);
535
536 /*
537 * The vblank arrays are dimensioned by MAX_CRTC - we can't
538 * pass IDs greater than this to those functions.
539 */
540 if (imxdrm->pipes >= MAX_CRTC) {
541 ret = -EINVAL;
542 goto err_busy;
543 }
544
545 if (imxdrm->drm->open_count) {
546 ret = -EBUSY;
547 goto err_busy;
548 }
549
550 imx_drm_crtc = kzalloc(sizeof(*imx_drm_crtc), GFP_KERNEL);
551 if (!imx_drm_crtc) {
552 ret = -ENOMEM;
553 goto err_alloc;
554 }
555
556 imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs;
557 imx_drm_crtc->pipe = imxdrm->pipes++;
558 imx_drm_crtc->cookie.cookie = cookie;
559 imx_drm_crtc->cookie.id = id;
560 imx_drm_crtc->mux_id = imx_drm_crtc->pipe;
561 imx_drm_crtc->crtc = crtc;
562 imx_drm_crtc->imxdrm = imxdrm;
563
564 imx_drm_crtc->owner = owner;
565
566 imxdrm->crtc[imx_drm_crtc->pipe] = imx_drm_crtc;
567
568 *new_crtc = imx_drm_crtc;
569
570 ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256);
571 if (ret)
572 goto err_register;
573
574 drm_crtc_helper_add(crtc,
575 imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
576
577 drm_crtc_init(imxdrm->drm, crtc,
578 imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
579
580 drm_mode_group_reinit(imxdrm->drm);
581
582 imx_drm_update_possible_crtcs();
583
584 mutex_unlock(&imxdrm->mutex);
585
586 return 0;
587
588 err_register:
589 imxdrm->crtc[imx_drm_crtc->pipe] = NULL;
590 kfree(imx_drm_crtc);
591 err_alloc:
592 err_busy:
593 mutex_unlock(&imxdrm->mutex);
594 return ret;
595 }
596 EXPORT_SYMBOL_GPL(imx_drm_add_crtc);
597
598 /*
599 * imx_drm_remove_crtc - remove a crtc
600 */
601 int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc)
602 {
603 struct imx_drm_device *imxdrm = imx_drm_crtc->imxdrm;
604
605 mutex_lock(&imxdrm->mutex);
606
607 drm_crtc_cleanup(imx_drm_crtc->crtc);
608
609 imxdrm->crtc[imx_drm_crtc->pipe] = NULL;
610
611 drm_mode_group_reinit(imxdrm->drm);
612
613 mutex_unlock(&imxdrm->mutex);
614
615 kfree(imx_drm_crtc);
616
617 return 0;
618 }
619 EXPORT_SYMBOL_GPL(imx_drm_remove_crtc);
620
621 /*
622 * imx_drm_add_encoder - add a new encoder
623 */
624 int imx_drm_add_encoder(struct drm_encoder *encoder,
625 struct imx_drm_encoder **newenc, struct module *owner)
626 {
627 struct imx_drm_device *imxdrm = __imx_drm_device();
628 struct imx_drm_encoder *imx_drm_encoder;
629 int ret;
630
631 mutex_lock(&imxdrm->mutex);
632
633 if (imxdrm->drm->open_count) {
634 ret = -EBUSY;
635 goto err_busy;
636 }
637
638 imx_drm_encoder = kzalloc(sizeof(*imx_drm_encoder), GFP_KERNEL);
639 if (!imx_drm_encoder) {
640 ret = -ENOMEM;
641 goto err_alloc;
642 }
643
644 imx_drm_encoder->encoder = encoder;
645 imx_drm_encoder->owner = owner;
646
647 ret = imx_drm_encoder_register(imx_drm_encoder);
648 if (ret) {
649 ret = -ENOMEM;
650 goto err_register;
651 }
652
653 list_add_tail(&imx_drm_encoder->list, &imxdrm->encoder_list);
654
655 *newenc = imx_drm_encoder;
656
657 mutex_unlock(&imxdrm->mutex);
658
659 return 0;
660
661 err_register:
662 kfree(imx_drm_encoder);
663 err_alloc:
664 err_busy:
665 mutex_unlock(&imxdrm->mutex);
666
667 return ret;
668 }
669 EXPORT_SYMBOL_GPL(imx_drm_add_encoder);
670
671 int imx_drm_encoder_add_possible_crtcs(
672 struct imx_drm_encoder *imx_drm_encoder,
673 struct device_node *np)
674 {
675 struct imx_drm_device *imxdrm = __imx_drm_device();
676 struct of_phandle_args args;
677 struct crtc_cookie *c;
678 int ret = 0;
679 int i;
680
681 if (!list_empty(&imx_drm_encoder->possible_crtcs))
682 return -EBUSY;
683
684 for (i = 0; !ret; i++) {
685 ret = of_parse_phandle_with_args(np, "crtcs",
686 "#crtc-cells", i, &args);
687 if (ret < 0)
688 break;
689
690 c = kzalloc(sizeof(*c), GFP_KERNEL);
691 if (!c) {
692 of_node_put(args.np);
693 return -ENOMEM;
694 }
695
696 c->cookie = args.np;
697 c->id = args.args_count > 0 ? args.args[0] : 0;
698
699 of_node_put(args.np);
700
701 mutex_lock(&imxdrm->mutex);
702
703 list_add_tail(&c->list, &imx_drm_encoder->possible_crtcs);
704
705 mutex_unlock(&imxdrm->mutex);
706 }
707
708 imx_drm_update_possible_crtcs();
709
710 return 0;
711 }
712 EXPORT_SYMBOL_GPL(imx_drm_encoder_add_possible_crtcs);
713
714 int imx_drm_encoder_get_mux_id(struct drm_encoder *encoder)
715 {
716 struct imx_drm_crtc *imx_crtc = imx_drm_find_crtc(encoder->crtc);
717
718 return imx_crtc ? imx_crtc->mux_id : -EINVAL;
719 }
720 EXPORT_SYMBOL_GPL(imx_drm_encoder_get_mux_id);
721
722 /*
723 * imx_drm_remove_encoder - remove an encoder
724 */
725 int imx_drm_remove_encoder(struct imx_drm_encoder *imx_drm_encoder)
726 {
727 struct imx_drm_device *imxdrm = __imx_drm_device();
728 struct crtc_cookie *c, *tmp;
729
730 mutex_lock(&imxdrm->mutex);
731
732 imx_drm_encoder_unregister(imx_drm_encoder);
733
734 list_del(&imx_drm_encoder->list);
735
736 list_for_each_entry_safe(c, tmp, &imx_drm_encoder->possible_crtcs,
737 list)
738 kfree(c);
739
740 mutex_unlock(&imxdrm->mutex);
741
742 kfree(imx_drm_encoder);
743
744 return 0;
745 }
746 EXPORT_SYMBOL_GPL(imx_drm_remove_encoder);
747
748 /*
749 * imx_drm_add_connector - add a connector
750 */
751 int imx_drm_add_connector(struct drm_connector *connector,
752 struct imx_drm_connector **new_con,
753 struct module *owner)
754 {
755 struct imx_drm_device *imxdrm = __imx_drm_device();
756 struct imx_drm_connector *imx_drm_connector;
757 int ret;
758
759 mutex_lock(&imxdrm->mutex);
760
761 if (imxdrm->drm->open_count) {
762 ret = -EBUSY;
763 goto err_busy;
764 }
765
766 imx_drm_connector = kzalloc(sizeof(*imx_drm_connector), GFP_KERNEL);
767 if (!imx_drm_connector) {
768 ret = -ENOMEM;
769 goto err_alloc;
770 }
771
772 imx_drm_connector->connector = connector;
773 imx_drm_connector->owner = owner;
774
775 ret = imx_drm_connector_register(imx_drm_connector);
776 if (ret)
777 goto err_register;
778
779 list_add_tail(&imx_drm_connector->list, &imxdrm->connector_list);
780
781 *new_con = imx_drm_connector;
782
783 mutex_unlock(&imxdrm->mutex);
784
785 return 0;
786
787 err_register:
788 kfree(imx_drm_connector);
789 err_alloc:
790 err_busy:
791 mutex_unlock(&imxdrm->mutex);
792
793 return ret;
794 }
795 EXPORT_SYMBOL_GPL(imx_drm_add_connector);
796
797 /*
798 * imx_drm_remove_connector - remove a connector
799 */
800 int imx_drm_remove_connector(struct imx_drm_connector *imx_drm_connector)
801 {
802 struct imx_drm_device *imxdrm = __imx_drm_device();
803
804 mutex_lock(&imxdrm->mutex);
805
806 imx_drm_connector_unregister(imx_drm_connector);
807
808 list_del(&imx_drm_connector->list);
809
810 mutex_unlock(&imxdrm->mutex);
811
812 kfree(imx_drm_connector);
813
814 return 0;
815 }
816 EXPORT_SYMBOL_GPL(imx_drm_remove_connector);
817
818 static const struct drm_ioctl_desc imx_drm_ioctls[] = {
819 /* none so far */
820 };
821
822 static struct drm_driver imx_drm_driver = {
823 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
824 .load = imx_drm_driver_load,
825 .unload = imx_drm_driver_unload,
826 .lastclose = imx_drm_driver_lastclose,
827 .preclose = imx_drm_driver_preclose,
828 .gem_free_object = drm_gem_cma_free_object,
829 .gem_vm_ops = &drm_gem_cma_vm_ops,
830 .dumb_create = drm_gem_cma_dumb_create,
831 .dumb_map_offset = drm_gem_cma_dumb_map_offset,
832 .dumb_destroy = drm_gem_dumb_destroy,
833
834 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
835 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
836 .gem_prime_import = drm_gem_prime_import,
837 .gem_prime_export = drm_gem_prime_export,
838 .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
839 .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
840 .gem_prime_vmap = drm_gem_cma_prime_vmap,
841 .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
842 .gem_prime_mmap = drm_gem_cma_prime_mmap,
843 .get_vblank_counter = drm_vblank_count,
844 .enable_vblank = imx_drm_enable_vblank,
845 .disable_vblank = imx_drm_disable_vblank,
846 .ioctls = imx_drm_ioctls,
847 .num_ioctls = ARRAY_SIZE(imx_drm_ioctls),
848 .fops = &imx_drm_driver_fops,
849 .name = "imx-drm",
850 .desc = "i.MX DRM graphics",
851 .date = "20120507",
852 .major = 1,
853 .minor = 0,
854 .patchlevel = 0,
855 };
856
857 static int compare_parent_of(struct device *dev, void *data)
858 {
859 struct of_phandle_args *args = data;
860 return dev->parent && dev->parent->of_node == args->np;
861 }
862
863 static int compare_of(struct device *dev, void *data)
864 {
865 return dev->of_node == data;
866 }
867
868 static int imx_drm_add_components(struct device *master, struct master *m)
869 {
870 struct device_node *np = master->of_node;
871 unsigned i;
872 int ret;
873
874 for (i = 0; ; i++) {
875 struct of_phandle_args args;
876
877 ret = of_parse_phandle_with_fixed_args(np, "crtcs", 1,
878 i, &args);
879 if (ret)
880 break;
881
882 ret = component_master_add_child(m, compare_parent_of, &args);
883 of_node_put(args.np);
884
885 if (ret)
886 return ret;
887 }
888
889 for (i = 0; ; i++) {
890 struct device_node *node;
891
892 node = of_parse_phandle(np, "connectors", i);
893 if (!node)
894 break;
895
896 ret = component_master_add_child(m, compare_of, node);
897 of_node_put(node);
898
899 if (ret)
900 return ret;
901 }
902 return 0;
903 }
904
905 static int imx_drm_bind(struct device *dev)
906 {
907 return drm_platform_init(&imx_drm_driver, to_platform_device(dev));
908 }
909
910 static void imx_drm_unbind(struct device *dev)
911 {
912 drm_put_dev(dev_get_drvdata(dev));
913 }
914
915 static const struct component_master_ops imx_drm_ops = {
916 .add_components = imx_drm_add_components,
917 .bind = imx_drm_bind,
918 .unbind = imx_drm_unbind,
919 };
920
921 static int imx_drm_platform_probe(struct platform_device *pdev)
922 {
923 int ret;
924
925 ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
926 if (ret)
927 return ret;
928
929 imx_drm_device->dev = &pdev->dev;
930
931 return component_master_add(&pdev->dev, &imx_drm_ops);
932 }
933
934 static int imx_drm_platform_remove(struct platform_device *pdev)
935 {
936 component_master_del(&pdev->dev, &imx_drm_ops);
937 return 0;
938 }
939
940 static const struct of_device_id imx_drm_dt_ids[] = {
941 { .compatible = "fsl,imx-drm", },
942 { /* sentinel */ },
943 };
944 MODULE_DEVICE_TABLE(of, imx_drm_dt_ids);
945
946 static struct platform_driver imx_drm_pdrv = {
947 .probe = imx_drm_platform_probe,
948 .remove = imx_drm_platform_remove,
949 .driver = {
950 .owner = THIS_MODULE,
951 .name = "imx-drm",
952 .of_match_table = imx_drm_dt_ids,
953 },
954 };
955
956 static int __init imx_drm_init(void)
957 {
958 int ret;
959
960 imx_drm_device = kzalloc(sizeof(*imx_drm_device), GFP_KERNEL);
961 if (!imx_drm_device)
962 return -ENOMEM;
963
964 mutex_init(&imx_drm_device->mutex);
965 INIT_LIST_HEAD(&imx_drm_device->connector_list);
966 INIT_LIST_HEAD(&imx_drm_device->encoder_list);
967
968 ret = platform_driver_register(&imx_drm_pdrv);
969 if (ret)
970 goto err_pdrv;
971
972 return 0;
973
974 err_pdrv:
975 kfree(imx_drm_device);
976
977 return ret;
978 }
979
980 static void __exit imx_drm_exit(void)
981 {
982 platform_driver_unregister(&imx_drm_pdrv);
983
984 kfree(imx_drm_device);
985 }
986
987 module_init(imx_drm_init);
988 module_exit(imx_drm_exit);
989
990 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
991 MODULE_DESCRIPTION("i.MX drm driver core");
992 MODULE_LICENSE("GPL");
This page took 0.081773 seconds and 5 git commands to generate.