5145215b46008c5b4f819c3295a23ef2f4fc4f87
[linux-2.6-microblaze.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 int zx_vou_enable_vblank(struct drm_crtc *crtc)
474 {
475         struct zx_crtc *zcrtc = to_zx_crtc(crtc);
476         struct zx_vou_hw *vou = crtc_to_vou(crtc);
477         u32 int_frame_mask = zcrtc->bits->int_frame_mask;
478
479         zx_writel_mask(vou->timing + TIMING_INT_CTRL, int_frame_mask,
480                        int_frame_mask);
481
482         return 0;
483 }
484
485 static void zx_vou_disable_vblank(struct drm_crtc *crtc)
486 {
487         struct zx_crtc *zcrtc = to_zx_crtc(crtc);
488         struct zx_vou_hw *vou = crtc_to_vou(crtc);
489
490         zx_writel_mask(vou->timing + TIMING_INT_CTRL,
491                        zcrtc->bits->int_frame_mask, 0);
492 }
493
494 static const struct drm_crtc_funcs zx_crtc_funcs = {
495         .destroy = drm_crtc_cleanup,
496         .set_config = drm_atomic_helper_set_config,
497         .page_flip = drm_atomic_helper_page_flip,
498         .reset = drm_atomic_helper_crtc_reset,
499         .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
500         .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
501         .enable_vblank = zx_vou_enable_vblank,
502         .disable_vblank = zx_vou_disable_vblank,
503 };
504
505 static int zx_crtc_init(struct drm_device *drm, struct zx_vou_hw *vou,
506                         enum vou_chn_type chn_type)
507 {
508         struct device *dev = vou->dev;
509         struct zx_plane *zplane;
510         struct zx_crtc *zcrtc;
511         int ret;
512
513         zcrtc = devm_kzalloc(dev, sizeof(*zcrtc), GFP_KERNEL);
514         if (!zcrtc)
515                 return -ENOMEM;
516
517         zcrtc->vou = vou;
518         zcrtc->chn_type = chn_type;
519
520         zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
521         if (!zplane)
522                 return -ENOMEM;
523
524         zplane->dev = dev;
525
526         if (chn_type == VOU_CHN_MAIN) {
527                 zplane->layer = vou->osd + MAIN_GL_OFFSET;
528                 zplane->csc = vou->osd + MAIN_CSC_OFFSET;
529                 zplane->hbsc = vou->osd + MAIN_HBSC_OFFSET;
530                 zplane->rsz = vou->otfppu + MAIN_RSZ_OFFSET;
531                 zplane->bits = &zx_gl_bits[0];
532                 zcrtc->chnreg = vou->osd + OSD_MAIN_CHN;
533                 zcrtc->regs = &main_crtc_regs;
534                 zcrtc->bits = &main_crtc_bits;
535         } else {
536                 zplane->layer = vou->osd + AUX_GL_OFFSET;
537                 zplane->csc = vou->osd + AUX_CSC_OFFSET;
538                 zplane->hbsc = vou->osd + AUX_HBSC_OFFSET;
539                 zplane->rsz = vou->otfppu + AUX_RSZ_OFFSET;
540                 zplane->bits = &zx_gl_bits[1];
541                 zcrtc->chnreg = vou->osd + OSD_AUX_CHN;
542                 zcrtc->regs = &aux_crtc_regs;
543                 zcrtc->bits = &aux_crtc_bits;
544         }
545
546         zcrtc->pixclk = devm_clk_get(dev, (chn_type == VOU_CHN_MAIN) ?
547                                           "main_wclk" : "aux_wclk");
548         if (IS_ERR(zcrtc->pixclk)) {
549                 ret = PTR_ERR(zcrtc->pixclk);
550                 DRM_DEV_ERROR(dev, "failed to get pix clk: %d\n", ret);
551                 return ret;
552         }
553
554         ret = zx_plane_init(drm, zplane, DRM_PLANE_TYPE_PRIMARY);
555         if (ret) {
556                 DRM_DEV_ERROR(dev, "failed to init primary plane: %d\n", ret);
557                 return ret;
558         }
559
560         zcrtc->primary = &zplane->plane;
561
562         ret = drm_crtc_init_with_planes(drm, &zcrtc->crtc, zcrtc->primary, NULL,
563                                         &zx_crtc_funcs, NULL);
564         if (ret) {
565                 DRM_DEV_ERROR(dev, "failed to init drm crtc: %d\n", ret);
566                 return ret;
567         }
568
569         drm_crtc_helper_add(&zcrtc->crtc, &zx_crtc_helper_funcs);
570
571         if (chn_type == VOU_CHN_MAIN)
572                 vou->main_crtc = zcrtc;
573         else
574                 vou->aux_crtc = zcrtc;
575
576         return 0;
577 }
578
579 void zx_vou_layer_enable(struct drm_plane *plane)
580 {
581         struct zx_crtc *zcrtc = to_zx_crtc(plane->state->crtc);
582         struct zx_vou_hw *vou = zcrtc->vou;
583         struct zx_plane *zplane = to_zx_plane(plane);
584         const struct vou_layer_bits *bits = zplane->bits;
585
586         if (zcrtc->chn_type == VOU_CHN_MAIN) {
587                 zx_writel_mask(vou->osd + OSD_CTRL0, bits->chnsel, 0);
588                 zx_writel_mask(vou->vouctl + VOU_CLK_SEL, bits->clksel, 0);
589         } else {
590                 zx_writel_mask(vou->osd + OSD_CTRL0, bits->chnsel,
591                                bits->chnsel);
592                 zx_writel_mask(vou->vouctl + VOU_CLK_SEL, bits->clksel,
593                                bits->clksel);
594         }
595
596         zx_writel_mask(vou->osd + OSD_CTRL0, bits->enable, bits->enable);
597 }
598
599 void zx_vou_layer_disable(struct drm_plane *plane)
600 {
601         struct zx_crtc *zcrtc = to_zx_crtc(plane->crtc);
602         struct zx_vou_hw *vou = zcrtc->vou;
603         struct zx_plane *zplane = to_zx_plane(plane);
604         const struct vou_layer_bits *bits = zplane->bits;
605
606         zx_writel_mask(vou->osd + OSD_CTRL0, bits->enable, 0);
607 }
608
609 static void zx_overlay_init(struct drm_device *drm, struct zx_vou_hw *vou)
610 {
611         struct device *dev = vou->dev;
612         struct zx_plane *zplane;
613         int i;
614         int ret;
615
616         /*
617          * VL0 has some quirks on scaling support which need special handling.
618          * Let's leave it out for now.
619          */
620         for (i = 1; i < VL_NUM; i++) {
621                 zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
622                 if (!zplane) {
623                         DRM_DEV_ERROR(dev, "failed to allocate zplane %d\n", i);
624                         return;
625                 }
626
627                 zplane->layer = vou->osd + OSD_VL_OFFSET(i);
628                 zplane->hbsc = vou->osd + HBSC_VL_OFFSET(i);
629                 zplane->rsz = vou->otfppu + RSZ_VL_OFFSET(i);
630                 zplane->bits = &zx_vl_bits[i];
631
632                 ret = zx_plane_init(drm, zplane, DRM_PLANE_TYPE_OVERLAY);
633                 if (ret) {
634                         DRM_DEV_ERROR(dev, "failed to init overlay %d\n", i);
635                         continue;
636                 }
637         }
638 }
639
640 static inline void zx_osd_int_update(struct zx_crtc *zcrtc)
641 {
642         struct drm_crtc *crtc = &zcrtc->crtc;
643         struct drm_plane *plane;
644
645         vou_chn_set_update(zcrtc);
646
647         drm_for_each_plane_mask(plane, crtc->dev, crtc->state->plane_mask)
648                 zx_plane_set_update(plane);
649 }
650
651 static irqreturn_t vou_irq_handler(int irq, void *dev_id)
652 {
653         struct zx_vou_hw *vou = dev_id;
654         u32 state;
655
656         /* Handle TIMING_CTRL frame interrupts */
657         state = zx_readl(vou->timing + TIMING_INT_STATE);
658         zx_writel(vou->timing + TIMING_INT_STATE, state);
659
660         if (state & TIMING_INT_MAIN_FRAME)
661                 drm_crtc_handle_vblank(&vou->main_crtc->crtc);
662
663         if (state & TIMING_INT_AUX_FRAME)
664                 drm_crtc_handle_vblank(&vou->aux_crtc->crtc);
665
666         /* Handle OSD interrupts */
667         state = zx_readl(vou->osd + OSD_INT_STA);
668         zx_writel(vou->osd + OSD_INT_CLRSTA, state);
669
670         if (state & OSD_INT_MAIN_UPT)
671                 zx_osd_int_update(vou->main_crtc);
672
673         if (state & OSD_INT_AUX_UPT)
674                 zx_osd_int_update(vou->aux_crtc);
675
676         if (state & OSD_INT_ERROR)
677                 DRM_DEV_ERROR(vou->dev, "OSD ERROR: 0x%08x!\n", state);
678
679         return IRQ_HANDLED;
680 }
681
682 static void vou_dtrc_init(struct zx_vou_hw *vou)
683 {
684         /* Clear bit for bypass by ID */
685         zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL,
686                        TILE2RASTESCAN_BYPASS_MODE, 0);
687
688         /* Select ARIDR mode */
689         zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL, DETILE_ARIDR_MODE_MASK,
690                        DETILE_ARID_IN_ARIDR);
691
692         /* Bypass decompression for both frames */
693         zx_writel_mask(vou->dtrc + DTRC_F0_CTRL, DTRC_DECOMPRESS_BYPASS,
694                        DTRC_DECOMPRESS_BYPASS);
695         zx_writel_mask(vou->dtrc + DTRC_F1_CTRL, DTRC_DECOMPRESS_BYPASS,
696                        DTRC_DECOMPRESS_BYPASS);
697
698         /* Set up ARID register */
699         zx_writel(vou->dtrc + DTRC_ARID, DTRC_ARID3(0xf) | DTRC_ARID2(0xe) |
700                   DTRC_ARID1(0xf) | DTRC_ARID0(0xe));
701 }
702
703 static void vou_hw_init(struct zx_vou_hw *vou)
704 {
705         /* Release reset for all VOU modules */
706         zx_writel(vou->vouctl + VOU_SOFT_RST, ~0);
707
708         /* Enable all VOU module clocks */
709         zx_writel(vou->vouctl + VOU_CLK_EN, ~0);
710
711         /* Clear both OSD and TIMING_CTRL interrupt state */
712         zx_writel(vou->osd + OSD_INT_CLRSTA, ~0);
713         zx_writel(vou->timing + TIMING_INT_STATE, ~0);
714
715         /* Enable OSD and TIMING_CTRL interrrupts */
716         zx_writel(vou->osd + OSD_INT_MSK, OSD_INT_ENABLE);
717         zx_writel(vou->timing + TIMING_INT_CTRL, TIMING_INT_ENABLE);
718
719         /* Select GPC as input to gl/vl scaler as a sane default setting */
720         zx_writel(vou->otfppu + OTFPPU_RSZ_DATA_SOURCE, 0x2a);
721
722         /*
723          * Needs to reset channel and layer logic per frame when frame starts
724          * to get VOU work properly.
725          */
726         zx_writel_mask(vou->osd + OSD_RST_CLR, RST_PER_FRAME, RST_PER_FRAME);
727
728         vou_dtrc_init(vou);
729 }
730
731 static int zx_crtc_bind(struct device *dev, struct device *master, void *data)
732 {
733         struct platform_device *pdev = to_platform_device(dev);
734         struct drm_device *drm = data;
735         struct zx_vou_hw *vou;
736         struct resource *res;
737         int irq;
738         int ret;
739
740         vou = devm_kzalloc(dev, sizeof(*vou), GFP_KERNEL);
741         if (!vou)
742                 return -ENOMEM;
743
744         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "osd");
745         vou->osd = devm_ioremap_resource(dev, res);
746         if (IS_ERR(vou->osd)) {
747                 ret = PTR_ERR(vou->osd);
748                 DRM_DEV_ERROR(dev, "failed to remap osd region: %d\n", ret);
749                 return ret;
750         }
751
752         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "timing_ctrl");
753         vou->timing = devm_ioremap_resource(dev, res);
754         if (IS_ERR(vou->timing)) {
755                 ret = PTR_ERR(vou->timing);
756                 DRM_DEV_ERROR(dev, "failed to remap timing_ctrl region: %d\n",
757                               ret);
758                 return ret;
759         }
760
761         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dtrc");
762         vou->dtrc = devm_ioremap_resource(dev, res);
763         if (IS_ERR(vou->dtrc)) {
764                 ret = PTR_ERR(vou->dtrc);
765                 DRM_DEV_ERROR(dev, "failed to remap dtrc region: %d\n", ret);
766                 return ret;
767         }
768
769         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vou_ctrl");
770         vou->vouctl = devm_ioremap_resource(dev, res);
771         if (IS_ERR(vou->vouctl)) {
772                 ret = PTR_ERR(vou->vouctl);
773                 DRM_DEV_ERROR(dev, "failed to remap vou_ctrl region: %d\n",
774                               ret);
775                 return ret;
776         }
777
778         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "otfppu");
779         vou->otfppu = devm_ioremap_resource(dev, res);
780         if (IS_ERR(vou->otfppu)) {
781                 ret = PTR_ERR(vou->otfppu);
782                 DRM_DEV_ERROR(dev, "failed to remap otfppu region: %d\n", ret);
783                 return ret;
784         }
785
786         irq = platform_get_irq(pdev, 0);
787         if (irq < 0)
788                 return irq;
789
790         vou->axi_clk = devm_clk_get(dev, "aclk");
791         if (IS_ERR(vou->axi_clk)) {
792                 ret = PTR_ERR(vou->axi_clk);
793                 DRM_DEV_ERROR(dev, "failed to get axi_clk: %d\n", ret);
794                 return ret;
795         }
796
797         vou->ppu_clk = devm_clk_get(dev, "ppu_wclk");
798         if (IS_ERR(vou->ppu_clk)) {
799                 ret = PTR_ERR(vou->ppu_clk);
800                 DRM_DEV_ERROR(dev, "failed to get ppu_clk: %d\n", ret);
801                 return ret;
802         }
803
804         ret = clk_prepare_enable(vou->axi_clk);
805         if (ret) {
806                 DRM_DEV_ERROR(dev, "failed to enable axi_clk: %d\n", ret);
807                 return ret;
808         }
809
810         clk_prepare_enable(vou->ppu_clk);
811         if (ret) {
812                 DRM_DEV_ERROR(dev, "failed to enable ppu_clk: %d\n", ret);
813                 goto disable_axi_clk;
814         }
815
816         vou->dev = dev;
817         dev_set_drvdata(dev, vou);
818
819         vou_hw_init(vou);
820
821         ret = devm_request_irq(dev, irq, vou_irq_handler, 0, "zx_vou", vou);
822         if (ret < 0) {
823                 DRM_DEV_ERROR(dev, "failed to request vou irq: %d\n", ret);
824                 goto disable_ppu_clk;
825         }
826
827         ret = zx_crtc_init(drm, vou, VOU_CHN_MAIN);
828         if (ret) {
829                 DRM_DEV_ERROR(dev, "failed to init main channel crtc: %d\n",
830                               ret);
831                 goto disable_ppu_clk;
832         }
833
834         ret = zx_crtc_init(drm, vou, VOU_CHN_AUX);
835         if (ret) {
836                 DRM_DEV_ERROR(dev, "failed to init aux channel crtc: %d\n",
837                               ret);
838                 goto disable_ppu_clk;
839         }
840
841         zx_overlay_init(drm, vou);
842
843         return 0;
844
845 disable_ppu_clk:
846         clk_disable_unprepare(vou->ppu_clk);
847 disable_axi_clk:
848         clk_disable_unprepare(vou->axi_clk);
849         return ret;
850 }
851
852 static void zx_crtc_unbind(struct device *dev, struct device *master,
853                            void *data)
854 {
855         struct zx_vou_hw *vou = dev_get_drvdata(dev);
856
857         clk_disable_unprepare(vou->axi_clk);
858         clk_disable_unprepare(vou->ppu_clk);
859 }
860
861 static const struct component_ops zx_crtc_component_ops = {
862         .bind = zx_crtc_bind,
863         .unbind = zx_crtc_unbind,
864 };
865
866 static int zx_crtc_probe(struct platform_device *pdev)
867 {
868         return component_add(&pdev->dev, &zx_crtc_component_ops);
869 }
870
871 static int zx_crtc_remove(struct platform_device *pdev)
872 {
873         component_del(&pdev->dev, &zx_crtc_component_ops);
874         return 0;
875 }
876
877 static const struct of_device_id zx_crtc_of_match[] = {
878         { .compatible = "zte,zx296718-dpc", },
879         { /* end */ },
880 };
881 MODULE_DEVICE_TABLE(of, zx_crtc_of_match);
882
883 struct platform_driver zx_crtc_driver = {
884         .probe = zx_crtc_probe,
885         .remove = zx_crtc_remove,
886         .driver = {
887                 .name = "zx-crtc",
888                 .of_match_table = zx_crtc_of_match,
889         },
890 };