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
;
74 #define to_ipu_crtc(x) container_of(x, struct ipu_crtc, base)
76 static void ipu_fb_enable(struct ipu_crtc
*ipu_crtc
)
78 struct ipu_soc
*ipu
= dev_get_drvdata(ipu_crtc
->dev
->parent
);
80 if (ipu_crtc
->enabled
)
84 ipu_plane_enable(ipu_crtc
->plane
[0]);
85 /* Start DC channel and DI after IDMAC */
86 ipu_dc_enable_channel(ipu_crtc
->dc
);
87 ipu_di_enable(ipu_crtc
->di
);
88 drm_crtc_vblank_on(&ipu_crtc
->base
);
90 ipu_crtc
->enabled
= 1;
93 static void ipu_fb_disable(struct ipu_crtc
*ipu_crtc
)
95 struct ipu_soc
*ipu
= dev_get_drvdata(ipu_crtc
->dev
->parent
);
97 if (!ipu_crtc
->enabled
)
100 /* Stop DC channel and DI before IDMAC */
101 ipu_dc_disable_channel(ipu_crtc
->dc
);
102 ipu_di_disable(ipu_crtc
->di
);
103 ipu_plane_disable(ipu_crtc
->plane
[0]);
105 drm_crtc_vblank_off(&ipu_crtc
->base
);
107 ipu_crtc
->enabled
= 0;
110 static void ipu_crtc_dpms(struct drm_crtc
*crtc
, int mode
)
112 struct ipu_crtc
*ipu_crtc
= to_ipu_crtc(crtc
);
114 dev_dbg(ipu_crtc
->dev
, "%s mode: %d\n", __func__
, mode
);
117 case DRM_MODE_DPMS_ON
:
118 ipu_fb_enable(ipu_crtc
);
120 case DRM_MODE_DPMS_STANDBY
:
121 case DRM_MODE_DPMS_SUSPEND
:
122 case DRM_MODE_DPMS_OFF
:
123 ipu_fb_disable(ipu_crtc
);
128 static void ipu_flip_unref_work_func(struct work_struct
*__work
)
130 struct ipu_flip_work
*work
=
131 container_of(__work
, struct ipu_flip_work
, unref_work
);
133 drm_gem_object_unreference_unlocked(work
->bo
);
137 static void ipu_flip_fence_work_func(struct work_struct
*__work
)
139 struct ipu_flip_work
*work
=
140 container_of(__work
, struct ipu_flip_work
, fence_work
);
143 /* wait for all fences attached to the FB obj to signal */
145 fence_wait(work
->excl
, false);
146 fence_put(work
->excl
);
148 for (i
= 0; i
< work
->shared_count
; i
++) {
149 fence_wait(work
->shared
[i
], false);
150 fence_put(work
->shared
[i
]);
153 work
->crtc
->flip_state
= IPU_FLIP_SUBMITTED
;
156 static int ipu_page_flip(struct drm_crtc
*crtc
,
157 struct drm_framebuffer
*fb
,
158 struct drm_pending_vblank_event
*event
,
159 uint32_t page_flip_flags
)
161 struct drm_gem_cma_object
*cma_obj
= drm_fb_cma_get_gem_obj(fb
, 0);
162 struct ipu_crtc
*ipu_crtc
= to_ipu_crtc(crtc
);
163 struct ipu_flip_work
*flip_work
;
166 if (ipu_crtc
->flip_state
!= IPU_FLIP_NONE
)
169 ret
= imx_drm_crtc_vblank_get(ipu_crtc
->imx_crtc
);
171 dev_dbg(ipu_crtc
->dev
, "failed to acquire vblank counter\n");
172 list_del(&event
->base
.link
);
177 flip_work
= kzalloc(sizeof *flip_work
, GFP_KERNEL
);
182 INIT_WORK(&flip_work
->unref_work
, ipu_flip_unref_work_func
);
183 flip_work
->page_flip_event
= event
;
185 /* get BO backing the old framebuffer and take a reference */
186 flip_work
->bo
= &drm_fb_cma_get_gem_obj(crtc
->primary
->fb
, 0)->base
;
187 drm_gem_object_reference(flip_work
->bo
);
189 ipu_crtc
->flip_work
= flip_work
;
191 * If the object has a DMABUF attached, we need to wait on its fences
194 if (cma_obj
->base
.dma_buf
) {
195 INIT_WORK(&flip_work
->fence_work
, ipu_flip_fence_work_func
);
196 flip_work
->crtc
= ipu_crtc
;
198 ret
= reservation_object_get_fences_rcu(
199 cma_obj
->base
.dma_buf
->resv
, &flip_work
->excl
,
200 &flip_work
->shared_count
, &flip_work
->shared
);
203 DRM_ERROR("failed to get fences for buffer\n");
207 /* No need to queue the worker if the are no fences */
208 if (!flip_work
->excl
&& !flip_work
->shared_count
) {
209 ipu_crtc
->flip_state
= IPU_FLIP_SUBMITTED
;
211 ipu_crtc
->flip_state
= IPU_FLIP_PENDING
;
212 queue_work(ipu_crtc
->flip_queue
,
213 &flip_work
->fence_work
);
216 ipu_crtc
->flip_state
= IPU_FLIP_SUBMITTED
;
222 drm_gem_object_unreference_unlocked(flip_work
->bo
);
224 ipu_crtc
->flip_work
= NULL
;
226 imx_drm_crtc_vblank_put(ipu_crtc
->imx_crtc
);
231 static const struct drm_crtc_funcs ipu_crtc_funcs
= {
232 .set_config
= drm_crtc_helper_set_config
,
233 .destroy
= drm_crtc_cleanup
,
234 .page_flip
= ipu_page_flip
,
237 static int ipu_crtc_mode_set(struct drm_crtc
*crtc
,
238 struct drm_display_mode
*orig_mode
,
239 struct drm_display_mode
*mode
,
241 struct drm_framebuffer
*old_fb
)
243 struct drm_device
*dev
= crtc
->dev
;
244 struct drm_encoder
*encoder
;
245 struct ipu_crtc
*ipu_crtc
= to_ipu_crtc(crtc
);
246 struct ipu_di_signal_cfg sig_cfg
= {};
247 unsigned long encoder_types
= 0;
250 dev_dbg(ipu_crtc
->dev
, "%s: mode->hdisplay: %d\n", __func__
,
252 dev_dbg(ipu_crtc
->dev
, "%s: mode->vdisplay: %d\n", __func__
,
255 list_for_each_entry(encoder
, &dev
->mode_config
.encoder_list
, head
)
256 if (encoder
->crtc
== crtc
)
257 encoder_types
|= BIT(encoder
->encoder_type
);
259 dev_dbg(ipu_crtc
->dev
, "%s: attached to encoder types 0x%lx\n",
260 __func__
, encoder_types
);
263 * If we have DAC or LDB, then we need the IPU DI clock to be
264 * the same as the LDB DI clock. For TVDAC, derive the IPU DI
265 * clock from 27 MHz TVE_DI clock, but allow to divide it.
267 if (encoder_types
& (BIT(DRM_MODE_ENCODER_DAC
) |
268 BIT(DRM_MODE_ENCODER_LVDS
)))
269 sig_cfg
.clkflags
= IPU_DI_CLKMODE_SYNC
| IPU_DI_CLKMODE_EXT
;
270 else if (encoder_types
& BIT(DRM_MODE_ENCODER_TVDAC
))
271 sig_cfg
.clkflags
= IPU_DI_CLKMODE_EXT
;
273 sig_cfg
.clkflags
= 0;
275 sig_cfg
.enable_pol
= !(ipu_crtc
->bus_flags
& DRM_BUS_FLAG_DE_LOW
);
276 /* Default to driving pixel data on negative clock edges */
277 sig_cfg
.clk_pol
= !!(ipu_crtc
->bus_flags
&
278 DRM_BUS_FLAG_PIXDATA_POSEDGE
);
279 sig_cfg
.bus_format
= ipu_crtc
->bus_format
;
280 sig_cfg
.v_to_h_sync
= 0;
281 sig_cfg
.hsync_pin
= ipu_crtc
->di_hsync_pin
;
282 sig_cfg
.vsync_pin
= ipu_crtc
->di_vsync_pin
;
284 drm_display_mode_to_videomode(mode
, &sig_cfg
.mode
);
286 ret
= ipu_dc_init_sync(ipu_crtc
->dc
, ipu_crtc
->di
,
287 mode
->flags
& DRM_MODE_FLAG_INTERLACE
,
288 ipu_crtc
->bus_format
, mode
->hdisplay
);
290 dev_err(ipu_crtc
->dev
,
291 "initializing display controller failed with %d\n",
296 ret
= ipu_di_init_sync_panel(ipu_crtc
->di
, &sig_cfg
);
298 dev_err(ipu_crtc
->dev
,
299 "initializing panel failed with %d\n", ret
);
303 return ipu_plane_mode_set(ipu_crtc
->plane
[0], crtc
, mode
,
305 0, 0, mode
->hdisplay
, mode
->vdisplay
,
306 x
, y
, mode
->hdisplay
, mode
->vdisplay
,
307 mode
->flags
& DRM_MODE_FLAG_INTERLACE
);
310 static void ipu_crtc_handle_pageflip(struct ipu_crtc
*ipu_crtc
)
313 struct drm_device
*drm
= ipu_crtc
->base
.dev
;
314 struct ipu_flip_work
*work
= ipu_crtc
->flip_work
;
316 spin_lock_irqsave(&drm
->event_lock
, flags
);
317 if (work
->page_flip_event
)
318 drm_crtc_send_vblank_event(&ipu_crtc
->base
,
319 work
->page_flip_event
);
320 imx_drm_crtc_vblank_put(ipu_crtc
->imx_crtc
);
321 spin_unlock_irqrestore(&drm
->event_lock
, flags
);
324 static irqreturn_t
ipu_irq_handler(int irq
, void *dev_id
)
326 struct ipu_crtc
*ipu_crtc
= dev_id
;
328 imx_drm_handle_vblank(ipu_crtc
->imx_crtc
);
330 if (ipu_crtc
->flip_state
== IPU_FLIP_SUBMITTED
) {
331 struct ipu_plane
*plane
= ipu_crtc
->plane
[0];
333 ipu_plane_set_base(plane
, ipu_crtc
->base
.primary
->fb
,
335 ipu_crtc_handle_pageflip(ipu_crtc
);
336 queue_work(ipu_crtc
->flip_queue
,
337 &ipu_crtc
->flip_work
->unref_work
);
338 ipu_crtc
->flip_state
= IPU_FLIP_NONE
;
344 static bool ipu_crtc_mode_fixup(struct drm_crtc
*crtc
,
345 const struct drm_display_mode
*mode
,
346 struct drm_display_mode
*adjusted_mode
)
348 struct ipu_crtc
*ipu_crtc
= to_ipu_crtc(crtc
);
352 drm_display_mode_to_videomode(adjusted_mode
, &vm
);
354 ret
= ipu_di_adjust_videomode(ipu_crtc
->di
, &vm
);
358 drm_display_mode_from_videomode(&vm
, adjusted_mode
);
363 static void ipu_crtc_prepare(struct drm_crtc
*crtc
)
365 struct ipu_crtc
*ipu_crtc
= to_ipu_crtc(crtc
);
367 ipu_fb_disable(ipu_crtc
);
370 static void ipu_crtc_commit(struct drm_crtc
*crtc
)
372 struct ipu_crtc
*ipu_crtc
= to_ipu_crtc(crtc
);
374 ipu_fb_enable(ipu_crtc
);
377 static const struct drm_crtc_helper_funcs ipu_helper_funcs
= {
378 .dpms
= ipu_crtc_dpms
,
379 .mode_fixup
= ipu_crtc_mode_fixup
,
380 .mode_set
= ipu_crtc_mode_set
,
381 .prepare
= ipu_crtc_prepare
,
382 .commit
= ipu_crtc_commit
,
385 static int ipu_enable_vblank(struct drm_crtc
*crtc
)
387 struct ipu_crtc
*ipu_crtc
= to_ipu_crtc(crtc
);
389 enable_irq(ipu_crtc
->irq
);
394 static void ipu_disable_vblank(struct drm_crtc
*crtc
)
396 struct ipu_crtc
*ipu_crtc
= to_ipu_crtc(crtc
);
398 disable_irq_nosync(ipu_crtc
->irq
);
401 static int ipu_set_interface_pix_fmt(struct drm_crtc
*crtc
,
402 u32 bus_format
, int hsync_pin
, int vsync_pin
, u32 bus_flags
)
404 struct ipu_crtc
*ipu_crtc
= to_ipu_crtc(crtc
);
406 ipu_crtc
->bus_format
= bus_format
;
407 ipu_crtc
->bus_flags
= bus_flags
;
408 ipu_crtc
->di_hsync_pin
= hsync_pin
;
409 ipu_crtc
->di_vsync_pin
= vsync_pin
;
414 static const struct imx_drm_crtc_helper_funcs ipu_crtc_helper_funcs
= {
415 .enable_vblank
= ipu_enable_vblank
,
416 .disable_vblank
= ipu_disable_vblank
,
417 .set_interface_pix_fmt
= ipu_set_interface_pix_fmt
,
418 .crtc_funcs
= &ipu_crtc_funcs
,
419 .crtc_helper_funcs
= &ipu_helper_funcs
,
422 static void ipu_put_resources(struct ipu_crtc
*ipu_crtc
)
424 if (!IS_ERR_OR_NULL(ipu_crtc
->dc
))
425 ipu_dc_put(ipu_crtc
->dc
);
426 if (!IS_ERR_OR_NULL(ipu_crtc
->di
))
427 ipu_di_put(ipu_crtc
->di
);
430 static int ipu_get_resources(struct ipu_crtc
*ipu_crtc
,
431 struct ipu_client_platformdata
*pdata
)
433 struct ipu_soc
*ipu
= dev_get_drvdata(ipu_crtc
->dev
->parent
);
436 ipu_crtc
->dc
= ipu_dc_get(ipu
, pdata
->dc
);
437 if (IS_ERR(ipu_crtc
->dc
)) {
438 ret
= PTR_ERR(ipu_crtc
->dc
);
442 ipu_crtc
->di
= ipu_di_get(ipu
, pdata
->di
);
443 if (IS_ERR(ipu_crtc
->di
)) {
444 ret
= PTR_ERR(ipu_crtc
->di
);
450 ipu_put_resources(ipu_crtc
);
455 static int ipu_crtc_init(struct ipu_crtc
*ipu_crtc
,
456 struct ipu_client_platformdata
*pdata
, struct drm_device
*drm
)
458 struct ipu_soc
*ipu
= dev_get_drvdata(ipu_crtc
->dev
->parent
);
462 ret
= ipu_get_resources(ipu_crtc
, pdata
);
464 dev_err(ipu_crtc
->dev
, "getting resources failed with %d.\n",
470 dp
= IPU_DP_FLOW_SYNC_BG
;
471 ipu_crtc
->plane
[0] = ipu_plane_init(drm
, ipu
, pdata
->dma
[0], dp
, 0,
472 DRM_PLANE_TYPE_PRIMARY
);
473 if (IS_ERR(ipu_crtc
->plane
[0])) {
474 ret
= PTR_ERR(ipu_crtc
->plane
[0]);
475 goto err_put_resources
;
478 ret
= imx_drm_add_crtc(drm
, &ipu_crtc
->base
, &ipu_crtc
->imx_crtc
,
479 &ipu_crtc
->plane
[0]->base
, &ipu_crtc_helper_funcs
,
482 dev_err(ipu_crtc
->dev
, "adding crtc failed with %d.\n", ret
);
483 goto err_put_resources
;
486 ret
= ipu_plane_get_resources(ipu_crtc
->plane
[0]);
488 dev_err(ipu_crtc
->dev
, "getting plane 0 resources failed with %d.\n",
490 goto err_remove_crtc
;
493 /* If this crtc is using the DP, add an overlay plane */
494 if (pdata
->dp
>= 0 && pdata
->dma
[1] > 0) {
495 ipu_crtc
->plane
[1] = ipu_plane_init(drm
, ipu
, pdata
->dma
[1],
497 drm_crtc_mask(&ipu_crtc
->base
),
498 DRM_PLANE_TYPE_OVERLAY
);
499 if (IS_ERR(ipu_crtc
->plane
[1]))
500 ipu_crtc
->plane
[1] = NULL
;
503 ipu_crtc
->irq
= ipu_plane_irq(ipu_crtc
->plane
[0]);
504 ret
= devm_request_irq(ipu_crtc
->dev
, ipu_crtc
->irq
, ipu_irq_handler
, 0,
505 "imx_drm", ipu_crtc
);
507 dev_err(ipu_crtc
->dev
, "irq request failed with %d.\n", ret
);
508 goto err_put_plane_res
;
510 /* Only enable IRQ when we actually need it to trigger work. */
511 disable_irq(ipu_crtc
->irq
);
513 ipu_crtc
->flip_queue
= create_singlethread_workqueue("ipu-crtc-flip");
518 ipu_plane_put_resources(ipu_crtc
->plane
[0]);
520 imx_drm_remove_crtc(ipu_crtc
->imx_crtc
);
522 ipu_put_resources(ipu_crtc
);
527 static int ipu_drm_bind(struct device
*dev
, struct device
*master
, void *data
)
529 struct ipu_client_platformdata
*pdata
= dev
->platform_data
;
530 struct drm_device
*drm
= data
;
531 struct ipu_crtc
*ipu_crtc
;
534 ipu_crtc
= devm_kzalloc(dev
, sizeof(*ipu_crtc
), GFP_KERNEL
);
540 ret
= ipu_crtc_init(ipu_crtc
, pdata
, drm
);
544 dev_set_drvdata(dev
, ipu_crtc
);
549 static void ipu_drm_unbind(struct device
*dev
, struct device
*master
,
552 struct ipu_crtc
*ipu_crtc
= dev_get_drvdata(dev
);
554 imx_drm_remove_crtc(ipu_crtc
->imx_crtc
);
556 destroy_workqueue(ipu_crtc
->flip_queue
);
557 ipu_plane_put_resources(ipu_crtc
->plane
[0]);
558 ipu_put_resources(ipu_crtc
);
561 static const struct component_ops ipu_crtc_ops
= {
562 .bind
= ipu_drm_bind
,
563 .unbind
= ipu_drm_unbind
,
566 static int ipu_drm_probe(struct platform_device
*pdev
)
568 struct device
*dev
= &pdev
->dev
;
571 if (!dev
->platform_data
)
574 ret
= dma_set_coherent_mask(dev
, DMA_BIT_MASK(32));
578 return component_add(dev
, &ipu_crtc_ops
);
581 static int ipu_drm_remove(struct platform_device
*pdev
)
583 component_del(&pdev
->dev
, &ipu_crtc_ops
);
587 static struct platform_driver ipu_drm_driver
= {
589 .name
= "imx-ipuv3-crtc",
591 .probe
= ipu_drm_probe
,
592 .remove
= ipu_drm_remove
,
594 module_platform_driver(ipu_drm_driver
);
596 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
597 MODULE_DESCRIPTION(DRIVER_DESC
);
598 MODULE_LICENSE("GPL");
599 MODULE_ALIAS("platform:imx-ipuv3-crtc");