imx-drm: imx-drm-core: use array instead of list for CRTCs
[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
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 struct imx_drm_device *__imx_drm_device(void);
74
75 int imx_drm_crtc_id(struct imx_drm_crtc *crtc)
76 {
77 return crtc->pipe;
78 }
79 EXPORT_SYMBOL_GPL(imx_drm_crtc_id);
80
81 static void imx_drm_driver_lastclose(struct drm_device *drm)
82 {
83 struct imx_drm_device *imxdrm = drm->dev_private;
84
85 if (imxdrm->fbhelper)
86 drm_fbdev_cma_restore_mode(imxdrm->fbhelper);
87 }
88
89 static int imx_drm_driver_unload(struct drm_device *drm)
90 {
91 struct imx_drm_device *imxdrm = drm->dev_private;
92
93 imx_drm_device_put();
94
95 drm_vblank_cleanup(drm);
96 drm_kms_helper_poll_fini(drm);
97 drm_mode_config_cleanup(drm);
98
99 return 0;
100 }
101
102 struct imx_drm_crtc *imx_drm_find_crtc(struct drm_crtc *crtc)
103 {
104 struct imx_drm_device *imxdrm = __imx_drm_device();
105 unsigned i;
106
107 for (i = 0; i < MAX_CRTC; i++)
108 if (imxdrm->crtc[i] && imxdrm->crtc[i]->crtc == crtc)
109 return imxdrm->crtc[i];
110
111 return NULL;
112 }
113
114 int imx_drm_crtc_panel_format_pins(struct drm_crtc *crtc, u32 encoder_type,
115 u32 interface_pix_fmt, int hsync_pin, int vsync_pin)
116 {
117 struct imx_drm_crtc_helper_funcs *helper;
118 struct imx_drm_crtc *imx_crtc;
119
120 imx_crtc = imx_drm_find_crtc(crtc);
121 if (!imx_crtc)
122 return -EINVAL;
123
124 helper = &imx_crtc->imx_drm_helper_funcs;
125 if (helper->set_interface_pix_fmt)
126 return helper->set_interface_pix_fmt(crtc,
127 encoder_type, interface_pix_fmt,
128 hsync_pin, vsync_pin);
129 return 0;
130 }
131 EXPORT_SYMBOL_GPL(imx_drm_crtc_panel_format_pins);
132
133 int imx_drm_crtc_panel_format(struct drm_crtc *crtc, u32 encoder_type,
134 u32 interface_pix_fmt)
135 {
136 return imx_drm_crtc_panel_format_pins(crtc, encoder_type,
137 interface_pix_fmt, 2, 3);
138 }
139 EXPORT_SYMBOL_GPL(imx_drm_crtc_panel_format);
140
141 int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc)
142 {
143 return drm_vblank_get(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe);
144 }
145 EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_get);
146
147 void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc)
148 {
149 drm_vblank_put(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe);
150 }
151 EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_put);
152
153 void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc)
154 {
155 drm_handle_vblank(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe);
156 }
157 EXPORT_SYMBOL_GPL(imx_drm_handle_vblank);
158
159 static int imx_drm_enable_vblank(struct drm_device *drm, int crtc)
160 {
161 struct imx_drm_device *imxdrm = drm->dev_private;
162 struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[crtc];
163 int ret;
164
165 if (!imx_drm_crtc)
166 return -EINVAL;
167
168 if (!imx_drm_crtc->imx_drm_helper_funcs.enable_vblank)
169 return -ENOSYS;
170
171 ret = imx_drm_crtc->imx_drm_helper_funcs.enable_vblank(
172 imx_drm_crtc->crtc);
173
174 return ret;
175 }
176
177 static void imx_drm_disable_vblank(struct drm_device *drm, int crtc)
178 {
179 struct imx_drm_device *imxdrm = drm->dev_private;
180 struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[crtc];
181
182 if (!imx_drm_crtc)
183 return;
184
185 if (!imx_drm_crtc->imx_drm_helper_funcs.disable_vblank)
186 return;
187
188 imx_drm_crtc->imx_drm_helper_funcs.disable_vblank(imx_drm_crtc->crtc);
189 }
190
191 static void imx_drm_driver_preclose(struct drm_device *drm,
192 struct drm_file *file)
193 {
194 int i;
195
196 if (!file->is_master)
197 return;
198
199 for (i = 0; i < MAX_CRTC; i++)
200 imx_drm_disable_vblank(drm, i);
201 }
202
203 static const struct file_operations imx_drm_driver_fops = {
204 .owner = THIS_MODULE,
205 .open = drm_open,
206 .release = drm_release,
207 .unlocked_ioctl = drm_ioctl,
208 .mmap = drm_gem_cma_mmap,
209 .poll = drm_poll,
210 .read = drm_read,
211 .llseek = noop_llseek,
212 };
213
214 static struct imx_drm_device *imx_drm_device;
215
216 static struct imx_drm_device *__imx_drm_device(void)
217 {
218 return imx_drm_device;
219 }
220
221 struct drm_device *imx_drm_device_get(void)
222 {
223 struct imx_drm_device *imxdrm = __imx_drm_device();
224 struct imx_drm_encoder *enc;
225 struct imx_drm_connector *con;
226 struct imx_drm_crtc *crtc;
227
228 list_for_each_entry(enc, &imxdrm->encoder_list, list) {
229 if (!try_module_get(enc->owner)) {
230 dev_err(imxdrm->dev, "could not get module %s\n",
231 module_name(enc->owner));
232 goto unwind_enc;
233 }
234 }
235
236 list_for_each_entry(con, &imxdrm->connector_list, list) {
237 if (!try_module_get(con->owner)) {
238 dev_err(imxdrm->dev, "could not get module %s\n",
239 module_name(con->owner));
240 goto unwind_con;
241 }
242 }
243
244 list_for_each_entry(crtc, &imxdrm->crtc_list, list) {
245 if (!try_module_get(crtc->owner)) {
246 dev_err(imxdrm->dev, "could not get module %s\n",
247 module_name(crtc->owner));
248 goto unwind_crtc;
249 }
250 }
251
252 return imxdrm->drm;
253
254 unwind_crtc:
255 list_for_each_entry_continue_reverse(crtc, &imxdrm->crtc_list, list)
256 module_put(crtc->owner);
257 unwind_con:
258 list_for_each_entry_continue_reverse(con, &imxdrm->connector_list, list)
259 module_put(con->owner);
260 unwind_enc:
261 list_for_each_entry_continue_reverse(enc, &imxdrm->encoder_list, list)
262 module_put(enc->owner);
263
264 mutex_unlock(&imxdrm->mutex);
265
266 return NULL;
267
268 }
269 EXPORT_SYMBOL_GPL(imx_drm_device_get);
270
271 void imx_drm_device_put(void)
272 {
273 struct imx_drm_device *imxdrm = __imx_drm_device();
274 struct imx_drm_encoder *enc;
275 struct imx_drm_connector *con;
276 struct imx_drm_crtc *crtc;
277
278 mutex_lock(&imxdrm->mutex);
279
280 list_for_each_entry(crtc, &imxdrm->crtc_list, list)
281 module_put(crtc->owner);
282
283 list_for_each_entry(con, &imxdrm->connector_list, list)
284 module_put(con->owner);
285
286 list_for_each_entry(enc, &imxdrm->encoder_list, list)
287 module_put(enc->owner);
288
289 mutex_unlock(&imxdrm->mutex);
290 }
291 EXPORT_SYMBOL_GPL(imx_drm_device_put);
292
293 static int drm_mode_group_reinit(struct drm_device *dev)
294 {
295 struct drm_mode_group *group = &dev->primary->mode_group;
296 uint32_t *id_list = group->id_list;
297 int ret;
298
299 ret = drm_mode_group_init_legacy_group(dev, group);
300 if (ret < 0)
301 return ret;
302
303 kfree(id_list);
304 return 0;
305 }
306
307 /*
308 * register an encoder to the drm core
309 */
310 static int imx_drm_encoder_register(struct imx_drm_encoder *imx_drm_encoder)
311 {
312 struct imx_drm_device *imxdrm = __imx_drm_device();
313
314 INIT_LIST_HEAD(&imx_drm_encoder->possible_crtcs);
315
316 drm_encoder_init(imxdrm->drm, imx_drm_encoder->encoder,
317 imx_drm_encoder->encoder->funcs,
318 imx_drm_encoder->encoder->encoder_type);
319
320 drm_mode_group_reinit(imxdrm->drm);
321
322 return 0;
323 }
324
325 /*
326 * unregister an encoder from the drm core
327 */
328 static void imx_drm_encoder_unregister(struct imx_drm_encoder
329 *imx_drm_encoder)
330 {
331 struct imx_drm_device *imxdrm = __imx_drm_device();
332
333 drm_encoder_cleanup(imx_drm_encoder->encoder);
334
335 drm_mode_group_reinit(imxdrm->drm);
336 }
337
338 /*
339 * register a connector to the drm core
340 */
341 static int imx_drm_connector_register(
342 struct imx_drm_connector *imx_drm_connector)
343 {
344 struct imx_drm_device *imxdrm = __imx_drm_device();
345
346 drm_connector_init(imxdrm->drm, imx_drm_connector->connector,
347 imx_drm_connector->connector->funcs,
348 imx_drm_connector->connector->connector_type);
349 drm_mode_group_reinit(imxdrm->drm);
350
351 return drm_sysfs_connector_add(imx_drm_connector->connector);
352 }
353
354 /*
355 * unregister a connector from the drm core
356 */
357 static void imx_drm_connector_unregister(
358 struct imx_drm_connector *imx_drm_connector)
359 {
360 struct imx_drm_device *imxdrm = __imx_drm_device();
361
362 drm_sysfs_connector_remove(imx_drm_connector->connector);
363 drm_connector_cleanup(imx_drm_connector->connector);
364
365 drm_mode_group_reinit(imxdrm->drm);
366 }
367
368 /*
369 * Called by the CRTC driver when all CRTCs are registered. This
370 * puts all the pieces together and initializes the driver.
371 * Once this is called no more CRTCs can be registered since
372 * the drm core has hardcoded the number of crtcs in several
373 * places.
374 */
375 static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
376 {
377 struct imx_drm_device *imxdrm = __imx_drm_device();
378 int ret;
379
380 imxdrm->drm = drm;
381
382 drm->dev_private = imxdrm;
383
384 /*
385 * enable drm irq mode.
386 * - with irq_enabled = true, we can use the vblank feature.
387 *
388 * P.S. note that we wouldn't use drm irq handler but
389 * just specific driver own one instead because
390 * drm framework supports only one irq handler and
391 * drivers can well take care of their interrupts
392 */
393 drm->irq_enabled = true;
394
395 drm_mode_config_init(drm);
396 imx_drm_mode_config_init(drm);
397
398 mutex_lock(&imxdrm->mutex);
399
400 drm_kms_helper_poll_init(drm);
401
402 /* setup the grouping for the legacy output */
403 ret = drm_mode_group_init_legacy_group(drm,
404 &drm->primary->mode_group);
405 if (ret)
406 goto err_kms;
407
408 ret = drm_vblank_init(drm, MAX_CRTC);
409 if (ret)
410 goto err_kms;
411
412 /*
413 * with vblank_disable_allowed = true, vblank interrupt will be disabled
414 * by drm timer once a current process gives up ownership of
415 * vblank event.(after drm_vblank_put function is called)
416 */
417 drm->vblank_disable_allowed = true;
418
419 if (!imx_drm_device_get()) {
420 ret = -EINVAL;
421 goto err_vblank;
422 }
423
424 platform_set_drvdata(drm->platformdev, drm);
425 mutex_unlock(&imxdrm->mutex);
426 return 0;
427
428 err_vblank:
429 drm_vblank_cleanup(drm);
430 err_kms:
431 drm_kms_helper_poll_fini(drm);
432 drm_mode_config_cleanup(drm);
433 mutex_unlock(&imxdrm->mutex);
434
435 return ret;
436 }
437
438 static void imx_drm_update_possible_crtcs(void)
439 {
440 struct imx_drm_device *imxdrm = __imx_drm_device();
441 struct imx_drm_crtc *imx_drm_crtc;
442 struct imx_drm_encoder *enc;
443 struct crtc_cookie *cookie;
444
445 list_for_each_entry(enc, &imxdrm->encoder_list, list) {
446 u32 possible_crtcs = 0;
447
448 list_for_each_entry(cookie, &enc->possible_crtcs, list) {
449 list_for_each_entry(imx_drm_crtc, &imxdrm->crtc_list, list) {
450 if (imx_drm_crtc->cookie.cookie == cookie->cookie &&
451 imx_drm_crtc->cookie.id == cookie->id) {
452 possible_crtcs |= 1 << imx_drm_crtc->pipe;
453 }
454 }
455 }
456 enc->encoder->possible_crtcs = possible_crtcs;
457 enc->encoder->possible_clones = possible_crtcs;
458 }
459 }
460
461 /*
462 * imx_drm_add_crtc - add a new crtc
463 *
464 * The return value if !NULL is a cookie for the caller to pass to
465 * imx_drm_remove_crtc later.
466 */
467 int imx_drm_add_crtc(struct drm_crtc *crtc,
468 struct imx_drm_crtc **new_crtc,
469 const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs,
470 struct module *owner, void *cookie, int id)
471 {
472 struct imx_drm_device *imxdrm = __imx_drm_device();
473 struct imx_drm_crtc *imx_drm_crtc;
474 int ret;
475
476 mutex_lock(&imxdrm->mutex);
477
478 /*
479 * The vblank arrays are dimensioned by MAX_CRTC - we can't
480 * pass IDs greater than this to those functions.
481 */
482 if (imxdrm->pipes >= MAX_CRTC) {
483 ret = -EINVAL;
484 goto err_busy;
485 }
486
487 if (imxdrm->drm->open_count) {
488 ret = -EBUSY;
489 goto err_busy;
490 }
491
492 imx_drm_crtc = kzalloc(sizeof(*imx_drm_crtc), GFP_KERNEL);
493 if (!imx_drm_crtc) {
494 ret = -ENOMEM;
495 goto err_alloc;
496 }
497
498 imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs;
499 imx_drm_crtc->pipe = imxdrm->pipes++;
500 imx_drm_crtc->cookie.cookie = cookie;
501 imx_drm_crtc->cookie.id = id;
502 imx_drm_crtc->mux_id = imx_drm_crtc->pipe;
503 imx_drm_crtc->crtc = crtc;
504 imx_drm_crtc->imxdrm = imxdrm;
505
506 imx_drm_crtc->owner = owner;
507
508 imxdrm->crtc[imx_drm_crtc->pipe] = imx_drm_crtc;
509
510 *new_crtc = imx_drm_crtc;
511
512 ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256);
513 if (ret)
514 goto err_register;
515
516 drm_crtc_helper_add(crtc,
517 imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
518
519 drm_crtc_init(imxdrm->drm, crtc,
520 imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs);
521
522 drm_mode_group_reinit(imxdrm->drm);
523
524 imx_drm_update_possible_crtcs();
525
526 mutex_unlock(&imxdrm->mutex);
527
528 return 0;
529
530 err_register:
531 imxdrm->crtc[imx_drm_crtc->pipe] = NULL;
532 kfree(imx_drm_crtc);
533 err_alloc:
534 err_busy:
535 mutex_unlock(&imxdrm->mutex);
536 return ret;
537 }
538 EXPORT_SYMBOL_GPL(imx_drm_add_crtc);
539
540 /*
541 * imx_drm_remove_crtc - remove a crtc
542 */
543 int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc)
544 {
545 struct imx_drm_device *imxdrm = imx_drm_crtc->imxdrm;
546
547 mutex_lock(&imxdrm->mutex);
548
549 drm_crtc_cleanup(imx_drm_crtc->crtc);
550
551 imxdrm->crtc[imx_drm_crtc->pipe] = NULL;
552
553 drm_mode_group_reinit(imxdrm->drm);
554
555 mutex_unlock(&imxdrm->mutex);
556
557 kfree(imx_drm_crtc);
558
559 return 0;
560 }
561 EXPORT_SYMBOL_GPL(imx_drm_remove_crtc);
562
563 /*
564 * imx_drm_add_encoder - add a new encoder
565 */
566 int imx_drm_add_encoder(struct drm_encoder *encoder,
567 struct imx_drm_encoder **newenc, struct module *owner)
568 {
569 struct imx_drm_device *imxdrm = __imx_drm_device();
570 struct imx_drm_encoder *imx_drm_encoder;
571 int ret;
572
573 mutex_lock(&imxdrm->mutex);
574
575 if (imxdrm->drm->open_count) {
576 ret = -EBUSY;
577 goto err_busy;
578 }
579
580 imx_drm_encoder = kzalloc(sizeof(*imx_drm_encoder), GFP_KERNEL);
581 if (!imx_drm_encoder) {
582 ret = -ENOMEM;
583 goto err_alloc;
584 }
585
586 imx_drm_encoder->encoder = encoder;
587 imx_drm_encoder->owner = owner;
588
589 ret = imx_drm_encoder_register(imx_drm_encoder);
590 if (ret) {
591 ret = -ENOMEM;
592 goto err_register;
593 }
594
595 list_add_tail(&imx_drm_encoder->list, &imxdrm->encoder_list);
596
597 *newenc = imx_drm_encoder;
598
599 mutex_unlock(&imxdrm->mutex);
600
601 return 0;
602
603 err_register:
604 kfree(imx_drm_encoder);
605 err_alloc:
606 err_busy:
607 mutex_unlock(&imxdrm->mutex);
608
609 return ret;
610 }
611 EXPORT_SYMBOL_GPL(imx_drm_add_encoder);
612
613 int imx_drm_encoder_add_possible_crtcs(
614 struct imx_drm_encoder *imx_drm_encoder,
615 struct device_node *np)
616 {
617 struct imx_drm_device *imxdrm = __imx_drm_device();
618 struct of_phandle_args args;
619 struct crtc_cookie *c;
620 int ret = 0;
621 int i;
622
623 if (!list_empty(&imx_drm_encoder->possible_crtcs))
624 return -EBUSY;
625
626 for (i = 0; !ret; i++) {
627 ret = of_parse_phandle_with_args(np, "crtcs",
628 "#crtc-cells", i, &args);
629 if (ret < 0)
630 break;
631
632 c = kzalloc(sizeof(*c), GFP_KERNEL);
633 if (!c) {
634 of_node_put(args.np);
635 return -ENOMEM;
636 }
637
638 c->cookie = args.np;
639 c->id = args.args_count > 0 ? args.args[0] : 0;
640
641 of_node_put(args.np);
642
643 mutex_lock(&imxdrm->mutex);
644
645 list_add_tail(&c->list, &imx_drm_encoder->possible_crtcs);
646
647 mutex_unlock(&imxdrm->mutex);
648 }
649
650 imx_drm_update_possible_crtcs();
651
652 return 0;
653 }
654 EXPORT_SYMBOL_GPL(imx_drm_encoder_add_possible_crtcs);
655
656 int imx_drm_encoder_get_mux_id(struct drm_encoder *encoder)
657 {
658 struct imx_drm_crtc *imx_crtc = imx_drm_find_crtc(encoder->crtc);
659
660 return imx_crtc ? imx_crtc->mux_id : -EINVAL;
661 }
662 EXPORT_SYMBOL_GPL(imx_drm_encoder_get_mux_id);
663
664 /*
665 * imx_drm_remove_encoder - remove an encoder
666 */
667 int imx_drm_remove_encoder(struct imx_drm_encoder *imx_drm_encoder)
668 {
669 struct imx_drm_device *imxdrm = __imx_drm_device();
670 struct crtc_cookie *c, *tmp;
671
672 mutex_lock(&imxdrm->mutex);
673
674 imx_drm_encoder_unregister(imx_drm_encoder);
675
676 list_del(&imx_drm_encoder->list);
677
678 list_for_each_entry_safe(c, tmp, &imx_drm_encoder->possible_crtcs,
679 list)
680 kfree(c);
681
682 mutex_unlock(&imxdrm->mutex);
683
684 kfree(imx_drm_encoder);
685
686 return 0;
687 }
688 EXPORT_SYMBOL_GPL(imx_drm_remove_encoder);
689
690 /*
691 * imx_drm_add_connector - add a connector
692 */
693 int imx_drm_add_connector(struct drm_connector *connector,
694 struct imx_drm_connector **new_con,
695 struct module *owner)
696 {
697 struct imx_drm_device *imxdrm = __imx_drm_device();
698 struct imx_drm_connector *imx_drm_connector;
699 int ret;
700
701 mutex_lock(&imxdrm->mutex);
702
703 if (imxdrm->drm->open_count) {
704 ret = -EBUSY;
705 goto err_busy;
706 }
707
708 imx_drm_connector = kzalloc(sizeof(*imx_drm_connector), GFP_KERNEL);
709 if (!imx_drm_connector) {
710 ret = -ENOMEM;
711 goto err_alloc;
712 }
713
714 imx_drm_connector->connector = connector;
715 imx_drm_connector->owner = owner;
716
717 ret = imx_drm_connector_register(imx_drm_connector);
718 if (ret)
719 goto err_register;
720
721 list_add_tail(&imx_drm_connector->list, &imxdrm->connector_list);
722
723 *new_con = imx_drm_connector;
724
725 mutex_unlock(&imxdrm->mutex);
726
727 return 0;
728
729 err_register:
730 kfree(imx_drm_connector);
731 err_alloc:
732 err_busy:
733 mutex_unlock(&imxdrm->mutex);
734
735 return ret;
736 }
737 EXPORT_SYMBOL_GPL(imx_drm_add_connector);
738
739 void imx_drm_fb_helper_set(struct drm_fbdev_cma *fbdev_helper)
740 {
741 struct imx_drm_device *imxdrm = __imx_drm_device();
742
743 imxdrm->fbhelper = fbdev_helper;
744 }
745 EXPORT_SYMBOL_GPL(imx_drm_fb_helper_set);
746
747 /*
748 * imx_drm_remove_connector - remove a connector
749 */
750 int imx_drm_remove_connector(struct imx_drm_connector *imx_drm_connector)
751 {
752 struct imx_drm_device *imxdrm = __imx_drm_device();
753
754 mutex_lock(&imxdrm->mutex);
755
756 imx_drm_connector_unregister(imx_drm_connector);
757
758 list_del(&imx_drm_connector->list);
759
760 mutex_unlock(&imxdrm->mutex);
761
762 kfree(imx_drm_connector);
763
764 return 0;
765 }
766 EXPORT_SYMBOL_GPL(imx_drm_remove_connector);
767
768 static const struct drm_ioctl_desc imx_drm_ioctls[] = {
769 /* none so far */
770 };
771
772 static struct drm_driver imx_drm_driver = {
773 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
774 .load = imx_drm_driver_load,
775 .unload = imx_drm_driver_unload,
776 .lastclose = imx_drm_driver_lastclose,
777 .preclose = imx_drm_driver_preclose,
778 .gem_free_object = drm_gem_cma_free_object,
779 .gem_vm_ops = &drm_gem_cma_vm_ops,
780 .dumb_create = drm_gem_cma_dumb_create,
781 .dumb_map_offset = drm_gem_cma_dumb_map_offset,
782 .dumb_destroy = drm_gem_dumb_destroy,
783
784 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
785 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
786 .gem_prime_import = drm_gem_prime_import,
787 .gem_prime_export = drm_gem_prime_export,
788 .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
789 .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
790 .gem_prime_vmap = drm_gem_cma_prime_vmap,
791 .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
792 .gem_prime_mmap = drm_gem_cma_prime_mmap,
793 .get_vblank_counter = drm_vblank_count,
794 .enable_vblank = imx_drm_enable_vblank,
795 .disable_vblank = imx_drm_disable_vblank,
796 .ioctls = imx_drm_ioctls,
797 .num_ioctls = ARRAY_SIZE(imx_drm_ioctls),
798 .fops = &imx_drm_driver_fops,
799 .name = "imx-drm",
800 .desc = "i.MX DRM graphics",
801 .date = "20120507",
802 .major = 1,
803 .minor = 0,
804 .patchlevel = 0,
805 };
806
807 static int imx_drm_platform_probe(struct platform_device *pdev)
808 {
809 int ret;
810
811 ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
812 if (ret)
813 return ret;
814
815 imx_drm_device->dev = &pdev->dev;
816
817 return drm_platform_init(&imx_drm_driver, pdev);
818 }
819
820 static int imx_drm_platform_remove(struct platform_device *pdev)
821 {
822 drm_put_dev(platform_get_drvdata(pdev));
823
824 return 0;
825 }
826
827 static struct platform_driver imx_drm_pdrv = {
828 .probe = imx_drm_platform_probe,
829 .remove = imx_drm_platform_remove,
830 .driver = {
831 .owner = THIS_MODULE,
832 .name = "imx-drm",
833 },
834 };
835
836 static struct platform_device *imx_drm_pdev;
837
838 static int __init imx_drm_init(void)
839 {
840 int ret;
841
842 imx_drm_device = kzalloc(sizeof(*imx_drm_device), GFP_KERNEL);
843 if (!imx_drm_device)
844 return -ENOMEM;
845
846 mutex_init(&imx_drm_device->mutex);
847 INIT_LIST_HEAD(&imx_drm_device->connector_list);
848 INIT_LIST_HEAD(&imx_drm_device->encoder_list);
849
850 imx_drm_pdev = platform_device_register_simple("imx-drm", -1, NULL, 0);
851 if (IS_ERR(imx_drm_pdev)) {
852 ret = PTR_ERR(imx_drm_pdev);
853 goto err_pdev;
854 }
855
856 ret = platform_driver_register(&imx_drm_pdrv);
857 if (ret)
858 goto err_pdrv;
859
860 return 0;
861
862 err_pdrv:
863 platform_device_unregister(imx_drm_pdev);
864 err_pdev:
865 kfree(imx_drm_device);
866
867 return ret;
868 }
869
870 static void __exit imx_drm_exit(void)
871 {
872 platform_device_unregister(imx_drm_pdev);
873 platform_driver_unregister(&imx_drm_pdrv);
874
875 kfree(imx_drm_device);
876 }
877
878 module_init(imx_drm_init);
879 module_exit(imx_drm_exit);
880
881 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
882 MODULE_DESCRIPTION("i.MX drm driver core");
883 MODULE_LICENSE("GPL");
This page took 0.056793 seconds and 6 git commands to generate.