162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd.
462306a36Sopenharmony_ci *		http://www.samsung.com
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Samsung EXYNOS5 SoC series G-Scaler driver
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/io.h>
1062306a36Sopenharmony_ci#include <linux/delay.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include "gsc-core.h"
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_civoid gsc_hw_set_sw_reset(struct gsc_dev *dev)
1562306a36Sopenharmony_ci{
1662306a36Sopenharmony_ci	writel(GSC_SW_RESET_SRESET, dev->regs + GSC_SW_RESET);
1762306a36Sopenharmony_ci}
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ciint gsc_wait_reset(struct gsc_dev *dev)
2062306a36Sopenharmony_ci{
2162306a36Sopenharmony_ci	unsigned long end = jiffies + msecs_to_jiffies(50);
2262306a36Sopenharmony_ci	u32 cfg;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	while (time_before(jiffies, end)) {
2562306a36Sopenharmony_ci		cfg = readl(dev->regs + GSC_SW_RESET);
2662306a36Sopenharmony_ci		if (!cfg)
2762306a36Sopenharmony_ci			return 0;
2862306a36Sopenharmony_ci		usleep_range(10, 20);
2962306a36Sopenharmony_ci	}
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	return -EBUSY;
3262306a36Sopenharmony_ci}
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_civoid gsc_hw_set_frm_done_irq_mask(struct gsc_dev *dev, bool mask)
3562306a36Sopenharmony_ci{
3662306a36Sopenharmony_ci	u32 cfg;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	cfg = readl(dev->regs + GSC_IRQ);
3962306a36Sopenharmony_ci	if (mask)
4062306a36Sopenharmony_ci		cfg |= GSC_IRQ_FRMDONE_MASK;
4162306a36Sopenharmony_ci	else
4262306a36Sopenharmony_ci		cfg &= ~GSC_IRQ_FRMDONE_MASK;
4362306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_IRQ);
4462306a36Sopenharmony_ci}
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_civoid gsc_hw_set_gsc_irq_enable(struct gsc_dev *dev, bool mask)
4762306a36Sopenharmony_ci{
4862306a36Sopenharmony_ci	u32 cfg;
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	cfg = readl(dev->regs + GSC_IRQ);
5162306a36Sopenharmony_ci	if (mask)
5262306a36Sopenharmony_ci		cfg |= GSC_IRQ_ENABLE;
5362306a36Sopenharmony_ci	else
5462306a36Sopenharmony_ci		cfg &= ~GSC_IRQ_ENABLE;
5562306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_IRQ);
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_civoid gsc_hw_set_input_buf_masking(struct gsc_dev *dev, u32 shift,
5962306a36Sopenharmony_ci				bool enable)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	u32 cfg = readl(dev->regs + GSC_IN_BASE_ADDR_Y_MASK);
6262306a36Sopenharmony_ci	u32 mask = 1 << shift;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	cfg &= ~mask;
6562306a36Sopenharmony_ci	cfg |= enable << shift;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_IN_BASE_ADDR_Y_MASK);
6862306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_IN_BASE_ADDR_CB_MASK);
6962306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_IN_BASE_ADDR_CR_MASK);
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_civoid gsc_hw_set_output_buf_masking(struct gsc_dev *dev, u32 shift,
7362306a36Sopenharmony_ci				bool enable)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	u32 cfg = readl(dev->regs + GSC_OUT_BASE_ADDR_Y_MASK);
7662306a36Sopenharmony_ci	u32 mask = 1 << shift;
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	cfg &= ~mask;
7962306a36Sopenharmony_ci	cfg |= enable << shift;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_Y_MASK);
8262306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_CB_MASK);
8362306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_CR_MASK);
8462306a36Sopenharmony_ci}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_civoid gsc_hw_set_input_addr(struct gsc_dev *dev, struct gsc_addr *addr,
8762306a36Sopenharmony_ci				int index)
8862306a36Sopenharmony_ci{
8962306a36Sopenharmony_ci	pr_debug("src_buf[%d]: %pad, cb: %pad, cr: %pad", index,
9062306a36Sopenharmony_ci			&addr->y, &addr->cb, &addr->cr);
9162306a36Sopenharmony_ci	writel(addr->y, dev->regs + GSC_IN_BASE_ADDR_Y(index));
9262306a36Sopenharmony_ci	writel(addr->cb, dev->regs + GSC_IN_BASE_ADDR_CB(index));
9362306a36Sopenharmony_ci	writel(addr->cr, dev->regs + GSC_IN_BASE_ADDR_CR(index));
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci}
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_civoid gsc_hw_set_output_addr(struct gsc_dev *dev,
9862306a36Sopenharmony_ci			     struct gsc_addr *addr, int index)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	pr_debug("dst_buf[%d]: %pad, cb: %pad, cr: %pad",
10162306a36Sopenharmony_ci			index, &addr->y, &addr->cb, &addr->cr);
10262306a36Sopenharmony_ci	writel(addr->y, dev->regs + GSC_OUT_BASE_ADDR_Y(index));
10362306a36Sopenharmony_ci	writel(addr->cb, dev->regs + GSC_OUT_BASE_ADDR_CB(index));
10462306a36Sopenharmony_ci	writel(addr->cr, dev->regs + GSC_OUT_BASE_ADDR_CR(index));
10562306a36Sopenharmony_ci}
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_civoid gsc_hw_set_input_path(struct gsc_ctx *ctx)
10862306a36Sopenharmony_ci{
10962306a36Sopenharmony_ci	struct gsc_dev *dev = ctx->gsc_dev;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	u32 cfg = readl(dev->regs + GSC_IN_CON);
11262306a36Sopenharmony_ci	cfg &= ~(GSC_IN_PATH_MASK | GSC_IN_LOCAL_SEL_MASK);
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	if (ctx->in_path == GSC_DMA)
11562306a36Sopenharmony_ci		cfg |= GSC_IN_PATH_MEMORY;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_IN_CON);
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_civoid gsc_hw_set_in_size(struct gsc_ctx *ctx)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	struct gsc_dev *dev = ctx->gsc_dev;
12362306a36Sopenharmony_ci	struct gsc_frame *frame = &ctx->s_frame;
12462306a36Sopenharmony_ci	u32 cfg;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	/* Set input pixel offset */
12762306a36Sopenharmony_ci	cfg = GSC_SRCIMG_OFFSET_X(frame->crop.left);
12862306a36Sopenharmony_ci	cfg |= GSC_SRCIMG_OFFSET_Y(frame->crop.top);
12962306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_SRCIMG_OFFSET);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	/* Set input original size */
13262306a36Sopenharmony_ci	cfg = GSC_SRCIMG_WIDTH(frame->f_width);
13362306a36Sopenharmony_ci	cfg |= GSC_SRCIMG_HEIGHT(frame->f_height);
13462306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_SRCIMG_SIZE);
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	/* Set input cropped size */
13762306a36Sopenharmony_ci	cfg = GSC_CROPPED_WIDTH(frame->crop.width);
13862306a36Sopenharmony_ci	cfg |= GSC_CROPPED_HEIGHT(frame->crop.height);
13962306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_CROPPED_SIZE);
14062306a36Sopenharmony_ci}
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_civoid gsc_hw_set_in_image_rgb(struct gsc_ctx *ctx)
14362306a36Sopenharmony_ci{
14462306a36Sopenharmony_ci	struct gsc_dev *dev = ctx->gsc_dev;
14562306a36Sopenharmony_ci	struct gsc_frame *frame = &ctx->s_frame;
14662306a36Sopenharmony_ci	u32 cfg;
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	cfg = readl(dev->regs + GSC_IN_CON);
14962306a36Sopenharmony_ci	if (frame->colorspace == V4L2_COLORSPACE_REC709)
15062306a36Sopenharmony_ci		cfg |= GSC_IN_RGB_HD_WIDE;
15162306a36Sopenharmony_ci	else
15262306a36Sopenharmony_ci		cfg |= GSC_IN_RGB_SD_WIDE;
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB565X)
15562306a36Sopenharmony_ci		cfg |= GSC_IN_RGB565;
15662306a36Sopenharmony_ci	else if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB32)
15762306a36Sopenharmony_ci		cfg |= GSC_IN_XRGB8888;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_IN_CON);
16062306a36Sopenharmony_ci}
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_civoid gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	struct gsc_dev *dev = ctx->gsc_dev;
16562306a36Sopenharmony_ci	struct gsc_frame *frame = &ctx->s_frame;
16662306a36Sopenharmony_ci	u32 i, depth = 0;
16762306a36Sopenharmony_ci	u32 cfg;
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	cfg = readl(dev->regs + GSC_IN_CON);
17062306a36Sopenharmony_ci	cfg &= ~(GSC_IN_RGB_TYPE_MASK | GSC_IN_YUV422_1P_ORDER_MASK |
17162306a36Sopenharmony_ci		 GSC_IN_CHROMA_ORDER_MASK | GSC_IN_FORMAT_MASK |
17262306a36Sopenharmony_ci		 GSC_IN_TILE_TYPE_MASK | GSC_IN_TILE_MODE);
17362306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_IN_CON);
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	if (is_rgb(frame->fmt->color)) {
17662306a36Sopenharmony_ci		gsc_hw_set_in_image_rgb(ctx);
17762306a36Sopenharmony_ci		return;
17862306a36Sopenharmony_ci	}
17962306a36Sopenharmony_ci	for (i = 0; i < frame->fmt->num_planes; i++)
18062306a36Sopenharmony_ci		depth += frame->fmt->depth[i];
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	switch (frame->fmt->num_comp) {
18362306a36Sopenharmony_ci	case 1:
18462306a36Sopenharmony_ci		cfg |= GSC_IN_YUV422_1P;
18562306a36Sopenharmony_ci		if (frame->fmt->yorder == GSC_LSB_Y)
18662306a36Sopenharmony_ci			cfg |= GSC_IN_YUV422_1P_ORDER_LSB_Y;
18762306a36Sopenharmony_ci		else
18862306a36Sopenharmony_ci			cfg |= GSC_IN_YUV422_1P_OEDER_LSB_C;
18962306a36Sopenharmony_ci		if (frame->fmt->corder == GSC_CBCR)
19062306a36Sopenharmony_ci			cfg |= GSC_IN_CHROMA_ORDER_CBCR;
19162306a36Sopenharmony_ci		else
19262306a36Sopenharmony_ci			cfg |= GSC_IN_CHROMA_ORDER_CRCB;
19362306a36Sopenharmony_ci		break;
19462306a36Sopenharmony_ci	case 2:
19562306a36Sopenharmony_ci		if (depth == 12)
19662306a36Sopenharmony_ci			cfg |= GSC_IN_YUV420_2P;
19762306a36Sopenharmony_ci		else
19862306a36Sopenharmony_ci			cfg |= GSC_IN_YUV422_2P;
19962306a36Sopenharmony_ci		if (frame->fmt->corder == GSC_CBCR)
20062306a36Sopenharmony_ci			cfg |= GSC_IN_CHROMA_ORDER_CBCR;
20162306a36Sopenharmony_ci		else
20262306a36Sopenharmony_ci			cfg |= GSC_IN_CHROMA_ORDER_CRCB;
20362306a36Sopenharmony_ci		break;
20462306a36Sopenharmony_ci	case 3:
20562306a36Sopenharmony_ci		if (depth == 12)
20662306a36Sopenharmony_ci			cfg |= GSC_IN_YUV420_3P;
20762306a36Sopenharmony_ci		else
20862306a36Sopenharmony_ci			cfg |= GSC_IN_YUV422_3P;
20962306a36Sopenharmony_ci		break;
21062306a36Sopenharmony_ci	}
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	if (is_tiled(frame->fmt))
21362306a36Sopenharmony_ci		cfg |= GSC_IN_TILE_C_16x8 | GSC_IN_TILE_MODE;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_IN_CON);
21662306a36Sopenharmony_ci}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_civoid gsc_hw_set_output_path(struct gsc_ctx *ctx)
21962306a36Sopenharmony_ci{
22062306a36Sopenharmony_ci	struct gsc_dev *dev = ctx->gsc_dev;
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	u32 cfg = readl(dev->regs + GSC_OUT_CON);
22362306a36Sopenharmony_ci	cfg &= ~GSC_OUT_PATH_MASK;
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	if (ctx->out_path == GSC_DMA)
22662306a36Sopenharmony_ci		cfg |= GSC_OUT_PATH_MEMORY;
22762306a36Sopenharmony_ci	else
22862306a36Sopenharmony_ci		cfg |= GSC_OUT_PATH_LOCAL;
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_OUT_CON);
23162306a36Sopenharmony_ci}
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_civoid gsc_hw_set_out_size(struct gsc_ctx *ctx)
23462306a36Sopenharmony_ci{
23562306a36Sopenharmony_ci	struct gsc_dev *dev = ctx->gsc_dev;
23662306a36Sopenharmony_ci	struct gsc_frame *frame = &ctx->d_frame;
23762306a36Sopenharmony_ci	u32 cfg;
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	/* Set output original size */
24062306a36Sopenharmony_ci	if (ctx->out_path == GSC_DMA) {
24162306a36Sopenharmony_ci		cfg = GSC_DSTIMG_OFFSET_X(frame->crop.left);
24262306a36Sopenharmony_ci		cfg |= GSC_DSTIMG_OFFSET_Y(frame->crop.top);
24362306a36Sopenharmony_ci		writel(cfg, dev->regs + GSC_DSTIMG_OFFSET);
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci		cfg = GSC_DSTIMG_WIDTH(frame->f_width);
24662306a36Sopenharmony_ci		cfg |= GSC_DSTIMG_HEIGHT(frame->f_height);
24762306a36Sopenharmony_ci		writel(cfg, dev->regs + GSC_DSTIMG_SIZE);
24862306a36Sopenharmony_ci	}
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	/* Set output scaled size */
25162306a36Sopenharmony_ci	if (ctx->gsc_ctrls.rotate->val == 90 ||
25262306a36Sopenharmony_ci	    ctx->gsc_ctrls.rotate->val == 270) {
25362306a36Sopenharmony_ci		cfg = GSC_SCALED_WIDTH(frame->crop.height);
25462306a36Sopenharmony_ci		cfg |= GSC_SCALED_HEIGHT(frame->crop.width);
25562306a36Sopenharmony_ci	} else {
25662306a36Sopenharmony_ci		cfg = GSC_SCALED_WIDTH(frame->crop.width);
25762306a36Sopenharmony_ci		cfg |= GSC_SCALED_HEIGHT(frame->crop.height);
25862306a36Sopenharmony_ci	}
25962306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_SCALED_SIZE);
26062306a36Sopenharmony_ci}
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_civoid gsc_hw_set_out_image_rgb(struct gsc_ctx *ctx)
26362306a36Sopenharmony_ci{
26462306a36Sopenharmony_ci	struct gsc_dev *dev = ctx->gsc_dev;
26562306a36Sopenharmony_ci	struct gsc_frame *frame = &ctx->d_frame;
26662306a36Sopenharmony_ci	u32 cfg;
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	cfg = readl(dev->regs + GSC_OUT_CON);
26962306a36Sopenharmony_ci	if (frame->colorspace == V4L2_COLORSPACE_REC709)
27062306a36Sopenharmony_ci		cfg |= GSC_OUT_RGB_HD_WIDE;
27162306a36Sopenharmony_ci	else
27262306a36Sopenharmony_ci		cfg |= GSC_OUT_RGB_SD_WIDE;
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB565X)
27562306a36Sopenharmony_ci		cfg |= GSC_OUT_RGB565;
27662306a36Sopenharmony_ci	else if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB32)
27762306a36Sopenharmony_ci		cfg |= GSC_OUT_XRGB8888;
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_OUT_CON);
28062306a36Sopenharmony_ci}
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_civoid gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
28362306a36Sopenharmony_ci{
28462306a36Sopenharmony_ci	struct gsc_dev *dev = ctx->gsc_dev;
28562306a36Sopenharmony_ci	struct gsc_frame *frame = &ctx->d_frame;
28662306a36Sopenharmony_ci	u32 i, depth = 0;
28762306a36Sopenharmony_ci	u32 cfg;
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	cfg = readl(dev->regs + GSC_OUT_CON);
29062306a36Sopenharmony_ci	cfg &= ~(GSC_OUT_RGB_TYPE_MASK | GSC_OUT_YUV422_1P_ORDER_MASK |
29162306a36Sopenharmony_ci		 GSC_OUT_CHROMA_ORDER_MASK | GSC_OUT_FORMAT_MASK |
29262306a36Sopenharmony_ci		 GSC_OUT_TILE_TYPE_MASK | GSC_OUT_TILE_MODE);
29362306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_OUT_CON);
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	if (is_rgb(frame->fmt->color)) {
29662306a36Sopenharmony_ci		gsc_hw_set_out_image_rgb(ctx);
29762306a36Sopenharmony_ci		return;
29862306a36Sopenharmony_ci	}
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	if (ctx->out_path != GSC_DMA) {
30162306a36Sopenharmony_ci		cfg |= GSC_OUT_YUV444;
30262306a36Sopenharmony_ci		goto end_set;
30362306a36Sopenharmony_ci	}
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	for (i = 0; i < frame->fmt->num_planes; i++)
30662306a36Sopenharmony_ci		depth += frame->fmt->depth[i];
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	switch (frame->fmt->num_comp) {
30962306a36Sopenharmony_ci	case 1:
31062306a36Sopenharmony_ci		cfg |= GSC_OUT_YUV422_1P;
31162306a36Sopenharmony_ci		if (frame->fmt->yorder == GSC_LSB_Y)
31262306a36Sopenharmony_ci			cfg |= GSC_OUT_YUV422_1P_ORDER_LSB_Y;
31362306a36Sopenharmony_ci		else
31462306a36Sopenharmony_ci			cfg |= GSC_OUT_YUV422_1P_OEDER_LSB_C;
31562306a36Sopenharmony_ci		if (frame->fmt->corder == GSC_CBCR)
31662306a36Sopenharmony_ci			cfg |= GSC_OUT_CHROMA_ORDER_CBCR;
31762306a36Sopenharmony_ci		else
31862306a36Sopenharmony_ci			cfg |= GSC_OUT_CHROMA_ORDER_CRCB;
31962306a36Sopenharmony_ci		break;
32062306a36Sopenharmony_ci	case 2:
32162306a36Sopenharmony_ci		if (depth == 12)
32262306a36Sopenharmony_ci			cfg |= GSC_OUT_YUV420_2P;
32362306a36Sopenharmony_ci		else
32462306a36Sopenharmony_ci			cfg |= GSC_OUT_YUV422_2P;
32562306a36Sopenharmony_ci		if (frame->fmt->corder == GSC_CBCR)
32662306a36Sopenharmony_ci			cfg |= GSC_OUT_CHROMA_ORDER_CBCR;
32762306a36Sopenharmony_ci		else
32862306a36Sopenharmony_ci			cfg |= GSC_OUT_CHROMA_ORDER_CRCB;
32962306a36Sopenharmony_ci		break;
33062306a36Sopenharmony_ci	case 3:
33162306a36Sopenharmony_ci		cfg |= GSC_OUT_YUV420_3P;
33262306a36Sopenharmony_ci		break;
33362306a36Sopenharmony_ci	}
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	if (is_tiled(frame->fmt))
33662306a36Sopenharmony_ci		cfg |= GSC_OUT_TILE_C_16x8 | GSC_OUT_TILE_MODE;
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ciend_set:
33962306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_OUT_CON);
34062306a36Sopenharmony_ci}
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_civoid gsc_hw_set_prescaler(struct gsc_ctx *ctx)
34362306a36Sopenharmony_ci{
34462306a36Sopenharmony_ci	struct gsc_dev *dev = ctx->gsc_dev;
34562306a36Sopenharmony_ci	struct gsc_scaler *sc = &ctx->scaler;
34662306a36Sopenharmony_ci	u32 cfg;
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	cfg = GSC_PRESC_SHFACTOR(sc->pre_shfactor);
34962306a36Sopenharmony_ci	cfg |= GSC_PRESC_H_RATIO(sc->pre_hratio);
35062306a36Sopenharmony_ci	cfg |= GSC_PRESC_V_RATIO(sc->pre_vratio);
35162306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_PRE_SCALE_RATIO);
35262306a36Sopenharmony_ci}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_civoid gsc_hw_set_mainscaler(struct gsc_ctx *ctx)
35562306a36Sopenharmony_ci{
35662306a36Sopenharmony_ci	struct gsc_dev *dev = ctx->gsc_dev;
35762306a36Sopenharmony_ci	struct gsc_scaler *sc = &ctx->scaler;
35862306a36Sopenharmony_ci	u32 cfg;
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	cfg = GSC_MAIN_H_RATIO_VALUE(sc->main_hratio);
36162306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_MAIN_H_RATIO);
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	cfg = GSC_MAIN_V_RATIO_VALUE(sc->main_vratio);
36462306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_MAIN_V_RATIO);
36562306a36Sopenharmony_ci}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_civoid gsc_hw_set_rotation(struct gsc_ctx *ctx)
36862306a36Sopenharmony_ci{
36962306a36Sopenharmony_ci	struct gsc_dev *dev = ctx->gsc_dev;
37062306a36Sopenharmony_ci	u32 cfg;
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci	cfg = readl(dev->regs + GSC_IN_CON);
37362306a36Sopenharmony_ci	cfg &= ~GSC_IN_ROT_MASK;
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	switch (ctx->gsc_ctrls.rotate->val) {
37662306a36Sopenharmony_ci	case 270:
37762306a36Sopenharmony_ci		cfg |= GSC_IN_ROT_270;
37862306a36Sopenharmony_ci		break;
37962306a36Sopenharmony_ci	case 180:
38062306a36Sopenharmony_ci		cfg |= GSC_IN_ROT_180;
38162306a36Sopenharmony_ci		break;
38262306a36Sopenharmony_ci	case 90:
38362306a36Sopenharmony_ci		if (ctx->gsc_ctrls.hflip->val)
38462306a36Sopenharmony_ci			cfg |= GSC_IN_ROT_90_XFLIP;
38562306a36Sopenharmony_ci		else if (ctx->gsc_ctrls.vflip->val)
38662306a36Sopenharmony_ci			cfg |= GSC_IN_ROT_90_YFLIP;
38762306a36Sopenharmony_ci		else
38862306a36Sopenharmony_ci			cfg |= GSC_IN_ROT_90;
38962306a36Sopenharmony_ci		break;
39062306a36Sopenharmony_ci	case 0:
39162306a36Sopenharmony_ci		if (ctx->gsc_ctrls.hflip->val)
39262306a36Sopenharmony_ci			cfg |= GSC_IN_ROT_XFLIP;
39362306a36Sopenharmony_ci		else if (ctx->gsc_ctrls.vflip->val)
39462306a36Sopenharmony_ci			cfg |= GSC_IN_ROT_YFLIP;
39562306a36Sopenharmony_ci	}
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_IN_CON);
39862306a36Sopenharmony_ci}
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_civoid gsc_hw_set_global_alpha(struct gsc_ctx *ctx)
40162306a36Sopenharmony_ci{
40262306a36Sopenharmony_ci	struct gsc_dev *dev = ctx->gsc_dev;
40362306a36Sopenharmony_ci	struct gsc_frame *frame = &ctx->d_frame;
40462306a36Sopenharmony_ci	u32 cfg;
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci	if (!is_rgb(frame->fmt->color)) {
40762306a36Sopenharmony_ci		pr_debug("Not a RGB format");
40862306a36Sopenharmony_ci		return;
40962306a36Sopenharmony_ci	}
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	cfg = readl(dev->regs + GSC_OUT_CON);
41262306a36Sopenharmony_ci	cfg &= ~GSC_OUT_GLOBAL_ALPHA_MASK;
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci	cfg |= GSC_OUT_GLOBAL_ALPHA(ctx->gsc_ctrls.global_alpha->val);
41562306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_OUT_CON);
41662306a36Sopenharmony_ci}
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_civoid gsc_hw_set_sfr_update(struct gsc_ctx *ctx)
41962306a36Sopenharmony_ci{
42062306a36Sopenharmony_ci	struct gsc_dev *dev = ctx->gsc_dev;
42162306a36Sopenharmony_ci	u32 cfg;
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	cfg = readl(dev->regs + GSC_ENABLE);
42462306a36Sopenharmony_ci	cfg |= GSC_ENABLE_SFR_UPDATE;
42562306a36Sopenharmony_ci	writel(cfg, dev->regs + GSC_ENABLE);
42662306a36Sopenharmony_ci}
427