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/module.h>
14 #include <linux/of_address.h>
15 #include <linux/platform_device.h>
17 #include <video/videomode.h>
19 #include <drm/drm_atomic_helper.h>
20 #include <drm/drm_crtc.h>
21 #include <drm/drm_fb_cma_helper.h>
22 #include <drm/drm_fb_helper.h>
23 #include <drm/drm_gem_cma_helper.h>
24 #include <drm/drm_of.h>
25 #include <drm/drm_plane_helper.h>
26 #include <drm/drm_probe_helper.h>
27 #include <drm/drm_vblank.h>
29 #include "zx_common_regs.h"
30 #include "zx_drm_drv.h"
33 #include "zx_vou_regs.h"
52 static const struct zx_crtc_regs main_crtc_regs = {
53 .fir_active = FIR_MAIN_ACTIVE,
54 .fir_htiming = FIR_MAIN_H_TIMING,
55 .fir_vtiming = FIR_MAIN_V_TIMING,
56 .sec_vtiming = SEC_MAIN_V_TIMING,
57 .timing_shift = TIMING_MAIN_SHIFT,
58 .timing_pi_shift = TIMING_MAIN_PI_SHIFT,
61 static const struct zx_crtc_regs aux_crtc_regs = {
62 .fir_active = FIR_AUX_ACTIVE,
63 .fir_htiming = FIR_AUX_H_TIMING,
64 .fir_vtiming = FIR_AUX_V_TIMING,
65 .sec_vtiming = SEC_AUX_V_TIMING,
66 .timing_shift = TIMING_AUX_SHIFT,
67 .timing_pi_shift = TIMING_AUX_PI_SHIFT,
75 u32 sec_vactive_shift;
82 u32 div_hdmi_pnx_shift;
88 static const struct zx_crtc_bits main_crtc_bits = {
89 .polarity_mask = MAIN_POL_MASK,
90 .polarity_shift = MAIN_POL_SHIFT,
91 .int_frame_mask = TIMING_INT_MAIN_FRAME,
92 .tc_enable = MAIN_TC_EN,
93 .sec_vactive_shift = SEC_VACT_MAIN_SHIFT,
94 .sec_vactive_mask = SEC_VACT_MAIN_MASK,
95 .interlace_select = MAIN_INTERLACE_SEL,
96 .pi_enable = MAIN_PI_EN,
97 .div_vga_shift = VGA_MAIN_DIV_SHIFT,
98 .div_pic_shift = PIC_MAIN_DIV_SHIFT,
99 .div_tvenc_shift = TVENC_MAIN_DIV_SHIFT,
100 .div_hdmi_pnx_shift = HDMI_MAIN_PNX_DIV_SHIFT,
101 .div_hdmi_shift = HDMI_MAIN_DIV_SHIFT,
102 .div_inf_shift = INF_MAIN_DIV_SHIFT,
103 .div_layer_shift = LAYER_MAIN_DIV_SHIFT,
106 static const struct zx_crtc_bits aux_crtc_bits = {
107 .polarity_mask = AUX_POL_MASK,
108 .polarity_shift = AUX_POL_SHIFT,
109 .int_frame_mask = TIMING_INT_AUX_FRAME,
110 .tc_enable = AUX_TC_EN,
111 .sec_vactive_shift = SEC_VACT_AUX_SHIFT,
112 .sec_vactive_mask = SEC_VACT_AUX_MASK,
113 .interlace_select = AUX_INTERLACE_SEL,
114 .pi_enable = AUX_PI_EN,
115 .div_vga_shift = VGA_AUX_DIV_SHIFT,
116 .div_pic_shift = PIC_AUX_DIV_SHIFT,
117 .div_tvenc_shift = TVENC_AUX_DIV_SHIFT,
118 .div_hdmi_pnx_shift = HDMI_AUX_PNX_DIV_SHIFT,
119 .div_hdmi_shift = HDMI_AUX_DIV_SHIFT,
120 .div_inf_shift = INF_AUX_DIV_SHIFT,
121 .div_layer_shift = LAYER_AUX_DIV_SHIFT,
125 struct drm_crtc crtc;
126 struct drm_plane *primary;
127 struct zx_vou_hw *vou;
128 void __iomem *chnreg;
129 void __iomem *chncsc;
130 void __iomem *dither;
131 const struct zx_crtc_regs *regs;
132 const struct zx_crtc_bits *bits;
133 enum vou_chn_type chn_type;
137 #define to_zx_crtc(x) container_of(x, struct zx_crtc, crtc)
139 struct vou_layer_bits {
145 static const struct vou_layer_bits zx_gl_bits[GL_NUM] = {
147 .enable = OSD_CTRL0_GL0_EN,
148 .chnsel = OSD_CTRL0_GL0_SEL,
149 .clksel = VOU_CLK_GL0_SEL,
151 .enable = OSD_CTRL0_GL1_EN,
152 .chnsel = OSD_CTRL0_GL1_SEL,
153 .clksel = VOU_CLK_GL1_SEL,
157 static const struct vou_layer_bits zx_vl_bits[VL_NUM] = {
159 .enable = OSD_CTRL0_VL0_EN,
160 .chnsel = OSD_CTRL0_VL0_SEL,
161 .clksel = VOU_CLK_VL0_SEL,
163 .enable = OSD_CTRL0_VL1_EN,
164 .chnsel = OSD_CTRL0_VL1_SEL,
165 .clksel = VOU_CLK_VL1_SEL,
167 .enable = OSD_CTRL0_VL2_EN,
168 .chnsel = OSD_CTRL0_VL2_SEL,
169 .clksel = VOU_CLK_VL2_SEL,
176 void __iomem *timing;
177 void __iomem *vouctl;
178 void __iomem *otfppu;
182 struct clk *main_clk;
184 struct zx_crtc *main_crtc;
185 struct zx_crtc *aux_crtc;
188 enum vou_inf_data_sel {
197 enum vou_inf_data_sel data_sel;
202 static struct vou_inf vou_infs[] = {
204 .data_sel = VOU_YUV444,
205 .clocks_en_bits = BIT(24) | BIT(18) | BIT(6),
206 .clocks_sel_bits = BIT(13) | BIT(2),
209 .data_sel = VOU_YUV444,
210 .clocks_en_bits = BIT(15),
211 .clocks_sel_bits = BIT(11) | BIT(0),
214 .data_sel = VOU_RGB_888,
215 .clocks_en_bits = BIT(1),
216 .clocks_sel_bits = BIT(10),
220 static inline struct zx_vou_hw *crtc_to_vou(struct drm_crtc *crtc)
222 struct zx_crtc *zcrtc = to_zx_crtc(crtc);
227 void vou_inf_hdmi_audio_sel(struct drm_crtc *crtc,
228 enum vou_inf_hdmi_audio aud)
230 struct zx_crtc *zcrtc = to_zx_crtc(crtc);
231 struct zx_vou_hw *vou = zcrtc->vou;
233 zx_writel_mask(vou->vouctl + VOU_INF_HDMI_CTRL, VOU_HDMI_AUD_MASK, aud);
236 void vou_inf_enable(enum vou_inf_id id, struct drm_crtc *crtc)
238 struct zx_crtc *zcrtc = to_zx_crtc(crtc);
239 struct zx_vou_hw *vou = zcrtc->vou;
240 struct vou_inf *inf = &vou_infs[id];
241 void __iomem *dither = zcrtc->dither;
242 void __iomem *csc = zcrtc->chncsc;
243 bool is_main = zcrtc->chn_type == VOU_CHN_MAIN;
244 u32 data_sel_shift = id << 1;
246 if (inf->data_sel != VOU_YUV444) {
247 /* Enable channel CSC for RGB output */
248 zx_writel_mask(csc + CSC_CTRL0, CSC_COV_MODE_MASK,
249 CSC_BT709_IMAGE_YCBCR2RGB << CSC_COV_MODE_SHIFT);
250 zx_writel_mask(csc + CSC_CTRL0, CSC_WORK_ENABLE,
253 /* Bypass Dither block for RGB output */
254 zx_writel_mask(dither + OSD_DITHER_CTRL0, DITHER_BYSPASS,
257 zx_writel_mask(csc + CSC_CTRL0, CSC_WORK_ENABLE, 0);
258 zx_writel_mask(dither + OSD_DITHER_CTRL0, DITHER_BYSPASS, 0);
261 /* Select data format */
262 zx_writel_mask(vou->vouctl + VOU_INF_DATA_SEL, 0x3 << data_sel_shift,
263 inf->data_sel << data_sel_shift);
266 zx_writel_mask(vou->vouctl + VOU_INF_CH_SEL, 0x1 << id,
267 zcrtc->chn_type << id);
269 /* Select interface clocks */
270 zx_writel_mask(vou->vouctl + VOU_CLK_SEL, inf->clocks_sel_bits,
271 is_main ? 0 : inf->clocks_sel_bits);
273 /* Enable interface clocks */
274 zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits,
275 inf->clocks_en_bits);
277 /* Enable the device */
278 zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << id, 1 << id);
281 void vou_inf_disable(enum vou_inf_id id, struct drm_crtc *crtc)
283 struct zx_vou_hw *vou = crtc_to_vou(crtc);
284 struct vou_inf *inf = &vou_infs[id];
286 /* Disable the device */
287 zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << id, 0);
289 /* Disable interface clocks */
290 zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits, 0);
293 void zx_vou_config_dividers(struct drm_crtc *crtc,
294 struct vou_div_config *configs, int num)
296 struct zx_crtc *zcrtc = to_zx_crtc(crtc);
297 struct zx_vou_hw *vou = zcrtc->vou;
298 const struct zx_crtc_bits *bits = zcrtc->bits;
301 /* Clear update flag bit */
302 zx_writel_mask(vou->vouctl + VOU_DIV_PARA, DIV_PARA_UPDATE, 0);
304 for (i = 0; i < num; i++) {
305 struct vou_div_config *cfg = configs + i;
311 shift = bits->div_vga_shift;
315 shift = bits->div_pic_shift;
319 shift = bits->div_tvenc_shift;
321 case VOU_DIV_HDMI_PNX:
323 shift = bits->div_hdmi_pnx_shift;
327 shift = bits->div_hdmi_shift;
331 shift = bits->div_inf_shift;
335 shift = bits->div_layer_shift;
341 /* Each divider occupies 3 bits */
342 zx_writel_mask(vou->vouctl + reg, 0x7 << shift,
346 /* Set update flag bit to get dividers effected */
347 zx_writel_mask(vou->vouctl + VOU_DIV_PARA, DIV_PARA_UPDATE,
351 static inline void vou_chn_set_update(struct zx_crtc *zcrtc)
353 zx_writel(zcrtc->chnreg + CHN_UPDATE, 1);
356 static void zx_crtc_atomic_enable(struct drm_crtc *crtc,
357 struct drm_crtc_state *old_state)
359 struct drm_display_mode *mode = &crtc->state->adjusted_mode;
360 bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
361 struct zx_crtc *zcrtc = to_zx_crtc(crtc);
362 struct zx_vou_hw *vou = zcrtc->vou;
363 const struct zx_crtc_regs *regs = zcrtc->regs;
364 const struct zx_crtc_bits *bits = zcrtc->bits;
371 drm_display_mode_to_videomode(mode, &vm);
373 /* Set up timing parameters */
374 val = V_ACTIVE((interlaced ? vm.vactive / 2 : vm.vactive) - 1);
375 val |= H_ACTIVE(vm.hactive - 1);
376 zx_writel(vou->timing + regs->fir_active, val);
378 val = SYNC_WIDE(vm.hsync_len - 1);
379 val |= BACK_PORCH(vm.hback_porch - 1);
380 val |= FRONT_PORCH(vm.hfront_porch - 1);
381 zx_writel(vou->timing + regs->fir_htiming, val);
383 val = SYNC_WIDE(vm.vsync_len - 1);
384 val |= BACK_PORCH(vm.vback_porch - 1);
385 val |= FRONT_PORCH(vm.vfront_porch - 1);
386 zx_writel(vou->timing + regs->fir_vtiming, val);
389 u32 shift = bits->sec_vactive_shift;
390 u32 mask = bits->sec_vactive_mask;
392 val = zx_readl(vou->timing + SEC_V_ACTIVE);
394 val |= ((vm.vactive / 2 - 1) << shift) & mask;
395 zx_writel(vou->timing + SEC_V_ACTIVE, val);
397 val = SYNC_WIDE(vm.vsync_len - 1);
399 * The vback_porch for the second field needs to shift one on
400 * the value for the first field.
402 val |= BACK_PORCH(vm.vback_porch);
403 val |= FRONT_PORCH(vm.vfront_porch - 1);
404 zx_writel(vou->timing + regs->sec_vtiming, val);
407 /* Set up polarities */
408 if (vm.flags & DISPLAY_FLAGS_VSYNC_LOW)
409 pol |= 1 << POL_VSYNC_SHIFT;
410 if (vm.flags & DISPLAY_FLAGS_HSYNC_LOW)
411 pol |= 1 << POL_HSYNC_SHIFT;
413 zx_writel_mask(vou->timing + TIMING_CTRL, bits->polarity_mask,
414 pol << bits->polarity_shift);
416 /* Setup SHIFT register by following what ZTE BSP does */
419 val |= V_SHIFT_VAL << 16;
420 zx_writel(vou->timing + regs->timing_shift, val);
421 zx_writel(vou->timing + regs->timing_pi_shift, H_PI_SHIFT_VAL);
423 /* Progressive or interlace scan select */
424 scan_mask = bits->interlace_select | bits->pi_enable;
425 zx_writel_mask(vou->timing + SCAN_CTRL, scan_mask,
426 interlaced ? scan_mask : 0);
428 /* Enable TIMING_CTRL */
429 zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable,
432 /* Configure channel screen size */
433 zx_writel_mask(zcrtc->chnreg + CHN_CTRL1, CHN_SCREEN_W_MASK,
434 vm.hactive << CHN_SCREEN_W_SHIFT);
435 zx_writel_mask(zcrtc->chnreg + CHN_CTRL1, CHN_SCREEN_H_MASK,
436 vm.vactive << CHN_SCREEN_H_SHIFT);
438 /* Configure channel interlace buffer control */
439 zx_writel_mask(zcrtc->chnreg + CHN_INTERLACE_BUF_CTRL, CHN_INTERLACE_EN,
440 interlaced ? CHN_INTERLACE_EN : 0);
443 vou_chn_set_update(zcrtc);
446 zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, CHN_ENABLE);
448 drm_crtc_vblank_on(crtc);
450 ret = clk_set_rate(zcrtc->pixclk, mode->clock * 1000);
452 DRM_DEV_ERROR(vou->dev, "failed to set pixclk rate: %d\n", ret);
456 ret = clk_prepare_enable(zcrtc->pixclk);
458 DRM_DEV_ERROR(vou->dev, "failed to enable pixclk: %d\n", ret);
461 static void zx_crtc_atomic_disable(struct drm_crtc *crtc,
462 struct drm_crtc_state *old_state)
464 struct zx_crtc *zcrtc = to_zx_crtc(crtc);
465 const struct zx_crtc_bits *bits = zcrtc->bits;
466 struct zx_vou_hw *vou = zcrtc->vou;
468 clk_disable_unprepare(zcrtc->pixclk);
470 drm_crtc_vblank_off(crtc);
472 /* Disable channel */
473 zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, 0);
475 /* Disable TIMING_CTRL */
476 zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable, 0);
479 static void zx_crtc_atomic_flush(struct drm_crtc *crtc,
480 struct drm_crtc_state *old_state)
482 struct drm_pending_vblank_event *event = crtc->state->event;
487 crtc->state->event = NULL;
489 spin_lock_irq(&crtc->dev->event_lock);
490 if (drm_crtc_vblank_get(crtc) == 0)
491 drm_crtc_arm_vblank_event(crtc, event);
493 drm_crtc_send_vblank_event(crtc, event);
494 spin_unlock_irq(&crtc->dev->event_lock);
497 static const struct drm_crtc_helper_funcs zx_crtc_helper_funcs = {
498 .atomic_flush = zx_crtc_atomic_flush,
499 .atomic_enable = zx_crtc_atomic_enable,
500 .atomic_disable = zx_crtc_atomic_disable,
503 static int zx_vou_enable_vblank(struct drm_crtc *crtc)
505 struct zx_crtc *zcrtc = to_zx_crtc(crtc);
506 struct zx_vou_hw *vou = crtc_to_vou(crtc);
507 u32 int_frame_mask = zcrtc->bits->int_frame_mask;
509 zx_writel_mask(vou->timing + TIMING_INT_CTRL, int_frame_mask,
515 static void zx_vou_disable_vblank(struct drm_crtc *crtc)
517 struct zx_crtc *zcrtc = to_zx_crtc(crtc);
518 struct zx_vou_hw *vou = crtc_to_vou(crtc);
520 zx_writel_mask(vou->timing + TIMING_INT_CTRL,
521 zcrtc->bits->int_frame_mask, 0);
524 static const struct drm_crtc_funcs zx_crtc_funcs = {
525 .destroy = drm_crtc_cleanup,
526 .set_config = drm_atomic_helper_set_config,
527 .page_flip = drm_atomic_helper_page_flip,
528 .reset = drm_atomic_helper_crtc_reset,
529 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
530 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
531 .enable_vblank = zx_vou_enable_vblank,
532 .disable_vblank = zx_vou_disable_vblank,
535 static int zx_crtc_init(struct drm_device *drm, struct zx_vou_hw *vou,
536 enum vou_chn_type chn_type)
538 struct device *dev = vou->dev;
539 struct zx_plane *zplane;
540 struct zx_crtc *zcrtc;
543 zcrtc = devm_kzalloc(dev, sizeof(*zcrtc), GFP_KERNEL);
548 zcrtc->chn_type = chn_type;
550 zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
556 if (chn_type == VOU_CHN_MAIN) {
557 zplane->layer = vou->osd + MAIN_GL_OFFSET;
558 zplane->csc = vou->osd + MAIN_GL_CSC_OFFSET;
559 zplane->hbsc = vou->osd + MAIN_HBSC_OFFSET;
560 zplane->rsz = vou->otfppu + MAIN_RSZ_OFFSET;
561 zplane->bits = &zx_gl_bits[0];
562 zcrtc->chnreg = vou->osd + OSD_MAIN_CHN;
563 zcrtc->chncsc = vou->osd + MAIN_CHN_CSC_OFFSET;
564 zcrtc->dither = vou->osd + MAIN_DITHER_OFFSET;
565 zcrtc->regs = &main_crtc_regs;
566 zcrtc->bits = &main_crtc_bits;
568 zplane->layer = vou->osd + AUX_GL_OFFSET;
569 zplane->csc = vou->osd + AUX_GL_CSC_OFFSET;
570 zplane->hbsc = vou->osd + AUX_HBSC_OFFSET;
571 zplane->rsz = vou->otfppu + AUX_RSZ_OFFSET;
572 zplane->bits = &zx_gl_bits[1];
573 zcrtc->chnreg = vou->osd + OSD_AUX_CHN;
574 zcrtc->chncsc = vou->osd + AUX_CHN_CSC_OFFSET;
575 zcrtc->dither = vou->osd + AUX_DITHER_OFFSET;
576 zcrtc->regs = &aux_crtc_regs;
577 zcrtc->bits = &aux_crtc_bits;
580 zcrtc->pixclk = devm_clk_get(dev, (chn_type == VOU_CHN_MAIN) ?
581 "main_wclk" : "aux_wclk");
582 if (IS_ERR(zcrtc->pixclk)) {
583 ret = PTR_ERR(zcrtc->pixclk);
584 DRM_DEV_ERROR(dev, "failed to get pix clk: %d\n", ret);
588 ret = zx_plane_init(drm, zplane, DRM_PLANE_TYPE_PRIMARY);
590 DRM_DEV_ERROR(dev, "failed to init primary plane: %d\n", ret);
594 zcrtc->primary = &zplane->plane;
596 ret = drm_crtc_init_with_planes(drm, &zcrtc->crtc, zcrtc->primary, NULL,
597 &zx_crtc_funcs, NULL);
599 DRM_DEV_ERROR(dev, "failed to init drm crtc: %d\n", ret);
603 drm_crtc_helper_add(&zcrtc->crtc, &zx_crtc_helper_funcs);
605 if (chn_type == VOU_CHN_MAIN)
606 vou->main_crtc = zcrtc;
608 vou->aux_crtc = zcrtc;
613 void zx_vou_layer_enable(struct drm_plane *plane)
615 struct zx_crtc *zcrtc = to_zx_crtc(plane->state->crtc);
616 struct zx_vou_hw *vou = zcrtc->vou;
617 struct zx_plane *zplane = to_zx_plane(plane);
618 const struct vou_layer_bits *bits = zplane->bits;
620 if (zcrtc->chn_type == VOU_CHN_MAIN) {
621 zx_writel_mask(vou->osd + OSD_CTRL0, bits->chnsel, 0);
622 zx_writel_mask(vou->vouctl + VOU_CLK_SEL, bits->clksel, 0);
624 zx_writel_mask(vou->osd + OSD_CTRL0, bits->chnsel,
626 zx_writel_mask(vou->vouctl + VOU_CLK_SEL, bits->clksel,
630 zx_writel_mask(vou->osd + OSD_CTRL0, bits->enable, bits->enable);
633 void zx_vou_layer_disable(struct drm_plane *plane,
634 struct drm_plane_state *old_state)
636 struct zx_crtc *zcrtc = to_zx_crtc(old_state->crtc);
637 struct zx_vou_hw *vou = zcrtc->vou;
638 struct zx_plane *zplane = to_zx_plane(plane);
639 const struct vou_layer_bits *bits = zplane->bits;
641 zx_writel_mask(vou->osd + OSD_CTRL0, bits->enable, 0);
644 static void zx_overlay_init(struct drm_device *drm, struct zx_vou_hw *vou)
646 struct device *dev = vou->dev;
647 struct zx_plane *zplane;
652 * VL0 has some quirks on scaling support which need special handling.
653 * Let's leave it out for now.
655 for (i = 1; i < VL_NUM; i++) {
656 zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
658 DRM_DEV_ERROR(dev, "failed to allocate zplane %d\n", i);
662 zplane->layer = vou->osd + OSD_VL_OFFSET(i);
663 zplane->hbsc = vou->osd + HBSC_VL_OFFSET(i);
664 zplane->rsz = vou->otfppu + RSZ_VL_OFFSET(i);
665 zplane->bits = &zx_vl_bits[i];
667 ret = zx_plane_init(drm, zplane, DRM_PLANE_TYPE_OVERLAY);
669 DRM_DEV_ERROR(dev, "failed to init overlay %d\n", i);
675 static inline void zx_osd_int_update(struct zx_crtc *zcrtc)
677 struct drm_crtc *crtc = &zcrtc->crtc;
678 struct drm_plane *plane;
680 vou_chn_set_update(zcrtc);
682 drm_for_each_plane_mask(plane, crtc->dev, crtc->state->plane_mask)
683 zx_plane_set_update(plane);
686 static irqreturn_t vou_irq_handler(int irq, void *dev_id)
688 struct zx_vou_hw *vou = dev_id;
691 /* Handle TIMING_CTRL frame interrupts */
692 state = zx_readl(vou->timing + TIMING_INT_STATE);
693 zx_writel(vou->timing + TIMING_INT_STATE, state);
695 if (state & TIMING_INT_MAIN_FRAME)
696 drm_crtc_handle_vblank(&vou->main_crtc->crtc);
698 if (state & TIMING_INT_AUX_FRAME)
699 drm_crtc_handle_vblank(&vou->aux_crtc->crtc);
701 /* Handle OSD interrupts */
702 state = zx_readl(vou->osd + OSD_INT_STA);
703 zx_writel(vou->osd + OSD_INT_CLRSTA, state);
705 if (state & OSD_INT_MAIN_UPT)
706 zx_osd_int_update(vou->main_crtc);
708 if (state & OSD_INT_AUX_UPT)
709 zx_osd_int_update(vou->aux_crtc);
711 if (state & OSD_INT_ERROR)
712 DRM_DEV_ERROR(vou->dev, "OSD ERROR: 0x%08x!\n", state);
717 static void vou_dtrc_init(struct zx_vou_hw *vou)
719 /* Clear bit for bypass by ID */
720 zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL,
721 TILE2RASTESCAN_BYPASS_MODE, 0);
723 /* Select ARIDR mode */
724 zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL, DETILE_ARIDR_MODE_MASK,
725 DETILE_ARID_IN_ARIDR);
727 /* Bypass decompression for both frames */
728 zx_writel_mask(vou->dtrc + DTRC_F0_CTRL, DTRC_DECOMPRESS_BYPASS,
729 DTRC_DECOMPRESS_BYPASS);
730 zx_writel_mask(vou->dtrc + DTRC_F1_CTRL, DTRC_DECOMPRESS_BYPASS,
731 DTRC_DECOMPRESS_BYPASS);
733 /* Set up ARID register */
734 zx_writel(vou->dtrc + DTRC_ARID, DTRC_ARID3(0xf) | DTRC_ARID2(0xe) |
735 DTRC_ARID1(0xf) | DTRC_ARID0(0xe));
738 static void vou_hw_init(struct zx_vou_hw *vou)
740 /* Release reset for all VOU modules */
741 zx_writel(vou->vouctl + VOU_SOFT_RST, ~0);
743 /* Enable all VOU module clocks */
744 zx_writel(vou->vouctl + VOU_CLK_EN, ~0);
746 /* Clear both OSD and TIMING_CTRL interrupt state */
747 zx_writel(vou->osd + OSD_INT_CLRSTA, ~0);
748 zx_writel(vou->timing + TIMING_INT_STATE, ~0);
750 /* Enable OSD and TIMING_CTRL interrrupts */
751 zx_writel(vou->osd + OSD_INT_MSK, OSD_INT_ENABLE);
752 zx_writel(vou->timing + TIMING_INT_CTRL, TIMING_INT_ENABLE);
754 /* Select GPC as input to gl/vl scaler as a sane default setting */
755 zx_writel(vou->otfppu + OTFPPU_RSZ_DATA_SOURCE, 0x2a);
758 * Needs to reset channel and layer logic per frame when frame starts
759 * to get VOU work properly.
761 zx_writel_mask(vou->osd + OSD_RST_CLR, RST_PER_FRAME, RST_PER_FRAME);
766 static int zx_crtc_bind(struct device *dev, struct device *master, void *data)
768 struct platform_device *pdev = to_platform_device(dev);
769 struct drm_device *drm = data;
770 struct zx_vou_hw *vou;
771 struct resource *res;
775 vou = devm_kzalloc(dev, sizeof(*vou), GFP_KERNEL);
779 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "osd");
780 vou->osd = devm_ioremap_resource(dev, res);
781 if (IS_ERR(vou->osd)) {
782 ret = PTR_ERR(vou->osd);
783 DRM_DEV_ERROR(dev, "failed to remap osd region: %d\n", ret);
787 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "timing_ctrl");
788 vou->timing = devm_ioremap_resource(dev, res);
789 if (IS_ERR(vou->timing)) {
790 ret = PTR_ERR(vou->timing);
791 DRM_DEV_ERROR(dev, "failed to remap timing_ctrl region: %d\n",
796 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dtrc");
797 vou->dtrc = devm_ioremap_resource(dev, res);
798 if (IS_ERR(vou->dtrc)) {
799 ret = PTR_ERR(vou->dtrc);
800 DRM_DEV_ERROR(dev, "failed to remap dtrc region: %d\n", ret);
804 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vou_ctrl");
805 vou->vouctl = devm_ioremap_resource(dev, res);
806 if (IS_ERR(vou->vouctl)) {
807 ret = PTR_ERR(vou->vouctl);
808 DRM_DEV_ERROR(dev, "failed to remap vou_ctrl region: %d\n",
813 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "otfppu");
814 vou->otfppu = devm_ioremap_resource(dev, res);
815 if (IS_ERR(vou->otfppu)) {
816 ret = PTR_ERR(vou->otfppu);
817 DRM_DEV_ERROR(dev, "failed to remap otfppu region: %d\n", ret);
821 irq = platform_get_irq(pdev, 0);
825 vou->axi_clk = devm_clk_get(dev, "aclk");
826 if (IS_ERR(vou->axi_clk)) {
827 ret = PTR_ERR(vou->axi_clk);
828 DRM_DEV_ERROR(dev, "failed to get axi_clk: %d\n", ret);
832 vou->ppu_clk = devm_clk_get(dev, "ppu_wclk");
833 if (IS_ERR(vou->ppu_clk)) {
834 ret = PTR_ERR(vou->ppu_clk);
835 DRM_DEV_ERROR(dev, "failed to get ppu_clk: %d\n", ret);
839 ret = clk_prepare_enable(vou->axi_clk);
841 DRM_DEV_ERROR(dev, "failed to enable axi_clk: %d\n", ret);
845 clk_prepare_enable(vou->ppu_clk);
847 DRM_DEV_ERROR(dev, "failed to enable ppu_clk: %d\n", ret);
848 goto disable_axi_clk;
852 dev_set_drvdata(dev, vou);
856 ret = devm_request_irq(dev, irq, vou_irq_handler, 0, "zx_vou", vou);
858 DRM_DEV_ERROR(dev, "failed to request vou irq: %d\n", ret);
859 goto disable_ppu_clk;
862 ret = zx_crtc_init(drm, vou, VOU_CHN_MAIN);
864 DRM_DEV_ERROR(dev, "failed to init main channel crtc: %d\n",
866 goto disable_ppu_clk;
869 ret = zx_crtc_init(drm, vou, VOU_CHN_AUX);
871 DRM_DEV_ERROR(dev, "failed to init aux channel crtc: %d\n",
873 goto disable_ppu_clk;
876 zx_overlay_init(drm, vou);
881 clk_disable_unprepare(vou->ppu_clk);
883 clk_disable_unprepare(vou->axi_clk);
887 static void zx_crtc_unbind(struct device *dev, struct device *master,
890 struct zx_vou_hw *vou = dev_get_drvdata(dev);
892 clk_disable_unprepare(vou->axi_clk);
893 clk_disable_unprepare(vou->ppu_clk);
896 static const struct component_ops zx_crtc_component_ops = {
897 .bind = zx_crtc_bind,
898 .unbind = zx_crtc_unbind,
901 static int zx_crtc_probe(struct platform_device *pdev)
903 return component_add(&pdev->dev, &zx_crtc_component_ops);
906 static int zx_crtc_remove(struct platform_device *pdev)
908 component_del(&pdev->dev, &zx_crtc_component_ops);
912 static const struct of_device_id zx_crtc_of_match[] = {
913 { .compatible = "zte,zx296718-dpc", },
916 MODULE_DEVICE_TABLE(of, zx_crtc_of_match);
918 struct platform_driver zx_crtc_driver = {
919 .probe = zx_crtc_probe,
920 .remove = zx_crtc_remove,
923 .of_match_table = zx_crtc_of_match,