]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpu/drm/zte/zx_vou.c
drm/zte: drop use of drmP.h
[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/module.h>
14 #include <linux/of_address.h>
15 #include <linux/platform_device.h>
16
17 #include <video/videomode.h>
18
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>
28
29 #include "zx_common_regs.h"
30 #include "zx_drm_drv.h"
31 #include "zx_plane.h"
32 #include "zx_vou.h"
33 #include "zx_vou_regs.h"
34
35 #define GL_NUM  2
36 #define VL_NUM  3
37
38 enum vou_chn_type {
39         VOU_CHN_MAIN,
40         VOU_CHN_AUX,
41 };
42
43 struct zx_crtc_regs {
44         u32 fir_active;
45         u32 fir_htiming;
46         u32 fir_vtiming;
47         u32 sec_vtiming;
48         u32 timing_shift;
49         u32 timing_pi_shift;
50 };
51
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,
59 };
60
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,
68 };
69
70 struct zx_crtc_bits {
71         u32 polarity_mask;
72         u32 polarity_shift;
73         u32 int_frame_mask;
74         u32 tc_enable;
75         u32 sec_vactive_shift;
76         u32 sec_vactive_mask;
77         u32 interlace_select;
78         u32 pi_enable;
79         u32 div_vga_shift;
80         u32 div_pic_shift;
81         u32 div_tvenc_shift;
82         u32 div_hdmi_pnx_shift;
83         u32 div_hdmi_shift;
84         u32 div_inf_shift;
85         u32 div_layer_shift;
86 };
87
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,
104 };
105
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,
122 };
123
124 struct zx_crtc {
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;
134         struct clk *pixclk;
135 };
136
137 #define to_zx_crtc(x) container_of(x, struct zx_crtc, crtc)
138
139 struct vou_layer_bits {
140         u32 enable;
141         u32 chnsel;
142         u32 clksel;
143 };
144
145 static const struct vou_layer_bits zx_gl_bits[GL_NUM] = {
146         {
147                 .enable = OSD_CTRL0_GL0_EN,
148                 .chnsel = OSD_CTRL0_GL0_SEL,
149                 .clksel = VOU_CLK_GL0_SEL,
150         }, {
151                 .enable = OSD_CTRL0_GL1_EN,
152                 .chnsel = OSD_CTRL0_GL1_SEL,
153                 .clksel = VOU_CLK_GL1_SEL,
154         },
155 };
156
157 static const struct vou_layer_bits zx_vl_bits[VL_NUM] = {
158         {
159                 .enable = OSD_CTRL0_VL0_EN,
160                 .chnsel = OSD_CTRL0_VL0_SEL,
161                 .clksel = VOU_CLK_VL0_SEL,
162         }, {
163                 .enable = OSD_CTRL0_VL1_EN,
164                 .chnsel = OSD_CTRL0_VL1_SEL,
165                 .clksel = VOU_CLK_VL1_SEL,
166         }, {
167                 .enable = OSD_CTRL0_VL2_EN,
168                 .chnsel = OSD_CTRL0_VL2_SEL,
169                 .clksel = VOU_CLK_VL2_SEL,
170         },
171 };
172
173 struct zx_vou_hw {
174         struct device *dev;
175         void __iomem *osd;
176         void __iomem *timing;
177         void __iomem *vouctl;
178         void __iomem *otfppu;
179         void __iomem *dtrc;
180         struct clk *axi_clk;
181         struct clk *ppu_clk;
182         struct clk *main_clk;
183         struct clk *aux_clk;
184         struct zx_crtc *main_crtc;
185         struct zx_crtc *aux_crtc;
186 };
187
188 enum vou_inf_data_sel {
189         VOU_YUV444      = 0,
190         VOU_RGB_101010  = 1,
191         VOU_RGB_888     = 2,
192         VOU_RGB_666     = 3,
193 };
194
195 struct vou_inf {
196         enum vou_inf_id id;
197         enum vou_inf_data_sel data_sel;
198         u32 clocks_en_bits;
199         u32 clocks_sel_bits;
200 };
201
202 static struct vou_inf vou_infs[] = {
203         [VOU_HDMI] = {
204                 .data_sel = VOU_YUV444,
205                 .clocks_en_bits = BIT(24) | BIT(18) | BIT(6),
206                 .clocks_sel_bits = BIT(13) | BIT(2),
207         },
208         [VOU_TV_ENC] = {
209                 .data_sel = VOU_YUV444,
210                 .clocks_en_bits = BIT(15),
211                 .clocks_sel_bits = BIT(11) | BIT(0),
212         },
213         [VOU_VGA] = {
214                 .data_sel = VOU_RGB_888,
215                 .clocks_en_bits = BIT(1),
216                 .clocks_sel_bits = BIT(10),
217         },
218 };
219
220 static inline struct zx_vou_hw *crtc_to_vou(struct drm_crtc *crtc)
221 {
222         struct zx_crtc *zcrtc = to_zx_crtc(crtc);
223
224         return zcrtc->vou;
225 }
226
227 void vou_inf_hdmi_audio_sel(struct drm_crtc *crtc,
228                             enum vou_inf_hdmi_audio aud)
229 {
230         struct zx_crtc *zcrtc = to_zx_crtc(crtc);
231         struct zx_vou_hw *vou = zcrtc->vou;
232
233         zx_writel_mask(vou->vouctl + VOU_INF_HDMI_CTRL, VOU_HDMI_AUD_MASK, aud);
234 }
235
236 void vou_inf_enable(enum vou_inf_id id, struct drm_crtc *crtc)
237 {
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;
245
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,
251                                CSC_WORK_ENABLE);
252
253                 /* Bypass Dither block for RGB output */
254                 zx_writel_mask(dither + OSD_DITHER_CTRL0, DITHER_BYSPASS,
255                                DITHER_BYSPASS);
256         } else {
257                 zx_writel_mask(csc + CSC_CTRL0, CSC_WORK_ENABLE, 0);
258                 zx_writel_mask(dither + OSD_DITHER_CTRL0, DITHER_BYSPASS, 0);
259         }
260
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);
264
265         /* Select channel */
266         zx_writel_mask(vou->vouctl + VOU_INF_CH_SEL, 0x1 << id,
267                        zcrtc->chn_type << id);
268
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);
272
273         /* Enable interface clocks */
274         zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits,
275                        inf->clocks_en_bits);
276
277         /* Enable the device */
278         zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << id, 1 << id);
279 }
280
281 void vou_inf_disable(enum vou_inf_id id, struct drm_crtc *crtc)
282 {
283         struct zx_vou_hw *vou = crtc_to_vou(crtc);
284         struct vou_inf *inf = &vou_infs[id];
285
286         /* Disable the device */
287         zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << id, 0);
288
289         /* Disable interface clocks */
290         zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits, 0);
291 }
292
293 void zx_vou_config_dividers(struct drm_crtc *crtc,
294                             struct vou_div_config *configs, int num)
295 {
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;
299         int i;
300
301         /* Clear update flag bit */
302         zx_writel_mask(vou->vouctl + VOU_DIV_PARA, DIV_PARA_UPDATE, 0);
303
304         for (i = 0; i < num; i++) {
305                 struct vou_div_config *cfg = configs + i;
306                 u32 reg, shift;
307
308                 switch (cfg->id) {
309                 case VOU_DIV_VGA:
310                         reg = VOU_CLK_SEL;
311                         shift = bits->div_vga_shift;
312                         break;
313                 case VOU_DIV_PIC:
314                         reg = VOU_CLK_SEL;
315                         shift = bits->div_pic_shift;
316                         break;
317                 case VOU_DIV_TVENC:
318                         reg = VOU_DIV_PARA;
319                         shift = bits->div_tvenc_shift;
320                         break;
321                 case VOU_DIV_HDMI_PNX:
322                         reg = VOU_DIV_PARA;
323                         shift = bits->div_hdmi_pnx_shift;
324                         break;
325                 case VOU_DIV_HDMI:
326                         reg = VOU_DIV_PARA;
327                         shift = bits->div_hdmi_shift;
328                         break;
329                 case VOU_DIV_INF:
330                         reg = VOU_DIV_PARA;
331                         shift = bits->div_inf_shift;
332                         break;
333                 case VOU_DIV_LAYER:
334                         reg = VOU_DIV_PARA;
335                         shift = bits->div_layer_shift;
336                         break;
337                 default:
338                         continue;
339                 }
340
341                 /* Each divider occupies 3 bits */
342                 zx_writel_mask(vou->vouctl + reg, 0x7 << shift,
343                                cfg->val << shift);
344         }
345
346         /* Set update flag bit to get dividers effected */
347         zx_writel_mask(vou->vouctl + VOU_DIV_PARA, DIV_PARA_UPDATE,
348                        DIV_PARA_UPDATE);
349 }
350
351 static inline void vou_chn_set_update(struct zx_crtc *zcrtc)
352 {
353         zx_writel(zcrtc->chnreg + CHN_UPDATE, 1);
354 }
355
356 static void zx_crtc_atomic_enable(struct drm_crtc *crtc,
357                                   struct drm_crtc_state *old_state)
358 {
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;
365         struct videomode vm;
366         u32 scan_mask;
367         u32 pol = 0;
368         u32 val;
369         int ret;
370
371         drm_display_mode_to_videomode(mode, &vm);
372
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);
377
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);
382
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);
387
388         if (interlaced) {
389                 u32 shift = bits->sec_vactive_shift;
390                 u32 mask = bits->sec_vactive_mask;
391
392                 val = zx_readl(vou->timing + SEC_V_ACTIVE);
393                 val &= ~mask;
394                 val |= ((vm.vactive / 2 - 1) << shift) & mask;
395                 zx_writel(vou->timing + SEC_V_ACTIVE, val);
396
397                 val = SYNC_WIDE(vm.vsync_len - 1);
398                 /*
399                  * The vback_porch for the second field needs to shift one on
400                  * the value for the first field.
401                  */
402                 val |= BACK_PORCH(vm.vback_porch);
403                 val |= FRONT_PORCH(vm.vfront_porch - 1);
404                 zx_writel(vou->timing + regs->sec_vtiming, val);
405         }
406
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;
412
413         zx_writel_mask(vou->timing + TIMING_CTRL, bits->polarity_mask,
414                        pol << bits->polarity_shift);
415
416         /* Setup SHIFT register by following what ZTE BSP does */
417         val = H_SHIFT_VAL;
418         if (interlaced)
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);
422
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);
427
428         /* Enable TIMING_CTRL */
429         zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable,
430                        bits->tc_enable);
431
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);
437
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);
441
442         /* Update channel */
443         vou_chn_set_update(zcrtc);
444
445         /* Enable channel */
446         zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, CHN_ENABLE);
447
448         drm_crtc_vblank_on(crtc);
449
450         ret = clk_set_rate(zcrtc->pixclk, mode->clock * 1000);
451         if (ret) {
452                 DRM_DEV_ERROR(vou->dev, "failed to set pixclk rate: %d\n", ret);
453                 return;
454         }
455
456         ret = clk_prepare_enable(zcrtc->pixclk);
457         if (ret)
458                 DRM_DEV_ERROR(vou->dev, "failed to enable pixclk: %d\n", ret);
459 }
460
461 static void zx_crtc_atomic_disable(struct drm_crtc *crtc,
462                                    struct drm_crtc_state *old_state)
463 {
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;
467
468         clk_disable_unprepare(zcrtc->pixclk);
469
470         drm_crtc_vblank_off(crtc);
471
472         /* Disable channel */
473         zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, 0);
474
475         /* Disable TIMING_CTRL */
476         zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable, 0);
477 }
478
479 static void zx_crtc_atomic_flush(struct drm_crtc *crtc,
480                                   struct drm_crtc_state *old_state)
481 {
482         struct drm_pending_vblank_event *event = crtc->state->event;
483
484         if (!event)
485                 return;
486
487         crtc->state->event = NULL;
488
489         spin_lock_irq(&crtc->dev->event_lock);
490         if (drm_crtc_vblank_get(crtc) == 0)
491                 drm_crtc_arm_vblank_event(crtc, event);
492         else
493                 drm_crtc_send_vblank_event(crtc, event);
494         spin_unlock_irq(&crtc->dev->event_lock);
495 }
496
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,
501 };
502
503 static int zx_vou_enable_vblank(struct drm_crtc *crtc)
504 {
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;
508
509         zx_writel_mask(vou->timing + TIMING_INT_CTRL, int_frame_mask,
510                        int_frame_mask);
511
512         return 0;
513 }
514
515 static void zx_vou_disable_vblank(struct drm_crtc *crtc)
516 {
517         struct zx_crtc *zcrtc = to_zx_crtc(crtc);
518         struct zx_vou_hw *vou = crtc_to_vou(crtc);
519
520         zx_writel_mask(vou->timing + TIMING_INT_CTRL,
521                        zcrtc->bits->int_frame_mask, 0);
522 }
523
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,
533 };
534
535 static int zx_crtc_init(struct drm_device *drm, struct zx_vou_hw *vou,
536                         enum vou_chn_type chn_type)
537 {
538         struct device *dev = vou->dev;
539         struct zx_plane *zplane;
540         struct zx_crtc *zcrtc;
541         int ret;
542
543         zcrtc = devm_kzalloc(dev, sizeof(*zcrtc), GFP_KERNEL);
544         if (!zcrtc)
545                 return -ENOMEM;
546
547         zcrtc->vou = vou;
548         zcrtc->chn_type = chn_type;
549
550         zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
551         if (!zplane)
552                 return -ENOMEM;
553
554         zplane->dev = dev;
555
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;
567         } else {
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;
578         }
579
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);
585                 return ret;
586         }
587
588         ret = zx_plane_init(drm, zplane, DRM_PLANE_TYPE_PRIMARY);
589         if (ret) {
590                 DRM_DEV_ERROR(dev, "failed to init primary plane: %d\n", ret);
591                 return ret;
592         }
593
594         zcrtc->primary = &zplane->plane;
595
596         ret = drm_crtc_init_with_planes(drm, &zcrtc->crtc, zcrtc->primary, NULL,
597                                         &zx_crtc_funcs, NULL);
598         if (ret) {
599                 DRM_DEV_ERROR(dev, "failed to init drm crtc: %d\n", ret);
600                 return ret;
601         }
602
603         drm_crtc_helper_add(&zcrtc->crtc, &zx_crtc_helper_funcs);
604
605         if (chn_type == VOU_CHN_MAIN)
606                 vou->main_crtc = zcrtc;
607         else
608                 vou->aux_crtc = zcrtc;
609
610         return 0;
611 }
612
613 void zx_vou_layer_enable(struct drm_plane *plane)
614 {
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;
619
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);
623         } else {
624                 zx_writel_mask(vou->osd + OSD_CTRL0, bits->chnsel,
625                                bits->chnsel);
626                 zx_writel_mask(vou->vouctl + VOU_CLK_SEL, bits->clksel,
627                                bits->clksel);
628         }
629
630         zx_writel_mask(vou->osd + OSD_CTRL0, bits->enable, bits->enable);
631 }
632
633 void zx_vou_layer_disable(struct drm_plane *plane,
634                           struct drm_plane_state *old_state)
635 {
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;
640
641         zx_writel_mask(vou->osd + OSD_CTRL0, bits->enable, 0);
642 }
643
644 static void zx_overlay_init(struct drm_device *drm, struct zx_vou_hw *vou)
645 {
646         struct device *dev = vou->dev;
647         struct zx_plane *zplane;
648         int i;
649         int ret;
650
651         /*
652          * VL0 has some quirks on scaling support which need special handling.
653          * Let's leave it out for now.
654          */
655         for (i = 1; i < VL_NUM; i++) {
656                 zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
657                 if (!zplane) {
658                         DRM_DEV_ERROR(dev, "failed to allocate zplane %d\n", i);
659                         return;
660                 }
661
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];
666
667                 ret = zx_plane_init(drm, zplane, DRM_PLANE_TYPE_OVERLAY);
668                 if (ret) {
669                         DRM_DEV_ERROR(dev, "failed to init overlay %d\n", i);
670                         continue;
671                 }
672         }
673 }
674
675 static inline void zx_osd_int_update(struct zx_crtc *zcrtc)
676 {
677         struct drm_crtc *crtc = &zcrtc->crtc;
678         struct drm_plane *plane;
679
680         vou_chn_set_update(zcrtc);
681
682         drm_for_each_plane_mask(plane, crtc->dev, crtc->state->plane_mask)
683                 zx_plane_set_update(plane);
684 }
685
686 static irqreturn_t vou_irq_handler(int irq, void *dev_id)
687 {
688         struct zx_vou_hw *vou = dev_id;
689         u32 state;
690
691         /* Handle TIMING_CTRL frame interrupts */
692         state = zx_readl(vou->timing + TIMING_INT_STATE);
693         zx_writel(vou->timing + TIMING_INT_STATE, state);
694
695         if (state & TIMING_INT_MAIN_FRAME)
696                 drm_crtc_handle_vblank(&vou->main_crtc->crtc);
697
698         if (state & TIMING_INT_AUX_FRAME)
699                 drm_crtc_handle_vblank(&vou->aux_crtc->crtc);
700
701         /* Handle OSD interrupts */
702         state = zx_readl(vou->osd + OSD_INT_STA);
703         zx_writel(vou->osd + OSD_INT_CLRSTA, state);
704
705         if (state & OSD_INT_MAIN_UPT)
706                 zx_osd_int_update(vou->main_crtc);
707
708         if (state & OSD_INT_AUX_UPT)
709                 zx_osd_int_update(vou->aux_crtc);
710
711         if (state & OSD_INT_ERROR)
712                 DRM_DEV_ERROR(vou->dev, "OSD ERROR: 0x%08x!\n", state);
713
714         return IRQ_HANDLED;
715 }
716
717 static void vou_dtrc_init(struct zx_vou_hw *vou)
718 {
719         /* Clear bit for bypass by ID */
720         zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL,
721                        TILE2RASTESCAN_BYPASS_MODE, 0);
722
723         /* Select ARIDR mode */
724         zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL, DETILE_ARIDR_MODE_MASK,
725                        DETILE_ARID_IN_ARIDR);
726
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);
732
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));
736 }
737
738 static void vou_hw_init(struct zx_vou_hw *vou)
739 {
740         /* Release reset for all VOU modules */
741         zx_writel(vou->vouctl + VOU_SOFT_RST, ~0);
742
743         /* Enable all VOU module clocks */
744         zx_writel(vou->vouctl + VOU_CLK_EN, ~0);
745
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);
749
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);
753
754         /* Select GPC as input to gl/vl scaler as a sane default setting */
755         zx_writel(vou->otfppu + OTFPPU_RSZ_DATA_SOURCE, 0x2a);
756
757         /*
758          * Needs to reset channel and layer logic per frame when frame starts
759          * to get VOU work properly.
760          */
761         zx_writel_mask(vou->osd + OSD_RST_CLR, RST_PER_FRAME, RST_PER_FRAME);
762
763         vou_dtrc_init(vou);
764 }
765
766 static int zx_crtc_bind(struct device *dev, struct device *master, void *data)
767 {
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;
772         int irq;
773         int ret;
774
775         vou = devm_kzalloc(dev, sizeof(*vou), GFP_KERNEL);
776         if (!vou)
777                 return -ENOMEM;
778
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);
784                 return ret;
785         }
786
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",
792                               ret);
793                 return ret;
794         }
795
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);
801                 return ret;
802         }
803
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",
809                               ret);
810                 return ret;
811         }
812
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);
818                 return ret;
819         }
820
821         irq = platform_get_irq(pdev, 0);
822         if (irq < 0)
823                 return irq;
824
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);
829                 return ret;
830         }
831
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);
836                 return ret;
837         }
838
839         ret = clk_prepare_enable(vou->axi_clk);
840         if (ret) {
841                 DRM_DEV_ERROR(dev, "failed to enable axi_clk: %d\n", ret);
842                 return ret;
843         }
844
845         clk_prepare_enable(vou->ppu_clk);
846         if (ret) {
847                 DRM_DEV_ERROR(dev, "failed to enable ppu_clk: %d\n", ret);
848                 goto disable_axi_clk;
849         }
850
851         vou->dev = dev;
852         dev_set_drvdata(dev, vou);
853
854         vou_hw_init(vou);
855
856         ret = devm_request_irq(dev, irq, vou_irq_handler, 0, "zx_vou", vou);
857         if (ret < 0) {
858                 DRM_DEV_ERROR(dev, "failed to request vou irq: %d\n", ret);
859                 goto disable_ppu_clk;
860         }
861
862         ret = zx_crtc_init(drm, vou, VOU_CHN_MAIN);
863         if (ret) {
864                 DRM_DEV_ERROR(dev, "failed to init main channel crtc: %d\n",
865                               ret);
866                 goto disable_ppu_clk;
867         }
868
869         ret = zx_crtc_init(drm, vou, VOU_CHN_AUX);
870         if (ret) {
871                 DRM_DEV_ERROR(dev, "failed to init aux channel crtc: %d\n",
872                               ret);
873                 goto disable_ppu_clk;
874         }
875
876         zx_overlay_init(drm, vou);
877
878         return 0;
879
880 disable_ppu_clk:
881         clk_disable_unprepare(vou->ppu_clk);
882 disable_axi_clk:
883         clk_disable_unprepare(vou->axi_clk);
884         return ret;
885 }
886
887 static void zx_crtc_unbind(struct device *dev, struct device *master,
888                            void *data)
889 {
890         struct zx_vou_hw *vou = dev_get_drvdata(dev);
891
892         clk_disable_unprepare(vou->axi_clk);
893         clk_disable_unprepare(vou->ppu_clk);
894 }
895
896 static const struct component_ops zx_crtc_component_ops = {
897         .bind = zx_crtc_bind,
898         .unbind = zx_crtc_unbind,
899 };
900
901 static int zx_crtc_probe(struct platform_device *pdev)
902 {
903         return component_add(&pdev->dev, &zx_crtc_component_ops);
904 }
905
906 static int zx_crtc_remove(struct platform_device *pdev)
907 {
908         component_del(&pdev->dev, &zx_crtc_component_ops);
909         return 0;
910 }
911
912 static const struct of_device_id zx_crtc_of_match[] = {
913         { .compatible = "zte,zx296718-dpc", },
914         { /* end */ },
915 };
916 MODULE_DEVICE_TABLE(of, zx_crtc_of_match);
917
918 struct platform_driver zx_crtc_driver = {
919         .probe = zx_crtc_probe,
920         .remove = zx_crtc_remove,
921         .driver = {
922                 .name = "zx-crtc",
923                 .of_match_table = zx_crtc_of_match,
924         },
925 };