2 * Copyright 2016 Linaro Ltd.
3 * Copyright 2016 ZTE Corporation.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
11 #include <linux/clk.h>
12 #include <linux/component.h>
13 #include <linux/of_address.h>
14 #include <video/videomode.h>
16 #include <drm/drm_atomic_helper.h>
17 #include <drm/drm_crtc.h>
18 #include <drm/drm_fb_cma_helper.h>
19 #include <drm/drm_fb_helper.h>
20 #include <drm/drm_gem_cma_helper.h>
21 #include <drm/drm_of.h>
22 #include <drm/drm_plane_helper.h>
23 #include <drm/drm_probe_helper.h>
26 #include "zx_common_regs.h"
27 #include "zx_drm_drv.h"
30 #include "zx_vou_regs.h"
49 static const struct zx_crtc_regs main_crtc_regs
= {
50 .fir_active
= FIR_MAIN_ACTIVE
,
51 .fir_htiming
= FIR_MAIN_H_TIMING
,
52 .fir_vtiming
= FIR_MAIN_V_TIMING
,
53 .sec_vtiming
= SEC_MAIN_V_TIMING
,
54 .timing_shift
= TIMING_MAIN_SHIFT
,
55 .timing_pi_shift
= TIMING_MAIN_PI_SHIFT
,
58 static const struct zx_crtc_regs aux_crtc_regs
= {
59 .fir_active
= FIR_AUX_ACTIVE
,
60 .fir_htiming
= FIR_AUX_H_TIMING
,
61 .fir_vtiming
= FIR_AUX_V_TIMING
,
62 .sec_vtiming
= SEC_AUX_V_TIMING
,
63 .timing_shift
= TIMING_AUX_SHIFT
,
64 .timing_pi_shift
= TIMING_AUX_PI_SHIFT
,
72 u32 sec_vactive_shift
;
79 u32 div_hdmi_pnx_shift
;
85 static const struct zx_crtc_bits main_crtc_bits
= {
86 .polarity_mask
= MAIN_POL_MASK
,
87 .polarity_shift
= MAIN_POL_SHIFT
,
88 .int_frame_mask
= TIMING_INT_MAIN_FRAME
,
89 .tc_enable
= MAIN_TC_EN
,
90 .sec_vactive_shift
= SEC_VACT_MAIN_SHIFT
,
91 .sec_vactive_mask
= SEC_VACT_MAIN_MASK
,
92 .interlace_select
= MAIN_INTERLACE_SEL
,
93 .pi_enable
= MAIN_PI_EN
,
94 .div_vga_shift
= VGA_MAIN_DIV_SHIFT
,
95 .div_pic_shift
= PIC_MAIN_DIV_SHIFT
,
96 .div_tvenc_shift
= TVENC_MAIN_DIV_SHIFT
,
97 .div_hdmi_pnx_shift
= HDMI_MAIN_PNX_DIV_SHIFT
,
98 .div_hdmi_shift
= HDMI_MAIN_DIV_SHIFT
,
99 .div_inf_shift
= INF_MAIN_DIV_SHIFT
,
100 .div_layer_shift
= LAYER_MAIN_DIV_SHIFT
,
103 static const struct zx_crtc_bits aux_crtc_bits
= {
104 .polarity_mask
= AUX_POL_MASK
,
105 .polarity_shift
= AUX_POL_SHIFT
,
106 .int_frame_mask
= TIMING_INT_AUX_FRAME
,
107 .tc_enable
= AUX_TC_EN
,
108 .sec_vactive_shift
= SEC_VACT_AUX_SHIFT
,
109 .sec_vactive_mask
= SEC_VACT_AUX_MASK
,
110 .interlace_select
= AUX_INTERLACE_SEL
,
111 .pi_enable
= AUX_PI_EN
,
112 .div_vga_shift
= VGA_AUX_DIV_SHIFT
,
113 .div_pic_shift
= PIC_AUX_DIV_SHIFT
,
114 .div_tvenc_shift
= TVENC_AUX_DIV_SHIFT
,
115 .div_hdmi_pnx_shift
= HDMI_AUX_PNX_DIV_SHIFT
,
116 .div_hdmi_shift
= HDMI_AUX_DIV_SHIFT
,
117 .div_inf_shift
= INF_AUX_DIV_SHIFT
,
118 .div_layer_shift
= LAYER_AUX_DIV_SHIFT
,
122 struct drm_crtc crtc
;
123 struct drm_plane
*primary
;
124 struct zx_vou_hw
*vou
;
125 void __iomem
*chnreg
;
126 void __iomem
*chncsc
;
127 void __iomem
*dither
;
128 const struct zx_crtc_regs
*regs
;
129 const struct zx_crtc_bits
*bits
;
130 enum vou_chn_type chn_type
;
134 #define to_zx_crtc(x) container_of(x, struct zx_crtc, crtc)
136 struct vou_layer_bits
{
142 static const struct vou_layer_bits zx_gl_bits
[GL_NUM
] = {
144 .enable
= OSD_CTRL0_GL0_EN
,
145 .chnsel
= OSD_CTRL0_GL0_SEL
,
146 .clksel
= VOU_CLK_GL0_SEL
,
148 .enable
= OSD_CTRL0_GL1_EN
,
149 .chnsel
= OSD_CTRL0_GL1_SEL
,
150 .clksel
= VOU_CLK_GL1_SEL
,
154 static const struct vou_layer_bits zx_vl_bits
[VL_NUM
] = {
156 .enable
= OSD_CTRL0_VL0_EN
,
157 .chnsel
= OSD_CTRL0_VL0_SEL
,
158 .clksel
= VOU_CLK_VL0_SEL
,
160 .enable
= OSD_CTRL0_VL1_EN
,
161 .chnsel
= OSD_CTRL0_VL1_SEL
,
162 .clksel
= VOU_CLK_VL1_SEL
,
164 .enable
= OSD_CTRL0_VL2_EN
,
165 .chnsel
= OSD_CTRL0_VL2_SEL
,
166 .clksel
= VOU_CLK_VL2_SEL
,
173 void __iomem
*timing
;
174 void __iomem
*vouctl
;
175 void __iomem
*otfppu
;
179 struct clk
*main_clk
;
181 struct zx_crtc
*main_crtc
;
182 struct zx_crtc
*aux_crtc
;
185 enum vou_inf_data_sel
{
194 enum vou_inf_data_sel data_sel
;
199 static struct vou_inf vou_infs
[] = {
201 .data_sel
= VOU_YUV444
,
202 .clocks_en_bits
= BIT(24) | BIT(18) | BIT(6),
203 .clocks_sel_bits
= BIT(13) | BIT(2),
206 .data_sel
= VOU_YUV444
,
207 .clocks_en_bits
= BIT(15),
208 .clocks_sel_bits
= BIT(11) | BIT(0),
211 .data_sel
= VOU_RGB_888
,
212 .clocks_en_bits
= BIT(1),
213 .clocks_sel_bits
= BIT(10),
217 static inline struct zx_vou_hw
*crtc_to_vou(struct drm_crtc
*crtc
)
219 struct zx_crtc
*zcrtc
= to_zx_crtc(crtc
);
224 void vou_inf_hdmi_audio_sel(struct drm_crtc
*crtc
,
225 enum vou_inf_hdmi_audio aud
)
227 struct zx_crtc
*zcrtc
= to_zx_crtc(crtc
);
228 struct zx_vou_hw
*vou
= zcrtc
->vou
;
230 zx_writel_mask(vou
->vouctl
+ VOU_INF_HDMI_CTRL
, VOU_HDMI_AUD_MASK
, aud
);
233 void vou_inf_enable(enum vou_inf_id id
, struct drm_crtc
*crtc
)
235 struct zx_crtc
*zcrtc
= to_zx_crtc(crtc
);
236 struct zx_vou_hw
*vou
= zcrtc
->vou
;
237 struct vou_inf
*inf
= &vou_infs
[id
];
238 void __iomem
*dither
= zcrtc
->dither
;
239 void __iomem
*csc
= zcrtc
->chncsc
;
240 bool is_main
= zcrtc
->chn_type
== VOU_CHN_MAIN
;
241 u32 data_sel_shift
= id
<< 1;
243 if (inf
->data_sel
!= VOU_YUV444
) {
244 /* Enable channel CSC for RGB output */
245 zx_writel_mask(csc
+ CSC_CTRL0
, CSC_COV_MODE_MASK
,
246 CSC_BT709_IMAGE_YCBCR2RGB
<< CSC_COV_MODE_SHIFT
);
247 zx_writel_mask(csc
+ CSC_CTRL0
, CSC_WORK_ENABLE
,
250 /* Bypass Dither block for RGB output */
251 zx_writel_mask(dither
+ OSD_DITHER_CTRL0
, DITHER_BYSPASS
,
254 zx_writel_mask(csc
+ CSC_CTRL0
, CSC_WORK_ENABLE
, 0);
255 zx_writel_mask(dither
+ OSD_DITHER_CTRL0
, DITHER_BYSPASS
, 0);
258 /* Select data format */
259 zx_writel_mask(vou
->vouctl
+ VOU_INF_DATA_SEL
, 0x3 << data_sel_shift
,
260 inf
->data_sel
<< data_sel_shift
);
263 zx_writel_mask(vou
->vouctl
+ VOU_INF_CH_SEL
, 0x1 << id
,
264 zcrtc
->chn_type
<< id
);
266 /* Select interface clocks */
267 zx_writel_mask(vou
->vouctl
+ VOU_CLK_SEL
, inf
->clocks_sel_bits
,
268 is_main
? 0 : inf
->clocks_sel_bits
);
270 /* Enable interface clocks */
271 zx_writel_mask(vou
->vouctl
+ VOU_CLK_EN
, inf
->clocks_en_bits
,
272 inf
->clocks_en_bits
);
274 /* Enable the device */
275 zx_writel_mask(vou
->vouctl
+ VOU_INF_EN
, 1 << id
, 1 << id
);
278 void vou_inf_disable(enum vou_inf_id id
, struct drm_crtc
*crtc
)
280 struct zx_vou_hw
*vou
= crtc_to_vou(crtc
);
281 struct vou_inf
*inf
= &vou_infs
[id
];
283 /* Disable the device */
284 zx_writel_mask(vou
->vouctl
+ VOU_INF_EN
, 1 << id
, 0);
286 /* Disable interface clocks */
287 zx_writel_mask(vou
->vouctl
+ VOU_CLK_EN
, inf
->clocks_en_bits
, 0);
290 void zx_vou_config_dividers(struct drm_crtc
*crtc
,
291 struct vou_div_config
*configs
, int num
)
293 struct zx_crtc
*zcrtc
= to_zx_crtc(crtc
);
294 struct zx_vou_hw
*vou
= zcrtc
->vou
;
295 const struct zx_crtc_bits
*bits
= zcrtc
->bits
;
298 /* Clear update flag bit */
299 zx_writel_mask(vou
->vouctl
+ VOU_DIV_PARA
, DIV_PARA_UPDATE
, 0);
301 for (i
= 0; i
< num
; i
++) {
302 struct vou_div_config
*cfg
= configs
+ i
;
308 shift
= bits
->div_vga_shift
;
312 shift
= bits
->div_pic_shift
;
316 shift
= bits
->div_tvenc_shift
;
318 case VOU_DIV_HDMI_PNX
:
320 shift
= bits
->div_hdmi_pnx_shift
;
324 shift
= bits
->div_hdmi_shift
;
328 shift
= bits
->div_inf_shift
;
332 shift
= bits
->div_layer_shift
;
338 /* Each divider occupies 3 bits */
339 zx_writel_mask(vou
->vouctl
+ reg
, 0x7 << shift
,
343 /* Set update flag bit to get dividers effected */
344 zx_writel_mask(vou
->vouctl
+ VOU_DIV_PARA
, DIV_PARA_UPDATE
,
348 static inline void vou_chn_set_update(struct zx_crtc
*zcrtc
)
350 zx_writel(zcrtc
->chnreg
+ CHN_UPDATE
, 1);
353 static void zx_crtc_atomic_enable(struct drm_crtc
*crtc
,
354 struct drm_crtc_state
*old_state
)
356 struct drm_display_mode
*mode
= &crtc
->state
->adjusted_mode
;
357 bool interlaced
= mode
->flags
& DRM_MODE_FLAG_INTERLACE
;
358 struct zx_crtc
*zcrtc
= to_zx_crtc(crtc
);
359 struct zx_vou_hw
*vou
= zcrtc
->vou
;
360 const struct zx_crtc_regs
*regs
= zcrtc
->regs
;
361 const struct zx_crtc_bits
*bits
= zcrtc
->bits
;
368 drm_display_mode_to_videomode(mode
, &vm
);
370 /* Set up timing parameters */
371 val
= V_ACTIVE((interlaced
? vm
.vactive
/ 2 : vm
.vactive
) - 1);
372 val
|= H_ACTIVE(vm
.hactive
- 1);
373 zx_writel(vou
->timing
+ regs
->fir_active
, val
);
375 val
= SYNC_WIDE(vm
.hsync_len
- 1);
376 val
|= BACK_PORCH(vm
.hback_porch
- 1);
377 val
|= FRONT_PORCH(vm
.hfront_porch
- 1);
378 zx_writel(vou
->timing
+ regs
->fir_htiming
, val
);
380 val
= SYNC_WIDE(vm
.vsync_len
- 1);
381 val
|= BACK_PORCH(vm
.vback_porch
- 1);
382 val
|= FRONT_PORCH(vm
.vfront_porch
- 1);
383 zx_writel(vou
->timing
+ regs
->fir_vtiming
, val
);
386 u32 shift
= bits
->sec_vactive_shift
;
387 u32 mask
= bits
->sec_vactive_mask
;
389 val
= zx_readl(vou
->timing
+ SEC_V_ACTIVE
);
391 val
|= ((vm
.vactive
/ 2 - 1) << shift
) & mask
;
392 zx_writel(vou
->timing
+ SEC_V_ACTIVE
, val
);
394 val
= SYNC_WIDE(vm
.vsync_len
- 1);
396 * The vback_porch for the second field needs to shift one on
397 * the value for the first field.
399 val
|= BACK_PORCH(vm
.vback_porch
);
400 val
|= FRONT_PORCH(vm
.vfront_porch
- 1);
401 zx_writel(vou
->timing
+ regs
->sec_vtiming
, val
);
404 /* Set up polarities */
405 if (vm
.flags
& DISPLAY_FLAGS_VSYNC_LOW
)
406 pol
|= 1 << POL_VSYNC_SHIFT
;
407 if (vm
.flags
& DISPLAY_FLAGS_HSYNC_LOW
)
408 pol
|= 1 << POL_HSYNC_SHIFT
;
410 zx_writel_mask(vou
->timing
+ TIMING_CTRL
, bits
->polarity_mask
,
411 pol
<< bits
->polarity_shift
);
413 /* Setup SHIFT register by following what ZTE BSP does */
416 val
|= V_SHIFT_VAL
<< 16;
417 zx_writel(vou
->timing
+ regs
->timing_shift
, val
);
418 zx_writel(vou
->timing
+ regs
->timing_pi_shift
, H_PI_SHIFT_VAL
);
420 /* Progressive or interlace scan select */
421 scan_mask
= bits
->interlace_select
| bits
->pi_enable
;
422 zx_writel_mask(vou
->timing
+ SCAN_CTRL
, scan_mask
,
423 interlaced
? scan_mask
: 0);
425 /* Enable TIMING_CTRL */
426 zx_writel_mask(vou
->timing
+ TIMING_TC_ENABLE
, bits
->tc_enable
,
429 /* Configure channel screen size */
430 zx_writel_mask(zcrtc
->chnreg
+ CHN_CTRL1
, CHN_SCREEN_W_MASK
,
431 vm
.hactive
<< CHN_SCREEN_W_SHIFT
);
432 zx_writel_mask(zcrtc
->chnreg
+ CHN_CTRL1
, CHN_SCREEN_H_MASK
,
433 vm
.vactive
<< CHN_SCREEN_H_SHIFT
);
435 /* Configure channel interlace buffer control */
436 zx_writel_mask(zcrtc
->chnreg
+ CHN_INTERLACE_BUF_CTRL
, CHN_INTERLACE_EN
,
437 interlaced
? CHN_INTERLACE_EN
: 0);
440 vou_chn_set_update(zcrtc
);
443 zx_writel_mask(zcrtc
->chnreg
+ CHN_CTRL0
, CHN_ENABLE
, CHN_ENABLE
);
445 drm_crtc_vblank_on(crtc
);
447 ret
= clk_set_rate(zcrtc
->pixclk
, mode
->clock
* 1000);
449 DRM_DEV_ERROR(vou
->dev
, "failed to set pixclk rate: %d\n", ret
);
453 ret
= clk_prepare_enable(zcrtc
->pixclk
);
455 DRM_DEV_ERROR(vou
->dev
, "failed to enable pixclk: %d\n", ret
);
458 static void zx_crtc_atomic_disable(struct drm_crtc
*crtc
,
459 struct drm_crtc_state
*old_state
)
461 struct zx_crtc
*zcrtc
= to_zx_crtc(crtc
);
462 const struct zx_crtc_bits
*bits
= zcrtc
->bits
;
463 struct zx_vou_hw
*vou
= zcrtc
->vou
;
465 clk_disable_unprepare(zcrtc
->pixclk
);
467 drm_crtc_vblank_off(crtc
);
469 /* Disable channel */
470 zx_writel_mask(zcrtc
->chnreg
+ CHN_CTRL0
, CHN_ENABLE
, 0);
472 /* Disable TIMING_CTRL */
473 zx_writel_mask(vou
->timing
+ TIMING_TC_ENABLE
, bits
->tc_enable
, 0);
476 static void zx_crtc_atomic_flush(struct drm_crtc
*crtc
,
477 struct drm_crtc_state
*old_state
)
479 struct drm_pending_vblank_event
*event
= crtc
->state
->event
;
484 crtc
->state
->event
= NULL
;
486 spin_lock_irq(&crtc
->dev
->event_lock
);
487 if (drm_crtc_vblank_get(crtc
) == 0)
488 drm_crtc_arm_vblank_event(crtc
, event
);
490 drm_crtc_send_vblank_event(crtc
, event
);
491 spin_unlock_irq(&crtc
->dev
->event_lock
);
494 static const struct drm_crtc_helper_funcs zx_crtc_helper_funcs
= {
495 .atomic_flush
= zx_crtc_atomic_flush
,
496 .atomic_enable
= zx_crtc_atomic_enable
,
497 .atomic_disable
= zx_crtc_atomic_disable
,
500 static int zx_vou_enable_vblank(struct drm_crtc
*crtc
)
502 struct zx_crtc
*zcrtc
= to_zx_crtc(crtc
);
503 struct zx_vou_hw
*vou
= crtc_to_vou(crtc
);
504 u32 int_frame_mask
= zcrtc
->bits
->int_frame_mask
;
506 zx_writel_mask(vou
->timing
+ TIMING_INT_CTRL
, int_frame_mask
,
512 static void zx_vou_disable_vblank(struct drm_crtc
*crtc
)
514 struct zx_crtc
*zcrtc
= to_zx_crtc(crtc
);
515 struct zx_vou_hw
*vou
= crtc_to_vou(crtc
);
517 zx_writel_mask(vou
->timing
+ TIMING_INT_CTRL
,
518 zcrtc
->bits
->int_frame_mask
, 0);
521 static const struct drm_crtc_funcs zx_crtc_funcs
= {
522 .destroy
= drm_crtc_cleanup
,
523 .set_config
= drm_atomic_helper_set_config
,
524 .page_flip
= drm_atomic_helper_page_flip
,
525 .reset
= drm_atomic_helper_crtc_reset
,
526 .atomic_duplicate_state
= drm_atomic_helper_crtc_duplicate_state
,
527 .atomic_destroy_state
= drm_atomic_helper_crtc_destroy_state
,
528 .enable_vblank
= zx_vou_enable_vblank
,
529 .disable_vblank
= zx_vou_disable_vblank
,
532 static int zx_crtc_init(struct drm_device
*drm
, struct zx_vou_hw
*vou
,
533 enum vou_chn_type chn_type
)
535 struct device
*dev
= vou
->dev
;
536 struct zx_plane
*zplane
;
537 struct zx_crtc
*zcrtc
;
540 zcrtc
= devm_kzalloc(dev
, sizeof(*zcrtc
), GFP_KERNEL
);
545 zcrtc
->chn_type
= chn_type
;
547 zplane
= devm_kzalloc(dev
, sizeof(*zplane
), GFP_KERNEL
);
553 if (chn_type
== VOU_CHN_MAIN
) {
554 zplane
->layer
= vou
->osd
+ MAIN_GL_OFFSET
;
555 zplane
->csc
= vou
->osd
+ MAIN_GL_CSC_OFFSET
;
556 zplane
->hbsc
= vou
->osd
+ MAIN_HBSC_OFFSET
;
557 zplane
->rsz
= vou
->otfppu
+ MAIN_RSZ_OFFSET
;
558 zplane
->bits
= &zx_gl_bits
[0];
559 zcrtc
->chnreg
= vou
->osd
+ OSD_MAIN_CHN
;
560 zcrtc
->chncsc
= vou
->osd
+ MAIN_CHN_CSC_OFFSET
;
561 zcrtc
->dither
= vou
->osd
+ MAIN_DITHER_OFFSET
;
562 zcrtc
->regs
= &main_crtc_regs
;
563 zcrtc
->bits
= &main_crtc_bits
;
565 zplane
->layer
= vou
->osd
+ AUX_GL_OFFSET
;
566 zplane
->csc
= vou
->osd
+ AUX_GL_CSC_OFFSET
;
567 zplane
->hbsc
= vou
->osd
+ AUX_HBSC_OFFSET
;
568 zplane
->rsz
= vou
->otfppu
+ AUX_RSZ_OFFSET
;
569 zplane
->bits
= &zx_gl_bits
[1];
570 zcrtc
->chnreg
= vou
->osd
+ OSD_AUX_CHN
;
571 zcrtc
->chncsc
= vou
->osd
+ AUX_CHN_CSC_OFFSET
;
572 zcrtc
->dither
= vou
->osd
+ AUX_DITHER_OFFSET
;
573 zcrtc
->regs
= &aux_crtc_regs
;
574 zcrtc
->bits
= &aux_crtc_bits
;
577 zcrtc
->pixclk
= devm_clk_get(dev
, (chn_type
== VOU_CHN_MAIN
) ?
578 "main_wclk" : "aux_wclk");
579 if (IS_ERR(zcrtc
->pixclk
)) {
580 ret
= PTR_ERR(zcrtc
->pixclk
);
581 DRM_DEV_ERROR(dev
, "failed to get pix clk: %d\n", ret
);
585 ret
= zx_plane_init(drm
, zplane
, DRM_PLANE_TYPE_PRIMARY
);
587 DRM_DEV_ERROR(dev
, "failed to init primary plane: %d\n", ret
);
591 zcrtc
->primary
= &zplane
->plane
;
593 ret
= drm_crtc_init_with_planes(drm
, &zcrtc
->crtc
, zcrtc
->primary
, NULL
,
594 &zx_crtc_funcs
, NULL
);
596 DRM_DEV_ERROR(dev
, "failed to init drm crtc: %d\n", ret
);
600 drm_crtc_helper_add(&zcrtc
->crtc
, &zx_crtc_helper_funcs
);
602 if (chn_type
== VOU_CHN_MAIN
)
603 vou
->main_crtc
= zcrtc
;
605 vou
->aux_crtc
= zcrtc
;
610 void zx_vou_layer_enable(struct drm_plane
*plane
)
612 struct zx_crtc
*zcrtc
= to_zx_crtc(plane
->state
->crtc
);
613 struct zx_vou_hw
*vou
= zcrtc
->vou
;
614 struct zx_plane
*zplane
= to_zx_plane(plane
);
615 const struct vou_layer_bits
*bits
= zplane
->bits
;
617 if (zcrtc
->chn_type
== VOU_CHN_MAIN
) {
618 zx_writel_mask(vou
->osd
+ OSD_CTRL0
, bits
->chnsel
, 0);
619 zx_writel_mask(vou
->vouctl
+ VOU_CLK_SEL
, bits
->clksel
, 0);
621 zx_writel_mask(vou
->osd
+ OSD_CTRL0
, bits
->chnsel
,
623 zx_writel_mask(vou
->vouctl
+ VOU_CLK_SEL
, bits
->clksel
,
627 zx_writel_mask(vou
->osd
+ OSD_CTRL0
, bits
->enable
, bits
->enable
);
630 void zx_vou_layer_disable(struct drm_plane
*plane
,
631 struct drm_plane_state
*old_state
)
633 struct zx_crtc
*zcrtc
= to_zx_crtc(old_state
->crtc
);
634 struct zx_vou_hw
*vou
= zcrtc
->vou
;
635 struct zx_plane
*zplane
= to_zx_plane(plane
);
636 const struct vou_layer_bits
*bits
= zplane
->bits
;
638 zx_writel_mask(vou
->osd
+ OSD_CTRL0
, bits
->enable
, 0);
641 static void zx_overlay_init(struct drm_device
*drm
, struct zx_vou_hw
*vou
)
643 struct device
*dev
= vou
->dev
;
644 struct zx_plane
*zplane
;
649 * VL0 has some quirks on scaling support which need special handling.
650 * Let's leave it out for now.
652 for (i
= 1; i
< VL_NUM
; i
++) {
653 zplane
= devm_kzalloc(dev
, sizeof(*zplane
), GFP_KERNEL
);
655 DRM_DEV_ERROR(dev
, "failed to allocate zplane %d\n", i
);
659 zplane
->layer
= vou
->osd
+ OSD_VL_OFFSET(i
);
660 zplane
->hbsc
= vou
->osd
+ HBSC_VL_OFFSET(i
);
661 zplane
->rsz
= vou
->otfppu
+ RSZ_VL_OFFSET(i
);
662 zplane
->bits
= &zx_vl_bits
[i
];
664 ret
= zx_plane_init(drm
, zplane
, DRM_PLANE_TYPE_OVERLAY
);
666 DRM_DEV_ERROR(dev
, "failed to init overlay %d\n", i
);
672 static inline void zx_osd_int_update(struct zx_crtc
*zcrtc
)
674 struct drm_crtc
*crtc
= &zcrtc
->crtc
;
675 struct drm_plane
*plane
;
677 vou_chn_set_update(zcrtc
);
679 drm_for_each_plane_mask(plane
, crtc
->dev
, crtc
->state
->plane_mask
)
680 zx_plane_set_update(plane
);
683 static irqreturn_t
vou_irq_handler(int irq
, void *dev_id
)
685 struct zx_vou_hw
*vou
= dev_id
;
688 /* Handle TIMING_CTRL frame interrupts */
689 state
= zx_readl(vou
->timing
+ TIMING_INT_STATE
);
690 zx_writel(vou
->timing
+ TIMING_INT_STATE
, state
);
692 if (state
& TIMING_INT_MAIN_FRAME
)
693 drm_crtc_handle_vblank(&vou
->main_crtc
->crtc
);
695 if (state
& TIMING_INT_AUX_FRAME
)
696 drm_crtc_handle_vblank(&vou
->aux_crtc
->crtc
);
698 /* Handle OSD interrupts */
699 state
= zx_readl(vou
->osd
+ OSD_INT_STA
);
700 zx_writel(vou
->osd
+ OSD_INT_CLRSTA
, state
);
702 if (state
& OSD_INT_MAIN_UPT
)
703 zx_osd_int_update(vou
->main_crtc
);
705 if (state
& OSD_INT_AUX_UPT
)
706 zx_osd_int_update(vou
->aux_crtc
);
708 if (state
& OSD_INT_ERROR
)
709 DRM_DEV_ERROR(vou
->dev
, "OSD ERROR: 0x%08x!\n", state
);
714 static void vou_dtrc_init(struct zx_vou_hw
*vou
)
716 /* Clear bit for bypass by ID */
717 zx_writel_mask(vou
->dtrc
+ DTRC_DETILE_CTRL
,
718 TILE2RASTESCAN_BYPASS_MODE
, 0);
720 /* Select ARIDR mode */
721 zx_writel_mask(vou
->dtrc
+ DTRC_DETILE_CTRL
, DETILE_ARIDR_MODE_MASK
,
722 DETILE_ARID_IN_ARIDR
);
724 /* Bypass decompression for both frames */
725 zx_writel_mask(vou
->dtrc
+ DTRC_F0_CTRL
, DTRC_DECOMPRESS_BYPASS
,
726 DTRC_DECOMPRESS_BYPASS
);
727 zx_writel_mask(vou
->dtrc
+ DTRC_F1_CTRL
, DTRC_DECOMPRESS_BYPASS
,
728 DTRC_DECOMPRESS_BYPASS
);
730 /* Set up ARID register */
731 zx_writel(vou
->dtrc
+ DTRC_ARID
, DTRC_ARID3(0xf) | DTRC_ARID2(0xe) |
732 DTRC_ARID1(0xf) | DTRC_ARID0(0xe));
735 static void vou_hw_init(struct zx_vou_hw
*vou
)
737 /* Release reset for all VOU modules */
738 zx_writel(vou
->vouctl
+ VOU_SOFT_RST
, ~0);
740 /* Enable all VOU module clocks */
741 zx_writel(vou
->vouctl
+ VOU_CLK_EN
, ~0);
743 /* Clear both OSD and TIMING_CTRL interrupt state */
744 zx_writel(vou
->osd
+ OSD_INT_CLRSTA
, ~0);
745 zx_writel(vou
->timing
+ TIMING_INT_STATE
, ~0);
747 /* Enable OSD and TIMING_CTRL interrrupts */
748 zx_writel(vou
->osd
+ OSD_INT_MSK
, OSD_INT_ENABLE
);
749 zx_writel(vou
->timing
+ TIMING_INT_CTRL
, TIMING_INT_ENABLE
);
751 /* Select GPC as input to gl/vl scaler as a sane default setting */
752 zx_writel(vou
->otfppu
+ OTFPPU_RSZ_DATA_SOURCE
, 0x2a);
755 * Needs to reset channel and layer logic per frame when frame starts
756 * to get VOU work properly.
758 zx_writel_mask(vou
->osd
+ OSD_RST_CLR
, RST_PER_FRAME
, RST_PER_FRAME
);
763 static int zx_crtc_bind(struct device
*dev
, struct device
*master
, void *data
)
765 struct platform_device
*pdev
= to_platform_device(dev
);
766 struct drm_device
*drm
= data
;
767 struct zx_vou_hw
*vou
;
768 struct resource
*res
;
772 vou
= devm_kzalloc(dev
, sizeof(*vou
), GFP_KERNEL
);
776 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "osd");
777 vou
->osd
= devm_ioremap_resource(dev
, res
);
778 if (IS_ERR(vou
->osd
)) {
779 ret
= PTR_ERR(vou
->osd
);
780 DRM_DEV_ERROR(dev
, "failed to remap osd region: %d\n", ret
);
784 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "timing_ctrl");
785 vou
->timing
= devm_ioremap_resource(dev
, res
);
786 if (IS_ERR(vou
->timing
)) {
787 ret
= PTR_ERR(vou
->timing
);
788 DRM_DEV_ERROR(dev
, "failed to remap timing_ctrl region: %d\n",
793 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "dtrc");
794 vou
->dtrc
= devm_ioremap_resource(dev
, res
);
795 if (IS_ERR(vou
->dtrc
)) {
796 ret
= PTR_ERR(vou
->dtrc
);
797 DRM_DEV_ERROR(dev
, "failed to remap dtrc region: %d\n", ret
);
801 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "vou_ctrl");
802 vou
->vouctl
= devm_ioremap_resource(dev
, res
);
803 if (IS_ERR(vou
->vouctl
)) {
804 ret
= PTR_ERR(vou
->vouctl
);
805 DRM_DEV_ERROR(dev
, "failed to remap vou_ctrl region: %d\n",
810 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, "otfppu");
811 vou
->otfppu
= devm_ioremap_resource(dev
, res
);
812 if (IS_ERR(vou
->otfppu
)) {
813 ret
= PTR_ERR(vou
->otfppu
);
814 DRM_DEV_ERROR(dev
, "failed to remap otfppu region: %d\n", ret
);
818 irq
= platform_get_irq(pdev
, 0);
822 vou
->axi_clk
= devm_clk_get(dev
, "aclk");
823 if (IS_ERR(vou
->axi_clk
)) {
824 ret
= PTR_ERR(vou
->axi_clk
);
825 DRM_DEV_ERROR(dev
, "failed to get axi_clk: %d\n", ret
);
829 vou
->ppu_clk
= devm_clk_get(dev
, "ppu_wclk");
830 if (IS_ERR(vou
->ppu_clk
)) {
831 ret
= PTR_ERR(vou
->ppu_clk
);
832 DRM_DEV_ERROR(dev
, "failed to get ppu_clk: %d\n", ret
);
836 ret
= clk_prepare_enable(vou
->axi_clk
);
838 DRM_DEV_ERROR(dev
, "failed to enable axi_clk: %d\n", ret
);
842 clk_prepare_enable(vou
->ppu_clk
);
844 DRM_DEV_ERROR(dev
, "failed to enable ppu_clk: %d\n", ret
);
845 goto disable_axi_clk
;
849 dev_set_drvdata(dev
, vou
);
853 ret
= devm_request_irq(dev
, irq
, vou_irq_handler
, 0, "zx_vou", vou
);
855 DRM_DEV_ERROR(dev
, "failed to request vou irq: %d\n", ret
);
856 goto disable_ppu_clk
;
859 ret
= zx_crtc_init(drm
, vou
, VOU_CHN_MAIN
);
861 DRM_DEV_ERROR(dev
, "failed to init main channel crtc: %d\n",
863 goto disable_ppu_clk
;
866 ret
= zx_crtc_init(drm
, vou
, VOU_CHN_AUX
);
868 DRM_DEV_ERROR(dev
, "failed to init aux channel crtc: %d\n",
870 goto disable_ppu_clk
;
873 zx_overlay_init(drm
, vou
);
878 clk_disable_unprepare(vou
->ppu_clk
);
880 clk_disable_unprepare(vou
->axi_clk
);
884 static void zx_crtc_unbind(struct device
*dev
, struct device
*master
,
887 struct zx_vou_hw
*vou
= dev_get_drvdata(dev
);
889 clk_disable_unprepare(vou
->axi_clk
);
890 clk_disable_unprepare(vou
->ppu_clk
);
893 static const struct component_ops zx_crtc_component_ops
= {
894 .bind
= zx_crtc_bind
,
895 .unbind
= zx_crtc_unbind
,
898 static int zx_crtc_probe(struct platform_device
*pdev
)
900 return component_add(&pdev
->dev
, &zx_crtc_component_ops
);
903 static int zx_crtc_remove(struct platform_device
*pdev
)
905 component_del(&pdev
->dev
, &zx_crtc_component_ops
);
909 static const struct of_device_id zx_crtc_of_match
[] = {
910 { .compatible
= "zte,zx296718-dpc", },
913 MODULE_DEVICE_TABLE(of
, zx_crtc_of_match
);
915 struct platform_driver zx_crtc_driver
= {
916 .probe
= zx_crtc_probe
,
917 .remove
= zx_crtc_remove
,
920 .of_match_table
= zx_crtc_of_match
,