2525#include <drm/drm_crtc_helper.h>
2626#include <linux/fb.h>
2727#include <linux/clk.h>
28+ #include <linux/errno.h>
2829#include <drm/drm_gem_cma_helper.h>
2930#include <drm/drm_fb_cma_helper.h>
3031
3132#include "ipu-v3/imx-ipu-v3.h"
3233#include "imx-drm.h"
34+ #include "ipuv3-plane.h"
3335
3436#define DRIVER_DESC "i.MX IPUv3 Graphics"
3537
3638struct ipu_crtc {
3739 struct device * dev ;
3840 struct drm_crtc base ;
3941 struct imx_drm_crtc * imx_crtc ;
40- struct ipuv3_channel * ipu_ch ;
42+
43+ /* plane[0] is the full plane, plane[1] is the partial plane */
44+ struct ipu_plane * plane [2 ];
45+
4146 struct ipu_dc * dc ;
42- struct ipu_dp * dp ;
43- struct dmfc_channel * dmfc ;
4447 struct ipu_di * di ;
4548 int enabled ;
4649 struct drm_pending_vblank_event * page_flip_event ;
@@ -54,35 +57,14 @@ struct ipu_crtc {
5457
5558#define to_ipu_crtc (x ) container_of(x, struct ipu_crtc, base)
5659
57- static int calc_vref (struct drm_display_mode * mode )
58- {
59- unsigned long htotal , vtotal ;
60-
61- htotal = mode -> htotal ;
62- vtotal = mode -> vtotal ;
63-
64- if (!htotal || !vtotal )
65- return 60 ;
66-
67- return mode -> clock * 1000 / vtotal / htotal ;
68- }
69-
70- static int calc_bandwidth (struct drm_display_mode * mode , unsigned int vref )
71- {
72- return mode -> hdisplay * mode -> vdisplay * vref ;
73- }
74-
7560static void ipu_fb_enable (struct ipu_crtc * ipu_crtc )
7661{
7762 if (ipu_crtc -> enabled )
7863 return ;
7964
8065 ipu_di_enable (ipu_crtc -> di );
81- ipu_dmfc_enable_channel (ipu_crtc -> dmfc );
82- ipu_idmac_enable_channel (ipu_crtc -> ipu_ch );
8366 ipu_dc_enable_channel (ipu_crtc -> dc );
84- if (ipu_crtc -> dp )
85- ipu_dp_enable_channel (ipu_crtc -> dp );
67+ ipu_plane_enable (ipu_crtc -> plane [0 ]);
8668
8769 ipu_crtc -> enabled = 1 ;
8870}
@@ -92,12 +74,8 @@ static void ipu_fb_disable(struct ipu_crtc *ipu_crtc)
9274 if (!ipu_crtc -> enabled )
9375 return ;
9476
95- if (ipu_crtc -> dp )
96- ipu_dp_disable_channel (ipu_crtc -> dp );
77+ ipu_plane_disable (ipu_crtc -> plane [0 ]);
9778 ipu_dc_disable_channel (ipu_crtc -> dc );
98- ipu_idmac_wait_busy (ipu_crtc -> ipu_ch , 50 );
99- ipu_idmac_disable_channel (ipu_crtc -> ipu_ch );
100- ipu_dmfc_disable_channel (ipu_crtc -> dmfc );
10179 ipu_di_disable (ipu_crtc -> di );
10280
10381 ipu_crtc -> enabled = 0 ;
@@ -153,79 +131,22 @@ static const struct drm_crtc_funcs ipu_crtc_funcs = {
153131 .page_flip = ipu_page_flip ,
154132};
155133
156- static int ipu_drm_set_base (struct drm_crtc * crtc , int x , int y )
157- {
158- struct ipu_crtc * ipu_crtc = to_ipu_crtc (crtc );
159- struct drm_gem_cma_object * cma_obj ;
160- struct drm_framebuffer * fb = crtc -> fb ;
161- unsigned long phys ;
162-
163- cma_obj = drm_fb_cma_get_gem_obj (fb , 0 );
164- if (!cma_obj ) {
165- DRM_LOG_KMS ("entry is null.\n" );
166- return - EFAULT ;
167- }
168-
169- phys = cma_obj -> paddr ;
170- phys += x * (fb -> bits_per_pixel >> 3 );
171- phys += y * fb -> pitches [0 ];
172-
173- dev_dbg (ipu_crtc -> dev , "%s: phys: 0x%lx\n" , __func__ , phys );
174- dev_dbg (ipu_crtc -> dev , "%s: xy: %dx%d\n" , __func__ , x , y );
175-
176- ipu_cpmem_set_stride (ipu_get_cpmem (ipu_crtc -> ipu_ch ), fb -> pitches [0 ]);
177- ipu_cpmem_set_buffer (ipu_get_cpmem (ipu_crtc -> ipu_ch ),
178- 0 , phys );
179-
180- return 0 ;
181- }
182-
183134static int ipu_crtc_mode_set (struct drm_crtc * crtc ,
184135 struct drm_display_mode * orig_mode ,
185136 struct drm_display_mode * mode ,
186137 int x , int y ,
187138 struct drm_framebuffer * old_fb )
188139{
189140 struct ipu_crtc * ipu_crtc = to_ipu_crtc (crtc );
190- struct drm_framebuffer * fb = ipu_crtc -> base .fb ;
191141 int ret ;
192142 struct ipu_di_signal_cfg sig_cfg = {};
193143 u32 out_pixel_fmt ;
194- struct ipu_ch_param __iomem * cpmem = ipu_get_cpmem (ipu_crtc -> ipu_ch );
195- int bpp ;
196- u32 v4l2_fmt ;
197144
198145 dev_dbg (ipu_crtc -> dev , "%s: mode->hdisplay: %d\n" , __func__ ,
199146 mode -> hdisplay );
200147 dev_dbg (ipu_crtc -> dev , "%s: mode->vdisplay: %d\n" , __func__ ,
201148 mode -> vdisplay );
202149
203- ipu_ch_param_zero (cpmem );
204-
205- switch (fb -> pixel_format ) {
206- case DRM_FORMAT_XRGB8888 :
207- case DRM_FORMAT_ARGB8888 :
208- v4l2_fmt = V4L2_PIX_FMT_RGB32 ;
209- bpp = 32 ;
210- break ;
211- case DRM_FORMAT_RGB565 :
212- v4l2_fmt = V4L2_PIX_FMT_RGB565 ;
213- bpp = 16 ;
214- break ;
215- case DRM_FORMAT_RGB888 :
216- v4l2_fmt = V4L2_PIX_FMT_RGB24 ;
217- bpp = 24 ;
218- break ;
219- case DRM_FORMAT_BGR888 :
220- v4l2_fmt = V4L2_PIX_FMT_BGR24 ;
221- bpp = 24 ;
222- break ;
223- default :
224- dev_err (ipu_crtc -> dev , "unsupported pixel format 0x%08x\n" ,
225- fb -> pixel_format );
226- return - EINVAL ;
227- }
228-
229150 out_pixel_fmt = ipu_crtc -> interface_pix_fmt ;
230151
231152 if (mode -> flags & DRM_MODE_FLAG_INTERLACE )
@@ -255,18 +176,6 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
255176 sig_cfg .hsync_pin = ipu_crtc -> di_hsync_pin ;
256177 sig_cfg .vsync_pin = ipu_crtc -> di_vsync_pin ;
257178
258- if (ipu_crtc -> dp ) {
259- ret = ipu_dp_setup_channel (ipu_crtc -> dp , IPUV3_COLORSPACE_RGB ,
260- IPUV3_COLORSPACE_RGB );
261- if (ret ) {
262- dev_err (ipu_crtc -> dev ,
263- "initializing display processor failed with %d\n" ,
264- ret );
265- return ret ;
266- }
267- ipu_dp_set_global_alpha (ipu_crtc -> dp , 1 , 0 , 1 );
268- }
269-
270179 ret = ipu_dc_init_sync (ipu_crtc -> dc , ipu_crtc -> di , sig_cfg .interlaced ,
271180 out_pixel_fmt , mode -> hdisplay );
272181 if (ret ) {
@@ -283,30 +192,9 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
283192 return ret ;
284193 }
285194
286- ipu_cpmem_set_resolution (cpmem , mode -> hdisplay , mode -> vdisplay );
287- ipu_cpmem_set_fmt (cpmem , v4l2_fmt );
288- ipu_cpmem_set_high_priority (ipu_crtc -> ipu_ch );
289-
290- ret = ipu_dmfc_init_channel (ipu_crtc -> dmfc , mode -> hdisplay );
291- if (ret ) {
292- dev_err (ipu_crtc -> dev ,
293- "initializing dmfc channel failed with %d\n" ,
294- ret );
295- return ret ;
296- }
297-
298- ret = ipu_dmfc_alloc_bandwidth (ipu_crtc -> dmfc ,
299- calc_bandwidth (mode , calc_vref (mode )), 64 );
300- if (ret ) {
301- dev_err (ipu_crtc -> dev ,
302- "allocating dmfc bandwidth failed with %d\n" ,
303- ret );
304- return ret ;
305- }
306-
307- ipu_drm_set_base (crtc , x , y );
308-
309- return 0 ;
195+ return ipu_plane_mode_set (ipu_crtc -> plane [0 ], crtc , mode , crtc -> fb ,
196+ 0 , 0 , mode -> hdisplay , mode -> vdisplay ,
197+ x , y , mode -> hdisplay , mode -> vdisplay );
310198}
311199
312200static void ipu_crtc_handle_pageflip (struct ipu_crtc * ipu_crtc )
@@ -330,7 +218,7 @@ static irqreturn_t ipu_irq_handler(int irq, void *dev_id)
330218
331219 if (ipu_crtc -> newfb ) {
332220 ipu_crtc -> newfb = NULL ;
333- ipu_drm_set_base ( & ipu_crtc -> base , 0 , 0 );
221+ ipu_plane_set_base ( ipu_crtc -> plane [ 0 ], ipu_crtc -> base . fb , 0 , 0 );
334222 ipu_crtc_handle_pageflip (ipu_crtc );
335223 }
336224
@@ -413,12 +301,8 @@ static const struct imx_drm_crtc_helper_funcs ipu_crtc_helper_funcs = {
413301
414302static void ipu_put_resources (struct ipu_crtc * ipu_crtc )
415303{
416- if (!IS_ERR_OR_NULL (ipu_crtc -> ipu_ch ))
417- ipu_idmac_put (ipu_crtc -> ipu_ch );
418- if (!IS_ERR_OR_NULL (ipu_crtc -> dmfc ))
419- ipu_dmfc_put (ipu_crtc -> dmfc );
420- if (!IS_ERR_OR_NULL (ipu_crtc -> dp ))
421- ipu_dp_put (ipu_crtc -> dp );
304+ if (!IS_ERR_OR_NULL (ipu_crtc -> dc ))
305+ ipu_dc_put (ipu_crtc -> dc );
422306 if (!IS_ERR_OR_NULL (ipu_crtc -> di ))
423307 ipu_di_put (ipu_crtc -> di );
424308}
@@ -429,32 +313,12 @@ static int ipu_get_resources(struct ipu_crtc *ipu_crtc,
429313 struct ipu_soc * ipu = dev_get_drvdata (ipu_crtc -> dev -> parent );
430314 int ret ;
431315
432- ipu_crtc -> ipu_ch = ipu_idmac_get (ipu , pdata -> dma [0 ]);
433- if (IS_ERR (ipu_crtc -> ipu_ch )) {
434- ret = PTR_ERR (ipu_crtc -> ipu_ch );
435- goto err_out ;
436- }
437-
438316 ipu_crtc -> dc = ipu_dc_get (ipu , pdata -> dc );
439317 if (IS_ERR (ipu_crtc -> dc )) {
440318 ret = PTR_ERR (ipu_crtc -> dc );
441319 goto err_out ;
442320 }
443321
444- ipu_crtc -> dmfc = ipu_dmfc_get (ipu , pdata -> dma [0 ]);
445- if (IS_ERR (ipu_crtc -> dmfc )) {
446- ret = PTR_ERR (ipu_crtc -> dmfc );
447- goto err_out ;
448- }
449-
450- if (pdata -> dp >= 0 ) {
451- ipu_crtc -> dp = ipu_dp_get (ipu , pdata -> dp );
452- if (IS_ERR (ipu_crtc -> dp )) {
453- ret = PTR_ERR (ipu_crtc -> dp );
454- goto err_out ;
455- }
456- }
457-
458322 ipu_crtc -> di = ipu_di_get (ipu , pdata -> di );
459323 if (IS_ERR (ipu_crtc -> di )) {
460324 ret = PTR_ERR (ipu_crtc -> di );
@@ -472,7 +336,9 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
472336 struct ipu_client_platformdata * pdata )
473337{
474338 struct ipu_soc * ipu = dev_get_drvdata (ipu_crtc -> dev -> parent );
339+ int dp = - EINVAL ;
475340 int ret ;
341+ int id ;
476342
477343 ret = ipu_get_resources (ipu_crtc , pdata );
478344 if (ret ) {
@@ -490,17 +356,42 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
490356 goto err_put_resources ;
491357 }
492358
493- ipu_crtc -> irq = ipu_idmac_channel_irq (ipu , ipu_crtc -> ipu_ch ,
494- IPU_IRQ_EOF );
359+ if (pdata -> dp >= 0 )
360+ dp = IPU_DP_FLOW_SYNC_BG ;
361+ id = imx_drm_crtc_id (ipu_crtc -> imx_crtc );
362+ ipu_crtc -> plane [0 ] = ipu_plane_init (ipu_crtc -> base .dev , ipu ,
363+ pdata -> dma [0 ], dp , BIT (id ), true);
364+ ret = ipu_plane_get_resources (ipu_crtc -> plane [0 ]);
365+ if (ret ) {
366+ dev_err (ipu_crtc -> dev , "getting plane 0 resources failed with %d.\n" ,
367+ ret );
368+ goto err_remove_crtc ;
369+ }
370+
371+ /* If this crtc is using the DP, add an overlay plane */
372+ if (pdata -> dp >= 0 && pdata -> dma [1 ] > 0 ) {
373+ ipu_crtc -> plane [1 ] = ipu_plane_init (ipu_crtc -> base .dev , ipu ,
374+ pdata -> dma [1 ],
375+ IPU_DP_FLOW_SYNC_FG ,
376+ BIT (id ), false);
377+ if (IS_ERR (ipu_crtc -> plane [1 ]))
378+ ipu_crtc -> plane [1 ] = NULL ;
379+ }
380+
381+ ipu_crtc -> irq = ipu_plane_irq (ipu_crtc -> plane [0 ]);
495382 ret = devm_request_irq (ipu_crtc -> dev , ipu_crtc -> irq , ipu_irq_handler , 0 ,
496383 "imx_drm" , ipu_crtc );
497384 if (ret < 0 ) {
498385 dev_err (ipu_crtc -> dev , "irq request failed with %d.\n" , ret );
499- goto err_put_resources ;
386+ goto err_put_plane_res ;
500387 }
501388
502389 return 0 ;
503390
391+ err_put_plane_res :
392+ ipu_plane_put_resources (ipu_crtc -> plane [0 ]);
393+ err_remove_crtc :
394+ imx_drm_remove_crtc (ipu_crtc -> imx_crtc );
504395err_put_resources :
505396 ipu_put_resources (ipu_crtc );
506397
@@ -539,6 +430,7 @@ static int ipu_drm_remove(struct platform_device *pdev)
539430
540431 imx_drm_remove_crtc (ipu_crtc -> imx_crtc );
541432
433+ ipu_plane_put_resources (ipu_crtc -> plane [0 ]);
542434 ipu_put_resources (ipu_crtc );
543435
544436 return 0 ;
0 commit comments