]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/gpu/drm/zte/zx_vou.c
Merge tag 'ktest-v4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
[karo-tx-linux.git] / drivers / gpu / drm / zte / zx_vou.c
1 /*
2  * Copyright 2016 Linaro Ltd.
3  * Copyright 2016 ZTE Corporation.
4  *
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.
8  *
9  */
10
11 #include <linux/clk.h>
12 #include <linux/component.h>
13 #include <linux/of_address.h>
14 #include <video/videomode.h>
15
16 #include <drm/drm_atomic_helper.h>
17 #include <drm/drm_crtc.h>
18 #include <drm/drm_crtc_helper.h>
19 #include <drm/drm_fb_cma_helper.h>
20 #include <drm/drm_fb_helper.h>
21 #include <drm/drm_gem_cma_helper.h>
22 #include <drm/drm_of.h>
23 #include <drm/drm_plane_helper.h>
24 #include <drm/drmP.h>
25
26 #include "zx_drm_drv.h"
27 #include "zx_plane.h"
28 #include "zx_vou.h"
29 #include "zx_vou_regs.h"
30
31 #define GL_NUM  2
32 #define VL_NUM  3
33
34 enum vou_chn_type {
35         VOU_CHN_MAIN,
36         VOU_CHN_AUX,
37 };
38
39 struct zx_crtc_regs {
40         u32 fir_active;
41         u32 fir_htiming;
42         u32 fir_vtiming;
43         u32 sec_vtiming;
44         u32 timing_shift;
45         u32 timing_pi_shift;
46 };
47
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,
55 };
56
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,
64 };
65
66 struct zx_crtc_bits {
67         u32 polarity_mask;
68         u32 polarity_shift;
69         u32 int_frame_mask;
70         u32 tc_enable;
71         u32 sec_vactive_shift;
72         u32 sec_vactive_mask;
73         u32 interlace_select;
74         u32 pi_enable;
75         u32 div_vga_shift;
76         u32 div_pic_shift;
77         u32 div_tvenc_shift;
78         u32 div_hdmi_pnx_shift;
79         u32 div_hdmi_shift;
80         u32 div_inf_shift;
81         u32 div_layer_shift;
82 };
83
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,
100 };
101
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,
118 };
119
120 struct zx_crtc {
121         struct drm_crtc crtc;
122         struct drm_plane *primary;
123         struct zx_vou_hw *vou;
124         void __iomem *chnreg;
125         const struct zx_crtc_regs *regs;
126         const struct zx_crtc_bits *bits;
127         enum vou_chn_type chn_type;
128         struct clk *pixclk;
129 };
130
131 #define to_zx_crtc(x) container_of(x, struct zx_crtc, crtc)
132
133 struct vou_layer_bits {
134         u32 enable;
135         u32 chnsel;
136         u32 clksel;
137 };
138
139 static const struct vou_layer_bits zx_gl_bits[GL_NUM] = {
140         {
141                 .enable = OSD_CTRL0_GL0_EN,
142                 .chnsel = OSD_CTRL0_GL0_SEL,
143                 .clksel = VOU_CLK_GL0_SEL,
144         }, {
145                 .enable = OSD_CTRL0_GL1_EN,
146                 .chnsel = OSD_CTRL0_GL1_SEL,
147                 .clksel = VOU_CLK_GL1_SEL,
148         },
149 };
150
151 static const struct vou_layer_bits zx_vl_bits[VL_NUM] = {
152         {
153                 .enable = OSD_CTRL0_VL0_EN,
154                 .chnsel = OSD_CTRL0_VL0_SEL,
155                 .clksel = VOU_CLK_VL0_SEL,
156         }, {
157                 .enable = OSD_CTRL0_VL1_EN,
158                 .chnsel = OSD_CTRL0_VL1_SEL,
159                 .clksel = VOU_CLK_VL1_SEL,
160         }, {
161                 .enable = OSD_CTRL0_VL2_EN,
162                 .chnsel = OSD_CTRL0_VL2_SEL,
163                 .clksel = VOU_CLK_VL2_SEL,
164         },
165 };
166
167 struct zx_vou_hw {
168         struct device *dev;
169         void __iomem *osd;
170         void __iomem *timing;
171         void __iomem *vouctl;
172         void __iomem *otfppu;
173         void __iomem *dtrc;
174         struct clk *axi_clk;
175         struct clk *ppu_clk;
176         struct clk *main_clk;
177         struct clk *aux_clk;
178         struct zx_crtc *main_crtc;
179         struct zx_crtc *aux_crtc;
180 };
181
182 enum vou_inf_data_sel {
183         VOU_YUV444      = 0,
184         VOU_RGB_101010  = 1,
185         VOU_RGB_888     = 2,
186         VOU_RGB_666     = 3,
187 };
188
189 struct vou_inf {
190         enum vou_inf_id id;
191         enum vou_inf_data_sel data_sel;
192         u32 clocks_en_bits;
193         u32 clocks_sel_bits;
194 };
195
196 static struct vou_inf vou_infs[] = {
197         [VOU_HDMI] = {
198                 .data_sel = VOU_YUV444,
199                 .clocks_en_bits = BIT(24) | BIT(18) | BIT(6),
200                 .clocks_sel_bits = BIT(13) | BIT(2),
201         },
202         [VOU_TV_ENC] = {
203                 .data_sel = VOU_YUV444,
204                 .clocks_en_bits = BIT(15),
205                 .clocks_sel_bits = BIT(11) | BIT(0),
206         },
207 };
208
209 static inline struct zx_vou_hw *crtc_to_vou(struct drm_crtc *crtc)
210 {
211         struct zx_crtc *zcrtc = to_zx_crtc(crtc);
212
213         return zcrtc->vou;
214 }
215
216 void vou_inf_hdmi_audio_sel(struct drm_crtc *crtc,
217                             enum vou_inf_hdmi_audio aud)
218 {
219         struct zx_crtc *zcrtc = to_zx_crtc(crtc);
220         struct zx_vou_hw *vou = zcrtc->vou;
221
222         zx_writel_mask(vou->vouctl + VOU_INF_HDMI_CTRL, VOU_HDMI_AUD_MASK, aud);
223 }
224
225 void vou_inf_enable(enum vou_inf_id id, struct drm_crtc *crtc)
226 {
227         struct zx_crtc *zcrtc = to_zx_crtc(crtc);
228         struct zx_vou_hw *vou = zcrtc->vou;
229         struct vou_inf *inf = &vou_infs[id];
230         bool is_main = zcrtc->chn_type == VOU_CHN_MAIN;
231         u32 data_sel_shift = id << 1;
232
233         /* Select data format */
234         zx_writel_mask(vou->vouctl + VOU_INF_DATA_SEL, 0x3 << data_sel_shift,
235                        inf->data_sel << data_sel_shift);
236
237         /* Select channel */
238         zx_writel_mask(vou->vouctl + VOU_INF_CH_SEL, 0x1 << id,
239                        zcrtc->chn_type << id);
240
241         /* Select interface clocks */
242         zx_writel_mask(vou->vouctl + VOU_CLK_SEL, inf->clocks_sel_bits,
243                        is_main ? 0 : inf->clocks_sel_bits);
244
245         /* Enable interface clocks */
246         zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits,
247                        inf->clocks_en_bits);
248
249         /* Enable the device */
250         zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << id, 1 << id);
251 }
252
253 void vou_inf_disable(enum vou_inf_id id, struct drm_crtc *crtc)
254 {
255         struct zx_vou_hw *vou = crtc_to_vou(crtc);
256         struct vou_inf *inf = &vou_infs[id];
257
258         /* Disable the device */
259         zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << id, 0);
260
261         /* Disable interface clocks */
262         zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits, 0);
263 }
264
265 void zx_vou_config_dividers(struct drm_crtc *crtc,
266                             struct vou_div_config *configs, int num)
267 {
268         struct zx_crtc *zcrtc = to_zx_crtc(crtc);
269         struct zx_vou_hw *vou = zcrtc->vou;
270         const struct zx_crtc_bits *bits = zcrtc->bits;
271         int i;
272
273         /* Clear update flag bit */
274         zx_writel_mask(vou->vouctl + VOU_DIV_PARA, DIV_PARA_UPDATE, 0);
275
276         for (i = 0; i < num; i++) {
277                 struct vou_div_config *cfg = configs + i;
278                 u32 reg, shift;
279
280                 switch (cfg->id) {
281                 case VOU_DIV_VGA:
282                         reg = VOU_CLK_SEL;
283                         shift = bits->div_vga_shift;
284                         break;
285                 case VOU_DIV_PIC:
286                         reg = VOU_CLK_SEL;
287                         shift = bits->div_pic_shift;
288                         break;
289                 case VOU_DIV_TVENC:
290                         reg = VOU_DIV_PARA;
291                         shift = bits->div_tvenc_shift;
292                         break;
293                 case VOU_DIV_HDMI_PNX:
294                         reg = VOU_DIV_PARA;
295                         shift = bits->div_hdmi_pnx_shift;
296                         break;
297                 case VOU_DIV_HDMI:
298                         reg = VOU_DIV_PARA;
299                         shift = bits->div_hdmi_shift;
300                         break;
301                 case VOU_DIV_INF:
302                         reg = VOU_DIV_PARA;
303                         shift = bits->div_inf_shift;
304                         break;
305                 case VOU_DIV_LAYER:
306                         reg = VOU_DIV_PARA;
307                         shift = bits->div_layer_shift;
308                         break;
309                 default:
310                         continue;
311                 }
312
313                 /* Each divider occupies 3 bits */
314                 zx_writel_mask(vou->vouctl + reg, 0x7 << shift,
315                                cfg->val << shift);
316         }
317
318         /* Set update flag bit to get dividers effected */
319         zx_writel_mask(vou->vouctl + VOU_DIV_PARA, DIV_PARA_UPDATE,
320                        DIV_PARA_UPDATE);
321 }
322
323 static inline void vou_chn_set_update(struct zx_crtc *zcrtc)
324 {
325         zx_writel(zcrtc->chnreg + CHN_UPDATE, 1);
326 }
327
328 static void zx_crtc_enable(struct drm_crtc *crtc)
329 {
330         struct drm_display_mode *mode = &crtc->state->adjusted_mode;
331         bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
332         struct zx_crtc *zcrtc = to_zx_crtc(crtc);
333         struct zx_vou_hw *vou = zcrtc->vou;
334         const struct zx_crtc_regs *regs = zcrtc->regs;
335         const struct zx_crtc_bits *bits = zcrtc->bits;
336         struct videomode vm;
337         u32 scan_mask;
338         u32 pol = 0;
339         u32 val;
340         int ret;
341
342         drm_display_mode_to_videomode(mode, &vm);
343
344         /* Set up timing parameters */
345         val = V_ACTIVE((interlaced ? vm.vactive / 2 : vm.vactive) - 1);
346         val |= H_ACTIVE(vm.hactive - 1);
347         zx_writel(vou->timing + regs->fir_active, val);
348
349         val = SYNC_WIDE(vm.hsync_len - 1);
350         val |= BACK_PORCH(vm.hback_porch - 1);
351         val |= FRONT_PORCH(vm.hfront_porch - 1);
352         zx_writel(vou->timing + regs->fir_htiming, val);
353
354         val = SYNC_WIDE(vm.vsync_len - 1);
355         val |= BACK_PORCH(vm.vback_porch - 1);
356         val |= FRONT_PORCH(vm.vfront_porch - 1);
357         zx_writel(vou->timing + regs->fir_vtiming, val);
358
359         if (interlaced) {
360                 u32 shift = bits->sec_vactive_shift;
361                 u32 mask = bits->sec_vactive_mask;
362
363                 val = zx_readl(vou->timing + SEC_V_ACTIVE);
364                 val &= ~mask;
365                 val |= ((vm.vactive / 2 - 1) << shift) & mask;
366                 zx_writel(vou->timing + SEC_V_ACTIVE, val);
367
368                 val = SYNC_WIDE(vm.vsync_len - 1);
369                 /*
370                  * The vback_porch for the second field needs to shift one on
371                  * the value for the first field.
372                  */
373                 val |= BACK_PORCH(vm.vback_porch);
374                 val |= FRONT_PORCH(vm.vfront_porch - 1);
375                 zx_writel(vou->timing + regs->sec_vtiming, val);
376         }
377
378         /* Set up polarities */
379         if (vm.flags & DISPLAY_FLAGS_VSYNC_LOW)
380                 pol |= 1 << POL_VSYNC_SHIFT;
381         if (vm.flags & DISPLAY_FLAGS_HSYNC_LOW)
382                 pol |= 1 << POL_HSYNC_SHIFT;
383
384         zx_writel_mask(vou->timing + TIMING_CTRL, bits->polarity_mask,
385                        pol << bits->polarity_shift);
386
387         /* Setup SHIFT register by following what ZTE BSP does */
388         val = H_SHIFT_VAL;
389         if (interlaced)
390                 val |= V_SHIFT_VAL << 16;
391         zx_writel(vou->timing + regs->timing_shift, val);
392         zx_writel(vou->timing + regs->timing_pi_shift, H_PI_SHIFT_VAL);
393
394         /* Progressive or interlace scan select */
395         scan_mask = bits->interlace_select | bits->pi_enable;
396         zx_writel_mask(vou->timing + SCAN_CTRL, scan_mask,
397                        interlaced ? scan_mask : 0);
398
399         /* Enable TIMING_CTRL */
400         zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable,
401                        bits->tc_enable);
402
403         /* Configure channel screen size */
404         zx_writel_mask(zcrtc->chnreg + CHN_CTRL1, CHN_SCREEN_W_MASK,
405                        vm.hactive << CHN_SCREEN_W_SHIFT);
406         zx_writel_mask(zcrtc->chnreg + CHN_CTRL1, CHN_SCREEN_H_MASK,
407                        vm.vactive << CHN_SCREEN_H_SHIFT);
408
409         /* Configure channel interlace buffer control */
410         zx_writel_mask(zcrtc->chnreg + CHN_INTERLACE_BUF_CTRL, CHN_INTERLACE_EN,
411                        interlaced ? CHN_INTERLACE_EN : 0);
412
413         /* Update channel */
414         vou_chn_set_update(zcrtc);
415
416         /* Enable channel */
417         zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, CHN_ENABLE);
418
419         drm_crtc_vblank_on(crtc);
420
421         ret = clk_set_rate(zcrtc->pixclk, mode->clock * 1000);
422         if (ret) {
423                 DRM_DEV_ERROR(vou->dev, "failed to set pixclk rate: %d\n", ret);
424                 return;
425         }
426
427         ret = clk_prepare_enable(zcrtc->pixclk);
428         if (ret)
429                 DRM_DEV_ERROR(vou->dev, "failed to enable pixclk: %d\n", ret);
430 }
431
432 static void zx_crtc_disable(struct drm_crtc *crtc)
433 {
434         struct zx_crtc *zcrtc = to_zx_crtc(crtc);
435         const struct zx_crtc_bits *bits = zcrtc->bits;
436         struct zx_vou_hw *vou = zcrtc->vou;
437
438         clk_disable_unprepare(zcrtc->pixclk);
439
440         drm_crtc_vblank_off(crtc);
441
442         /* Disable channel */
443         zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, 0);
444
445         /* Disable TIMING_CTRL */
446         zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable, 0);
447 }
448
449 static void zx_crtc_atomic_flush(struct drm_crtc *crtc,
450                                   struct drm_crtc_state *old_state)
451 {
452         struct drm_pending_vblank_event *event = crtc->state->event;
453
454         if (!event)
455                 return;
456
457         crtc->state->event = NULL;
458
459         spin_lock_irq(&crtc->dev->event_lock);
460         if (drm_crtc_vblank_get(crtc) == 0)
461                 drm_crtc_arm_vblank_event(crtc, event);
462         else
463                 drm_crtc_send_vblank_event(crtc, event);
464         spin_unlock_irq(&crtc->dev->event_lock);
465 }
466
467 static const struct drm_crtc_helper_funcs zx_crtc_helper_funcs = {
468         .enable = zx_crtc_enable,
469         .disable = zx_crtc_disable,
470         .atomic_flush = zx_crtc_atomic_flush,
471 };
472
473 static const struct drm_crtc_funcs zx_crtc_funcs = {
474         .destroy = drm_crtc_cleanup,
475         .set_config = drm_atomic_helper_set_config,
476         .page_flip = drm_atomic_helper_page_flip,
477         .reset = drm_atomic_helper_crtc_reset,
478         .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
479         .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
480 };
481
482 static int zx_crtc_init(struct drm_device *drm, struct zx_vou_hw *vou,
483                         enum vou_chn_type chn_type)
484 {
485         struct device *dev = vou->dev;
486         struct zx_plane *zplane;
487         struct zx_crtc *zcrtc;
488         int ret;
489
490         zcrtc = devm_kzalloc(dev, sizeof(*zcrtc), GFP_KERNEL);
491         if (!zcrtc)
492                 return -ENOMEM;
493
494         zcrtc->vou = vou;
495         zcrtc->chn_type = chn_type;
496
497         zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
498         if (!zplane)
499                 return -ENOMEM;
500
501         zplane->dev = dev;
502
503         if (chn_type == VOU_CHN_MAIN) {
504                 zplane->layer = vou->osd + MAIN_GL_OFFSET;
505                 zplane->csc = vou->osd + MAIN_CSC_OFFSET;
506                 zplane->hbsc = vou->osd + MAIN_HBSC_OFFSET;
507                 zplane->rsz = vou->otfppu + MAIN_RSZ_OFFSET;
508                 zplane->bits = &zx_gl_bits[0];
509                 zcrtc->chnreg = vou->osd + OSD_MAIN_CHN;
510                 zcrtc->regs = &main_crtc_regs;
511                 zcrtc->bits = &main_crtc_bits;
512         } else {
513                 zplane->layer = vou->osd + AUX_GL_OFFSET;
514                 zplane->csc = vou->osd + AUX_CSC_OFFSET;
515                 zplane->hbsc = vou->osd + AUX_HBSC_OFFSET;
516                 zplane->rsz = vou->otfppu + AUX_RSZ_OFFSET;
517                 zplane->bits = &zx_gl_bits[1];
518                 zcrtc->chnreg = vou->osd + OSD_AUX_CHN;
519                 zcrtc->regs = &aux_crtc_regs;
520                 zcrtc->bits = &aux_crtc_bits;
521         }
522
523         zcrtc->pixclk = devm_clk_get(dev, (chn_type == VOU_CHN_MAIN) ?
524                                           "main_wclk" : "aux_wclk");
525         if (IS_ERR(zcrtc->pixclk)) {
526                 ret = PTR_ERR(zcrtc->pixclk);
527                 DRM_DEV_ERROR(dev, "failed to get pix clk: %d\n", ret);
528                 return ret;
529         }
530
531         ret = zx_plane_init(drm, zplane, DRM_PLANE_TYPE_PRIMARY);
532         if (ret) {
533                 DRM_DEV_ERROR(dev, "failed to init primary plane: %d\n", ret);
534                 return ret;
535         }
536
537         zcrtc->primary = &zplane->plane;
538
539         ret = drm_crtc_init_with_planes(drm, &zcrtc->crtc, zcrtc->primary, NULL,
540                                         &zx_crtc_funcs, NULL);
541         if (ret) {
542                 DRM_DEV_ERROR(dev, "failed to init drm crtc: %d\n", ret);
543                 return ret;
544         }
545
546         drm_crtc_helper_add(&zcrtc->crtc, &zx_crtc_helper_funcs);
547
548         if (chn_type == VOU_CHN_MAIN)
549                 vou->main_crtc = zcrtc;
550         else
551                 vou->aux_crtc = zcrtc;
552
553         return 0;
554 }
555
556 int zx_vou_enable_vblank(struct drm_device *drm, unsigned int pipe)
557 {
558         struct drm_crtc *crtc;
559         struct zx_crtc *zcrtc;
560         struct zx_vou_hw *vou;
561         u32 int_frame_mask;
562
563         crtc = drm_crtc_from_index(drm, pipe);
564         if (!crtc)
565                 return 0;
566
567         vou = crtc_to_vou(crtc);
568         zcrtc = to_zx_crtc(crtc);
569         int_frame_mask = zcrtc->bits->int_frame_mask;
570
571         zx_writel_mask(vou->timing + TIMING_INT_CTRL, int_frame_mask,
572                        int_frame_mask);
573
574         return 0;
575 }
576
577 void zx_vou_disable_vblank(struct drm_device *drm, unsigned int pipe)
578 {
579         struct drm_crtc *crtc;
580         struct zx_crtc *zcrtc;
581         struct zx_vou_hw *vou;
582
583         crtc = drm_crtc_from_index(drm, pipe);
584         if (!crtc)
585                 return;
586
587         vou = crtc_to_vou(crtc);
588         zcrtc = to_zx_crtc(crtc);
589
590         zx_writel_mask(vou->timing + TIMING_INT_CTRL,
591                        zcrtc->bits->int_frame_mask, 0);
592 }
593
594 void zx_vou_layer_enable(struct drm_plane *plane)
595 {
596         struct zx_crtc *zcrtc = to_zx_crtc(plane->state->crtc);
597         struct zx_vou_hw *vou = zcrtc->vou;
598         struct zx_plane *zplane = to_zx_plane(plane);
599         const struct vou_layer_bits *bits = zplane->bits;
600
601         if (zcrtc->chn_type == VOU_CHN_MAIN) {
602                 zx_writel_mask(vou->osd + OSD_CTRL0, bits->chnsel, 0);
603                 zx_writel_mask(vou->vouctl + VOU_CLK_SEL, bits->clksel, 0);
604         } else {
605                 zx_writel_mask(vou->osd + OSD_CTRL0, bits->chnsel,
606                                bits->chnsel);
607                 zx_writel_mask(vou->vouctl + VOU_CLK_SEL, bits->clksel,
608                                bits->clksel);
609         }
610
611         zx_writel_mask(vou->osd + OSD_CTRL0, bits->enable, bits->enable);
612 }
613
614 void zx_vou_layer_disable(struct drm_plane *plane)
615 {
616         struct zx_crtc *zcrtc = to_zx_crtc(plane->crtc);
617         struct zx_vou_hw *vou = zcrtc->vou;
618         struct zx_plane *zplane = to_zx_plane(plane);
619         const struct vou_layer_bits *bits = zplane->bits;
620
621         zx_writel_mask(vou->osd + OSD_CTRL0, bits->enable, 0);
622 }
623
624 static void zx_overlay_init(struct drm_device *drm, struct zx_vou_hw *vou)
625 {
626         struct device *dev = vou->dev;
627         struct zx_plane *zplane;
628         int i;
629         int ret;
630
631         /*
632          * VL0 has some quirks on scaling support which need special handling.
633          * Let's leave it out for now.
634          */
635         for (i = 1; i < VL_NUM; i++) {
636                 zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
637                 if (!zplane) {
638                         DRM_DEV_ERROR(dev, "failed to allocate zplane %d\n", i);
639                         return;
640                 }
641
642                 zplane->layer = vou->osd + OSD_VL_OFFSET(i);
643                 zplane->hbsc = vou->osd + HBSC_VL_OFFSET(i);
644                 zplane->rsz = vou->otfppu + RSZ_VL_OFFSET(i);
645                 zplane->bits = &zx_vl_bits[i];
646
647                 ret = zx_plane_init(drm, zplane, DRM_PLANE_TYPE_OVERLAY);
648                 if (ret) {
649                         DRM_DEV_ERROR(dev, "failed to init overlay %d\n", i);
650                         continue;
651                 }
652         }
653 }
654
655 static inline void zx_osd_int_update(struct zx_crtc *zcrtc)
656 {
657         struct drm_crtc *crtc = &zcrtc->crtc;
658         struct drm_plane *plane;
659
660         vou_chn_set_update(zcrtc);
661
662         drm_for_each_plane_mask(plane, crtc->dev, crtc->state->plane_mask)
663                 zx_plane_set_update(plane);
664 }
665
666 static irqreturn_t vou_irq_handler(int irq, void *dev_id)
667 {
668         struct zx_vou_hw *vou = dev_id;
669         u32 state;
670
671         /* Handle TIMING_CTRL frame interrupts */
672         state = zx_readl(vou->timing + TIMING_INT_STATE);
673         zx_writel(vou->timing + TIMING_INT_STATE, state);
674
675         if (state & TIMING_INT_MAIN_FRAME)
676                 drm_crtc_handle_vblank(&vou->main_crtc->crtc);
677
678         if (state & TIMING_INT_AUX_FRAME)
679                 drm_crtc_handle_vblank(&vou->aux_crtc->crtc);
680
681         /* Handle OSD interrupts */
682         state = zx_readl(vou->osd + OSD_INT_STA);
683         zx_writel(vou->osd + OSD_INT_CLRSTA, state);
684
685         if (state & OSD_INT_MAIN_UPT)
686                 zx_osd_int_update(vou->main_crtc);
687
688         if (state & OSD_INT_AUX_UPT)
689                 zx_osd_int_update(vou->aux_crtc);
690
691         if (state & OSD_INT_ERROR)
692                 DRM_DEV_ERROR(vou->dev, "OSD ERROR: 0x%08x!\n", state);
693
694         return IRQ_HANDLED;
695 }
696
697 static void vou_dtrc_init(struct zx_vou_hw *vou)
698 {
699         /* Clear bit for bypass by ID */
700         zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL,
701                        TILE2RASTESCAN_BYPASS_MODE, 0);
702
703         /* Select ARIDR mode */
704         zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL, DETILE_ARIDR_MODE_MASK,
705                        DETILE_ARID_IN_ARIDR);
706
707         /* Bypass decompression for both frames */
708         zx_writel_mask(vou->dtrc + DTRC_F0_CTRL, DTRC_DECOMPRESS_BYPASS,
709                        DTRC_DECOMPRESS_BYPASS);
710         zx_writel_mask(vou->dtrc + DTRC_F1_CTRL, DTRC_DECOMPRESS_BYPASS,
711                        DTRC_DECOMPRESS_BYPASS);
712
713         /* Set up ARID register */
714         zx_writel(vou->dtrc + DTRC_ARID, DTRC_ARID3(0xf) | DTRC_ARID2(0xe) |
715                   DTRC_ARID1(0xf) | DTRC_ARID0(0xe));
716 }
717
718 static void vou_hw_init(struct zx_vou_hw *vou)
719 {
720         /* Release reset for all VOU modules */
721         zx_writel(vou->vouctl + VOU_SOFT_RST, ~0);
722
723         /* Enable clock auto-gating for all VOU modules */
724         zx_writel(vou->vouctl + VOU_CLK_REQEN, ~0);
725
726         /* Enable all VOU module clocks */
727         zx_writel(vou->vouctl + VOU_CLK_EN, ~0);
728
729         /* Clear both OSD and TIMING_CTRL interrupt state */
730         zx_writel(vou->osd + OSD_INT_CLRSTA, ~0);
731         zx_writel(vou->timing + TIMING_INT_STATE, ~0);
732
733         /* Enable OSD and TIMING_CTRL interrrupts */
734         zx_writel(vou->osd + OSD_INT_MSK, OSD_INT_ENABLE);
735         zx_writel(vou->timing + TIMING_INT_CTRL, TIMING_INT_ENABLE);
736
737         /* Select GPC as input to gl/vl scaler as a sane default setting */
738         zx_writel(vou->otfppu + OTFPPU_RSZ_DATA_SOURCE, 0x2a);
739
740         /*
741          * Needs to reset channel and layer logic per frame when frame starts
742          * to get VOU work properly.
743          */
744         zx_writel_mask(vou->osd + OSD_RST_CLR, RST_PER_FRAME, RST_PER_FRAME);
745
746         vou_dtrc_init(vou);
747 }
748
749 static int zx_crtc_bind(struct device *dev, struct device *master, void *data)
750 {
751         struct platform_device *pdev = to_platform_device(dev);
752         struct drm_device *drm = data;
753         struct zx_vou_hw *vou;
754         struct resource *res;
755         int irq;
756         int ret;
757
758         vou = devm_kzalloc(dev, sizeof(*vou), GFP_KERNEL);
759         if (!vou)
760                 return -ENOMEM;
761
762         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "osd");
763         vou->osd = devm_ioremap_resource(dev, res);
764         if (IS_ERR(vou->osd)) {
765                 ret = PTR_ERR(vou->osd);
766                 DRM_DEV_ERROR(dev, "failed to remap osd region: %d\n", ret);
767                 return ret;
768         }
769
770         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "timing_ctrl");
771         vou->timing = devm_ioremap_resource(dev, res);
772         if (IS_ERR(vou->timing)) {
773                 ret = PTR_ERR(vou->timing);
774                 DRM_DEV_ERROR(dev, "failed to remap timing_ctrl region: %d\n",
775                               ret);
776                 return ret;
777         }
778
779         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dtrc");
780         vou->dtrc = devm_ioremap_resource(dev, res);
781         if (IS_ERR(vou->dtrc)) {
782                 ret = PTR_ERR(vou->dtrc);
783                 DRM_DEV_ERROR(dev, "failed to remap dtrc region: %d\n", ret);
784                 return ret;
785         }
786
787         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vou_ctrl");
788         vou->vouctl = devm_ioremap_resource(dev, res);
789         if (IS_ERR(vou->vouctl)) {
790                 ret = PTR_ERR(vou->vouctl);
791                 DRM_DEV_ERROR(dev, "failed to remap vou_ctrl region: %d\n",
792                               ret);
793                 return ret;
794         }
795
796         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "otfppu");
797         vou->otfppu = devm_ioremap_resource(dev, res);
798         if (IS_ERR(vou->otfppu)) {
799                 ret = PTR_ERR(vou->otfppu);
800                 DRM_DEV_ERROR(dev, "failed to remap otfppu region: %d\n", ret);
801                 return ret;
802         }
803
804         irq = platform_get_irq(pdev, 0);
805         if (irq < 0)
806                 return irq;
807
808         vou->axi_clk = devm_clk_get(dev, "aclk");
809         if (IS_ERR(vou->axi_clk)) {
810                 ret = PTR_ERR(vou->axi_clk);
811                 DRM_DEV_ERROR(dev, "failed to get axi_clk: %d\n", ret);
812                 return ret;
813         }
814
815         vou->ppu_clk = devm_clk_get(dev, "ppu_wclk");
816         if (IS_ERR(vou->ppu_clk)) {
817                 ret = PTR_ERR(vou->ppu_clk);
818                 DRM_DEV_ERROR(dev, "failed to get ppu_clk: %d\n", ret);
819                 return ret;
820         }
821
822         ret = clk_prepare_enable(vou->axi_clk);
823         if (ret) {
824                 DRM_DEV_ERROR(dev, "failed to enable axi_clk: %d\n", ret);
825                 return ret;
826         }
827
828         clk_prepare_enable(vou->ppu_clk);
829         if (ret) {
830                 DRM_DEV_ERROR(dev, "failed to enable ppu_clk: %d\n", ret);
831                 goto disable_axi_clk;
832         }
833
834         vou->dev = dev;
835         dev_set_drvdata(dev, vou);
836
837         vou_hw_init(vou);
838
839         ret = devm_request_irq(dev, irq, vou_irq_handler, 0, "zx_vou", vou);
840         if (ret < 0) {
841                 DRM_DEV_ERROR(dev, "failed to request vou irq: %d\n", ret);
842                 goto disable_ppu_clk;
843         }
844
845         ret = zx_crtc_init(drm, vou, VOU_CHN_MAIN);
846         if (ret) {
847                 DRM_DEV_ERROR(dev, "failed to init main channel crtc: %d\n",
848                               ret);
849                 goto disable_ppu_clk;
850         }
851
852         ret = zx_crtc_init(drm, vou, VOU_CHN_AUX);
853         if (ret) {
854                 DRM_DEV_ERROR(dev, "failed to init aux channel crtc: %d\n",
855                               ret);
856                 goto disable_ppu_clk;
857         }
858
859         zx_overlay_init(drm, vou);
860
861         return 0;
862
863 disable_ppu_clk:
864         clk_disable_unprepare(vou->ppu_clk);
865 disable_axi_clk:
866         clk_disable_unprepare(vou->axi_clk);
867         return ret;
868 }
869
870 static void zx_crtc_unbind(struct device *dev, struct device *master,
871                            void *data)
872 {
873         struct zx_vou_hw *vou = dev_get_drvdata(dev);
874
875         clk_disable_unprepare(vou->axi_clk);
876         clk_disable_unprepare(vou->ppu_clk);
877 }
878
879 static const struct component_ops zx_crtc_component_ops = {
880         .bind = zx_crtc_bind,
881         .unbind = zx_crtc_unbind,
882 };
883
884 static int zx_crtc_probe(struct platform_device *pdev)
885 {
886         return component_add(&pdev->dev, &zx_crtc_component_ops);
887 }
888
889 static int zx_crtc_remove(struct platform_device *pdev)
890 {
891         component_del(&pdev->dev, &zx_crtc_component_ops);
892         return 0;
893 }
894
895 static const struct of_device_id zx_crtc_of_match[] = {
896         { .compatible = "zte,zx296718-dpc", },
897         { /* end */ },
898 };
899 MODULE_DEVICE_TABLE(of, zx_crtc_of_match);
900
901 struct platform_driver zx_crtc_driver = {
902         .probe = zx_crtc_probe,
903         .remove = zx_crtc_remove,
904         .driver = {
905                 .name = "zx-crtc",
906                 .of_match_table = zx_crtc_of_match,
907         },
908 };