1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright 2016 Linaro Ltd.
4 * Copyright 2016 ZTE Corporation.
8 #include <linux/component.h>
9 #include <linux/module.h>
10 #include <linux/of_address.h>
11 #include <linux/platform_device.h>
13 #include <video/videomode.h>
15 #include <drm/drm_atomic_helper.h>
16 #include <drm/drm_crtc.h>
17 #include <drm/drm_fb_cma_helper.h>
18 #include <drm/drm_fb_helper.h>
19 #include <drm/drm_gem_cma_helper.h>
20 #include <drm/drm_of.h>
21 #include <drm/drm_plane_helper.h>
22 #include <drm/drm_probe_helper.h>
23 #include <drm/drm_vblank.h>
25 #include "zx_common_regs.h"
26 #include "zx_drm_drv.h"
29 #include "zx_vou_regs.h"
48 static const struct zx_crtc_regs main_crtc_regs
= {
49 .fir_active
= FIR_MAIN_ACTIVE
,
50 .fir_htiming
= FIR_MAIN_H_TIMING
,
51 .fir_vtiming
= FIR_MAIN_V_TIMING
,
52 .sec_vtiming
= SEC_MAIN_V_TIMING
,
53 .timing_shift
= TIMING_MAIN_SHIFT
,
54 .timing_pi_shift
= TIMING_MAIN_PI_SHIFT
,
57 static const struct zx_crtc_regs aux_crtc_regs
= {
58 .fir_active
= FIR_AUX_ACTIVE
,
59 .fir_htiming
= FIR_AUX_H_TIMING
,
60 .fir_vtiming
= FIR_AUX_V_TIMING
,
61 .sec_vtiming
= SEC_AUX_V_TIMING
,
62 .timing_shift
= TIMING_AUX_SHIFT
,
63 .timing_pi_shift
= TIMING_AUX_PI_SHIFT
,
71 u32 sec_vactive_shift
;
78 u32 div_hdmi_pnx_shift
;
84 static const struct zx_crtc_bits main_crtc_bits
= {
85 .polarity_mask
= MAIN_POL_MASK
,
86 .polarity_shift
= MAIN_POL_SHIFT
,
87 .int_frame_mask
= TIMING_INT_MAIN_FRAME
,
88 .tc_enable
= MAIN_TC_EN
,
89 .sec_vactive_shift
= SEC_VACT_MAIN_SHIFT
,
90 .sec_vactive_mask
= SEC_VACT_MAIN_MASK
,
91 .interlace_select
= MAIN_INTERLACE_SEL
,
92 .pi_enable
= MAIN_PI_EN
,
93 .div_vga_shift
= VGA_MAIN_DIV_SHIFT
,
94 .div_pic_shift
= PIC_MAIN_DIV_SHIFT
,
95 .div_tvenc_shift
= TVENC_MAIN_DIV_SHIFT
,
96 .div_hdmi_pnx_shift
= HDMI_MAIN_PNX_DIV_SHIFT
,
97 .div_hdmi_shift
= HDMI_MAIN_DIV_SHIFT
,
98 .div_inf_shift
= INF_MAIN_DIV_SHIFT
,
99 .div_layer_shift
= LAYER_MAIN_DIV_SHIFT
,
102 static const struct zx_crtc_bits aux_crtc_bits
= {
103 .polarity_mask
= AUX_POL_MASK
,
104 .polarity_shift
= AUX_POL_SHIFT
,
105 .int_frame_mask
= TIMING_INT_AUX_FRAME
,
106 .tc_enable
= AUX_TC_EN
,
107 .sec_vactive_shift
= SEC_VACT_AUX_SHIFT
,
108 .sec_vactive_mask
= SEC_VACT_AUX_MASK
,
109 .interlace_select
= AUX_INTERLACE_SEL
,
110 .pi_enable
= AUX_PI_EN
,
111 .div_vga_shift
= VGA_AUX_DIV_SHIFT
,
112 .div_pic_shift
= PIC_AUX_DIV_SHIFT
,
113 .div_tvenc_shift
= TVENC_AUX_DIV_SHIFT
,
114 .div_hdmi_pnx_shift
= HDMI_AUX_PNX_DIV_SHIFT
,
115 .div_hdmi_shift
= HDMI_AUX_DIV_SHIFT
,
116 .div_inf_shift
= INF_AUX_DIV_SHIFT
,
117 .div_layer_shift
= LAYER_AUX_DIV_SHIFT
,
121 struct drm_crtc crtc
;
122 struct drm_plane
*primary
;
123 struct zx_vou_hw
*vou
;
124 void __iomem
*chnreg
;
125 void __iomem
*chncsc
;
126 void __iomem
*dither
;
127 const struct zx_crtc_regs
*regs
;
128 const struct zx_crtc_bits
*bits
;
129 enum vou_chn_type chn_type
;
133 #define to_zx_crtc(x) container_of(x, struct zx_crtc, crtc)
135 struct vou_layer_bits
{
141 static const struct vou_layer_bits zx_gl_bits
[GL_NUM
] = {
143 .enable
= OSD_CTRL0_GL0_EN
,
144 .chnsel
= OSD_CTRL0_GL0_SEL
,
145 .clksel
= VOU_CLK_GL0_SEL
,
147 .enable
= OSD_CTRL0_GL1_EN
,
148 .chnsel
= OSD_CTRL0_GL1_SEL
,
149 .clksel
= VOU_CLK_GL1_SEL
,
153 static const struct vou_layer_bits zx_vl_bits
[VL_NUM
] = {
155 .enable
= OSD_CTRL0_VL0_EN
,
156 .chnsel
= OSD_CTRL0_VL0_SEL
,
157 .clksel
= VOU_CLK_VL0_SEL
,
159 .enable
= OSD_CTRL0_VL1_EN
,
160 .chnsel
= OSD_CTRL0_VL1_SEL
,
161 .clksel
= VOU_CLK_VL1_SEL
,
163 .enable
= OSD_CTRL0_VL2_EN
,
164 .chnsel
= OSD_CTRL0_VL2_SEL
,
165 .clksel
= VOU_CLK_VL2_SEL
,
172 void __iomem
*timing
;
173 void __iomem
*vouctl
;
174 void __iomem
*otfppu
;
178 struct clk
*main_clk
;
180 struct zx_crtc
*main_crtc
;
181 struct zx_crtc
*aux_crtc
;
184 enum vou_inf_data_sel
{
193 enum vou_inf_data_sel data_sel
;
198 static struct vou_inf vou_infs
[] = {
200 .data_sel
= VOU_YUV444
,
201 .clocks_en_bits
= BIT(24) | BIT(18) | BIT(6),
202 .clocks_sel_bits
= BIT(13) | BIT(2),
205 .data_sel
= VOU_YUV444
,
206 .clocks_en_bits
= BIT(15),
207 .clocks_sel_bits
= BIT(11) | BIT(0),
210 .data_sel
= VOU_RGB_888
,
211 .clocks_en_bits
= BIT(1),
212 .clocks_sel_bits
= BIT(10),
216 static inline struct zx_vou_hw
*crtc_to_vou(struct drm_crtc
*crtc
)
218 struct zx_crtc
*zcrtc
= to_zx_crtc(crtc
);
223 void vou_inf_hdmi_audio_sel(struct drm_crtc
*crtc
,
224 enum vou_inf_hdmi_audio aud
)
226 struct zx_crtc
*zcrtc
= to_zx_crtc(crtc
);
227 struct zx_vou_hw
*vou
= zcrtc
->vou
;
229 zx_writel_mask(vou
->vouctl
+ VOU_INF_HDMI_CTRL
, VOU_HDMI_AUD_MASK
, aud
);
232 void vou_inf_enable(enum vou_inf_id id
, struct drm_crtc
*crtc
)
234 struct zx_crtc
*zcrtc
= to_zx_crtc(crtc
);
235 struct zx_vou_hw
*vou
= zcrtc
->vou
;
236 struct vou_inf
*inf
= &vou_infs
[id
];
237 void __iomem
*dither
= zcrtc
->dither
;
238 void __iomem
*csc
= zcrtc
->chncsc
;
239 bool is_main
= zcrtc
->chn_type
== VOU_CHN_MAIN
;
240 u32 data_sel_shift
= id
<< 1;
242 if (inf
->data_sel
!= VOU_YUV444
) {
243 /* Enable channel CSC for RGB output */
244 zx_writel_mask(csc
+ CSC_CTRL0
, CSC_COV_MODE_MASK
,
245 CSC_BT709_IMAGE_YCBCR2RGB
<< CSC_COV_MODE_SHIFT
);
246 zx_writel_mask(csc
+ CSC_CTRL0
, CSC_WORK_ENABLE
,
249 /* Bypass Dither block for RGB output */
250 zx_writel_mask(dither
+ OSD_DITHER_CTRL0
, DITHER_BYSPASS
,
253 zx_writel_mask(csc
+ CSC_CTRL0
, CSC_WORK_ENABLE
, 0);
254 zx_writel_mask(dither
+ OSD_DITHER_CTRL0
, DITHER_BYSPASS
, 0);
257 /* Select data format */
258 zx_writel_mask(vou
->vouctl
+ VOU_INF_DATA_SEL
, 0x3 << data_sel_shift
,
259 inf
->data_sel
<< data_sel_shift
);
262 zx_writel_mask(vou
->vouctl
+ VOU_INF_CH_SEL
, 0x1 << id
,
263 zcrtc
->chn_type
<< id
);
265 /* Select interface clocks */
266 zx_writel_mask(vou
->vouctl
+ VOU_CLK_SEL
, inf
->clocks_sel_bits
,
267 is_main
? 0 : inf
->clocks_sel_bits
);
269 /* Enable interface clocks */
270 zx_writel_mask(vou
->vouctl
+ VOU_CLK_EN
, inf
->clocks_en_bits
,
271 inf
->clocks_en_bits
);
273 /* Enable the device */
274 zx_writel_mask(vou
->vouctl
+ VOU_INF_EN
, 1 << id
, 1 << id
);
277 void vou_inf_disable(enum vou_inf_id id
, struct drm_crtc
*crtc
)
279 struct zx_vou_hw
*vou
= crtc_to_vou(crtc
);
280 struct vou_inf
*inf
= &vou_infs
[id
];
282 /* Disable the device */
283 zx_writel_mask(vou
->vouctl
+ VOU_INF_EN
, 1 << id
, 0);
285 /* Disable interface clocks */
286 zx_writel_mask(vou
->vouctl
+ VOU_CLK_EN
, inf
->clocks_en_bits
, 0);
289 void zx_vou_config_dividers(struct drm_crtc
*crtc
,
290 struct vou_div_config
*configs
, int num
)
292 struct zx_crtc
*zcrtc
= to_zx_crtc(crtc
);
293 struct zx_vou_hw
*vou
= zcrtc
->vou
;
294 const struct zx_crtc_bits
*bits
= zcrtc
->bits
;
297 /* Clear update flag bit */
298 zx_writel_mask(vou
->vouctl
+ VOU_DIV_PARA
, DIV_PARA_UPDATE
, 0);
300 for (i
= 0; i
< num
; i
++) {
301 struct vou_div_config
*cfg
= configs
+ i
;
307 shift
= bits
->div_vga_shift
;
311 shift
= bits
->div_pic_shift
;
315 shift
= bits
->div_tvenc_shift
;
317 case VOU_DIV_HDMI_PNX
:
319 shift
= bits
->div_hdmi_pnx_shift
;
323 shift
= bits
->div_hdmi_shift
;
327 shift
= bits
->div_inf_shift
;
331 shift
= bits
->div_layer_shift
;
337 /* Each divider occupies 3 bits */
338 zx_writel_mask(vou
->vouctl
+ reg
, 0x7 << shift
,
342 /* Set update flag bit to get dividers effected */
343 zx_writel_mask(vou
->vouctl
+ VOU_DIV_PARA
, DIV_PARA_UPDATE
,
347 static inline void vou_chn_set_update(struct zx_crtc
*zcrtc
)
349 zx_writel(zcrtc
->chnreg
+ CHN_UPDATE
, 1);
352 static void zx_crtc_atomic_enable(struct drm_crtc
*crtc
,
353 struct drm_atomic_state
*state
)
355 struct drm_display_mode
*mode
= &crtc
->state
->adjusted_mode
;
356 bool interlaced
= mode
->flags
& DRM_MODE_FLAG_INTERLACE
;
357 struct zx_crtc
*zcrtc
= to_zx_crtc(crtc
);
358 struct zx_vou_hw
*vou
= zcrtc
->vou
;
359 const struct zx_crtc_regs
*regs
= zcrtc
->regs
;
360 const struct zx_crtc_bits
*bits
= zcrtc
->bits
;
367 drm_display_mode_to_videomode(mode
, &vm
);
369 /* Set up timing parameters */
370 val
= V_ACTIVE((interlaced
? vm
.vactive
/ 2 : vm
.vactive
) - 1);
371 val
|= H_ACTIVE(vm
.hactive
- 1);
372 zx_writel(vou
->timing
+ regs
->fir_active
, val
);
374 val
= SYNC_WIDE(vm
.hsync_len
- 1);
375 val
|= BACK_PORCH(vm
.hback_porch
- 1);
376 val
|= FRONT_PORCH(vm
.hfront_porch
- 1);
377 zx_writel(vou
->timing
+ regs
->fir_htiming
, val
);
379 val
= SYNC_WIDE(vm
.vsync_len
- 1);
380 val
|= BACK_PORCH(vm
.vback_porch
- 1);
381 val
|= FRONT_PORCH(vm
.vfront_porch
- 1);
382 zx_writel(vou
->timing
+ regs
->fir_vtiming
, val
);
385 u32 shift
= bits
->sec_vactive_shift
;
386 u32 mask
= bits
->sec_vactive_mask
;
388 val
= zx_readl(vou
->timing
+ SEC_V_ACTIVE
);
390 val
|= ((vm
.vactive
/ 2 - 1) << shift
) & mask
;
391 zx_writel(vou
->timing
+ SEC_V_ACTIVE
, val
);
393 val
= SYNC_WIDE(vm
.vsync_len
- 1);
395 * The vback_porch for the second field needs to shift one on
396 * the value for the first field.
398 val
|= BACK_PORCH(vm
.vback_porch
);
399 val
|= FRONT_PORCH(vm
.vfront_porch
- 1);
400 zx_writel(vou
->timing
+ regs
->sec_vtiming
, val
);
403 /* Set up polarities */
404 if (vm
.flags
& DISPLAY_FLAGS_VSYNC_LOW
)
405 pol
|= 1 << POL_VSYNC_SHIFT
;
406 if (vm
.flags
& DISPLAY_FLAGS_HSYNC_LOW
)
407 pol
|= 1 << POL_HSYNC_SHIFT
;
409 zx_writel_mask(vou
->timing
+ TIMING_CTRL
, bits
->polarity_mask
,
410 pol
<< bits
->polarity_shift
);
412 /* Setup SHIFT register by following what ZTE BSP does */
415 val
|= V_SHIFT_VAL
<< 16;
416 zx_writel(vou
->timing
+ regs
->timing_shift
, val
);
417 zx_writel(vou
->timing
+ regs
->timing_pi_shift
, H_PI_SHIFT_VAL
);
419 /* Progressive or interlace scan select */
420 scan_mask
= bits
->interlace_select
| bits
->pi_enable
;
421 zx_writel_mask(vou
->timing
+ SCAN_CTRL
, scan_mask
,
422 interlaced
? scan_mask
: 0);
424 /* Enable TIMING_CTRL */
425 zx_writel_mask(vou
->timing
+ TIMING_TC_ENABLE
, bits
->tc_enable
,
428 /* Configure channel screen size */
429 zx_writel_mask(zcrtc
->chnreg
+ CHN_CTRL1
, CHN_SCREEN_W_MASK
,
430 vm
.hactive
<< CHN_SCREEN_W_SHIFT
);
431 zx_writel_mask(zcrtc
->chnreg
+ CHN_CTRL1
, CHN_SCREEN_H_MASK
,
432 vm
.vactive
<< CHN_SCREEN_H_SHIFT
);
434 /* Configure channel interlace buffer control */
435 zx_writel_mask(zcrtc
->chnreg
+ CHN_INTERLACE_BUF_CTRL
, CHN_INTERLACE_EN
,
436 interlaced
? CHN_INTERLACE_EN
: 0);
439 vou_chn_set_update(zcrtc
);
442 zx_writel_mask(zcrtc
->chnreg
+ CHN_CTRL0
, CHN_ENABLE
, CHN_ENABLE
);
444 drm_crtc_vblank_on(crtc
);
446 ret
= clk_set_rate(zcrtc
->pixclk
, mode
->clock
* 1000);
448 DRM_DEV_ERROR(vou
->dev
, "failed to set pixclk rate: %d\n", ret
);
452 ret
= clk_prepare_enable(zcrtc
->pixclk
);
454 DRM_DEV_ERROR(vou
->dev
, "failed to enable pixclk: %d\n", ret
);
457 static void zx_crtc_atomic_disable(struct drm_crtc
*crtc
,
458 struct drm_atomic_state
*state
)
460 struct zx_crtc
*zcrtc
= to_zx_crtc(crtc
);
461 const struct zx_crtc_bits
*bits
= zcrtc
->bits
;
462 struct zx_vou_hw
*vou
= zcrtc
->vou
;
464 clk_disable_unprepare(zcrtc
->pixclk
);
466 drm_crtc_vblank_off(crtc
);
468 /* Disable channel */
469 zx_writel_mask(zcrtc
->chnreg
+ CHN_CTRL0
, CHN_ENABLE
, 0);
471 /* Disable TIMING_CTRL */
472 zx_writel_mask(vou
->timing
+ TIMING_TC_ENABLE
, bits
->tc_enable
, 0);
475 static void zx_crtc_atomic_flush(struct drm_crtc
*crtc
,
476 struct drm_atomic_state
*state
)
478 struct drm_pending_vblank_event
*event
= crtc
->state
->event
;
483 crtc
->state
->event
= NULL
;
485 spin_lock_irq(&crtc
->dev
->event_lock
);
486 if (drm_crtc_vblank_get(crtc
) == 0)
487 drm_crtc_arm_vblank_event(crtc
, event
);
489 drm_crtc_send_vblank_event(crtc
, event
);
490 spin_unlock_irq(&crtc
->dev
->event_lock
);
493 static const struct drm_crtc_helper_funcs zx_crtc_helper_funcs
= {
494 .atomic_flush
= zx_crtc_atomic_flush
,
495 .atomic_enable
= zx_crtc_atomic_enable
,
496 .atomic_disable
= zx_crtc_atomic_disable
,
499 static int zx_vou_enable_vblank(struct drm_crtc
*crtc
)
501 struct zx_crtc
*zcrtc
= to_zx_crtc(crtc
);
502 struct zx_vou_hw
*vou
= crtc_to_vou(crtc
);
503 u32 int_frame_mask
= zcrtc
->bits
->int_frame_mask
;
505 zx_writel_mask(vou
->timing
+ TIMING_INT_CTRL
, int_frame_mask
,
511 static void zx_vou_disable_vblank(struct drm_crtc
*crtc
)
513 struct zx_crtc
*zcrtc
= to_zx_crtc(crtc
);
514 struct zx_vou_hw
*vou
= crtc_to_vou(crtc
);
516 zx_writel_mask(vou
->timing
+ TIMING_INT_CTRL
,
517 zcrtc
->bits
->int_frame_mask
, 0);
520 static const struct drm_crtc_funcs zx_crtc_funcs
= {
521 .destroy
= drm_crtc_cleanup
,
522 .set_config
= drm_atomic_helper_set_config
,
523 .page_flip
= drm_atomic_helper_page_flip
,
524 .reset
= drm_atomic_helper_crtc_reset
,
525 .atomic_duplicate_state
= drm_atomic_helper_crtc_duplicate_state
,
526 .atomic_destroy_state
= drm_atomic_helper_crtc_destroy_state
,
527 .enable_vblank
= zx_vou_enable_vblank
,
528 .disable_vblank
= zx_vou_disable_vblank
,
531 static int zx_crtc_init(struct drm_device
*drm
, struct zx_vou_hw
*vou
,
532 enum vou_chn_type chn_type
)
534 struct device
*dev
= vou
->dev
;
535 struct zx_plane
*zplane
;
536 struct zx_crtc
*zcrtc
;
539 zcrtc
= devm_kzalloc(dev
, sizeof(*zcrtc
), GFP_KERNEL
);
544 zcrtc
->chn_type
= chn_type
;
546 zplane
= devm_kzalloc(dev
, sizeof(*zplane
), GFP_KERNEL
);
552 if (chn_type
== VOU_CHN_MAIN
) {
553 zplane
->layer
= vou
->osd
+ MAIN_GL_OFFSET
;
554 zplane
->csc
= vou
->osd
+ MAIN_GL_CSC_OFFSET
;
555 zplane
->hbsc
= vou
->osd
+ MAIN_HBSC_OFFSET
;
556 zplane
->rsz
= vou
->otfppu
+ MAIN_RSZ_OFFSET
;
557 zplane
->bits
= &zx_gl_bits
[0];
558 zcrtc
->chnreg
= vou
->osd
+ OSD_MAIN_CHN
;
559 zcrtc
->chncsc
= vou
->osd
+ MAIN_CHN_CSC_OFFSET
;
560 zcrtc
->dither
= vou
->osd
+ MAIN_DITHER_OFFSET
;
561 zcrtc
->regs
= &main_crtc_regs
;
562 zcrtc
->bits
= &main_crtc_bits
;
564 zplane
->layer
= vou
->osd
+ AUX_GL_OFFSET
;
565 zplane
->csc
= vou
->osd
+ AUX_GL_CSC_OFFSET
;
566 zplane
->hbsc
= vou
->osd
+ AUX_HBSC_OFFSET
;
567 zplane
->rsz
= vou
->otfppu
+ AUX_RSZ_OFFSET
;
568 zplane
->bits
= &zx_gl_bits
[1];
569 zcrtc
->chnreg
= vou
->osd
+ OSD_AUX_CHN
;
570 zcrtc
->chncsc
= vou
->osd
+ AUX_CHN_CSC_OFFSET
;
571 zcrtc
->dither
= vou
->osd
+ AUX_DITHER_OFFSET
;
572 zcrtc
->regs
= &aux_crtc_regs
;
573 zcrtc
->bits
= &aux_crtc_bits
;
576 zcrtc
->pixclk
= devm_clk_get(dev
, (chn_type
== VOU_CHN_MAIN
) ?
577 "main_wclk" : "aux_wclk");
578 if (IS_ERR(zcrtc
->pixclk
)) {
579 ret
= PTR_ERR(zcrtc
->pixclk
);
580 DRM_DEV_ERROR(dev
, "failed to get pix clk: %d\n", ret
);
584 ret
= zx_plane_init(drm
, zplane
, DRM_PLANE_TYPE_PRIMARY
);
586 DRM_DEV_ERROR(dev
, "failed to init primary plane: %d\n", ret
);
590 zcrtc
->primary
= &zplane
->plane
;
592 ret
= drm_crtc_init_with_planes(drm
, &zcrtc
->crtc
, zcrtc
->primary
, NULL
,
593 &zx_crtc_funcs
, NULL
);
595 DRM_DEV_ERROR(dev
, "failed to init drm crtc: %d\n", ret
);
599 drm_crtc_helper_add(&zcrtc
->crtc
, &zx_crtc_helper_funcs
);
601 if (chn_type
== VOU_CHN_MAIN
)
602 vou
->main_crtc
= zcrtc
;
604 vou
->aux_crtc
= zcrtc
;
609 void zx_vou_layer_enable(struct drm_plane
*plane
)
611 struct zx_crtc
*zcrtc
= to_zx_crtc(plane
->state
->crtc
);
612 struct zx_vou_hw
*vou
= zcrtc
->vou
;
613 struct zx_plane
*zplane
= to_zx_plane(plane
);
614 const struct vou_layer_bits
*bits
= zplane
->bits
;
616 if (zcrtc
->chn_type
== VOU_CHN_MAIN
) {
617 zx_writel_mask(vou
->osd
+ OSD_CTRL0
, bits
->chnsel
, 0);
618 zx_writel_mask(vou
->vouctl
+ VOU_CLK_SEL
, bits
->clksel
, 0);
620 zx_writel_mask(vou
->osd
+ OSD_CTRL0
, bits
->chnsel
,
622 zx_writel_mask(vou
->vouctl
+ VOU_CLK_SEL
, bits
->clksel
,
626 zx_writel_mask(vou
->osd
+ OSD_CTRL0
, bits
->enable
, bits
->enable
);
629 void zx_vou_layer_disable(struct drm_plane
*plane
,
630 struct drm_plane_state
*old_state
)
632 struct zx_crtc
*zcrtc
= to_zx_crtc(old_state
->crtc
);
633 struct zx_vou_hw
*vou
= zcrtc
->vou
;
634 struct zx_plane
*zplane
= to_zx_plane(plane
);
635 const struct vou_layer_bits
*bits
= zplane
->bits
;
637 zx_writel_mask(vou
->osd
+ OSD_CTRL0
, bits
->enable
, 0);
640 static void zx_overlay_init(struct drm_device
*drm
, struct zx_vou_hw
*vou
)
642 struct device
*dev
= vou
->dev
;
643 struct zx_plane
*zplane
;
648 * VL0 has some quirks on scaling support which need special handling.
649 * Let's leave it out for now.
651 for (i
= 1; i
< VL_NUM
; i
++) {
652 zplane
= devm_kzalloc(dev
, sizeof(*zplane
), GFP_KERNEL
);
654 DRM_DEV_ERROR(dev
, "failed to allocate zplane %d\n", i
);
658 zplane
->layer
= vou
->osd
+ OSD_VL_OFFSET(i
);
659 zplane
->hbsc
= vou
->osd
+ HBSC_VL_OFFSET(i
);
660 zplane
->rsz
= vou
->otfppu
+ RSZ_VL_OFFSET(i
);
661 zplane
->bits
= &zx_vl_bits
[i
];
663 ret
= zx_plane_init(drm
, zplane
, DRM_PLANE_TYPE_OVERLAY
);
665 DRM_DEV_ERROR(dev
, "failed to init overlay %d\n", i
);
671 static inline void zx_osd_int_update(struct zx_crtc
*zcrtc
)
673 struct drm_crtc
*crtc
= &zcrtc
->crtc
;
674 struct drm_plane
*plane
;
676 vou_chn_set_update(zcrtc
);
678 drm_for_each_plane_mask(plane
, crtc
->dev
, crtc
->state
->plane_mask
)
679 zx_plane_set_update(plane
);
682 static irqreturn_t
vou_irq_handler(int irq
, void *dev_id
)
684 struct zx_vou_hw
*vou
= dev_id
;
687 /* Handle TIMING_CTRL frame interrupts */
688 state
= zx_readl(vou
->timing
+ TIMING_INT_STATE
);
689 zx_writel(vou
->timing
+ TIMING_INT_STATE
, state
);
691 if (state
& TIMING_INT_MAIN_FRAME
)
692 drm_crtc_handle_vblank(&vou
->main_crtc
->crtc
);
694 if (state
& TIMING_INT_AUX_FRAME
)
695 drm_crtc_handle_vblank(&vou
->aux_crtc
->crtc
);
697 /* Handle OSD interrupts */
698 state
= zx_readl(vou
->osd
+ OSD_INT_STA
);
699 zx_writel(vou
->osd
+ OSD_INT_CLRSTA
, state
);
701 if (state
& OSD_INT_MAIN_UPT
)
702 zx_osd_int_update(vou
->main_crtc
);
704 if (state
& OSD_INT_AUX_UPT
)
705 zx_osd_int_update(vou
->aux_crtc
);
707 if (state
& OSD_INT_ERROR
)
708 DRM_DEV_ERROR(vou
->dev
, "OSD ERROR: 0x%08x!\n", state
);
713 static void vou_dtrc_init(struct zx_vou_hw
*vou
)
715 /* Clear bit for bypass by ID */
716 zx_writel_mask(vou
->dtrc
+ DTRC_DETILE_CTRL
,
717 TILE2RASTESCAN_BYPASS_MODE
, 0);
719 /* Select ARIDR mode */
720 zx_writel_mask(vou
->dtrc
+ DTRC_DETILE_CTRL
, DETILE_ARIDR_MODE_MASK
,
721 DETILE_ARID_IN_ARIDR
);
723 /* Bypass decompression for both frames */
724 zx_writel_mask(vou
->dtrc
+ DTRC_F0_CTRL
, DTRC_DECOMPRESS_BYPASS
,
725 DTRC_DECOMPRESS_BYPASS
);
726 zx_writel_mask(vou
->dtrc
+ DTRC_F1_CTRL
, DTRC_DECOMPRESS_BYPASS
,
727 DTRC_DECOMPRESS_BYPASS
);
729 /* Set up ARID register */
730 zx_writel(vou
->dtrc
+ DTRC_ARID
, DTRC_ARID3(0xf) | DTRC_ARID2(0xe) |
731 DTRC_ARID1(0xf) | DTRC_ARID0(0xe));
734 static void vou_hw_init(struct zx_vou_hw
*vou
)
736 /* Release reset for all VOU modules */
737 zx_writel(vou
->vouctl
+ VOU_SOFT_RST
, ~0);
739 /* Enable all VOU module clocks */
740 zx_writel(vou
->vouctl
+ VOU_CLK_EN
, ~0);
742 /* Clear both OSD and TIMING_CTRL interrupt state */
743 zx_writel(vou
->osd
+ OSD_INT_CLRSTA
, ~0);
744 zx_writel(vou
->timing
+ TIMING_INT_STATE
, ~0);
746 /* Enable OSD and TIMING_CTRL interrrupts */
747 zx_writel(vou
->osd
+ OSD_INT_MSK
, OSD_INT_ENABLE
);
748 zx_writel(vou
->timing
+ TIMING_INT_CTRL
, TIMING_INT_ENABLE
);
750 /* Select GPC as input to gl/vl scaler as a sane default setting */
751 zx_writel(vou
->otfppu
+ OTFPPU_RSZ_DATA_SOURCE
, 0x2a);
754 * Needs to reset channel and layer logic per frame when frame starts
755 * to get VOU work properly.
757 zx_writel_mask(vou
->osd
+ OSD_RST_CLR
, RST_PER_FRAME
, RST_PER_FRAME
);
762 static int zx_crtc_bind(struct device
*dev
, struct device
*master
, void *data
)
764 struct platform_device
*pdev
= to_platform_device(dev
);
765 struct drm_device
*drm
= data
;
766 struct zx_vou_hw
*vou
;
767 struct resource
*res
;
771 vou
= devm_kzalloc(dev
, sizeof(*vou
), GFP_KERNEL
);
775 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "osd");
776 vou
->osd
= devm_ioremap_resource(dev
, res
);
777 if (IS_ERR(vou
->osd
)) {
778 ret
= PTR_ERR(vou
->osd
);
779 DRM_DEV_ERROR(dev
, "failed to remap osd region: %d\n", ret
);
783 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "timing_ctrl");
784 vou
->timing
= devm_ioremap_resource(dev
, res
);
785 if (IS_ERR(vou
->timing
)) {
786 ret
= PTR_ERR(vou
->timing
);
787 DRM_DEV_ERROR(dev
, "failed to remap timing_ctrl region: %d\n",
792 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "dtrc");
793 vou
->dtrc
= devm_ioremap_resource(dev
, res
);
794 if (IS_ERR(vou
->dtrc
)) {
795 ret
= PTR_ERR(vou
->dtrc
);
796 DRM_DEV_ERROR(dev
, "failed to remap dtrc region: %d\n", ret
);
800 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "vou_ctrl");
801 vou
->vouctl
= devm_ioremap_resource(dev
, res
);
802 if (IS_ERR(vou
->vouctl
)) {
803 ret
= PTR_ERR(vou
->vouctl
);
804 DRM_DEV_ERROR(dev
, "failed to remap vou_ctrl region: %d\n",
809 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "otfppu");
810 vou
->otfppu
= devm_ioremap_resource(dev
, res
);
811 if (IS_ERR(vou
->otfppu
)) {
812 ret
= PTR_ERR(vou
->otfppu
);
813 DRM_DEV_ERROR(dev
, "failed to remap otfppu region: %d\n", ret
);
817 irq
= platform_get_irq(pdev
, 0);
821 vou
->axi_clk
= devm_clk_get(dev
, "aclk");
822 if (IS_ERR(vou
->axi_clk
)) {
823 ret
= PTR_ERR(vou
->axi_clk
);
824 DRM_DEV_ERROR(dev
, "failed to get axi_clk: %d\n", ret
);
828 vou
->ppu_clk
= devm_clk_get(dev
, "ppu_wclk");
829 if (IS_ERR(vou
->ppu_clk
)) {
830 ret
= PTR_ERR(vou
->ppu_clk
);
831 DRM_DEV_ERROR(dev
, "failed to get ppu_clk: %d\n", ret
);
835 ret
= clk_prepare_enable(vou
->axi_clk
);
837 DRM_DEV_ERROR(dev
, "failed to enable axi_clk: %d\n", ret
);
841 clk_prepare_enable(vou
->ppu_clk
);
843 DRM_DEV_ERROR(dev
, "failed to enable ppu_clk: %d\n", ret
);
844 goto disable_axi_clk
;
848 dev_set_drvdata(dev
, vou
);
852 ret
= devm_request_irq(dev
, irq
, vou_irq_handler
, 0, "zx_vou", vou
);
854 DRM_DEV_ERROR(dev
, "failed to request vou irq: %d\n", ret
);
855 goto disable_ppu_clk
;
858 ret
= zx_crtc_init(drm
, vou
, VOU_CHN_MAIN
);
860 DRM_DEV_ERROR(dev
, "failed to init main channel crtc: %d\n",
862 goto disable_ppu_clk
;
865 ret
= zx_crtc_init(drm
, vou
, VOU_CHN_AUX
);
867 DRM_DEV_ERROR(dev
, "failed to init aux channel crtc: %d\n",
869 goto disable_ppu_clk
;
872 zx_overlay_init(drm
, vou
);
877 clk_disable_unprepare(vou
->ppu_clk
);
879 clk_disable_unprepare(vou
->axi_clk
);
883 static void zx_crtc_unbind(struct device
*dev
, struct device
*master
,
886 struct zx_vou_hw
*vou
= dev_get_drvdata(dev
);
888 clk_disable_unprepare(vou
->axi_clk
);
889 clk_disable_unprepare(vou
->ppu_clk
);
892 static const struct component_ops zx_crtc_component_ops
= {
893 .bind
= zx_crtc_bind
,
894 .unbind
= zx_crtc_unbind
,
897 static int zx_crtc_probe(struct platform_device
*pdev
)
899 return component_add(&pdev
->dev
, &zx_crtc_component_ops
);
902 static int zx_crtc_remove(struct platform_device
*pdev
)
904 component_del(&pdev
->dev
, &zx_crtc_component_ops
);
908 static const struct of_device_id zx_crtc_of_match
[] = {
909 { .compatible
= "zte,zx296718-dpc", },
912 MODULE_DEVICE_TABLE(of
, zx_crtc_of_match
);
914 struct platform_driver zx_crtc_driver
= {
915 .probe
= zx_crtc_probe
,
916 .remove
= zx_crtc_remove
,
919 .of_match_table
= zx_crtc_of_match
,