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