• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/dma-buf.h>
19 #include <linux/module.h>
20 #include <linux/platform_device.h>
21 #include <linux/reservation.h>
22 #include <drm/drmP.h>
23 #include <drm/drm_atomic.h>
24 #include <drm/drm_atomic_helper.h>
25 #include <drm/drm_fb_helper.h>
26 #include <drm/drm_crtc_helper.h>
27 #include <drm/drm_gem_cma_helper.h>
28 #include <drm/drm_fb_cma_helper.h>
29 #include <drm/drm_plane_helper.h>
30 #include <drm/drm_of.h>
31 #include <video/imx-ipu-v3.h>
32 
33 #include "imx-drm.h"
34 
35 #define MAX_CRTC	4
36 
37 struct imx_drm_component {
38 	struct device_node *of_node;
39 	struct list_head list;
40 };
41 
42 struct imx_drm_device {
43 	struct drm_device			*drm;
44 	struct imx_drm_crtc			*crtc[MAX_CRTC];
45 	unsigned int				pipes;
46 	struct drm_fbdev_cma			*fbhelper;
47 	struct drm_atomic_state			*state;
48 };
49 
50 struct imx_drm_crtc {
51 	struct drm_crtc				*crtc;
52 	struct imx_drm_crtc_helper_funcs	imx_drm_helper_funcs;
53 };
54 
55 #if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION)
56 static int legacyfb_depth = 16;
57 module_param(legacyfb_depth, int, 0444);
58 #endif
59 
imx_drm_driver_lastclose(struct drm_device * drm)60 static void imx_drm_driver_lastclose(struct drm_device *drm)
61 {
62 	struct imx_drm_device *imxdrm = drm->dev_private;
63 
64 	drm_fbdev_cma_restore_mode(imxdrm->fbhelper);
65 }
66 
imx_drm_enable_vblank(struct drm_device * drm,unsigned int pipe)67 static int imx_drm_enable_vblank(struct drm_device *drm, unsigned int pipe)
68 {
69 	struct imx_drm_device *imxdrm = drm->dev_private;
70 	struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[pipe];
71 	int ret;
72 
73 	if (!imx_drm_crtc)
74 		return -EINVAL;
75 
76 	if (!imx_drm_crtc->imx_drm_helper_funcs.enable_vblank)
77 		return -ENOSYS;
78 
79 	ret = imx_drm_crtc->imx_drm_helper_funcs.enable_vblank(
80 			imx_drm_crtc->crtc);
81 
82 	return ret;
83 }
84 
imx_drm_disable_vblank(struct drm_device * drm,unsigned int pipe)85 static void imx_drm_disable_vblank(struct drm_device *drm, unsigned int pipe)
86 {
87 	struct imx_drm_device *imxdrm = drm->dev_private;
88 	struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[pipe];
89 
90 	if (!imx_drm_crtc)
91 		return;
92 
93 	if (!imx_drm_crtc->imx_drm_helper_funcs.disable_vblank)
94 		return;
95 
96 	imx_drm_crtc->imx_drm_helper_funcs.disable_vblank(imx_drm_crtc->crtc);
97 }
98 
99 static const struct file_operations imx_drm_driver_fops = {
100 	.owner = THIS_MODULE,
101 	.open = drm_open,
102 	.release = drm_release,
103 	.unlocked_ioctl = drm_ioctl,
104 	.mmap = drm_gem_cma_mmap,
105 	.poll = drm_poll,
106 	.read = drm_read,
107 	.llseek = noop_llseek,
108 };
109 
imx_drm_connector_destroy(struct drm_connector * connector)110 void imx_drm_connector_destroy(struct drm_connector *connector)
111 {
112 	drm_connector_unregister(connector);
113 	drm_connector_cleanup(connector);
114 }
115 EXPORT_SYMBOL_GPL(imx_drm_connector_destroy);
116 
imx_drm_encoder_destroy(struct drm_encoder * encoder)117 void imx_drm_encoder_destroy(struct drm_encoder *encoder)
118 {
119 	drm_encoder_cleanup(encoder);
120 }
121 EXPORT_SYMBOL_GPL(imx_drm_encoder_destroy);
122 
imx_drm_output_poll_changed(struct drm_device * drm)123 static void imx_drm_output_poll_changed(struct drm_device *drm)
124 {
125 	struct imx_drm_device *imxdrm = drm->dev_private;
126 
127 	drm_fbdev_cma_hotplug_event(imxdrm->fbhelper);
128 }
129 
imx_drm_atomic_check(struct drm_device * dev,struct drm_atomic_state * state)130 static int imx_drm_atomic_check(struct drm_device *dev,
131 				struct drm_atomic_state *state)
132 {
133 	int ret;
134 
135 	ret = drm_atomic_helper_check_modeset(dev, state);
136 	if (ret)
137 		return ret;
138 
139 	ret = drm_atomic_helper_check_planes(dev, state);
140 	if (ret)
141 		return ret;
142 
143 	/*
144 	 * Check modeset again in case crtc_state->mode_changed is
145 	 * updated in plane's ->atomic_check callback.
146 	 */
147 	ret = drm_atomic_helper_check_modeset(dev, state);
148 	if (ret)
149 		return ret;
150 
151 	return ret;
152 }
153 
imx_drm_atomic_commit(struct drm_device * dev,struct drm_atomic_state * state,bool nonblock)154 static int imx_drm_atomic_commit(struct drm_device *dev,
155 				 struct drm_atomic_state *state,
156 				 bool nonblock)
157 {
158 	struct drm_plane_state *plane_state;
159 	struct drm_plane *plane;
160 	struct dma_buf *dma_buf;
161 	int i;
162 
163 	/*
164 	 * If the plane fb has an dma-buf attached, fish out the exclusive
165 	 * fence for the atomic helper to wait on.
166 	 */
167 	for_each_plane_in_state(state, plane, plane_state, i) {
168 		if ((plane->state->fb != plane_state->fb) && plane_state->fb) {
169 			dma_buf = drm_fb_cma_get_gem_obj(plane_state->fb,
170 							 0)->base.dma_buf;
171 			if (!dma_buf)
172 				continue;
173 			plane_state->fence =
174 				reservation_object_get_excl_rcu(dma_buf->resv);
175 		}
176 	}
177 
178 	return drm_atomic_helper_commit(dev, state, nonblock);
179 }
180 
181 static const struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
182 	.fb_create = drm_fb_cma_create,
183 	.output_poll_changed = imx_drm_output_poll_changed,
184 	.atomic_check = imx_drm_atomic_check,
185 	.atomic_commit = imx_drm_atomic_commit,
186 };
187 
imx_drm_atomic_commit_tail(struct drm_atomic_state * state)188 static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state)
189 {
190 	struct drm_device *dev = state->dev;
191 
192 	drm_atomic_helper_commit_modeset_disables(dev, state);
193 
194 	drm_atomic_helper_commit_planes(dev, state,
195 				DRM_PLANE_COMMIT_ACTIVE_ONLY |
196 				DRM_PLANE_COMMIT_NO_DISABLE_AFTER_MODESET);
197 
198 	drm_atomic_helper_commit_modeset_enables(dev, state);
199 
200 	drm_atomic_helper_commit_hw_done(state);
201 
202 	drm_atomic_helper_wait_for_vblanks(dev, state);
203 
204 	drm_atomic_helper_cleanup_planes(dev, state);
205 }
206 
207 static struct drm_mode_config_helper_funcs imx_drm_mode_config_helpers = {
208 	.atomic_commit_tail = imx_drm_atomic_commit_tail,
209 };
210 
211 /*
212  * imx_drm_add_crtc - add a new crtc
213  */
imx_drm_add_crtc(struct drm_device * drm,struct drm_crtc * crtc,struct imx_drm_crtc ** new_crtc,struct drm_plane * primary_plane,const struct imx_drm_crtc_helper_funcs * imx_drm_helper_funcs,struct device_node * port)214 int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc,
215 		struct imx_drm_crtc **new_crtc, struct drm_plane *primary_plane,
216 		const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs,
217 		struct device_node *port)
218 {
219 	struct imx_drm_device *imxdrm = drm->dev_private;
220 	struct imx_drm_crtc *imx_drm_crtc;
221 
222 	/*
223 	 * The vblank arrays are dimensioned by MAX_CRTC - we can't
224 	 * pass IDs greater than this to those functions.
225 	 */
226 	if (imxdrm->pipes >= MAX_CRTC)
227 		return -EINVAL;
228 
229 	if (imxdrm->drm->open_count)
230 		return -EBUSY;
231 
232 	imx_drm_crtc = kzalloc(sizeof(*imx_drm_crtc), GFP_KERNEL);
233 	if (!imx_drm_crtc)
234 		return -ENOMEM;
235 
236 	imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs;
237 	imx_drm_crtc->crtc = crtc;
238 
239 	crtc->port = port;
240 
241 	imxdrm->crtc[imxdrm->pipes++] = imx_drm_crtc;
242 
243 	*new_crtc = imx_drm_crtc;
244 
245 	drm_crtc_helper_add(crtc,
246 			imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs);
247 
248 	drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
249 			imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs, NULL);
250 
251 	return 0;
252 }
253 EXPORT_SYMBOL_GPL(imx_drm_add_crtc);
254 
255 /*
256  * imx_drm_remove_crtc - remove a crtc
257  */
imx_drm_remove_crtc(struct imx_drm_crtc * imx_drm_crtc)258 int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc)
259 {
260 	struct imx_drm_device *imxdrm = imx_drm_crtc->crtc->dev->dev_private;
261 	unsigned int pipe = drm_crtc_index(imx_drm_crtc->crtc);
262 
263 	drm_crtc_cleanup(imx_drm_crtc->crtc);
264 
265 	imxdrm->crtc[pipe] = NULL;
266 
267 	kfree(imx_drm_crtc);
268 
269 	return 0;
270 }
271 EXPORT_SYMBOL_GPL(imx_drm_remove_crtc);
272 
imx_drm_encoder_parse_of(struct drm_device * drm,struct drm_encoder * encoder,struct device_node * np)273 int imx_drm_encoder_parse_of(struct drm_device *drm,
274 	struct drm_encoder *encoder, struct device_node *np)
275 {
276 	uint32_t crtc_mask = drm_of_find_possible_crtcs(drm, np);
277 
278 	/*
279 	 * If we failed to find the CRTC(s) which this encoder is
280 	 * supposed to be connected to, it's because the CRTC has
281 	 * not been registered yet.  Defer probing, and hope that
282 	 * the required CRTC is added later.
283 	 */
284 	if (crtc_mask == 0)
285 		return -EPROBE_DEFER;
286 
287 	encoder->possible_crtcs = crtc_mask;
288 
289 	/* FIXME: this is the mask of outputs which can clone this output. */
290 	encoder->possible_clones = ~0;
291 
292 	return 0;
293 }
294 EXPORT_SYMBOL_GPL(imx_drm_encoder_parse_of);
295 
296 static const struct drm_ioctl_desc imx_drm_ioctls[] = {
297 	/* none so far */
298 };
299 
300 static struct drm_driver imx_drm_driver = {
301 	.driver_features	= DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
302 				  DRIVER_ATOMIC,
303 	.lastclose		= imx_drm_driver_lastclose,
304 	.gem_free_object_unlocked = drm_gem_cma_free_object,
305 	.gem_vm_ops		= &drm_gem_cma_vm_ops,
306 	.dumb_create		= drm_gem_cma_dumb_create,
307 	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
308 	.dumb_destroy		= drm_gem_dumb_destroy,
309 
310 	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
311 	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
312 	.gem_prime_import	= drm_gem_prime_import,
313 	.gem_prime_export	= drm_gem_prime_export,
314 	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table,
315 	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
316 	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
317 	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
318 	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
319 	.get_vblank_counter	= drm_vblank_no_hw_counter,
320 	.enable_vblank		= imx_drm_enable_vblank,
321 	.disable_vblank		= imx_drm_disable_vblank,
322 	.ioctls			= imx_drm_ioctls,
323 	.num_ioctls		= ARRAY_SIZE(imx_drm_ioctls),
324 	.fops			= &imx_drm_driver_fops,
325 	.name			= "imx-drm",
326 	.desc			= "i.MX DRM graphics",
327 	.date			= "20120507",
328 	.major			= 1,
329 	.minor			= 0,
330 	.patchlevel		= 0,
331 };
332 
compare_of(struct device * dev,void * data)333 static int compare_of(struct device *dev, void *data)
334 {
335 	struct device_node *np = data;
336 
337 	/* Special case for DI, dev->of_node may not be set yet */
338 	if (strcmp(dev->driver->name, "imx-ipuv3-crtc") == 0) {
339 		struct ipu_client_platformdata *pdata = dev->platform_data;
340 
341 		return pdata->of_node == np;
342 	}
343 
344 	/* Special case for LDB, one device for two channels */
345 	if (of_node_cmp(np->name, "lvds-channel") == 0) {
346 		np = of_get_parent(np);
347 		of_node_put(np);
348 	}
349 
350 	return dev->of_node == np;
351 }
352 
imx_drm_bind(struct device * dev)353 static int imx_drm_bind(struct device *dev)
354 {
355 	struct drm_device *drm;
356 	struct imx_drm_device *imxdrm;
357 	int ret;
358 
359 	drm = drm_dev_alloc(&imx_drm_driver, dev);
360 	if (IS_ERR(drm))
361 		return PTR_ERR(drm);
362 
363 	imxdrm = devm_kzalloc(dev, sizeof(*imxdrm), GFP_KERNEL);
364 	if (!imxdrm) {
365 		ret = -ENOMEM;
366 		goto err_unref;
367 	}
368 
369 	imxdrm->drm = drm;
370 	drm->dev_private = imxdrm;
371 
372 	/*
373 	 * enable drm irq mode.
374 	 * - with irq_enabled = true, we can use the vblank feature.
375 	 *
376 	 * P.S. note that we wouldn't use drm irq handler but
377 	 *      just specific driver own one instead because
378 	 *      drm framework supports only one irq handler and
379 	 *      drivers can well take care of their interrupts
380 	 */
381 	drm->irq_enabled = true;
382 
383 	/*
384 	 * set max width and height as default value(4096x4096).
385 	 * this value would be used to check framebuffer size limitation
386 	 * at drm_mode_addfb().
387 	 */
388 	drm->mode_config.min_width = 64;
389 	drm->mode_config.min_height = 64;
390 	drm->mode_config.max_width = 4096;
391 	drm->mode_config.max_height = 4096;
392 	drm->mode_config.funcs = &imx_drm_mode_config_funcs;
393 	drm->mode_config.helper_private = &imx_drm_mode_config_helpers;
394 
395 	drm_mode_config_init(drm);
396 
397 	ret = drm_vblank_init(drm, MAX_CRTC);
398 	if (ret)
399 		goto err_kms;
400 
401 	dev_set_drvdata(dev, drm);
402 
403 	/* Now try and bind all our sub-components */
404 	ret = component_bind_all(dev, drm);
405 	if (ret)
406 		goto err_vblank;
407 
408 	drm_mode_config_reset(drm);
409 
410 	/*
411 	 * All components are now initialised, so setup the fb helper.
412 	 * The fb helper takes copies of key hardware information, so the
413 	 * crtcs/connectors/encoders must not change after this point.
414 	 */
415 #if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION)
416 	if (legacyfb_depth != 16 && legacyfb_depth != 32) {
417 		dev_warn(dev, "Invalid legacyfb_depth.  Defaulting to 16bpp\n");
418 		legacyfb_depth = 16;
419 	}
420 	imxdrm->fbhelper = drm_fbdev_cma_init(drm, legacyfb_depth,
421 				drm->mode_config.num_crtc, MAX_CRTC);
422 	if (IS_ERR(imxdrm->fbhelper)) {
423 		ret = PTR_ERR(imxdrm->fbhelper);
424 		imxdrm->fbhelper = NULL;
425 		goto err_unbind;
426 	}
427 #endif
428 
429 	drm_kms_helper_poll_init(drm);
430 
431 	ret = drm_dev_register(drm, 0);
432 	if (ret)
433 		goto err_fbhelper;
434 
435 	return 0;
436 
437 err_fbhelper:
438 	drm_kms_helper_poll_fini(drm);
439 #if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION)
440 	if (imxdrm->fbhelper)
441 		drm_fbdev_cma_fini(imxdrm->fbhelper);
442 err_unbind:
443 #endif
444 	component_unbind_all(drm->dev, drm);
445 err_vblank:
446 	drm_vblank_cleanup(drm);
447 err_kms:
448 	drm_mode_config_cleanup(drm);
449 err_unref:
450 	drm_dev_unref(drm);
451 
452 	return ret;
453 }
454 
imx_drm_unbind(struct device * dev)455 static void imx_drm_unbind(struct device *dev)
456 {
457 	struct drm_device *drm = dev_get_drvdata(dev);
458 	struct imx_drm_device *imxdrm = drm->dev_private;
459 
460 	drm_dev_unregister(drm);
461 
462 	drm_kms_helper_poll_fini(drm);
463 
464 	if (imxdrm->fbhelper)
465 		drm_fbdev_cma_fini(imxdrm->fbhelper);
466 
467 	drm_mode_config_cleanup(drm);
468 
469 	component_unbind_all(drm->dev, drm);
470 	dev_set_drvdata(dev, NULL);
471 
472 	drm_dev_unref(drm);
473 }
474 
475 static const struct component_master_ops imx_drm_ops = {
476 	.bind = imx_drm_bind,
477 	.unbind = imx_drm_unbind,
478 };
479 
imx_drm_platform_probe(struct platform_device * pdev)480 static int imx_drm_platform_probe(struct platform_device *pdev)
481 {
482 	int ret = drm_of_component_probe(&pdev->dev, compare_of, &imx_drm_ops);
483 
484 	if (!ret)
485 		ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
486 
487 	return ret;
488 }
489 
imx_drm_platform_remove(struct platform_device * pdev)490 static int imx_drm_platform_remove(struct platform_device *pdev)
491 {
492 	component_master_del(&pdev->dev, &imx_drm_ops);
493 	return 0;
494 }
495 
496 #ifdef CONFIG_PM_SLEEP
imx_drm_suspend(struct device * dev)497 static int imx_drm_suspend(struct device *dev)
498 {
499 	struct drm_device *drm_dev = dev_get_drvdata(dev);
500 	struct imx_drm_device *imxdrm;
501 
502 	/* The drm_dev is NULL before .load hook is called */
503 	if (drm_dev == NULL)
504 		return 0;
505 
506 	drm_kms_helper_poll_disable(drm_dev);
507 
508 	imxdrm = drm_dev->dev_private;
509 	imxdrm->state = drm_atomic_helper_suspend(drm_dev);
510 	if (IS_ERR(imxdrm->state)) {
511 		drm_kms_helper_poll_enable(drm_dev);
512 		return PTR_ERR(imxdrm->state);
513 	}
514 
515 	return 0;
516 }
517 
imx_drm_resume(struct device * dev)518 static int imx_drm_resume(struct device *dev)
519 {
520 	struct drm_device *drm_dev = dev_get_drvdata(dev);
521 	struct imx_drm_device *imx_drm;
522 
523 	if (drm_dev == NULL)
524 		return 0;
525 
526 	imx_drm = drm_dev->dev_private;
527 	drm_atomic_helper_resume(drm_dev, imx_drm->state);
528 	drm_kms_helper_poll_enable(drm_dev);
529 
530 	return 0;
531 }
532 #endif
533 
534 static SIMPLE_DEV_PM_OPS(imx_drm_pm_ops, imx_drm_suspend, imx_drm_resume);
535 
536 static const struct of_device_id imx_drm_dt_ids[] = {
537 	{ .compatible = "fsl,imx-display-subsystem", },
538 	{ /* sentinel */ },
539 };
540 MODULE_DEVICE_TABLE(of, imx_drm_dt_ids);
541 
542 static struct platform_driver imx_drm_pdrv = {
543 	.probe		= imx_drm_platform_probe,
544 	.remove		= imx_drm_platform_remove,
545 	.driver		= {
546 		.name	= "imx-drm",
547 		.pm	= &imx_drm_pm_ops,
548 		.of_match_table = imx_drm_dt_ids,
549 	},
550 };
551 module_platform_driver(imx_drm_pdrv);
552 
553 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
554 MODULE_DESCRIPTION("i.MX drm driver core");
555 MODULE_LICENSE("GPL");
556