Linux Audio

Check our new training course

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