xref: /OK3568_Linux_fs/kernel/drivers/gpu/drm/imx/dcss/dcss-dtg.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright 2019 NXP.
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include <linux/clk.h>
7*4882a593Smuzhiyun #include <linux/delay.h>
8*4882a593Smuzhiyun #include <linux/interrupt.h>
9*4882a593Smuzhiyun #include <linux/of.h>
10*4882a593Smuzhiyun #include <linux/platform_device.h>
11*4882a593Smuzhiyun #include <linux/slab.h>
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include "dcss-dev.h"
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #define DCSS_DTG_TC_CONTROL_STATUS			0x00
16*4882a593Smuzhiyun #define   CH3_EN					BIT(0)
17*4882a593Smuzhiyun #define   CH2_EN					BIT(1)
18*4882a593Smuzhiyun #define   CH1_EN					BIT(2)
19*4882a593Smuzhiyun #define   OVL_DATA_MODE					BIT(3)
20*4882a593Smuzhiyun #define   BLENDER_VIDEO_ALPHA_SEL			BIT(7)
21*4882a593Smuzhiyun #define   DTG_START					BIT(8)
22*4882a593Smuzhiyun #define   DBY_MODE_EN					BIT(9)
23*4882a593Smuzhiyun #define   CH1_ALPHA_SEL					BIT(10)
24*4882a593Smuzhiyun #define   CSS_PIX_COMP_SWAP_POS				12
25*4882a593Smuzhiyun #define   CSS_PIX_COMP_SWAP_MASK			GENMASK(14, 12)
26*4882a593Smuzhiyun #define   DEFAULT_FG_ALPHA_POS				24
27*4882a593Smuzhiyun #define   DEFAULT_FG_ALPHA_MASK				GENMASK(31, 24)
28*4882a593Smuzhiyun #define DCSS_DTG_TC_DTG					0x04
29*4882a593Smuzhiyun #define DCSS_DTG_TC_DISP_TOP				0x08
30*4882a593Smuzhiyun #define DCSS_DTG_TC_DISP_BOT				0x0C
31*4882a593Smuzhiyun #define DCSS_DTG_TC_CH1_TOP				0x10
32*4882a593Smuzhiyun #define DCSS_DTG_TC_CH1_BOT				0x14
33*4882a593Smuzhiyun #define DCSS_DTG_TC_CH2_TOP				0x18
34*4882a593Smuzhiyun #define DCSS_DTG_TC_CH2_BOT				0x1C
35*4882a593Smuzhiyun #define DCSS_DTG_TC_CH3_TOP				0x20
36*4882a593Smuzhiyun #define DCSS_DTG_TC_CH3_BOT				0x24
37*4882a593Smuzhiyun #define   TC_X_POS					0
38*4882a593Smuzhiyun #define   TC_X_MASK					GENMASK(12, 0)
39*4882a593Smuzhiyun #define   TC_Y_POS					16
40*4882a593Smuzhiyun #define   TC_Y_MASK					GENMASK(28, 16)
41*4882a593Smuzhiyun #define DCSS_DTG_TC_CTXLD				0x28
42*4882a593Smuzhiyun #define   TC_CTXLD_DB_Y_POS				0
43*4882a593Smuzhiyun #define   TC_CTXLD_DB_Y_MASK				GENMASK(12, 0)
44*4882a593Smuzhiyun #define   TC_CTXLD_SB_Y_POS				16
45*4882a593Smuzhiyun #define   TC_CTXLD_SB_Y_MASK				GENMASK(28, 16)
46*4882a593Smuzhiyun #define DCSS_DTG_TC_CH1_BKRND				0x2C
47*4882a593Smuzhiyun #define DCSS_DTG_TC_CH2_BKRND				0x30
48*4882a593Smuzhiyun #define   BKRND_R_Y_COMP_POS				20
49*4882a593Smuzhiyun #define   BKRND_R_Y_COMP_MASK				GENMASK(29, 20)
50*4882a593Smuzhiyun #define   BKRND_G_U_COMP_POS				10
51*4882a593Smuzhiyun #define   BKRND_G_U_COMP_MASK				GENMASK(19, 10)
52*4882a593Smuzhiyun #define   BKRND_B_V_COMP_POS				0
53*4882a593Smuzhiyun #define   BKRND_B_V_COMP_MASK				GENMASK(9, 0)
54*4882a593Smuzhiyun #define DCSS_DTG_BLENDER_DBY_RANGEINV			0x38
55*4882a593Smuzhiyun #define DCSS_DTG_BLENDER_DBY_RANGEMIN			0x3C
56*4882a593Smuzhiyun #define DCSS_DTG_BLENDER_DBY_BDP			0x40
57*4882a593Smuzhiyun #define DCSS_DTG_BLENDER_BKRND_I			0x44
58*4882a593Smuzhiyun #define DCSS_DTG_BLENDER_BKRND_P			0x48
59*4882a593Smuzhiyun #define DCSS_DTG_BLENDER_BKRND_T			0x4C
60*4882a593Smuzhiyun #define DCSS_DTG_LINE0_INT				0x50
61*4882a593Smuzhiyun #define DCSS_DTG_LINE1_INT				0x54
62*4882a593Smuzhiyun #define DCSS_DTG_BG_ALPHA_DEFAULT			0x58
63*4882a593Smuzhiyun #define DCSS_DTG_INT_STATUS				0x5C
64*4882a593Smuzhiyun #define DCSS_DTG_INT_CONTROL				0x60
65*4882a593Smuzhiyun #define DCSS_DTG_TC_CH3_BKRND				0x64
66*4882a593Smuzhiyun #define DCSS_DTG_INT_MASK				0x68
67*4882a593Smuzhiyun #define   LINE0_IRQ					BIT(0)
68*4882a593Smuzhiyun #define   LINE1_IRQ					BIT(1)
69*4882a593Smuzhiyun #define   LINE2_IRQ					BIT(2)
70*4882a593Smuzhiyun #define   LINE3_IRQ					BIT(3)
71*4882a593Smuzhiyun #define DCSS_DTG_LINE2_INT				0x6C
72*4882a593Smuzhiyun #define DCSS_DTG_LINE3_INT				0x70
73*4882a593Smuzhiyun #define DCSS_DTG_DBY_OL					0x74
74*4882a593Smuzhiyun #define DCSS_DTG_DBY_BL					0x78
75*4882a593Smuzhiyun #define DCSS_DTG_DBY_EL					0x7C
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun struct dcss_dtg {
78*4882a593Smuzhiyun 	struct device *dev;
79*4882a593Smuzhiyun 	struct dcss_ctxld *ctxld;
80*4882a593Smuzhiyun 	void __iomem *base_reg;
81*4882a593Smuzhiyun 	u32 base_ofs;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	u32 ctx_id;
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	bool in_use;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	u32 dis_ulc_x;
88*4882a593Smuzhiyun 	u32 dis_ulc_y;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	u32 control_status;
91*4882a593Smuzhiyun 	u32 alpha;
92*4882a593Smuzhiyun 	u32 alpha_cfg;
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	int ctxld_kick_irq;
95*4882a593Smuzhiyun 	bool ctxld_kick_irq_en;
96*4882a593Smuzhiyun };
97*4882a593Smuzhiyun 
dcss_dtg_write(struct dcss_dtg * dtg,u32 val,u32 ofs)98*4882a593Smuzhiyun static void dcss_dtg_write(struct dcss_dtg *dtg, u32 val, u32 ofs)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun 	if (!dtg->in_use)
101*4882a593Smuzhiyun 		dcss_writel(val, dtg->base_reg + ofs);
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	dcss_ctxld_write(dtg->ctxld, dtg->ctx_id,
104*4882a593Smuzhiyun 			 val, dtg->base_ofs + ofs);
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun 
dcss_dtg_irq_handler(int irq,void * data)107*4882a593Smuzhiyun static irqreturn_t dcss_dtg_irq_handler(int irq, void *data)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun 	struct dcss_dtg *dtg = data;
110*4882a593Smuzhiyun 	u32 status;
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	status = dcss_readl(dtg->base_reg + DCSS_DTG_INT_STATUS);
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	if (!(status & LINE0_IRQ))
115*4882a593Smuzhiyun 		return IRQ_NONE;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	dcss_ctxld_kick(dtg->ctxld);
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	dcss_writel(status & LINE0_IRQ, dtg->base_reg + DCSS_DTG_INT_CONTROL);
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	return IRQ_HANDLED;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun 
dcss_dtg_irq_config(struct dcss_dtg * dtg,struct platform_device * pdev)124*4882a593Smuzhiyun static int dcss_dtg_irq_config(struct dcss_dtg *dtg,
125*4882a593Smuzhiyun 			       struct platform_device *pdev)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun 	int ret;
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	dtg->ctxld_kick_irq = platform_get_irq_byname(pdev, "ctxld_kick");
130*4882a593Smuzhiyun 	if (dtg->ctxld_kick_irq < 0)
131*4882a593Smuzhiyun 		return dtg->ctxld_kick_irq;
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	dcss_update(0, LINE0_IRQ | LINE1_IRQ,
134*4882a593Smuzhiyun 		    dtg->base_reg + DCSS_DTG_INT_MASK);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	ret = request_irq(dtg->ctxld_kick_irq, dcss_dtg_irq_handler,
137*4882a593Smuzhiyun 			  0, "dcss_ctxld_kick", dtg);
138*4882a593Smuzhiyun 	if (ret) {
139*4882a593Smuzhiyun 		dev_err(dtg->dev, "dtg: irq request failed.\n");
140*4882a593Smuzhiyun 		return ret;
141*4882a593Smuzhiyun 	}
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	disable_irq(dtg->ctxld_kick_irq);
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	dtg->ctxld_kick_irq_en = false;
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	return 0;
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun 
dcss_dtg_init(struct dcss_dev * dcss,unsigned long dtg_base)150*4882a593Smuzhiyun int dcss_dtg_init(struct dcss_dev *dcss, unsigned long dtg_base)
151*4882a593Smuzhiyun {
152*4882a593Smuzhiyun 	int ret = 0;
153*4882a593Smuzhiyun 	struct dcss_dtg *dtg;
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	dtg = kzalloc(sizeof(*dtg), GFP_KERNEL);
156*4882a593Smuzhiyun 	if (!dtg)
157*4882a593Smuzhiyun 		return -ENOMEM;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	dcss->dtg = dtg;
160*4882a593Smuzhiyun 	dtg->dev = dcss->dev;
161*4882a593Smuzhiyun 	dtg->ctxld = dcss->ctxld;
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	dtg->base_reg = ioremap(dtg_base, SZ_4K);
164*4882a593Smuzhiyun 	if (!dtg->base_reg) {
165*4882a593Smuzhiyun 		dev_err(dcss->dev, "dtg: unable to remap dtg base\n");
166*4882a593Smuzhiyun 		ret = -ENOMEM;
167*4882a593Smuzhiyun 		goto err_ioremap;
168*4882a593Smuzhiyun 	}
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	dtg->base_ofs = dtg_base;
171*4882a593Smuzhiyun 	dtg->ctx_id = CTX_DB;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	dtg->alpha = 255;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	dtg->control_status |= OVL_DATA_MODE | BLENDER_VIDEO_ALPHA_SEL |
176*4882a593Smuzhiyun 		((dtg->alpha << DEFAULT_FG_ALPHA_POS) & DEFAULT_FG_ALPHA_MASK);
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	ret = dcss_dtg_irq_config(dtg, to_platform_device(dcss->dev));
179*4882a593Smuzhiyun 	if (ret)
180*4882a593Smuzhiyun 		goto err_irq;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	return 0;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun err_irq:
185*4882a593Smuzhiyun 	iounmap(dtg->base_reg);
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun err_ioremap:
188*4882a593Smuzhiyun 	kfree(dtg);
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	return ret;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun 
dcss_dtg_exit(struct dcss_dtg * dtg)193*4882a593Smuzhiyun void dcss_dtg_exit(struct dcss_dtg *dtg)
194*4882a593Smuzhiyun {
195*4882a593Smuzhiyun 	free_irq(dtg->ctxld_kick_irq, dtg);
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	if (dtg->base_reg)
198*4882a593Smuzhiyun 		iounmap(dtg->base_reg);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	kfree(dtg);
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun 
dcss_dtg_sync_set(struct dcss_dtg * dtg,struct videomode * vm)203*4882a593Smuzhiyun void dcss_dtg_sync_set(struct dcss_dtg *dtg, struct videomode *vm)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun 	struct dcss_dev *dcss = dcss_drv_dev_to_dcss(dtg->dev);
206*4882a593Smuzhiyun 	u16 dtg_lrc_x, dtg_lrc_y;
207*4882a593Smuzhiyun 	u16 dis_ulc_x, dis_ulc_y;
208*4882a593Smuzhiyun 	u16 dis_lrc_x, dis_lrc_y;
209*4882a593Smuzhiyun 	u32 sb_ctxld_trig, db_ctxld_trig;
210*4882a593Smuzhiyun 	u32 pixclock = vm->pixelclock;
211*4882a593Smuzhiyun 	u32 actual_clk;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	dtg_lrc_x = vm->hfront_porch + vm->hback_porch + vm->hsync_len +
214*4882a593Smuzhiyun 		    vm->hactive - 1;
215*4882a593Smuzhiyun 	dtg_lrc_y = vm->vfront_porch + vm->vback_porch + vm->vsync_len +
216*4882a593Smuzhiyun 		    vm->vactive - 1;
217*4882a593Smuzhiyun 	dis_ulc_x = vm->hsync_len + vm->hback_porch - 1;
218*4882a593Smuzhiyun 	dis_ulc_y = vm->vsync_len + vm->vfront_porch + vm->vback_porch - 1;
219*4882a593Smuzhiyun 	dis_lrc_x = vm->hsync_len + vm->hback_porch + vm->hactive - 1;
220*4882a593Smuzhiyun 	dis_lrc_y = vm->vsync_len + vm->vfront_porch + vm->vback_porch +
221*4882a593Smuzhiyun 		    vm->vactive - 1;
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	clk_disable_unprepare(dcss->pix_clk);
224*4882a593Smuzhiyun 	clk_set_rate(dcss->pix_clk, vm->pixelclock);
225*4882a593Smuzhiyun 	clk_prepare_enable(dcss->pix_clk);
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	actual_clk = clk_get_rate(dcss->pix_clk);
228*4882a593Smuzhiyun 	if (pixclock != actual_clk) {
229*4882a593Smuzhiyun 		dev_info(dtg->dev,
230*4882a593Smuzhiyun 			 "Pixel clock set to %u kHz instead of %u kHz.\n",
231*4882a593Smuzhiyun 			 (actual_clk / 1000), (pixclock / 1000));
232*4882a593Smuzhiyun 	}
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	dcss_dtg_write(dtg, ((dtg_lrc_y << TC_Y_POS) | dtg_lrc_x),
235*4882a593Smuzhiyun 		       DCSS_DTG_TC_DTG);
236*4882a593Smuzhiyun 	dcss_dtg_write(dtg, ((dis_ulc_y << TC_Y_POS) | dis_ulc_x),
237*4882a593Smuzhiyun 		       DCSS_DTG_TC_DISP_TOP);
238*4882a593Smuzhiyun 	dcss_dtg_write(dtg, ((dis_lrc_y << TC_Y_POS) | dis_lrc_x),
239*4882a593Smuzhiyun 		       DCSS_DTG_TC_DISP_BOT);
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	dtg->dis_ulc_x = dis_ulc_x;
242*4882a593Smuzhiyun 	dtg->dis_ulc_y = dis_ulc_y;
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	sb_ctxld_trig = ((0 * dis_lrc_y / 100) << TC_CTXLD_SB_Y_POS) &
245*4882a593Smuzhiyun 							TC_CTXLD_SB_Y_MASK;
246*4882a593Smuzhiyun 	db_ctxld_trig = ((99 * dis_lrc_y / 100) << TC_CTXLD_DB_Y_POS) &
247*4882a593Smuzhiyun 							TC_CTXLD_DB_Y_MASK;
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 	dcss_dtg_write(dtg, sb_ctxld_trig | db_ctxld_trig, DCSS_DTG_TC_CTXLD);
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	/* vblank trigger */
252*4882a593Smuzhiyun 	dcss_dtg_write(dtg, 0, DCSS_DTG_LINE1_INT);
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 	/* CTXLD trigger */
255*4882a593Smuzhiyun 	dcss_dtg_write(dtg, ((90 * dis_lrc_y) / 100) << 16, DCSS_DTG_LINE0_INT);
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun 
dcss_dtg_plane_pos_set(struct dcss_dtg * dtg,int ch_num,int px,int py,int pw,int ph)258*4882a593Smuzhiyun void dcss_dtg_plane_pos_set(struct dcss_dtg *dtg, int ch_num,
259*4882a593Smuzhiyun 			    int px, int py, int pw, int ph)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun 	u16 p_ulc_x, p_ulc_y;
262*4882a593Smuzhiyun 	u16 p_lrc_x, p_lrc_y;
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	p_ulc_x = dtg->dis_ulc_x + px;
265*4882a593Smuzhiyun 	p_ulc_y = dtg->dis_ulc_y + py;
266*4882a593Smuzhiyun 	p_lrc_x = p_ulc_x + pw;
267*4882a593Smuzhiyun 	p_lrc_y = p_ulc_y + ph;
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	if (!px && !py && !pw && !ph) {
270*4882a593Smuzhiyun 		dcss_dtg_write(dtg, 0, DCSS_DTG_TC_CH1_TOP + 0x8 * ch_num);
271*4882a593Smuzhiyun 		dcss_dtg_write(dtg, 0, DCSS_DTG_TC_CH1_BOT + 0x8 * ch_num);
272*4882a593Smuzhiyun 	} else {
273*4882a593Smuzhiyun 		dcss_dtg_write(dtg, ((p_ulc_y << TC_Y_POS) | p_ulc_x),
274*4882a593Smuzhiyun 			       DCSS_DTG_TC_CH1_TOP + 0x8 * ch_num);
275*4882a593Smuzhiyun 		dcss_dtg_write(dtg, ((p_lrc_y << TC_Y_POS) | p_lrc_x),
276*4882a593Smuzhiyun 			       DCSS_DTG_TC_CH1_BOT + 0x8 * ch_num);
277*4882a593Smuzhiyun 	}
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun 
dcss_dtg_global_alpha_changed(struct dcss_dtg * dtg,int ch_num,int alpha)280*4882a593Smuzhiyun bool dcss_dtg_global_alpha_changed(struct dcss_dtg *dtg, int ch_num, int alpha)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun 	if (ch_num)
283*4882a593Smuzhiyun 		return false;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	return alpha != dtg->alpha;
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun 
dcss_dtg_plane_alpha_set(struct dcss_dtg * dtg,int ch_num,const struct drm_format_info * format,int alpha)288*4882a593Smuzhiyun void dcss_dtg_plane_alpha_set(struct dcss_dtg *dtg, int ch_num,
289*4882a593Smuzhiyun 			      const struct drm_format_info *format, int alpha)
290*4882a593Smuzhiyun {
291*4882a593Smuzhiyun 	/* we care about alpha only when channel 0 is concerned */
292*4882a593Smuzhiyun 	if (ch_num)
293*4882a593Smuzhiyun 		return;
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun 	/*
296*4882a593Smuzhiyun 	 * Use global alpha if pixel format does not have alpha channel or the
297*4882a593Smuzhiyun 	 * user explicitly chose to use global alpha (i.e. alpha is not OPAQUE).
298*4882a593Smuzhiyun 	 */
299*4882a593Smuzhiyun 	if (!format->has_alpha || alpha != 255)
300*4882a593Smuzhiyun 		dtg->alpha_cfg = (alpha << DEFAULT_FG_ALPHA_POS) & DEFAULT_FG_ALPHA_MASK;
301*4882a593Smuzhiyun 	else /* use per-pixel alpha otherwise */
302*4882a593Smuzhiyun 		dtg->alpha_cfg = CH1_ALPHA_SEL;
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	dtg->alpha = alpha;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun 
dcss_dtg_css_set(struct dcss_dtg * dtg)307*4882a593Smuzhiyun void dcss_dtg_css_set(struct dcss_dtg *dtg)
308*4882a593Smuzhiyun {
309*4882a593Smuzhiyun 	dtg->control_status |=
310*4882a593Smuzhiyun 			(0x5 << CSS_PIX_COMP_SWAP_POS) & CSS_PIX_COMP_SWAP_MASK;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun 
dcss_dtg_enable(struct dcss_dtg * dtg)313*4882a593Smuzhiyun void dcss_dtg_enable(struct dcss_dtg *dtg)
314*4882a593Smuzhiyun {
315*4882a593Smuzhiyun 	dtg->control_status |= DTG_START;
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 	dtg->control_status &= ~(CH1_ALPHA_SEL | DEFAULT_FG_ALPHA_MASK);
318*4882a593Smuzhiyun 	dtg->control_status |= dtg->alpha_cfg;
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	dcss_dtg_write(dtg, dtg->control_status, DCSS_DTG_TC_CONTROL_STATUS);
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	dtg->in_use = true;
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun 
dcss_dtg_shutoff(struct dcss_dtg * dtg)325*4882a593Smuzhiyun void dcss_dtg_shutoff(struct dcss_dtg *dtg)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun 	dtg->control_status &= ~DTG_START;
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	dcss_writel(dtg->control_status,
330*4882a593Smuzhiyun 		    dtg->base_reg + DCSS_DTG_TC_CONTROL_STATUS);
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	dtg->in_use = false;
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun 
dcss_dtg_is_enabled(struct dcss_dtg * dtg)335*4882a593Smuzhiyun bool dcss_dtg_is_enabled(struct dcss_dtg *dtg)
336*4882a593Smuzhiyun {
337*4882a593Smuzhiyun 	return dtg->in_use;
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun 
dcss_dtg_ch_enable(struct dcss_dtg * dtg,int ch_num,bool en)340*4882a593Smuzhiyun void dcss_dtg_ch_enable(struct dcss_dtg *dtg, int ch_num, bool en)
341*4882a593Smuzhiyun {
342*4882a593Smuzhiyun 	u32 ch_en_map[] = {CH1_EN, CH2_EN, CH3_EN};
343*4882a593Smuzhiyun 	u32 control_status;
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	control_status = dtg->control_status & ~ch_en_map[ch_num];
346*4882a593Smuzhiyun 	control_status |= en ? ch_en_map[ch_num] : 0;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	control_status &= ~(CH1_ALPHA_SEL | DEFAULT_FG_ALPHA_MASK);
349*4882a593Smuzhiyun 	control_status |= dtg->alpha_cfg;
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	if (dtg->control_status != control_status)
352*4882a593Smuzhiyun 		dcss_dtg_write(dtg, control_status, DCSS_DTG_TC_CONTROL_STATUS);
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	dtg->control_status = control_status;
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun 
dcss_dtg_vblank_irq_enable(struct dcss_dtg * dtg,bool en)357*4882a593Smuzhiyun void dcss_dtg_vblank_irq_enable(struct dcss_dtg *dtg, bool en)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun 	u32 status;
360*4882a593Smuzhiyun 	u32 mask = en ? LINE1_IRQ : 0;
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun 	if (en) {
363*4882a593Smuzhiyun 		status = dcss_readl(dtg->base_reg + DCSS_DTG_INT_STATUS);
364*4882a593Smuzhiyun 		dcss_writel(status & LINE1_IRQ,
365*4882a593Smuzhiyun 			    dtg->base_reg + DCSS_DTG_INT_CONTROL);
366*4882a593Smuzhiyun 	}
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	dcss_update(mask, LINE1_IRQ, dtg->base_reg + DCSS_DTG_INT_MASK);
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun 
dcss_dtg_ctxld_kick_irq_enable(struct dcss_dtg * dtg,bool en)371*4882a593Smuzhiyun void dcss_dtg_ctxld_kick_irq_enable(struct dcss_dtg *dtg, bool en)
372*4882a593Smuzhiyun {
373*4882a593Smuzhiyun 	u32 status;
374*4882a593Smuzhiyun 	u32 mask = en ? LINE0_IRQ : 0;
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 	if (en) {
377*4882a593Smuzhiyun 		status = dcss_readl(dtg->base_reg + DCSS_DTG_INT_STATUS);
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun 		if (!dtg->ctxld_kick_irq_en) {
380*4882a593Smuzhiyun 			dcss_writel(status & LINE0_IRQ,
381*4882a593Smuzhiyun 				    dtg->base_reg + DCSS_DTG_INT_CONTROL);
382*4882a593Smuzhiyun 			enable_irq(dtg->ctxld_kick_irq);
383*4882a593Smuzhiyun 			dtg->ctxld_kick_irq_en = true;
384*4882a593Smuzhiyun 			dcss_update(mask, LINE0_IRQ,
385*4882a593Smuzhiyun 				    dtg->base_reg + DCSS_DTG_INT_MASK);
386*4882a593Smuzhiyun 		}
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 		return;
389*4882a593Smuzhiyun 	}
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 	if (!dtg->ctxld_kick_irq_en)
392*4882a593Smuzhiyun 		return;
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	disable_irq_nosync(dtg->ctxld_kick_irq);
395*4882a593Smuzhiyun 	dtg->ctxld_kick_irq_en = false;
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	dcss_update(mask, LINE0_IRQ, dtg->base_reg + DCSS_DTG_INT_MASK);
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun 
dcss_dtg_vblank_irq_clear(struct dcss_dtg * dtg)400*4882a593Smuzhiyun void dcss_dtg_vblank_irq_clear(struct dcss_dtg *dtg)
401*4882a593Smuzhiyun {
402*4882a593Smuzhiyun 	dcss_update(LINE1_IRQ, LINE1_IRQ, dtg->base_reg + DCSS_DTG_INT_CONTROL);
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun 
dcss_dtg_vblank_irq_valid(struct dcss_dtg * dtg)405*4882a593Smuzhiyun bool dcss_dtg_vblank_irq_valid(struct dcss_dtg *dtg)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun 	return !!(dcss_readl(dtg->base_reg + DCSS_DTG_INT_STATUS) & LINE1_IRQ);
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun 
410