Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright 2016 Linaro Ltd.
  4 * Copyright 2016 ZTE Corporation.
  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		/* Enable channel CSC for RGB output */
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		/* Bypass Dither block for RGB output */
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	/* Select data format */
258	zx_writel_mask(vou->vouctl + VOU_INF_DATA_SEL, 0x3 << data_sel_shift,
259		       inf->data_sel << data_sel_shift);
260
261	/* Select channel */
262	zx_writel_mask(vou->vouctl + VOU_INF_CH_SEL, 0x1 << id,
263		       zcrtc->chn_type << id);
264
265	/* Select interface clocks */
266	zx_writel_mask(vou->vouctl + VOU_CLK_SEL, inf->clocks_sel_bits,
267		       is_main ? 0 : inf->clocks_sel_bits);
268
269	/* Enable interface clocks */
270	zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits,
271		       inf->clocks_en_bits);
272
273	/* Enable the device */
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	/* Disable the device */
283	zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << id, 0);
284
285	/* Disable interface clocks */
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	/* Clear update flag bit */
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		/* Each divider occupies 3 bits */
338		zx_writel_mask(vou->vouctl + reg, 0x7 << shift,
339			       cfg->val << shift);
340	}
341
342	/* Set update flag bit to get dividers effected */
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_crtc_state *old_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	/* Set up timing parameters */
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		 * The vback_porch for the second field needs to shift one on
396		 * the value for the first field.
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	/* Set up polarities */
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	/* Setup SHIFT register by following what ZTE BSP does */
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	/* Progressive or interlace scan select */
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	/* Enable TIMING_CTRL */
425	zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable,
426		       bits->tc_enable);
427
428	/* Configure channel screen size */
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	/* Configure channel interlace buffer control */
435	zx_writel_mask(zcrtc->chnreg + CHN_INTERLACE_BUF_CTRL, CHN_INTERLACE_EN,
436		       interlaced ? CHN_INTERLACE_EN : 0);
437
438	/* Update channel */
439	vou_chn_set_update(zcrtc);
440
441	/* Enable channel */
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_crtc_state *old_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	/* Disable channel */
469	zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, 0);
470
471	/* Disable TIMING_CTRL */
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_crtc_state *old_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	 * VL0 has some quirks on scaling support which need special handling.
649	 * Let's leave it out for now.
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	/* Handle TIMING_CTRL frame interrupts */
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	/* Handle OSD interrupts */
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	/* Clear bit for bypass by ID */
716	zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL,
717		       TILE2RASTESCAN_BYPASS_MODE, 0);
718
719	/* Select ARIDR mode */
720	zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL, DETILE_ARIDR_MODE_MASK,
721		       DETILE_ARID_IN_ARIDR);
722
723	/* Bypass decompression for both frames */
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	/* Set up ARID register */
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	/* Release reset for all VOU modules */
737	zx_writel(vou->vouctl + VOU_SOFT_RST, ~0);
738
739	/* Enable all VOU module clocks */
740	zx_writel(vou->vouctl + VOU_CLK_EN, ~0);
741
742	/* Clear both OSD and TIMING_CTRL interrupt state */
743	zx_writel(vou->osd + OSD_INT_CLRSTA, ~0);
744	zx_writel(vou->timing + TIMING_INT_STATE, ~0);
745
746	/* Enable OSD and TIMING_CTRL interrrupts */
747	zx_writel(vou->osd + OSD_INT_MSK, OSD_INT_ENABLE);
748	zx_writel(vou->timing + TIMING_INT_CTRL, TIMING_INT_ENABLE);
749
750	/* Select GPC as input to gl/vl scaler as a sane default setting */
751	zx_writel(vou->otfppu + OTFPPU_RSZ_DATA_SOURCE, 0x2a);
752
753	/*
754	 * Needs to reset channel and layer logic per frame when frame starts
755	 * to get VOU work properly.
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	{ /* end */ },
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};