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