dt-bindings: mtd: ingenic: Use standard ecc-engine property
[linux/fpc-iii.git] / drivers / gpu / drm / zte / zx_vou.c
blob15400ffb1d225570c0ebf48a97b4603ebf61fef2
1 /*
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.
9 */
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>
24 #include <drm/drmP.h>
26 #include "zx_common_regs.h"
27 #include "zx_drm_drv.h"
28 #include "zx_plane.h"
29 #include "zx_vou.h"
30 #include "zx_vou_regs.h"
32 #define GL_NUM 2
33 #define VL_NUM 3
35 enum vou_chn_type {
36 VOU_CHN_MAIN,
37 VOU_CHN_AUX,
40 struct zx_crtc_regs {
41 u32 fir_active;
42 u32 fir_htiming;
43 u32 fir_vtiming;
44 u32 sec_vtiming;
45 u32 timing_shift;
46 u32 timing_pi_shift;
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,
67 struct zx_crtc_bits {
68 u32 polarity_mask;
69 u32 polarity_shift;
70 u32 int_frame_mask;
71 u32 tc_enable;
72 u32 sec_vactive_shift;
73 u32 sec_vactive_mask;
74 u32 interlace_select;
75 u32 pi_enable;
76 u32 div_vga_shift;
77 u32 div_pic_shift;
78 u32 div_tvenc_shift;
79 u32 div_hdmi_pnx_shift;
80 u32 div_hdmi_shift;
81 u32 div_inf_shift;
82 u32 div_layer_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,
121 struct zx_crtc {
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;
131 struct clk *pixclk;
134 #define to_zx_crtc(x) container_of(x, struct zx_crtc, crtc)
136 struct vou_layer_bits {
137 u32 enable;
138 u32 chnsel;
139 u32 clksel;
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,
147 }, {
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,
159 }, {
160 .enable = OSD_CTRL0_VL1_EN,
161 .chnsel = OSD_CTRL0_VL1_SEL,
162 .clksel = VOU_CLK_VL1_SEL,
163 }, {
164 .enable = OSD_CTRL0_VL2_EN,
165 .chnsel = OSD_CTRL0_VL2_SEL,
166 .clksel = VOU_CLK_VL2_SEL,
170 struct zx_vou_hw {
171 struct device *dev;
172 void __iomem *osd;
173 void __iomem *timing;
174 void __iomem *vouctl;
175 void __iomem *otfppu;
176 void __iomem *dtrc;
177 struct clk *axi_clk;
178 struct clk *ppu_clk;
179 struct clk *main_clk;
180 struct clk *aux_clk;
181 struct zx_crtc *main_crtc;
182 struct zx_crtc *aux_crtc;
185 enum vou_inf_data_sel {
186 VOU_YUV444 = 0,
187 VOU_RGB_101010 = 1,
188 VOU_RGB_888 = 2,
189 VOU_RGB_666 = 3,
192 struct vou_inf {
193 enum vou_inf_id id;
194 enum vou_inf_data_sel data_sel;
195 u32 clocks_en_bits;
196 u32 clocks_sel_bits;
199 static struct vou_inf vou_infs[] = {
200 [VOU_HDMI] = {
201 .data_sel = VOU_YUV444,
202 .clocks_en_bits = BIT(24) | BIT(18) | BIT(6),
203 .clocks_sel_bits = BIT(13) | BIT(2),
205 [VOU_TV_ENC] = {
206 .data_sel = VOU_YUV444,
207 .clocks_en_bits = BIT(15),
208 .clocks_sel_bits = BIT(11) | BIT(0),
210 [VOU_VGA] = {
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);
221 return zcrtc->vou;
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,
248 CSC_WORK_ENABLE);
250 /* Bypass Dither block for RGB output */
251 zx_writel_mask(dither + OSD_DITHER_CTRL0, DITHER_BYSPASS,
252 DITHER_BYSPASS);
253 } else {
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);
262 /* Select channel */
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;
296 int i;
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;
303 u32 reg, shift;
305 switch (cfg->id) {
306 case VOU_DIV_VGA:
307 reg = VOU_CLK_SEL;
308 shift = bits->div_vga_shift;
309 break;
310 case VOU_DIV_PIC:
311 reg = VOU_CLK_SEL;
312 shift = bits->div_pic_shift;
313 break;
314 case VOU_DIV_TVENC:
315 reg = VOU_DIV_PARA;
316 shift = bits->div_tvenc_shift;
317 break;
318 case VOU_DIV_HDMI_PNX:
319 reg = VOU_DIV_PARA;
320 shift = bits->div_hdmi_pnx_shift;
321 break;
322 case VOU_DIV_HDMI:
323 reg = VOU_DIV_PARA;
324 shift = bits->div_hdmi_shift;
325 break;
326 case VOU_DIV_INF:
327 reg = VOU_DIV_PARA;
328 shift = bits->div_inf_shift;
329 break;
330 case VOU_DIV_LAYER:
331 reg = VOU_DIV_PARA;
332 shift = bits->div_layer_shift;
333 break;
334 default:
335 continue;
338 /* Each divider occupies 3 bits */
339 zx_writel_mask(vou->vouctl + reg, 0x7 << shift,
340 cfg->val << shift);
343 /* Set update flag bit to get dividers effected */
344 zx_writel_mask(vou->vouctl + VOU_DIV_PARA, DIV_PARA_UPDATE,
345 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;
362 struct videomode vm;
363 u32 scan_mask;
364 u32 pol = 0;
365 u32 val;
366 int ret;
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);
385 if (interlaced) {
386 u32 shift = bits->sec_vactive_shift;
387 u32 mask = bits->sec_vactive_mask;
389 val = zx_readl(vou->timing + SEC_V_ACTIVE);
390 val &= ~mask;
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 */
414 val = H_SHIFT_VAL;
415 if (interlaced)
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,
427 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);
439 /* Update channel */
440 vou_chn_set_update(zcrtc);
442 /* Enable channel */
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);
448 if (ret) {
449 DRM_DEV_ERROR(vou->dev, "failed to set pixclk rate: %d\n", ret);
450 return;
453 ret = clk_prepare_enable(zcrtc->pixclk);
454 if (ret)
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;
481 if (!event)
482 return;
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);
489 else
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,
507 int_frame_mask);
509 return 0;
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;
538 int ret;
540 zcrtc = devm_kzalloc(dev, sizeof(*zcrtc), GFP_KERNEL);
541 if (!zcrtc)
542 return -ENOMEM;
544 zcrtc->vou = vou;
545 zcrtc->chn_type = chn_type;
547 zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
548 if (!zplane)
549 return -ENOMEM;
551 zplane->dev = dev;
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;
564 } else {
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);
582 return ret;
585 ret = zx_plane_init(drm, zplane, DRM_PLANE_TYPE_PRIMARY);
586 if (ret) {
587 DRM_DEV_ERROR(dev, "failed to init primary plane: %d\n", ret);
588 return ret;
591 zcrtc->primary = &zplane->plane;
593 ret = drm_crtc_init_with_planes(drm, &zcrtc->crtc, zcrtc->primary, NULL,
594 &zx_crtc_funcs, NULL);
595 if (ret) {
596 DRM_DEV_ERROR(dev, "failed to init drm crtc: %d\n", ret);
597 return ret;
600 drm_crtc_helper_add(&zcrtc->crtc, &zx_crtc_helper_funcs);
602 if (chn_type == VOU_CHN_MAIN)
603 vou->main_crtc = zcrtc;
604 else
605 vou->aux_crtc = zcrtc;
607 return 0;
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);
620 } else {
621 zx_writel_mask(vou->osd + OSD_CTRL0, bits->chnsel,
622 bits->chnsel);
623 zx_writel_mask(vou->vouctl + VOU_CLK_SEL, bits->clksel,
624 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;
645 int i;
646 int ret;
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);
654 if (!zplane) {
655 DRM_DEV_ERROR(dev, "failed to allocate zplane %d\n", i);
656 return;
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);
665 if (ret) {
666 DRM_DEV_ERROR(dev, "failed to init overlay %d\n", i);
667 continue;
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;
686 u32 state;
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);
711 return IRQ_HANDLED;
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);
760 vou_dtrc_init(vou);
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;
769 int irq;
770 int ret;
772 vou = devm_kzalloc(dev, sizeof(*vou), GFP_KERNEL);
773 if (!vou)
774 return -ENOMEM;
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);
781 return 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",
789 ret);
790 return ret;
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);
798 return 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",
806 ret);
807 return ret;
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);
815 return ret;
818 irq = platform_get_irq(pdev, 0);
819 if (irq < 0)
820 return irq;
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);
826 return 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);
833 return ret;
836 ret = clk_prepare_enable(vou->axi_clk);
837 if (ret) {
838 DRM_DEV_ERROR(dev, "failed to enable axi_clk: %d\n", ret);
839 return ret;
842 clk_prepare_enable(vou->ppu_clk);
843 if (ret) {
844 DRM_DEV_ERROR(dev, "failed to enable ppu_clk: %d\n", ret);
845 goto disable_axi_clk;
848 vou->dev = dev;
849 dev_set_drvdata(dev, vou);
851 vou_hw_init(vou);
853 ret = devm_request_irq(dev, irq, vou_irq_handler, 0, "zx_vou", vou);
854 if (ret < 0) {
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);
860 if (ret) {
861 DRM_DEV_ERROR(dev, "failed to init main channel crtc: %d\n",
862 ret);
863 goto disable_ppu_clk;
866 ret = zx_crtc_init(drm, vou, VOU_CHN_AUX);
867 if (ret) {
868 DRM_DEV_ERROR(dev, "failed to init aux channel crtc: %d\n",
869 ret);
870 goto disable_ppu_clk;
873 zx_overlay_init(drm, vou);
875 return 0;
877 disable_ppu_clk:
878 clk_disable_unprepare(vou->ppu_clk);
879 disable_axi_clk:
880 clk_disable_unprepare(vou->axi_clk);
881 return ret;
884 static void zx_crtc_unbind(struct device *dev, struct device *master,
885 void *data)
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);
906 return 0;
909 static const struct of_device_id zx_crtc_of_match[] = {
910 { .compatible = "zte,zx296718-dpc", },
911 { /* end */ },
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,
918 .driver = {
919 .name = "zx-crtc",
920 .of_match_table = zx_crtc_of_match,