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