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