1*3bae07d4SMauro Carvalho Chehab // SPDX-License-Identifier: GPL-2.0-or-later
2*3bae07d4SMauro Carvalho Chehab /*
3*3bae07d4SMauro Carvalho Chehab  * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd.
4*3bae07d4SMauro Carvalho Chehab  *		http://www.samsung.com
5*3bae07d4SMauro Carvalho Chehab  *
6*3bae07d4SMauro Carvalho Chehab  * Samsung EXYNOS5 SoC series G-Scaler driver
7*3bae07d4SMauro Carvalho Chehab  */
8*3bae07d4SMauro Carvalho Chehab 
9*3bae07d4SMauro Carvalho Chehab #include <linux/io.h>
10*3bae07d4SMauro Carvalho Chehab #include <linux/delay.h>
11*3bae07d4SMauro Carvalho Chehab 
12*3bae07d4SMauro Carvalho Chehab #include "gsc-core.h"
13*3bae07d4SMauro Carvalho Chehab 
gsc_hw_set_sw_reset(struct gsc_dev * dev)14*3bae07d4SMauro Carvalho Chehab void gsc_hw_set_sw_reset(struct gsc_dev *dev)
15*3bae07d4SMauro Carvalho Chehab {
16*3bae07d4SMauro Carvalho Chehab 	writel(GSC_SW_RESET_SRESET, dev->regs + GSC_SW_RESET);
17*3bae07d4SMauro Carvalho Chehab }
18*3bae07d4SMauro Carvalho Chehab 
gsc_wait_reset(struct gsc_dev * dev)19*3bae07d4SMauro Carvalho Chehab int gsc_wait_reset(struct gsc_dev *dev)
20*3bae07d4SMauro Carvalho Chehab {
21*3bae07d4SMauro Carvalho Chehab 	unsigned long end = jiffies + msecs_to_jiffies(50);
22*3bae07d4SMauro Carvalho Chehab 	u32 cfg;
23*3bae07d4SMauro Carvalho Chehab 
24*3bae07d4SMauro Carvalho Chehab 	while (time_before(jiffies, end)) {
25*3bae07d4SMauro Carvalho Chehab 		cfg = readl(dev->regs + GSC_SW_RESET);
26*3bae07d4SMauro Carvalho Chehab 		if (!cfg)
27*3bae07d4SMauro Carvalho Chehab 			return 0;
28*3bae07d4SMauro Carvalho Chehab 		usleep_range(10, 20);
29*3bae07d4SMauro Carvalho Chehab 	}
30*3bae07d4SMauro Carvalho Chehab 
31*3bae07d4SMauro Carvalho Chehab 	return -EBUSY;
32*3bae07d4SMauro Carvalho Chehab }
33*3bae07d4SMauro Carvalho Chehab 
gsc_hw_set_frm_done_irq_mask(struct gsc_dev * dev,bool mask)34*3bae07d4SMauro Carvalho Chehab void gsc_hw_set_frm_done_irq_mask(struct gsc_dev *dev, bool mask)
35*3bae07d4SMauro Carvalho Chehab {
36*3bae07d4SMauro Carvalho Chehab 	u32 cfg;
37*3bae07d4SMauro Carvalho Chehab 
38*3bae07d4SMauro Carvalho Chehab 	cfg = readl(dev->regs + GSC_IRQ);
39*3bae07d4SMauro Carvalho Chehab 	if (mask)
40*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_IRQ_FRMDONE_MASK;
41*3bae07d4SMauro Carvalho Chehab 	else
42*3bae07d4SMauro Carvalho Chehab 		cfg &= ~GSC_IRQ_FRMDONE_MASK;
43*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_IRQ);
44*3bae07d4SMauro Carvalho Chehab }
45*3bae07d4SMauro Carvalho Chehab 
gsc_hw_set_gsc_irq_enable(struct gsc_dev * dev,bool mask)46*3bae07d4SMauro Carvalho Chehab void gsc_hw_set_gsc_irq_enable(struct gsc_dev *dev, bool mask)
47*3bae07d4SMauro Carvalho Chehab {
48*3bae07d4SMauro Carvalho Chehab 	u32 cfg;
49*3bae07d4SMauro Carvalho Chehab 
50*3bae07d4SMauro Carvalho Chehab 	cfg = readl(dev->regs + GSC_IRQ);
51*3bae07d4SMauro Carvalho Chehab 	if (mask)
52*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_IRQ_ENABLE;
53*3bae07d4SMauro Carvalho Chehab 	else
54*3bae07d4SMauro Carvalho Chehab 		cfg &= ~GSC_IRQ_ENABLE;
55*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_IRQ);
56*3bae07d4SMauro Carvalho Chehab }
57*3bae07d4SMauro Carvalho Chehab 
gsc_hw_set_input_buf_masking(struct gsc_dev * dev,u32 shift,bool enable)58*3bae07d4SMauro Carvalho Chehab void gsc_hw_set_input_buf_masking(struct gsc_dev *dev, u32 shift,
59*3bae07d4SMauro Carvalho Chehab 				bool enable)
60*3bae07d4SMauro Carvalho Chehab {
61*3bae07d4SMauro Carvalho Chehab 	u32 cfg = readl(dev->regs + GSC_IN_BASE_ADDR_Y_MASK);
62*3bae07d4SMauro Carvalho Chehab 	u32 mask = 1 << shift;
63*3bae07d4SMauro Carvalho Chehab 
64*3bae07d4SMauro Carvalho Chehab 	cfg &= ~mask;
65*3bae07d4SMauro Carvalho Chehab 	cfg |= enable << shift;
66*3bae07d4SMauro Carvalho Chehab 
67*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_IN_BASE_ADDR_Y_MASK);
68*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_IN_BASE_ADDR_CB_MASK);
69*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_IN_BASE_ADDR_CR_MASK);
70*3bae07d4SMauro Carvalho Chehab }
71*3bae07d4SMauro Carvalho Chehab 
gsc_hw_set_output_buf_masking(struct gsc_dev * dev,u32 shift,bool enable)72*3bae07d4SMauro Carvalho Chehab void gsc_hw_set_output_buf_masking(struct gsc_dev *dev, u32 shift,
73*3bae07d4SMauro Carvalho Chehab 				bool enable)
74*3bae07d4SMauro Carvalho Chehab {
75*3bae07d4SMauro Carvalho Chehab 	u32 cfg = readl(dev->regs + GSC_OUT_BASE_ADDR_Y_MASK);
76*3bae07d4SMauro Carvalho Chehab 	u32 mask = 1 << shift;
77*3bae07d4SMauro Carvalho Chehab 
78*3bae07d4SMauro Carvalho Chehab 	cfg &= ~mask;
79*3bae07d4SMauro Carvalho Chehab 	cfg |= enable << shift;
80*3bae07d4SMauro Carvalho Chehab 
81*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_Y_MASK);
82*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_CB_MASK);
83*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_CR_MASK);
84*3bae07d4SMauro Carvalho Chehab }
85*3bae07d4SMauro Carvalho Chehab 
gsc_hw_set_input_addr(struct gsc_dev * dev,struct gsc_addr * addr,int index)86*3bae07d4SMauro Carvalho Chehab void gsc_hw_set_input_addr(struct gsc_dev *dev, struct gsc_addr *addr,
87*3bae07d4SMauro Carvalho Chehab 				int index)
88*3bae07d4SMauro Carvalho Chehab {
89*3bae07d4SMauro Carvalho Chehab 	pr_debug("src_buf[%d]: %pad, cb: %pad, cr: %pad", index,
90*3bae07d4SMauro Carvalho Chehab 			&addr->y, &addr->cb, &addr->cr);
91*3bae07d4SMauro Carvalho Chehab 	writel(addr->y, dev->regs + GSC_IN_BASE_ADDR_Y(index));
92*3bae07d4SMauro Carvalho Chehab 	writel(addr->cb, dev->regs + GSC_IN_BASE_ADDR_CB(index));
93*3bae07d4SMauro Carvalho Chehab 	writel(addr->cr, dev->regs + GSC_IN_BASE_ADDR_CR(index));
94*3bae07d4SMauro Carvalho Chehab 
95*3bae07d4SMauro Carvalho Chehab }
96*3bae07d4SMauro Carvalho Chehab 
gsc_hw_set_output_addr(struct gsc_dev * dev,struct gsc_addr * addr,int index)97*3bae07d4SMauro Carvalho Chehab void gsc_hw_set_output_addr(struct gsc_dev *dev,
98*3bae07d4SMauro Carvalho Chehab 			     struct gsc_addr *addr, int index)
99*3bae07d4SMauro Carvalho Chehab {
100*3bae07d4SMauro Carvalho Chehab 	pr_debug("dst_buf[%d]: %pad, cb: %pad, cr: %pad",
101*3bae07d4SMauro Carvalho Chehab 			index, &addr->y, &addr->cb, &addr->cr);
102*3bae07d4SMauro Carvalho Chehab 	writel(addr->y, dev->regs + GSC_OUT_BASE_ADDR_Y(index));
103*3bae07d4SMauro Carvalho Chehab 	writel(addr->cb, dev->regs + GSC_OUT_BASE_ADDR_CB(index));
104*3bae07d4SMauro Carvalho Chehab 	writel(addr->cr, dev->regs + GSC_OUT_BASE_ADDR_CR(index));
105*3bae07d4SMauro Carvalho Chehab }
106*3bae07d4SMauro Carvalho Chehab 
gsc_hw_set_input_path(struct gsc_ctx * ctx)107*3bae07d4SMauro Carvalho Chehab void gsc_hw_set_input_path(struct gsc_ctx *ctx)
108*3bae07d4SMauro Carvalho Chehab {
109*3bae07d4SMauro Carvalho Chehab 	struct gsc_dev *dev = ctx->gsc_dev;
110*3bae07d4SMauro Carvalho Chehab 
111*3bae07d4SMauro Carvalho Chehab 	u32 cfg = readl(dev->regs + GSC_IN_CON);
112*3bae07d4SMauro Carvalho Chehab 	cfg &= ~(GSC_IN_PATH_MASK | GSC_IN_LOCAL_SEL_MASK);
113*3bae07d4SMauro Carvalho Chehab 
114*3bae07d4SMauro Carvalho Chehab 	if (ctx->in_path == GSC_DMA)
115*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_IN_PATH_MEMORY;
116*3bae07d4SMauro Carvalho Chehab 
117*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_IN_CON);
118*3bae07d4SMauro Carvalho Chehab }
119*3bae07d4SMauro Carvalho Chehab 
gsc_hw_set_in_size(struct gsc_ctx * ctx)120*3bae07d4SMauro Carvalho Chehab void gsc_hw_set_in_size(struct gsc_ctx *ctx)
121*3bae07d4SMauro Carvalho Chehab {
122*3bae07d4SMauro Carvalho Chehab 	struct gsc_dev *dev = ctx->gsc_dev;
123*3bae07d4SMauro Carvalho Chehab 	struct gsc_frame *frame = &ctx->s_frame;
124*3bae07d4SMauro Carvalho Chehab 	u32 cfg;
125*3bae07d4SMauro Carvalho Chehab 
126*3bae07d4SMauro Carvalho Chehab 	/* Set input pixel offset */
127*3bae07d4SMauro Carvalho Chehab 	cfg = GSC_SRCIMG_OFFSET_X(frame->crop.left);
128*3bae07d4SMauro Carvalho Chehab 	cfg |= GSC_SRCIMG_OFFSET_Y(frame->crop.top);
129*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_SRCIMG_OFFSET);
130*3bae07d4SMauro Carvalho Chehab 
131*3bae07d4SMauro Carvalho Chehab 	/* Set input original size */
132*3bae07d4SMauro Carvalho Chehab 	cfg = GSC_SRCIMG_WIDTH(frame->f_width);
133*3bae07d4SMauro Carvalho Chehab 	cfg |= GSC_SRCIMG_HEIGHT(frame->f_height);
134*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_SRCIMG_SIZE);
135*3bae07d4SMauro Carvalho Chehab 
136*3bae07d4SMauro Carvalho Chehab 	/* Set input cropped size */
137*3bae07d4SMauro Carvalho Chehab 	cfg = GSC_CROPPED_WIDTH(frame->crop.width);
138*3bae07d4SMauro Carvalho Chehab 	cfg |= GSC_CROPPED_HEIGHT(frame->crop.height);
139*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_CROPPED_SIZE);
140*3bae07d4SMauro Carvalho Chehab }
141*3bae07d4SMauro Carvalho Chehab 
gsc_hw_set_in_image_rgb(struct gsc_ctx * ctx)142*3bae07d4SMauro Carvalho Chehab void gsc_hw_set_in_image_rgb(struct gsc_ctx *ctx)
143*3bae07d4SMauro Carvalho Chehab {
144*3bae07d4SMauro Carvalho Chehab 	struct gsc_dev *dev = ctx->gsc_dev;
145*3bae07d4SMauro Carvalho Chehab 	struct gsc_frame *frame = &ctx->s_frame;
146*3bae07d4SMauro Carvalho Chehab 	u32 cfg;
147*3bae07d4SMauro Carvalho Chehab 
148*3bae07d4SMauro Carvalho Chehab 	cfg = readl(dev->regs + GSC_IN_CON);
149*3bae07d4SMauro Carvalho Chehab 	if (frame->colorspace == V4L2_COLORSPACE_REC709)
150*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_IN_RGB_HD_WIDE;
151*3bae07d4SMauro Carvalho Chehab 	else
152*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_IN_RGB_SD_WIDE;
153*3bae07d4SMauro Carvalho Chehab 
154*3bae07d4SMauro Carvalho Chehab 	if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB565X)
155*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_IN_RGB565;
156*3bae07d4SMauro Carvalho Chehab 	else if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB32)
157*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_IN_XRGB8888;
158*3bae07d4SMauro Carvalho Chehab 
159*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_IN_CON);
160*3bae07d4SMauro Carvalho Chehab }
161*3bae07d4SMauro Carvalho Chehab 
gsc_hw_set_in_image_format(struct gsc_ctx * ctx)162*3bae07d4SMauro Carvalho Chehab void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
163*3bae07d4SMauro Carvalho Chehab {
164*3bae07d4SMauro Carvalho Chehab 	struct gsc_dev *dev = ctx->gsc_dev;
165*3bae07d4SMauro Carvalho Chehab 	struct gsc_frame *frame = &ctx->s_frame;
166*3bae07d4SMauro Carvalho Chehab 	u32 i, depth = 0;
167*3bae07d4SMauro Carvalho Chehab 	u32 cfg;
168*3bae07d4SMauro Carvalho Chehab 
169*3bae07d4SMauro Carvalho Chehab 	cfg = readl(dev->regs + GSC_IN_CON);
170*3bae07d4SMauro Carvalho Chehab 	cfg &= ~(GSC_IN_RGB_TYPE_MASK | GSC_IN_YUV422_1P_ORDER_MASK |
171*3bae07d4SMauro Carvalho Chehab 		 GSC_IN_CHROMA_ORDER_MASK | GSC_IN_FORMAT_MASK |
172*3bae07d4SMauro Carvalho Chehab 		 GSC_IN_TILE_TYPE_MASK | GSC_IN_TILE_MODE);
173*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_IN_CON);
174*3bae07d4SMauro Carvalho Chehab 
175*3bae07d4SMauro Carvalho Chehab 	if (is_rgb(frame->fmt->color)) {
176*3bae07d4SMauro Carvalho Chehab 		gsc_hw_set_in_image_rgb(ctx);
177*3bae07d4SMauro Carvalho Chehab 		return;
178*3bae07d4SMauro Carvalho Chehab 	}
179*3bae07d4SMauro Carvalho Chehab 	for (i = 0; i < frame->fmt->num_planes; i++)
180*3bae07d4SMauro Carvalho Chehab 		depth += frame->fmt->depth[i];
181*3bae07d4SMauro Carvalho Chehab 
182*3bae07d4SMauro Carvalho Chehab 	switch (frame->fmt->num_comp) {
183*3bae07d4SMauro Carvalho Chehab 	case 1:
184*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_IN_YUV422_1P;
185*3bae07d4SMauro Carvalho Chehab 		if (frame->fmt->yorder == GSC_LSB_Y)
186*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_IN_YUV422_1P_ORDER_LSB_Y;
187*3bae07d4SMauro Carvalho Chehab 		else
188*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_IN_YUV422_1P_OEDER_LSB_C;
189*3bae07d4SMauro Carvalho Chehab 		if (frame->fmt->corder == GSC_CBCR)
190*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_IN_CHROMA_ORDER_CBCR;
191*3bae07d4SMauro Carvalho Chehab 		else
192*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_IN_CHROMA_ORDER_CRCB;
193*3bae07d4SMauro Carvalho Chehab 		break;
194*3bae07d4SMauro Carvalho Chehab 	case 2:
195*3bae07d4SMauro Carvalho Chehab 		if (depth == 12)
196*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_IN_YUV420_2P;
197*3bae07d4SMauro Carvalho Chehab 		else
198*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_IN_YUV422_2P;
199*3bae07d4SMauro Carvalho Chehab 		if (frame->fmt->corder == GSC_CBCR)
200*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_IN_CHROMA_ORDER_CBCR;
201*3bae07d4SMauro Carvalho Chehab 		else
202*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_IN_CHROMA_ORDER_CRCB;
203*3bae07d4SMauro Carvalho Chehab 		break;
204*3bae07d4SMauro Carvalho Chehab 	case 3:
205*3bae07d4SMauro Carvalho Chehab 		if (depth == 12)
206*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_IN_YUV420_3P;
207*3bae07d4SMauro Carvalho Chehab 		else
208*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_IN_YUV422_3P;
209*3bae07d4SMauro Carvalho Chehab 		break;
210*3bae07d4SMauro Carvalho Chehab 	}
211*3bae07d4SMauro Carvalho Chehab 
212*3bae07d4SMauro Carvalho Chehab 	if (is_tiled(frame->fmt))
213*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_IN_TILE_C_16x8 | GSC_IN_TILE_MODE;
214*3bae07d4SMauro Carvalho Chehab 
215*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_IN_CON);
216*3bae07d4SMauro Carvalho Chehab }
217*3bae07d4SMauro Carvalho Chehab 
gsc_hw_set_output_path(struct gsc_ctx * ctx)218*3bae07d4SMauro Carvalho Chehab void gsc_hw_set_output_path(struct gsc_ctx *ctx)
219*3bae07d4SMauro Carvalho Chehab {
220*3bae07d4SMauro Carvalho Chehab 	struct gsc_dev *dev = ctx->gsc_dev;
221*3bae07d4SMauro Carvalho Chehab 
222*3bae07d4SMauro Carvalho Chehab 	u32 cfg = readl(dev->regs + GSC_OUT_CON);
223*3bae07d4SMauro Carvalho Chehab 	cfg &= ~GSC_OUT_PATH_MASK;
224*3bae07d4SMauro Carvalho Chehab 
225*3bae07d4SMauro Carvalho Chehab 	if (ctx->out_path == GSC_DMA)
226*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_OUT_PATH_MEMORY;
227*3bae07d4SMauro Carvalho Chehab 	else
228*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_OUT_PATH_LOCAL;
229*3bae07d4SMauro Carvalho Chehab 
230*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_OUT_CON);
231*3bae07d4SMauro Carvalho Chehab }
232*3bae07d4SMauro Carvalho Chehab 
gsc_hw_set_out_size(struct gsc_ctx * ctx)233*3bae07d4SMauro Carvalho Chehab void gsc_hw_set_out_size(struct gsc_ctx *ctx)
234*3bae07d4SMauro Carvalho Chehab {
235*3bae07d4SMauro Carvalho Chehab 	struct gsc_dev *dev = ctx->gsc_dev;
236*3bae07d4SMauro Carvalho Chehab 	struct gsc_frame *frame = &ctx->d_frame;
237*3bae07d4SMauro Carvalho Chehab 	u32 cfg;
238*3bae07d4SMauro Carvalho Chehab 
239*3bae07d4SMauro Carvalho Chehab 	/* Set output original size */
240*3bae07d4SMauro Carvalho Chehab 	if (ctx->out_path == GSC_DMA) {
241*3bae07d4SMauro Carvalho Chehab 		cfg = GSC_DSTIMG_OFFSET_X(frame->crop.left);
242*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_DSTIMG_OFFSET_Y(frame->crop.top);
243*3bae07d4SMauro Carvalho Chehab 		writel(cfg, dev->regs + GSC_DSTIMG_OFFSET);
244*3bae07d4SMauro Carvalho Chehab 
245*3bae07d4SMauro Carvalho Chehab 		cfg = GSC_DSTIMG_WIDTH(frame->f_width);
246*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_DSTIMG_HEIGHT(frame->f_height);
247*3bae07d4SMauro Carvalho Chehab 		writel(cfg, dev->regs + GSC_DSTIMG_SIZE);
248*3bae07d4SMauro Carvalho Chehab 	}
249*3bae07d4SMauro Carvalho Chehab 
250*3bae07d4SMauro Carvalho Chehab 	/* Set output scaled size */
251*3bae07d4SMauro Carvalho Chehab 	if (ctx->gsc_ctrls.rotate->val == 90 ||
252*3bae07d4SMauro Carvalho Chehab 	    ctx->gsc_ctrls.rotate->val == 270) {
253*3bae07d4SMauro Carvalho Chehab 		cfg = GSC_SCALED_WIDTH(frame->crop.height);
254*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_SCALED_HEIGHT(frame->crop.width);
255*3bae07d4SMauro Carvalho Chehab 	} else {
256*3bae07d4SMauro Carvalho Chehab 		cfg = GSC_SCALED_WIDTH(frame->crop.width);
257*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_SCALED_HEIGHT(frame->crop.height);
258*3bae07d4SMauro Carvalho Chehab 	}
259*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_SCALED_SIZE);
260*3bae07d4SMauro Carvalho Chehab }
261*3bae07d4SMauro Carvalho Chehab 
gsc_hw_set_out_image_rgb(struct gsc_ctx * ctx)262*3bae07d4SMauro Carvalho Chehab void gsc_hw_set_out_image_rgb(struct gsc_ctx *ctx)
263*3bae07d4SMauro Carvalho Chehab {
264*3bae07d4SMauro Carvalho Chehab 	struct gsc_dev *dev = ctx->gsc_dev;
265*3bae07d4SMauro Carvalho Chehab 	struct gsc_frame *frame = &ctx->d_frame;
266*3bae07d4SMauro Carvalho Chehab 	u32 cfg;
267*3bae07d4SMauro Carvalho Chehab 
268*3bae07d4SMauro Carvalho Chehab 	cfg = readl(dev->regs + GSC_OUT_CON);
269*3bae07d4SMauro Carvalho Chehab 	if (frame->colorspace == V4L2_COLORSPACE_REC709)
270*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_OUT_RGB_HD_WIDE;
271*3bae07d4SMauro Carvalho Chehab 	else
272*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_OUT_RGB_SD_WIDE;
273*3bae07d4SMauro Carvalho Chehab 
274*3bae07d4SMauro Carvalho Chehab 	if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB565X)
275*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_OUT_RGB565;
276*3bae07d4SMauro Carvalho Chehab 	else if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB32)
277*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_OUT_XRGB8888;
278*3bae07d4SMauro Carvalho Chehab 
279*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_OUT_CON);
280*3bae07d4SMauro Carvalho Chehab }
281*3bae07d4SMauro Carvalho Chehab 
gsc_hw_set_out_image_format(struct gsc_ctx * ctx)282*3bae07d4SMauro Carvalho Chehab void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
283*3bae07d4SMauro Carvalho Chehab {
284*3bae07d4SMauro Carvalho Chehab 	struct gsc_dev *dev = ctx->gsc_dev;
285*3bae07d4SMauro Carvalho Chehab 	struct gsc_frame *frame = &ctx->d_frame;
286*3bae07d4SMauro Carvalho Chehab 	u32 i, depth = 0;
287*3bae07d4SMauro Carvalho Chehab 	u32 cfg;
288*3bae07d4SMauro Carvalho Chehab 
289*3bae07d4SMauro Carvalho Chehab 	cfg = readl(dev->regs + GSC_OUT_CON);
290*3bae07d4SMauro Carvalho Chehab 	cfg &= ~(GSC_OUT_RGB_TYPE_MASK | GSC_OUT_YUV422_1P_ORDER_MASK |
291*3bae07d4SMauro Carvalho Chehab 		 GSC_OUT_CHROMA_ORDER_MASK | GSC_OUT_FORMAT_MASK |
292*3bae07d4SMauro Carvalho Chehab 		 GSC_OUT_TILE_TYPE_MASK | GSC_OUT_TILE_MODE);
293*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_OUT_CON);
294*3bae07d4SMauro Carvalho Chehab 
295*3bae07d4SMauro Carvalho Chehab 	if (is_rgb(frame->fmt->color)) {
296*3bae07d4SMauro Carvalho Chehab 		gsc_hw_set_out_image_rgb(ctx);
297*3bae07d4SMauro Carvalho Chehab 		return;
298*3bae07d4SMauro Carvalho Chehab 	}
299*3bae07d4SMauro Carvalho Chehab 
300*3bae07d4SMauro Carvalho Chehab 	if (ctx->out_path != GSC_DMA) {
301*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_OUT_YUV444;
302*3bae07d4SMauro Carvalho Chehab 		goto end_set;
303*3bae07d4SMauro Carvalho Chehab 	}
304*3bae07d4SMauro Carvalho Chehab 
305*3bae07d4SMauro Carvalho Chehab 	for (i = 0; i < frame->fmt->num_planes; i++)
306*3bae07d4SMauro Carvalho Chehab 		depth += frame->fmt->depth[i];
307*3bae07d4SMauro Carvalho Chehab 
308*3bae07d4SMauro Carvalho Chehab 	switch (frame->fmt->num_comp) {
309*3bae07d4SMauro Carvalho Chehab 	case 1:
310*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_OUT_YUV422_1P;
311*3bae07d4SMauro Carvalho Chehab 		if (frame->fmt->yorder == GSC_LSB_Y)
312*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_OUT_YUV422_1P_ORDER_LSB_Y;
313*3bae07d4SMauro Carvalho Chehab 		else
314*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_OUT_YUV422_1P_OEDER_LSB_C;
315*3bae07d4SMauro Carvalho Chehab 		if (frame->fmt->corder == GSC_CBCR)
316*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_OUT_CHROMA_ORDER_CBCR;
317*3bae07d4SMauro Carvalho Chehab 		else
318*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_OUT_CHROMA_ORDER_CRCB;
319*3bae07d4SMauro Carvalho Chehab 		break;
320*3bae07d4SMauro Carvalho Chehab 	case 2:
321*3bae07d4SMauro Carvalho Chehab 		if (depth == 12)
322*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_OUT_YUV420_2P;
323*3bae07d4SMauro Carvalho Chehab 		else
324*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_OUT_YUV422_2P;
325*3bae07d4SMauro Carvalho Chehab 		if (frame->fmt->corder == GSC_CBCR)
326*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_OUT_CHROMA_ORDER_CBCR;
327*3bae07d4SMauro Carvalho Chehab 		else
328*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_OUT_CHROMA_ORDER_CRCB;
329*3bae07d4SMauro Carvalho Chehab 		break;
330*3bae07d4SMauro Carvalho Chehab 	case 3:
331*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_OUT_YUV420_3P;
332*3bae07d4SMauro Carvalho Chehab 		break;
333*3bae07d4SMauro Carvalho Chehab 	}
334*3bae07d4SMauro Carvalho Chehab 
335*3bae07d4SMauro Carvalho Chehab 	if (is_tiled(frame->fmt))
336*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_OUT_TILE_C_16x8 | GSC_OUT_TILE_MODE;
337*3bae07d4SMauro Carvalho Chehab 
338*3bae07d4SMauro Carvalho Chehab end_set:
339*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_OUT_CON);
340*3bae07d4SMauro Carvalho Chehab }
341*3bae07d4SMauro Carvalho Chehab 
gsc_hw_set_prescaler(struct gsc_ctx * ctx)342*3bae07d4SMauro Carvalho Chehab void gsc_hw_set_prescaler(struct gsc_ctx *ctx)
343*3bae07d4SMauro Carvalho Chehab {
344*3bae07d4SMauro Carvalho Chehab 	struct gsc_dev *dev = ctx->gsc_dev;
345*3bae07d4SMauro Carvalho Chehab 	struct gsc_scaler *sc = &ctx->scaler;
346*3bae07d4SMauro Carvalho Chehab 	u32 cfg;
347*3bae07d4SMauro Carvalho Chehab 
348*3bae07d4SMauro Carvalho Chehab 	cfg = GSC_PRESC_SHFACTOR(sc->pre_shfactor);
349*3bae07d4SMauro Carvalho Chehab 	cfg |= GSC_PRESC_H_RATIO(sc->pre_hratio);
350*3bae07d4SMauro Carvalho Chehab 	cfg |= GSC_PRESC_V_RATIO(sc->pre_vratio);
351*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_PRE_SCALE_RATIO);
352*3bae07d4SMauro Carvalho Chehab }
353*3bae07d4SMauro Carvalho Chehab 
gsc_hw_set_mainscaler(struct gsc_ctx * ctx)354*3bae07d4SMauro Carvalho Chehab void gsc_hw_set_mainscaler(struct gsc_ctx *ctx)
355*3bae07d4SMauro Carvalho Chehab {
356*3bae07d4SMauro Carvalho Chehab 	struct gsc_dev *dev = ctx->gsc_dev;
357*3bae07d4SMauro Carvalho Chehab 	struct gsc_scaler *sc = &ctx->scaler;
358*3bae07d4SMauro Carvalho Chehab 	u32 cfg;
359*3bae07d4SMauro Carvalho Chehab 
360*3bae07d4SMauro Carvalho Chehab 	cfg = GSC_MAIN_H_RATIO_VALUE(sc->main_hratio);
361*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_MAIN_H_RATIO);
362*3bae07d4SMauro Carvalho Chehab 
363*3bae07d4SMauro Carvalho Chehab 	cfg = GSC_MAIN_V_RATIO_VALUE(sc->main_vratio);
364*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_MAIN_V_RATIO);
365*3bae07d4SMauro Carvalho Chehab }
366*3bae07d4SMauro Carvalho Chehab 
gsc_hw_set_rotation(struct gsc_ctx * ctx)367*3bae07d4SMauro Carvalho Chehab void gsc_hw_set_rotation(struct gsc_ctx *ctx)
368*3bae07d4SMauro Carvalho Chehab {
369*3bae07d4SMauro Carvalho Chehab 	struct gsc_dev *dev = ctx->gsc_dev;
370*3bae07d4SMauro Carvalho Chehab 	u32 cfg;
371*3bae07d4SMauro Carvalho Chehab 
372*3bae07d4SMauro Carvalho Chehab 	cfg = readl(dev->regs + GSC_IN_CON);
373*3bae07d4SMauro Carvalho Chehab 	cfg &= ~GSC_IN_ROT_MASK;
374*3bae07d4SMauro Carvalho Chehab 
375*3bae07d4SMauro Carvalho Chehab 	switch (ctx->gsc_ctrls.rotate->val) {
376*3bae07d4SMauro Carvalho Chehab 	case 270:
377*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_IN_ROT_270;
378*3bae07d4SMauro Carvalho Chehab 		break;
379*3bae07d4SMauro Carvalho Chehab 	case 180:
380*3bae07d4SMauro Carvalho Chehab 		cfg |= GSC_IN_ROT_180;
381*3bae07d4SMauro Carvalho Chehab 		break;
382*3bae07d4SMauro Carvalho Chehab 	case 90:
383*3bae07d4SMauro Carvalho Chehab 		if (ctx->gsc_ctrls.hflip->val)
384*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_IN_ROT_90_XFLIP;
385*3bae07d4SMauro Carvalho Chehab 		else if (ctx->gsc_ctrls.vflip->val)
386*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_IN_ROT_90_YFLIP;
387*3bae07d4SMauro Carvalho Chehab 		else
388*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_IN_ROT_90;
389*3bae07d4SMauro Carvalho Chehab 		break;
390*3bae07d4SMauro Carvalho Chehab 	case 0:
391*3bae07d4SMauro Carvalho Chehab 		if (ctx->gsc_ctrls.hflip->val)
392*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_IN_ROT_XFLIP;
393*3bae07d4SMauro Carvalho Chehab 		else if (ctx->gsc_ctrls.vflip->val)
394*3bae07d4SMauro Carvalho Chehab 			cfg |= GSC_IN_ROT_YFLIP;
395*3bae07d4SMauro Carvalho Chehab 	}
396*3bae07d4SMauro Carvalho Chehab 
397*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_IN_CON);
398*3bae07d4SMauro Carvalho Chehab }
399*3bae07d4SMauro Carvalho Chehab 
gsc_hw_set_global_alpha(struct gsc_ctx * ctx)400*3bae07d4SMauro Carvalho Chehab void gsc_hw_set_global_alpha(struct gsc_ctx *ctx)
401*3bae07d4SMauro Carvalho Chehab {
402*3bae07d4SMauro Carvalho Chehab 	struct gsc_dev *dev = ctx->gsc_dev;
403*3bae07d4SMauro Carvalho Chehab 	struct gsc_frame *frame = &ctx->d_frame;
404*3bae07d4SMauro Carvalho Chehab 	u32 cfg;
405*3bae07d4SMauro Carvalho Chehab 
406*3bae07d4SMauro Carvalho Chehab 	if (!is_rgb(frame->fmt->color)) {
407*3bae07d4SMauro Carvalho Chehab 		pr_debug("Not a RGB format");
408*3bae07d4SMauro Carvalho Chehab 		return;
409*3bae07d4SMauro Carvalho Chehab 	}
410*3bae07d4SMauro Carvalho Chehab 
411*3bae07d4SMauro Carvalho Chehab 	cfg = readl(dev->regs + GSC_OUT_CON);
412*3bae07d4SMauro Carvalho Chehab 	cfg &= ~GSC_OUT_GLOBAL_ALPHA_MASK;
413*3bae07d4SMauro Carvalho Chehab 
414*3bae07d4SMauro Carvalho Chehab 	cfg |= GSC_OUT_GLOBAL_ALPHA(ctx->gsc_ctrls.global_alpha->val);
415*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_OUT_CON);
416*3bae07d4SMauro Carvalho Chehab }
417*3bae07d4SMauro Carvalho Chehab 
gsc_hw_set_sfr_update(struct gsc_ctx * ctx)418*3bae07d4SMauro Carvalho Chehab void gsc_hw_set_sfr_update(struct gsc_ctx *ctx)
419*3bae07d4SMauro Carvalho Chehab {
420*3bae07d4SMauro Carvalho Chehab 	struct gsc_dev *dev = ctx->gsc_dev;
421*3bae07d4SMauro Carvalho Chehab 	u32 cfg;
422*3bae07d4SMauro Carvalho Chehab 
423*3bae07d4SMauro Carvalho Chehab 	cfg = readl(dev->regs + GSC_ENABLE);
424*3bae07d4SMauro Carvalho Chehab 	cfg |= GSC_ENABLE_SFR_UPDATE;
425*3bae07d4SMauro Carvalho Chehab 	writel(cfg, dev->regs + GSC_ENABLE);
426*3bae07d4SMauro Carvalho Chehab }
427