2 * i.MX IPUv3 Graphics driver
4 * Copyright (C) 2011 Sascha Hauer, Pengutronix
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.
15 #include <linux/component.h>
16 #include <linux/module.h>
17 #include <linux/export.h>
18 #include <linux/device.h>
19 #include <linux/platform_device.h>
21 #include <drm/drm_crtc_helper.h>
23 #include <linux/clk.h>
24 #include <linux/errno.h>
25 #include <linux/reservation.h>
26 #include <linux/dma-buf.h>
27 #include <drm/drm_gem_cma_helper.h>
28 #include <drm/drm_fb_cma_helper.h>
30 #include <video/imx-ipu-v3.h>
32 #include "ipuv3-plane.h"
34 #define DRIVER_DESC "i.MX IPUv3 Graphics"
36 enum ipu_flip_status
{
42 struct ipu_flip_work
{
43 struct work_struct unref_work
;
44 struct drm_gem_object
*bo
;
45 struct drm_pending_vblank_event
*page_flip_event
;
46 struct work_struct fence_work
;
47 struct ipu_crtc
*crtc
;
49 unsigned shared_count
;
50 struct fence
**shared
;
56 struct imx_drm_crtc
*imx_crtc
;
58 /* plane[0] is the full plane, plane[1] is the partial plane */
59 struct ipu_plane
*plane
[2];
64 enum ipu_flip_status flip_state
;
65 struct workqueue_struct
*flip_queue
;
66 struct ipu_flip_work
*flip_work
;
73 #define to_ipu_crtc(x) container_of(x, struct ipu_crtc, base)
75 static void ipu_fb_enable(struct ipu_crtc
*ipu_crtc
)
77 struct ipu_soc
*ipu
= dev_get_drvdata(ipu_crtc
->dev
->parent
);
79 if (ipu_crtc
->enabled
)
83 ipu_plane_enable(ipu_crtc
->plane
[0]);
84 /* Start DC channel and DI after IDMAC */
85 ipu_dc_enable_channel(ipu_crtc
->dc
);
86 ipu_di_enable(ipu_crtc
->di
);
87 drm_crtc_vblank_on(&ipu_crtc
->base
);
89 ipu_crtc
->enabled
= 1;
92 static void ipu_fb_disable(struct ipu_crtc
*ipu_crtc
)
94 struct ipu_soc
*ipu
= dev_get_drvdata(ipu_crtc
->dev
->parent
);
96 if (!ipu_crtc
->enabled
)
99 /* Stop DC channel and DI before IDMAC */
100 ipu_dc_disable_channel(ipu_crtc
->dc
);
101 ipu_di_disable(ipu_crtc
->di
);
102 ipu_plane_disable(ipu_crtc
->plane
[0]);
104 drm_crtc_vblank_off(&ipu_crtc
->base
);
106 ipu_crtc
->enabled
= 0;
109 static void ipu_crtc_dpms(struct drm_crtc
*crtc
, int mode
)
111 struct ipu_crtc
*ipu_crtc
= to_ipu_crtc(crtc
);
113 dev_dbg(ipu_crtc
->dev
, "%s mode: %d\n", __func__
, mode
);
116 case DRM_MODE_DPMS_ON
:
117 ipu_fb_enable(ipu_crtc
);
119 case DRM_MODE_DPMS_STANDBY
:
120 case DRM_MODE_DPMS_SUSPEND
:
121 case DRM_MODE_DPMS_OFF
:
122 ipu_fb_disable(ipu_crtc
);
127 static void ipu_flip_unref_work_func(struct work_struct
*__work
)
129 struct ipu_flip_work
*work
=
130 container_of(__work
, struct ipu_flip_work
, unref_work
);
132 drm_gem_object_unreference_unlocked(work
->bo
);
136 static void ipu_flip_fence_work_func(struct work_struct
*__work
)
138 struct ipu_flip_work
*work
=
139 container_of(__work
, struct ipu_flip_work
, fence_work
);
142 /* wait for all fences attached to the FB obj to signal */
144 fence_wait(work
->excl
, false);
145 fence_put(work
->excl
);
147 for (i
= 0; i
< work
->shared_count
; i
++) {
148 fence_wait(work
->shared
[i
], false);
149 fence_put(work
->shared
[i
]);
152 work
->crtc
->flip_state
= IPU_FLIP_SUBMITTED
;
155 static int ipu_page_flip(struct drm_crtc
*crtc
,
156 struct drm_framebuffer
*fb
,
157 struct drm_pending_vblank_event
*event
,
158 uint32_t page_flip_flags
)
160 struct drm_gem_cma_object
*cma_obj
= drm_fb_cma_get_gem_obj(fb
, 0);
161 struct ipu_crtc
*ipu_crtc
= to_ipu_crtc(crtc
);
162 struct ipu_flip_work
*flip_work
;
165 if (ipu_crtc
->flip_state
!= IPU_FLIP_NONE
)
168 ret
= imx_drm_crtc_vblank_get(ipu_crtc
->imx_crtc
);
170 dev_dbg(ipu_crtc
->dev
, "failed to acquire vblank counter\n");
171 list_del(&event
->base
.link
);
176 flip_work
= kzalloc(sizeof *flip_work
, GFP_KERNEL
);
181 INIT_WORK(&flip_work
->unref_work
, ipu_flip_unref_work_func
);
182 flip_work
->page_flip_event
= event
;
184 /* get BO backing the old framebuffer and take a reference */
185 flip_work
->bo
= &drm_fb_cma_get_gem_obj(crtc
->primary
->fb
, 0)->base
;
186 drm_gem_object_reference(flip_work
->bo
);
188 ipu_crtc
->flip_work
= flip_work
;
190 * If the object has a DMABUF attached, we need to wait on its fences
193 if (cma_obj
->base
.dma_buf
) {
194 INIT_WORK(&flip_work
->fence_work
, ipu_flip_fence_work_func
);
195 flip_work
->crtc
= ipu_crtc
;
197 ret
= reservation_object_get_fences_rcu(
198 cma_obj
->base
.dma_buf
->resv
, &flip_work
->excl
,
199 &flip_work
->shared_count
, &flip_work
->shared
);
202 DRM_ERROR("failed to get fences for buffer\n");
206 /* No need to queue the worker if the are no fences */
207 if (!flip_work
->excl
&& !flip_work
->shared_count
) {
208 ipu_crtc
->flip_state
= IPU_FLIP_SUBMITTED
;
210 ipu_crtc
->flip_state
= IPU_FLIP_PENDING
;
211 queue_work(ipu_crtc
->flip_queue
,
212 &flip_work
->fence_work
);
215 ipu_crtc
->flip_state
= IPU_FLIP_SUBMITTED
;
221 drm_gem_object_unreference_unlocked(flip_work
->bo
);
223 ipu_crtc
->flip_work
= NULL
;
225 imx_drm_crtc_vblank_put(ipu_crtc
->imx_crtc
);
230 static const struct drm_crtc_funcs ipu_crtc_funcs
= {
231 .set_config
= drm_crtc_helper_set_config
,
232 .destroy
= drm_crtc_cleanup
,
233 .page_flip
= ipu_page_flip
,
236 static int ipu_crtc_mode_set(struct drm_crtc
*crtc
,
237 struct drm_display_mode
*orig_mode
,
238 struct drm_display_mode
*mode
,
240 struct drm_framebuffer
*old_fb
)
242 struct drm_device
*dev
= crtc
->dev
;
243 struct drm_encoder
*encoder
;
244 struct ipu_crtc
*ipu_crtc
= to_ipu_crtc(crtc
);
245 struct ipu_di_signal_cfg sig_cfg
= {};
246 unsigned long encoder_types
= 0;
249 dev_dbg(ipu_crtc
->dev
, "%s: mode->hdisplay: %d\n", __func__
,
251 dev_dbg(ipu_crtc
->dev
, "%s: mode->vdisplay: %d\n", __func__
,
254 list_for_each_entry(encoder
, &dev
->mode_config
.encoder_list
, head
)
255 if (encoder
->crtc
== crtc
)
256 encoder_types
|= BIT(encoder
->encoder_type
);
258 dev_dbg(ipu_crtc
->dev
, "%s: attached to encoder types 0x%lx\n",
259 __func__
, encoder_types
);
262 * If we have DAC or LDB, then we need the IPU DI clock to be
263 * the same as the LDB DI clock. For TVDAC, derive the IPU DI
264 * clock from 27 MHz TVE_DI clock, but allow to divide it.
266 if (encoder_types
& (BIT(DRM_MODE_ENCODER_DAC
) |
267 BIT(DRM_MODE_ENCODER_LVDS
)))
268 sig_cfg
.clkflags
= IPU_DI_CLKMODE_SYNC
| IPU_DI_CLKMODE_EXT
;
269 else if (encoder_types
& BIT(DRM_MODE_ENCODER_TVDAC
))
270 sig_cfg
.clkflags
= IPU_DI_CLKMODE_EXT
;
272 sig_cfg
.clkflags
= 0;
274 sig_cfg
.enable_pol
= 1;
276 sig_cfg
.bus_format
= ipu_crtc
->bus_format
;
277 sig_cfg
.v_to_h_sync
= 0;
278 sig_cfg
.hsync_pin
= ipu_crtc
->di_hsync_pin
;
279 sig_cfg
.vsync_pin
= ipu_crtc
->di_vsync_pin
;
281 drm_display_mode_to_videomode(mode
, &sig_cfg
.mode
);
283 ret
= ipu_dc_init_sync(ipu_crtc
->dc
, ipu_crtc
->di
,
284 mode
->flags
& DRM_MODE_FLAG_INTERLACE
,
285 ipu_crtc
->bus_format
, mode
->hdisplay
);
287 dev_err(ipu_crtc
->dev
,
288 "initializing display controller failed with %d\n",
293 ret
= ipu_di_init_sync_panel(ipu_crtc
->di
, &sig_cfg
);
295 dev_err(ipu_crtc
->dev
,
296 "initializing panel failed with %d\n", ret
);
300 return ipu_plane_mode_set(ipu_crtc
->plane
[0], crtc
, mode
,
302 0, 0, mode
->hdisplay
, mode
->vdisplay
,
303 x
, y
, mode
->hdisplay
, mode
->vdisplay
,
304 mode
->flags
& DRM_MODE_FLAG_INTERLACE
);
307 static void ipu_crtc_handle_pageflip(struct ipu_crtc
*ipu_crtc
)
310 struct drm_device
*drm
= ipu_crtc
->base
.dev
;
311 struct ipu_flip_work
*work
= ipu_crtc
->flip_work
;
313 spin_lock_irqsave(&drm
->event_lock
, flags
);
314 if (work
->page_flip_event
)
315 drm_crtc_send_vblank_event(&ipu_crtc
->base
,
316 work
->page_flip_event
);
317 imx_drm_crtc_vblank_put(ipu_crtc
->imx_crtc
);
318 spin_unlock_irqrestore(&drm
->event_lock
, flags
);
321 static irqreturn_t
ipu_irq_handler(int irq
, void *dev_id
)
323 struct ipu_crtc
*ipu_crtc
= dev_id
;
325 imx_drm_handle_vblank(ipu_crtc
->imx_crtc
);
327 if (ipu_crtc
->flip_state
== IPU_FLIP_SUBMITTED
) {
328 struct ipu_plane
*plane
= ipu_crtc
->plane
[0];
330 ipu_plane_set_base(plane
, ipu_crtc
->base
.primary
->fb
,
332 ipu_crtc_handle_pageflip(ipu_crtc
);
333 queue_work(ipu_crtc
->flip_queue
,
334 &ipu_crtc
->flip_work
->unref_work
);
335 ipu_crtc
->flip_state
= IPU_FLIP_NONE
;
341 static bool ipu_crtc_mode_fixup(struct drm_crtc
*crtc
,
342 const struct drm_display_mode
*mode
,
343 struct drm_display_mode
*adjusted_mode
)
345 struct ipu_crtc
*ipu_crtc
= to_ipu_crtc(crtc
);
349 drm_display_mode_to_videomode(adjusted_mode
, &vm
);
351 ret
= ipu_di_adjust_videomode(ipu_crtc
->di
, &vm
);
355 drm_display_mode_from_videomode(&vm
, adjusted_mode
);
360 static void ipu_crtc_prepare(struct drm_crtc
*crtc
)
362 struct ipu_crtc
*ipu_crtc
= to_ipu_crtc(crtc
);
364 ipu_fb_disable(ipu_crtc
);
367 static void ipu_crtc_commit(struct drm_crtc
*crtc
)
369 struct ipu_crtc
*ipu_crtc
= to_ipu_crtc(crtc
);
371 ipu_fb_enable(ipu_crtc
);
374 static const struct drm_crtc_helper_funcs ipu_helper_funcs
= {
375 .dpms
= ipu_crtc_dpms
,
376 .mode_fixup
= ipu_crtc_mode_fixup
,
377 .mode_set
= ipu_crtc_mode_set
,
378 .prepare
= ipu_crtc_prepare
,
379 .commit
= ipu_crtc_commit
,
382 static int ipu_enable_vblank(struct drm_crtc
*crtc
)
384 struct ipu_crtc
*ipu_crtc
= to_ipu_crtc(crtc
);
386 enable_irq(ipu_crtc
->irq
);
391 static void ipu_disable_vblank(struct drm_crtc
*crtc
)
393 struct ipu_crtc
*ipu_crtc
= to_ipu_crtc(crtc
);
395 disable_irq_nosync(ipu_crtc
->irq
);
398 static int ipu_set_interface_pix_fmt(struct drm_crtc
*crtc
,
399 u32 bus_format
, int hsync_pin
, int vsync_pin
)
401 struct ipu_crtc
*ipu_crtc
= to_ipu_crtc(crtc
);
403 ipu_crtc
->bus_format
= bus_format
;
404 ipu_crtc
->di_hsync_pin
= hsync_pin
;
405 ipu_crtc
->di_vsync_pin
= vsync_pin
;
410 static const struct imx_drm_crtc_helper_funcs ipu_crtc_helper_funcs
= {
411 .enable_vblank
= ipu_enable_vblank
,
412 .disable_vblank
= ipu_disable_vblank
,
413 .set_interface_pix_fmt
= ipu_set_interface_pix_fmt
,
414 .crtc_funcs
= &ipu_crtc_funcs
,
415 .crtc_helper_funcs
= &ipu_helper_funcs
,
418 static void ipu_put_resources(struct ipu_crtc
*ipu_crtc
)
420 if (!IS_ERR_OR_NULL(ipu_crtc
->dc
))
421 ipu_dc_put(ipu_crtc
->dc
);
422 if (!IS_ERR_OR_NULL(ipu_crtc
->di
))
423 ipu_di_put(ipu_crtc
->di
);
426 static int ipu_get_resources(struct ipu_crtc
*ipu_crtc
,
427 struct ipu_client_platformdata
*pdata
)
429 struct ipu_soc
*ipu
= dev_get_drvdata(ipu_crtc
->dev
->parent
);
432 ipu_crtc
->dc
= ipu_dc_get(ipu
, pdata
->dc
);
433 if (IS_ERR(ipu_crtc
->dc
)) {
434 ret
= PTR_ERR(ipu_crtc
->dc
);
438 ipu_crtc
->di
= ipu_di_get(ipu
, pdata
->di
);
439 if (IS_ERR(ipu_crtc
->di
)) {
440 ret
= PTR_ERR(ipu_crtc
->di
);
446 ipu_put_resources(ipu_crtc
);
451 static int ipu_crtc_init(struct ipu_crtc
*ipu_crtc
,
452 struct ipu_client_platformdata
*pdata
, struct drm_device
*drm
)
454 struct ipu_soc
*ipu
= dev_get_drvdata(ipu_crtc
->dev
->parent
);
458 ret
= ipu_get_resources(ipu_crtc
, pdata
);
460 dev_err(ipu_crtc
->dev
, "getting resources failed with %d.\n",
466 dp
= IPU_DP_FLOW_SYNC_BG
;
467 ipu_crtc
->plane
[0] = ipu_plane_init(drm
, ipu
, pdata
->dma
[0], dp
, 0,
468 DRM_PLANE_TYPE_PRIMARY
);
469 if (IS_ERR(ipu_crtc
->plane
[0])) {
470 ret
= PTR_ERR(ipu_crtc
->plane
[0]);
471 goto err_put_resources
;
474 ret
= imx_drm_add_crtc(drm
, &ipu_crtc
->base
, &ipu_crtc
->imx_crtc
,
475 &ipu_crtc
->plane
[0]->base
, &ipu_crtc_helper_funcs
,
476 ipu_crtc
->dev
->of_node
);
478 dev_err(ipu_crtc
->dev
, "adding crtc failed with %d.\n", ret
);
479 goto err_put_resources
;
482 ret
= ipu_plane_get_resources(ipu_crtc
->plane
[0]);
484 dev_err(ipu_crtc
->dev
, "getting plane 0 resources failed with %d.\n",
486 goto err_remove_crtc
;
489 /* If this crtc is using the DP, add an overlay plane */
490 if (pdata
->dp
>= 0 && pdata
->dma
[1] > 0) {
491 ipu_crtc
->plane
[1] = ipu_plane_init(drm
, ipu
, pdata
->dma
[1],
493 drm_crtc_mask(&ipu_crtc
->base
),
494 DRM_PLANE_TYPE_OVERLAY
);
495 if (IS_ERR(ipu_crtc
->plane
[1]))
496 ipu_crtc
->plane
[1] = NULL
;
499 ipu_crtc
->irq
= ipu_plane_irq(ipu_crtc
->plane
[0]);
500 ret
= devm_request_irq(ipu_crtc
->dev
, ipu_crtc
->irq
, ipu_irq_handler
, 0,
501 "imx_drm", ipu_crtc
);
503 dev_err(ipu_crtc
->dev
, "irq request failed with %d.\n", ret
);
504 goto err_put_plane_res
;
506 /* Only enable IRQ when we actually need it to trigger work. */
507 disable_irq(ipu_crtc
->irq
);
509 ipu_crtc
->flip_queue
= create_singlethread_workqueue("ipu-crtc-flip");
514 ipu_plane_put_resources(ipu_crtc
->plane
[0]);
516 imx_drm_remove_crtc(ipu_crtc
->imx_crtc
);
518 ipu_put_resources(ipu_crtc
);
523 static int ipu_drm_bind(struct device
*dev
, struct device
*master
, void *data
)
525 struct ipu_client_platformdata
*pdata
= dev
->platform_data
;
526 struct drm_device
*drm
= data
;
527 struct ipu_crtc
*ipu_crtc
;
530 ipu_crtc
= devm_kzalloc(dev
, sizeof(*ipu_crtc
), GFP_KERNEL
);
536 ret
= ipu_crtc_init(ipu_crtc
, pdata
, drm
);
540 dev_set_drvdata(dev
, ipu_crtc
);
545 static void ipu_drm_unbind(struct device
*dev
, struct device
*master
,
548 struct ipu_crtc
*ipu_crtc
= dev_get_drvdata(dev
);
550 imx_drm_remove_crtc(ipu_crtc
->imx_crtc
);
552 destroy_workqueue(ipu_crtc
->flip_queue
);
553 ipu_plane_put_resources(ipu_crtc
->plane
[0]);
554 ipu_put_resources(ipu_crtc
);
557 static const struct component_ops ipu_crtc_ops
= {
558 .bind
= ipu_drm_bind
,
559 .unbind
= ipu_drm_unbind
,
562 static int ipu_drm_probe(struct platform_device
*pdev
)
564 struct device
*dev
= &pdev
->dev
;
567 if (!dev
->platform_data
)
570 ret
= dma_set_coherent_mask(dev
, DMA_BIT_MASK(32));
574 return component_add(dev
, &ipu_crtc_ops
);
577 static int ipu_drm_remove(struct platform_device
*pdev
)
579 component_del(&pdev
->dev
, &ipu_crtc_ops
);
583 static struct platform_driver ipu_drm_driver
= {
585 .name
= "imx-ipuv3-crtc",
587 .probe
= ipu_drm_probe
,
588 .remove
= ipu_drm_remove
,
590 module_platform_driver(ipu_drm_driver
);
592 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
593 MODULE_DESCRIPTION(DRIVER_DESC
);
594 MODULE_LICENSE("GPL");
595 MODULE_ALIAS("platform:imx-ipuv3-crtc");