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