18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2012-2014 Mentor Graphics Inc.
48c2ecf20Sopenharmony_ci * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <linux/types.h>
88c2ecf20Sopenharmony_ci#include <linux/init.h>
98c2ecf20Sopenharmony_ci#include <linux/errno.h>
108c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
118c2ecf20Sopenharmony_ci#include <linux/bitrev.h>
128c2ecf20Sopenharmony_ci#include <linux/io.h>
138c2ecf20Sopenharmony_ci#include <linux/err.h>
148c2ecf20Sopenharmony_ci#include <linux/sizes.h>
158c2ecf20Sopenharmony_ci#include "ipu-prv.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci/* IC Register Offsets */
188c2ecf20Sopenharmony_ci#define IC_CONF                 0x0000
198c2ecf20Sopenharmony_ci#define IC_PRP_ENC_RSC          0x0004
208c2ecf20Sopenharmony_ci#define IC_PRP_VF_RSC           0x0008
218c2ecf20Sopenharmony_ci#define IC_PP_RSC               0x000C
228c2ecf20Sopenharmony_ci#define IC_CMBP_1               0x0010
238c2ecf20Sopenharmony_ci#define IC_CMBP_2               0x0014
248c2ecf20Sopenharmony_ci#define IC_IDMAC_1              0x0018
258c2ecf20Sopenharmony_ci#define IC_IDMAC_2              0x001C
268c2ecf20Sopenharmony_ci#define IC_IDMAC_3              0x0020
278c2ecf20Sopenharmony_ci#define IC_IDMAC_4              0x0024
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci/* IC Register Fields */
308c2ecf20Sopenharmony_ci#define IC_CONF_PRPENC_EN       (1 << 0)
318c2ecf20Sopenharmony_ci#define IC_CONF_PRPENC_CSC1     (1 << 1)
328c2ecf20Sopenharmony_ci#define IC_CONF_PRPENC_ROT_EN   (1 << 2)
338c2ecf20Sopenharmony_ci#define IC_CONF_PRPVF_EN        (1 << 8)
348c2ecf20Sopenharmony_ci#define IC_CONF_PRPVF_CSC1      (1 << 9)
358c2ecf20Sopenharmony_ci#define IC_CONF_PRPVF_CSC2      (1 << 10)
368c2ecf20Sopenharmony_ci#define IC_CONF_PRPVF_CMB       (1 << 11)
378c2ecf20Sopenharmony_ci#define IC_CONF_PRPVF_ROT_EN    (1 << 12)
388c2ecf20Sopenharmony_ci#define IC_CONF_PP_EN           (1 << 16)
398c2ecf20Sopenharmony_ci#define IC_CONF_PP_CSC1         (1 << 17)
408c2ecf20Sopenharmony_ci#define IC_CONF_PP_CSC2         (1 << 18)
418c2ecf20Sopenharmony_ci#define IC_CONF_PP_CMB          (1 << 19)
428c2ecf20Sopenharmony_ci#define IC_CONF_PP_ROT_EN       (1 << 20)
438c2ecf20Sopenharmony_ci#define IC_CONF_IC_GLB_LOC_A    (1 << 28)
448c2ecf20Sopenharmony_ci#define IC_CONF_KEY_COLOR_EN    (1 << 29)
458c2ecf20Sopenharmony_ci#define IC_CONF_RWS_EN          (1 << 30)
468c2ecf20Sopenharmony_ci#define IC_CONF_CSI_MEM_WR_EN   (1 << 31)
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci#define IC_IDMAC_1_CB0_BURST_16         (1 << 0)
498c2ecf20Sopenharmony_ci#define IC_IDMAC_1_CB1_BURST_16         (1 << 1)
508c2ecf20Sopenharmony_ci#define IC_IDMAC_1_CB2_BURST_16         (1 << 2)
518c2ecf20Sopenharmony_ci#define IC_IDMAC_1_CB3_BURST_16         (1 << 3)
528c2ecf20Sopenharmony_ci#define IC_IDMAC_1_CB4_BURST_16         (1 << 4)
538c2ecf20Sopenharmony_ci#define IC_IDMAC_1_CB5_BURST_16         (1 << 5)
548c2ecf20Sopenharmony_ci#define IC_IDMAC_1_CB6_BURST_16         (1 << 6)
558c2ecf20Sopenharmony_ci#define IC_IDMAC_1_CB7_BURST_16         (1 << 7)
568c2ecf20Sopenharmony_ci#define IC_IDMAC_1_PRPENC_ROT_MASK      (0x7 << 11)
578c2ecf20Sopenharmony_ci#define IC_IDMAC_1_PRPENC_ROT_OFFSET    11
588c2ecf20Sopenharmony_ci#define IC_IDMAC_1_PRPVF_ROT_MASK       (0x7 << 14)
598c2ecf20Sopenharmony_ci#define IC_IDMAC_1_PRPVF_ROT_OFFSET     14
608c2ecf20Sopenharmony_ci#define IC_IDMAC_1_PP_ROT_MASK          (0x7 << 17)
618c2ecf20Sopenharmony_ci#define IC_IDMAC_1_PP_ROT_OFFSET        17
628c2ecf20Sopenharmony_ci#define IC_IDMAC_1_PP_FLIP_RS           (1 << 22)
638c2ecf20Sopenharmony_ci#define IC_IDMAC_1_PRPVF_FLIP_RS        (1 << 21)
648c2ecf20Sopenharmony_ci#define IC_IDMAC_1_PRPENC_FLIP_RS       (1 << 20)
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci#define IC_IDMAC_2_PRPENC_HEIGHT_MASK   (0x3ff << 0)
678c2ecf20Sopenharmony_ci#define IC_IDMAC_2_PRPENC_HEIGHT_OFFSET 0
688c2ecf20Sopenharmony_ci#define IC_IDMAC_2_PRPVF_HEIGHT_MASK    (0x3ff << 10)
698c2ecf20Sopenharmony_ci#define IC_IDMAC_2_PRPVF_HEIGHT_OFFSET  10
708c2ecf20Sopenharmony_ci#define IC_IDMAC_2_PP_HEIGHT_MASK       (0x3ff << 20)
718c2ecf20Sopenharmony_ci#define IC_IDMAC_2_PP_HEIGHT_OFFSET     20
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci#define IC_IDMAC_3_PRPENC_WIDTH_MASK    (0x3ff << 0)
748c2ecf20Sopenharmony_ci#define IC_IDMAC_3_PRPENC_WIDTH_OFFSET  0
758c2ecf20Sopenharmony_ci#define IC_IDMAC_3_PRPVF_WIDTH_MASK     (0x3ff << 10)
768c2ecf20Sopenharmony_ci#define IC_IDMAC_3_PRPVF_WIDTH_OFFSET   10
778c2ecf20Sopenharmony_ci#define IC_IDMAC_3_PP_WIDTH_MASK        (0x3ff << 20)
788c2ecf20Sopenharmony_ci#define IC_IDMAC_3_PP_WIDTH_OFFSET      20
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_cistruct ic_task_regoffs {
818c2ecf20Sopenharmony_ci	u32 rsc;
828c2ecf20Sopenharmony_ci	u32 tpmem_csc[2];
838c2ecf20Sopenharmony_ci};
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_cistruct ic_task_bitfields {
868c2ecf20Sopenharmony_ci	u32 ic_conf_en;
878c2ecf20Sopenharmony_ci	u32 ic_conf_rot_en;
888c2ecf20Sopenharmony_ci	u32 ic_conf_cmb_en;
898c2ecf20Sopenharmony_ci	u32 ic_conf_csc1_en;
908c2ecf20Sopenharmony_ci	u32 ic_conf_csc2_en;
918c2ecf20Sopenharmony_ci	u32 ic_cmb_galpha_bit;
928c2ecf20Sopenharmony_ci};
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_cistatic const struct ic_task_regoffs ic_task_reg[IC_NUM_TASKS] = {
958c2ecf20Sopenharmony_ci	[IC_TASK_ENCODER] = {
968c2ecf20Sopenharmony_ci		.rsc = IC_PRP_ENC_RSC,
978c2ecf20Sopenharmony_ci		.tpmem_csc = {0x2008, 0},
988c2ecf20Sopenharmony_ci	},
998c2ecf20Sopenharmony_ci	[IC_TASK_VIEWFINDER] = {
1008c2ecf20Sopenharmony_ci		.rsc = IC_PRP_VF_RSC,
1018c2ecf20Sopenharmony_ci		.tpmem_csc = {0x4028, 0x4040},
1028c2ecf20Sopenharmony_ci	},
1038c2ecf20Sopenharmony_ci	[IC_TASK_POST_PROCESSOR] = {
1048c2ecf20Sopenharmony_ci		.rsc = IC_PP_RSC,
1058c2ecf20Sopenharmony_ci		.tpmem_csc = {0x6060, 0x6078},
1068c2ecf20Sopenharmony_ci	},
1078c2ecf20Sopenharmony_ci};
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_cistatic const struct ic_task_bitfields ic_task_bit[IC_NUM_TASKS] = {
1108c2ecf20Sopenharmony_ci	[IC_TASK_ENCODER] = {
1118c2ecf20Sopenharmony_ci		.ic_conf_en = IC_CONF_PRPENC_EN,
1128c2ecf20Sopenharmony_ci		.ic_conf_rot_en = IC_CONF_PRPENC_ROT_EN,
1138c2ecf20Sopenharmony_ci		.ic_conf_cmb_en = 0,    /* NA */
1148c2ecf20Sopenharmony_ci		.ic_conf_csc1_en = IC_CONF_PRPENC_CSC1,
1158c2ecf20Sopenharmony_ci		.ic_conf_csc2_en = 0,   /* NA */
1168c2ecf20Sopenharmony_ci		.ic_cmb_galpha_bit = 0, /* NA */
1178c2ecf20Sopenharmony_ci	},
1188c2ecf20Sopenharmony_ci	[IC_TASK_VIEWFINDER] = {
1198c2ecf20Sopenharmony_ci		.ic_conf_en = IC_CONF_PRPVF_EN,
1208c2ecf20Sopenharmony_ci		.ic_conf_rot_en = IC_CONF_PRPVF_ROT_EN,
1218c2ecf20Sopenharmony_ci		.ic_conf_cmb_en = IC_CONF_PRPVF_CMB,
1228c2ecf20Sopenharmony_ci		.ic_conf_csc1_en = IC_CONF_PRPVF_CSC1,
1238c2ecf20Sopenharmony_ci		.ic_conf_csc2_en = IC_CONF_PRPVF_CSC2,
1248c2ecf20Sopenharmony_ci		.ic_cmb_galpha_bit = 0,
1258c2ecf20Sopenharmony_ci	},
1268c2ecf20Sopenharmony_ci	[IC_TASK_POST_PROCESSOR] = {
1278c2ecf20Sopenharmony_ci		.ic_conf_en = IC_CONF_PP_EN,
1288c2ecf20Sopenharmony_ci		.ic_conf_rot_en = IC_CONF_PP_ROT_EN,
1298c2ecf20Sopenharmony_ci		.ic_conf_cmb_en = IC_CONF_PP_CMB,
1308c2ecf20Sopenharmony_ci		.ic_conf_csc1_en = IC_CONF_PP_CSC1,
1318c2ecf20Sopenharmony_ci		.ic_conf_csc2_en = IC_CONF_PP_CSC2,
1328c2ecf20Sopenharmony_ci		.ic_cmb_galpha_bit = 8,
1338c2ecf20Sopenharmony_ci	},
1348c2ecf20Sopenharmony_ci};
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_cistruct ipu_ic_priv;
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistruct ipu_ic {
1398c2ecf20Sopenharmony_ci	enum ipu_ic_task task;
1408c2ecf20Sopenharmony_ci	const struct ic_task_regoffs *reg;
1418c2ecf20Sopenharmony_ci	const struct ic_task_bitfields *bit;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	struct ipu_ic_colorspace in_cs;
1448c2ecf20Sopenharmony_ci	struct ipu_ic_colorspace g_in_cs;
1458c2ecf20Sopenharmony_ci	struct ipu_ic_colorspace out_cs;
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	bool graphics;
1488c2ecf20Sopenharmony_ci	bool rotation;
1498c2ecf20Sopenharmony_ci	bool in_use;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	struct ipu_ic_priv *priv;
1528c2ecf20Sopenharmony_ci};
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_cistruct ipu_ic_priv {
1558c2ecf20Sopenharmony_ci	void __iomem *base;
1568c2ecf20Sopenharmony_ci	void __iomem *tpmem_base;
1578c2ecf20Sopenharmony_ci	spinlock_t lock;
1588c2ecf20Sopenharmony_ci	struct ipu_soc *ipu;
1598c2ecf20Sopenharmony_ci	int use_count;
1608c2ecf20Sopenharmony_ci	int irt_use_count;
1618c2ecf20Sopenharmony_ci	struct ipu_ic task[IC_NUM_TASKS];
1628c2ecf20Sopenharmony_ci};
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_cistatic inline u32 ipu_ic_read(struct ipu_ic *ic, unsigned offset)
1658c2ecf20Sopenharmony_ci{
1668c2ecf20Sopenharmony_ci	return readl(ic->priv->base + offset);
1678c2ecf20Sopenharmony_ci}
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cistatic inline void ipu_ic_write(struct ipu_ic *ic, u32 value, unsigned offset)
1708c2ecf20Sopenharmony_ci{
1718c2ecf20Sopenharmony_ci	writel(value, ic->priv->base + offset);
1728c2ecf20Sopenharmony_ci}
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_cistatic int init_csc(struct ipu_ic *ic,
1758c2ecf20Sopenharmony_ci		    const struct ipu_ic_csc *csc,
1768c2ecf20Sopenharmony_ci		    int csc_index)
1778c2ecf20Sopenharmony_ci{
1788c2ecf20Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
1798c2ecf20Sopenharmony_ci	u32 __iomem *base;
1808c2ecf20Sopenharmony_ci	const u16 (*c)[3];
1818c2ecf20Sopenharmony_ci	const u16 *a;
1828c2ecf20Sopenharmony_ci	u32 param;
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci	base = (u32 __iomem *)
1858c2ecf20Sopenharmony_ci		(priv->tpmem_base + ic->reg->tpmem_csc[csc_index]);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	/* Cast to unsigned */
1888c2ecf20Sopenharmony_ci	c = (const u16 (*)[3])csc->params.coeff;
1898c2ecf20Sopenharmony_ci	a = (const u16 *)csc->params.offset;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	param = ((a[0] & 0x1f) << 27) | ((c[0][0] & 0x1ff) << 18) |
1928c2ecf20Sopenharmony_ci		((c[1][1] & 0x1ff) << 9) | (c[2][2] & 0x1ff);
1938c2ecf20Sopenharmony_ci	writel(param, base++);
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	param = ((a[0] & 0x1fe0) >> 5) | (csc->params.scale << 8) |
1968c2ecf20Sopenharmony_ci		(csc->params.sat << 10);
1978c2ecf20Sopenharmony_ci	writel(param, base++);
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	param = ((a[1] & 0x1f) << 27) | ((c[0][1] & 0x1ff) << 18) |
2008c2ecf20Sopenharmony_ci		((c[1][0] & 0x1ff) << 9) | (c[2][0] & 0x1ff);
2018c2ecf20Sopenharmony_ci	writel(param, base++);
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	param = ((a[1] & 0x1fe0) >> 5);
2048c2ecf20Sopenharmony_ci	writel(param, base++);
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	param = ((a[2] & 0x1f) << 27) | ((c[0][2] & 0x1ff) << 18) |
2078c2ecf20Sopenharmony_ci		((c[1][2] & 0x1ff) << 9) | (c[2][1] & 0x1ff);
2088c2ecf20Sopenharmony_ci	writel(param, base++);
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	param = ((a[2] & 0x1fe0) >> 5);
2118c2ecf20Sopenharmony_ci	writel(param, base++);
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	return 0;
2148c2ecf20Sopenharmony_ci}
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_cistatic int calc_resize_coeffs(struct ipu_ic *ic,
2178c2ecf20Sopenharmony_ci			      u32 in_size, u32 out_size,
2188c2ecf20Sopenharmony_ci			      u32 *resize_coeff,
2198c2ecf20Sopenharmony_ci			      u32 *downsize_coeff)
2208c2ecf20Sopenharmony_ci{
2218c2ecf20Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
2228c2ecf20Sopenharmony_ci	struct ipu_soc *ipu = priv->ipu;
2238c2ecf20Sopenharmony_ci	u32 temp_size, temp_downsize;
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	/*
2268c2ecf20Sopenharmony_ci	 * Input size cannot be more than 4096, and output size cannot
2278c2ecf20Sopenharmony_ci	 * be more than 1024
2288c2ecf20Sopenharmony_ci	 */
2298c2ecf20Sopenharmony_ci	if (in_size > 4096) {
2308c2ecf20Sopenharmony_ci		dev_err(ipu->dev, "Unsupported resize (in_size > 4096)\n");
2318c2ecf20Sopenharmony_ci		return -EINVAL;
2328c2ecf20Sopenharmony_ci	}
2338c2ecf20Sopenharmony_ci	if (out_size > 1024) {
2348c2ecf20Sopenharmony_ci		dev_err(ipu->dev, "Unsupported resize (out_size > 1024)\n");
2358c2ecf20Sopenharmony_ci		return -EINVAL;
2368c2ecf20Sopenharmony_ci	}
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	/* Cannot downsize more than 4:1 */
2398c2ecf20Sopenharmony_ci	if ((out_size << 2) < in_size) {
2408c2ecf20Sopenharmony_ci		dev_err(ipu->dev, "Unsupported downsize\n");
2418c2ecf20Sopenharmony_ci		return -EINVAL;
2428c2ecf20Sopenharmony_ci	}
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	/* Compute downsizing coefficient */
2458c2ecf20Sopenharmony_ci	temp_downsize = 0;
2468c2ecf20Sopenharmony_ci	temp_size = in_size;
2478c2ecf20Sopenharmony_ci	while (((temp_size > 1024) || (temp_size >= out_size * 2)) &&
2488c2ecf20Sopenharmony_ci	       (temp_downsize < 2)) {
2498c2ecf20Sopenharmony_ci		temp_size >>= 1;
2508c2ecf20Sopenharmony_ci		temp_downsize++;
2518c2ecf20Sopenharmony_ci	}
2528c2ecf20Sopenharmony_ci	*downsize_coeff = temp_downsize;
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	/*
2558c2ecf20Sopenharmony_ci	 * compute resizing coefficient using the following equation:
2568c2ecf20Sopenharmony_ci	 * resize_coeff = M * (SI - 1) / (SO - 1)
2578c2ecf20Sopenharmony_ci	 * where M = 2^13, SI = input size, SO = output size
2588c2ecf20Sopenharmony_ci	 */
2598c2ecf20Sopenharmony_ci	*resize_coeff = (8192L * (temp_size - 1)) / (out_size - 1);
2608c2ecf20Sopenharmony_ci	if (*resize_coeff >= 16384L) {
2618c2ecf20Sopenharmony_ci		dev_err(ipu->dev, "Warning! Overflow on resize coeff.\n");
2628c2ecf20Sopenharmony_ci		*resize_coeff = 0x3FFF;
2638c2ecf20Sopenharmony_ci	}
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	return 0;
2668c2ecf20Sopenharmony_ci}
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_civoid ipu_ic_task_enable(struct ipu_ic *ic)
2698c2ecf20Sopenharmony_ci{
2708c2ecf20Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
2718c2ecf20Sopenharmony_ci	unsigned long flags;
2728c2ecf20Sopenharmony_ci	u32 ic_conf;
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	ic_conf = ipu_ic_read(ic, IC_CONF);
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	ic_conf |= ic->bit->ic_conf_en;
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	if (ic->rotation)
2818c2ecf20Sopenharmony_ci		ic_conf |= ic->bit->ic_conf_rot_en;
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	if (ic->in_cs.cs != ic->out_cs.cs)
2848c2ecf20Sopenharmony_ci		ic_conf |= ic->bit->ic_conf_csc1_en;
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	if (ic->graphics) {
2878c2ecf20Sopenharmony_ci		ic_conf |= ic->bit->ic_conf_cmb_en;
2888c2ecf20Sopenharmony_ci		ic_conf |= ic->bit->ic_conf_csc1_en;
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci		if (ic->g_in_cs.cs != ic->out_cs.cs)
2918c2ecf20Sopenharmony_ci			ic_conf |= ic->bit->ic_conf_csc2_en;
2928c2ecf20Sopenharmony_ci	}
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	ipu_ic_write(ic, ic_conf, IC_CONF);
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
2978c2ecf20Sopenharmony_ci}
2988c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ipu_ic_task_enable);
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_civoid ipu_ic_task_disable(struct ipu_ic *ic)
3018c2ecf20Sopenharmony_ci{
3028c2ecf20Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
3038c2ecf20Sopenharmony_ci	unsigned long flags;
3048c2ecf20Sopenharmony_ci	u32 ic_conf;
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	ic_conf = ipu_ic_read(ic, IC_CONF);
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	ic_conf &= ~(ic->bit->ic_conf_en |
3118c2ecf20Sopenharmony_ci		     ic->bit->ic_conf_csc1_en |
3128c2ecf20Sopenharmony_ci		     ic->bit->ic_conf_rot_en);
3138c2ecf20Sopenharmony_ci	if (ic->bit->ic_conf_csc2_en)
3148c2ecf20Sopenharmony_ci		ic_conf &= ~ic->bit->ic_conf_csc2_en;
3158c2ecf20Sopenharmony_ci	if (ic->bit->ic_conf_cmb_en)
3168c2ecf20Sopenharmony_ci		ic_conf &= ~ic->bit->ic_conf_cmb_en;
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	ipu_ic_write(ic, ic_conf, IC_CONF);
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
3218c2ecf20Sopenharmony_ci}
3228c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ipu_ic_task_disable);
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ciint ipu_ic_task_graphics_init(struct ipu_ic *ic,
3258c2ecf20Sopenharmony_ci			      const struct ipu_ic_colorspace *g_in_cs,
3268c2ecf20Sopenharmony_ci			      bool galpha_en, u32 galpha,
3278c2ecf20Sopenharmony_ci			      bool colorkey_en, u32 colorkey)
3288c2ecf20Sopenharmony_ci{
3298c2ecf20Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
3308c2ecf20Sopenharmony_ci	struct ipu_ic_csc csc2;
3318c2ecf20Sopenharmony_ci	unsigned long flags;
3328c2ecf20Sopenharmony_ci	u32 reg, ic_conf;
3338c2ecf20Sopenharmony_ci	int ret = 0;
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	if (ic->task == IC_TASK_ENCODER)
3368c2ecf20Sopenharmony_ci		return -EINVAL;
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	ic_conf = ipu_ic_read(ic, IC_CONF);
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	if (!(ic_conf & ic->bit->ic_conf_csc1_en)) {
3438c2ecf20Sopenharmony_ci		struct ipu_ic_csc csc1;
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci		ret = ipu_ic_calc_csc(&csc1,
3468c2ecf20Sopenharmony_ci				      V4L2_YCBCR_ENC_601,
3478c2ecf20Sopenharmony_ci				      V4L2_QUANTIZATION_FULL_RANGE,
3488c2ecf20Sopenharmony_ci				      IPUV3_COLORSPACE_RGB,
3498c2ecf20Sopenharmony_ci				      V4L2_YCBCR_ENC_601,
3508c2ecf20Sopenharmony_ci				      V4L2_QUANTIZATION_FULL_RANGE,
3518c2ecf20Sopenharmony_ci				      IPUV3_COLORSPACE_RGB);
3528c2ecf20Sopenharmony_ci		if (ret)
3538c2ecf20Sopenharmony_ci			goto unlock;
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci		/* need transparent CSC1 conversion */
3568c2ecf20Sopenharmony_ci		ret = init_csc(ic, &csc1, 0);
3578c2ecf20Sopenharmony_ci		if (ret)
3588c2ecf20Sopenharmony_ci			goto unlock;
3598c2ecf20Sopenharmony_ci	}
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	ic->g_in_cs = *g_in_cs;
3628c2ecf20Sopenharmony_ci	csc2.in_cs = ic->g_in_cs;
3638c2ecf20Sopenharmony_ci	csc2.out_cs = ic->out_cs;
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	ret = __ipu_ic_calc_csc(&csc2);
3668c2ecf20Sopenharmony_ci	if (ret)
3678c2ecf20Sopenharmony_ci		goto unlock;
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	ret = init_csc(ic, &csc2, 1);
3708c2ecf20Sopenharmony_ci	if (ret)
3718c2ecf20Sopenharmony_ci		goto unlock;
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	if (galpha_en) {
3748c2ecf20Sopenharmony_ci		ic_conf |= IC_CONF_IC_GLB_LOC_A;
3758c2ecf20Sopenharmony_ci		reg = ipu_ic_read(ic, IC_CMBP_1);
3768c2ecf20Sopenharmony_ci		reg &= ~(0xff << ic->bit->ic_cmb_galpha_bit);
3778c2ecf20Sopenharmony_ci		reg |= (galpha << ic->bit->ic_cmb_galpha_bit);
3788c2ecf20Sopenharmony_ci		ipu_ic_write(ic, reg, IC_CMBP_1);
3798c2ecf20Sopenharmony_ci	} else
3808c2ecf20Sopenharmony_ci		ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	if (colorkey_en) {
3838c2ecf20Sopenharmony_ci		ic_conf |= IC_CONF_KEY_COLOR_EN;
3848c2ecf20Sopenharmony_ci		ipu_ic_write(ic, colorkey, IC_CMBP_2);
3858c2ecf20Sopenharmony_ci	} else
3868c2ecf20Sopenharmony_ci		ic_conf &= ~IC_CONF_KEY_COLOR_EN;
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	ipu_ic_write(ic, ic_conf, IC_CONF);
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	ic->graphics = true;
3918c2ecf20Sopenharmony_ciunlock:
3928c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
3938c2ecf20Sopenharmony_ci	return ret;
3948c2ecf20Sopenharmony_ci}
3958c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ipu_ic_task_graphics_init);
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ciint ipu_ic_task_init_rsc(struct ipu_ic *ic,
3988c2ecf20Sopenharmony_ci			 const struct ipu_ic_csc *csc,
3998c2ecf20Sopenharmony_ci			 int in_width, int in_height,
4008c2ecf20Sopenharmony_ci			 int out_width, int out_height,
4018c2ecf20Sopenharmony_ci			 u32 rsc)
4028c2ecf20Sopenharmony_ci{
4038c2ecf20Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
4048c2ecf20Sopenharmony_ci	u32 downsize_coeff, resize_coeff;
4058c2ecf20Sopenharmony_ci	unsigned long flags;
4068c2ecf20Sopenharmony_ci	int ret = 0;
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	if (!rsc) {
4098c2ecf20Sopenharmony_ci		/* Setup vertical resizing */
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci		ret = calc_resize_coeffs(ic, in_height, out_height,
4128c2ecf20Sopenharmony_ci					 &resize_coeff, &downsize_coeff);
4138c2ecf20Sopenharmony_ci		if (ret)
4148c2ecf20Sopenharmony_ci			return ret;
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci		rsc = (downsize_coeff << 30) | (resize_coeff << 16);
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci		/* Setup horizontal resizing */
4198c2ecf20Sopenharmony_ci		ret = calc_resize_coeffs(ic, in_width, out_width,
4208c2ecf20Sopenharmony_ci					 &resize_coeff, &downsize_coeff);
4218c2ecf20Sopenharmony_ci		if (ret)
4228c2ecf20Sopenharmony_ci			return ret;
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci		rsc |= (downsize_coeff << 14) | resize_coeff;
4258c2ecf20Sopenharmony_ci	}
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	ipu_ic_write(ic, rsc, ic->reg->rsc);
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	/* Setup color space conversion */
4328c2ecf20Sopenharmony_ci	ic->in_cs = csc->in_cs;
4338c2ecf20Sopenharmony_ci	ic->out_cs = csc->out_cs;
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	ret = init_csc(ic, csc, 0);
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
4388c2ecf20Sopenharmony_ci	return ret;
4398c2ecf20Sopenharmony_ci}
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ciint ipu_ic_task_init(struct ipu_ic *ic,
4428c2ecf20Sopenharmony_ci		     const struct ipu_ic_csc *csc,
4438c2ecf20Sopenharmony_ci		     int in_width, int in_height,
4448c2ecf20Sopenharmony_ci		     int out_width, int out_height)
4458c2ecf20Sopenharmony_ci{
4468c2ecf20Sopenharmony_ci	return ipu_ic_task_init_rsc(ic, csc,
4478c2ecf20Sopenharmony_ci				    in_width, in_height,
4488c2ecf20Sopenharmony_ci				    out_width, out_height, 0);
4498c2ecf20Sopenharmony_ci}
4508c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ipu_ic_task_init);
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ciint ipu_ic_task_idma_init(struct ipu_ic *ic, struct ipuv3_channel *channel,
4538c2ecf20Sopenharmony_ci			  u32 width, u32 height, int burst_size,
4548c2ecf20Sopenharmony_ci			  enum ipu_rotate_mode rot)
4558c2ecf20Sopenharmony_ci{
4568c2ecf20Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
4578c2ecf20Sopenharmony_ci	struct ipu_soc *ipu = priv->ipu;
4588c2ecf20Sopenharmony_ci	u32 ic_idmac_1, ic_idmac_2, ic_idmac_3;
4598c2ecf20Sopenharmony_ci	u32 temp_rot = bitrev8(rot) >> 5;
4608c2ecf20Sopenharmony_ci	bool need_hor_flip = false;
4618c2ecf20Sopenharmony_ci	unsigned long flags;
4628c2ecf20Sopenharmony_ci	int ret = 0;
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	if ((burst_size != 8) && (burst_size != 16)) {
4658c2ecf20Sopenharmony_ci		dev_err(ipu->dev, "Illegal burst length for IC\n");
4668c2ecf20Sopenharmony_ci		return -EINVAL;
4678c2ecf20Sopenharmony_ci	}
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	width--;
4708c2ecf20Sopenharmony_ci	height--;
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci	if (temp_rot & 0x2)	/* Need horizontal flip */
4738c2ecf20Sopenharmony_ci		need_hor_flip = true;
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	ic_idmac_1 = ipu_ic_read(ic, IC_IDMAC_1);
4788c2ecf20Sopenharmony_ci	ic_idmac_2 = ipu_ic_read(ic, IC_IDMAC_2);
4798c2ecf20Sopenharmony_ci	ic_idmac_3 = ipu_ic_read(ic, IC_IDMAC_3);
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci	switch (channel->num) {
4828c2ecf20Sopenharmony_ci	case IPUV3_CHANNEL_IC_PP_MEM:
4838c2ecf20Sopenharmony_ci		if (burst_size == 16)
4848c2ecf20Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_CB2_BURST_16;
4858c2ecf20Sopenharmony_ci		else
4868c2ecf20Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_CB2_BURST_16;
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci		if (need_hor_flip)
4898c2ecf20Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_PP_FLIP_RS;
4908c2ecf20Sopenharmony_ci		else
4918c2ecf20Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_PP_FLIP_RS;
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci		ic_idmac_2 &= ~IC_IDMAC_2_PP_HEIGHT_MASK;
4948c2ecf20Sopenharmony_ci		ic_idmac_2 |= height << IC_IDMAC_2_PP_HEIGHT_OFFSET;
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci		ic_idmac_3 &= ~IC_IDMAC_3_PP_WIDTH_MASK;
4978c2ecf20Sopenharmony_ci		ic_idmac_3 |= width << IC_IDMAC_3_PP_WIDTH_OFFSET;
4988c2ecf20Sopenharmony_ci		break;
4998c2ecf20Sopenharmony_ci	case IPUV3_CHANNEL_MEM_IC_PP:
5008c2ecf20Sopenharmony_ci		if (burst_size == 16)
5018c2ecf20Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_CB5_BURST_16;
5028c2ecf20Sopenharmony_ci		else
5038c2ecf20Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_CB5_BURST_16;
5048c2ecf20Sopenharmony_ci		break;
5058c2ecf20Sopenharmony_ci	case IPUV3_CHANNEL_MEM_ROT_PP:
5068c2ecf20Sopenharmony_ci		ic_idmac_1 &= ~IC_IDMAC_1_PP_ROT_MASK;
5078c2ecf20Sopenharmony_ci		ic_idmac_1 |= temp_rot << IC_IDMAC_1_PP_ROT_OFFSET;
5088c2ecf20Sopenharmony_ci		break;
5098c2ecf20Sopenharmony_ci	case IPUV3_CHANNEL_MEM_IC_PRP_VF:
5108c2ecf20Sopenharmony_ci		if (burst_size == 16)
5118c2ecf20Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_CB6_BURST_16;
5128c2ecf20Sopenharmony_ci		else
5138c2ecf20Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_CB6_BURST_16;
5148c2ecf20Sopenharmony_ci		break;
5158c2ecf20Sopenharmony_ci	case IPUV3_CHANNEL_IC_PRP_ENC_MEM:
5168c2ecf20Sopenharmony_ci		if (burst_size == 16)
5178c2ecf20Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_CB0_BURST_16;
5188c2ecf20Sopenharmony_ci		else
5198c2ecf20Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_CB0_BURST_16;
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci		if (need_hor_flip)
5228c2ecf20Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_PRPENC_FLIP_RS;
5238c2ecf20Sopenharmony_ci		else
5248c2ecf20Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_FLIP_RS;
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci		ic_idmac_2 &= ~IC_IDMAC_2_PRPENC_HEIGHT_MASK;
5278c2ecf20Sopenharmony_ci		ic_idmac_2 |= height << IC_IDMAC_2_PRPENC_HEIGHT_OFFSET;
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci		ic_idmac_3 &= ~IC_IDMAC_3_PRPENC_WIDTH_MASK;
5308c2ecf20Sopenharmony_ci		ic_idmac_3 |= width << IC_IDMAC_3_PRPENC_WIDTH_OFFSET;
5318c2ecf20Sopenharmony_ci		break;
5328c2ecf20Sopenharmony_ci	case IPUV3_CHANNEL_MEM_ROT_ENC:
5338c2ecf20Sopenharmony_ci		ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_ROT_MASK;
5348c2ecf20Sopenharmony_ci		ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPENC_ROT_OFFSET;
5358c2ecf20Sopenharmony_ci		break;
5368c2ecf20Sopenharmony_ci	case IPUV3_CHANNEL_IC_PRP_VF_MEM:
5378c2ecf20Sopenharmony_ci		if (burst_size == 16)
5388c2ecf20Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_CB1_BURST_16;
5398c2ecf20Sopenharmony_ci		else
5408c2ecf20Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_CB1_BURST_16;
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci		if (need_hor_flip)
5438c2ecf20Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_PRPVF_FLIP_RS;
5448c2ecf20Sopenharmony_ci		else
5458c2ecf20Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_FLIP_RS;
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci		ic_idmac_2 &= ~IC_IDMAC_2_PRPVF_HEIGHT_MASK;
5488c2ecf20Sopenharmony_ci		ic_idmac_2 |= height << IC_IDMAC_2_PRPVF_HEIGHT_OFFSET;
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci		ic_idmac_3 &= ~IC_IDMAC_3_PRPVF_WIDTH_MASK;
5518c2ecf20Sopenharmony_ci		ic_idmac_3 |= width << IC_IDMAC_3_PRPVF_WIDTH_OFFSET;
5528c2ecf20Sopenharmony_ci		break;
5538c2ecf20Sopenharmony_ci	case IPUV3_CHANNEL_MEM_ROT_VF:
5548c2ecf20Sopenharmony_ci		ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_ROT_MASK;
5558c2ecf20Sopenharmony_ci		ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPVF_ROT_OFFSET;
5568c2ecf20Sopenharmony_ci		break;
5578c2ecf20Sopenharmony_ci	case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:
5588c2ecf20Sopenharmony_ci		if (burst_size == 16)
5598c2ecf20Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_CB3_BURST_16;
5608c2ecf20Sopenharmony_ci		else
5618c2ecf20Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_CB3_BURST_16;
5628c2ecf20Sopenharmony_ci		break;
5638c2ecf20Sopenharmony_ci	case IPUV3_CHANNEL_G_MEM_IC_PP:
5648c2ecf20Sopenharmony_ci		if (burst_size == 16)
5658c2ecf20Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_CB4_BURST_16;
5668c2ecf20Sopenharmony_ci		else
5678c2ecf20Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_CB4_BURST_16;
5688c2ecf20Sopenharmony_ci		break;
5698c2ecf20Sopenharmony_ci	case IPUV3_CHANNEL_VDI_MEM_IC_VF:
5708c2ecf20Sopenharmony_ci		if (burst_size == 16)
5718c2ecf20Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_CB7_BURST_16;
5728c2ecf20Sopenharmony_ci		else
5738c2ecf20Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_CB7_BURST_16;
5748c2ecf20Sopenharmony_ci		break;
5758c2ecf20Sopenharmony_ci	default:
5768c2ecf20Sopenharmony_ci		goto unlock;
5778c2ecf20Sopenharmony_ci	}
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	ipu_ic_write(ic, ic_idmac_1, IC_IDMAC_1);
5808c2ecf20Sopenharmony_ci	ipu_ic_write(ic, ic_idmac_2, IC_IDMAC_2);
5818c2ecf20Sopenharmony_ci	ipu_ic_write(ic, ic_idmac_3, IC_IDMAC_3);
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	if (ipu_rot_mode_is_irt(rot))
5848c2ecf20Sopenharmony_ci		ic->rotation = true;
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ciunlock:
5878c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
5888c2ecf20Sopenharmony_ci	return ret;
5898c2ecf20Sopenharmony_ci}
5908c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ipu_ic_task_idma_init);
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_cistatic void ipu_irt_enable(struct ipu_ic *ic)
5938c2ecf20Sopenharmony_ci{
5948c2ecf20Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	if (!priv->irt_use_count)
5978c2ecf20Sopenharmony_ci		ipu_module_enable(priv->ipu, IPU_CONF_ROT_EN);
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	priv->irt_use_count++;
6008c2ecf20Sopenharmony_ci}
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_cistatic void ipu_irt_disable(struct ipu_ic *ic)
6038c2ecf20Sopenharmony_ci{
6048c2ecf20Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci	if (priv->irt_use_count) {
6078c2ecf20Sopenharmony_ci		if (!--priv->irt_use_count)
6088c2ecf20Sopenharmony_ci			ipu_module_disable(priv->ipu, IPU_CONF_ROT_EN);
6098c2ecf20Sopenharmony_ci	}
6108c2ecf20Sopenharmony_ci}
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ciint ipu_ic_enable(struct ipu_ic *ic)
6138c2ecf20Sopenharmony_ci{
6148c2ecf20Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
6158c2ecf20Sopenharmony_ci	unsigned long flags;
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	if (!priv->use_count)
6208c2ecf20Sopenharmony_ci		ipu_module_enable(priv->ipu, IPU_CONF_IC_EN);
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	priv->use_count++;
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	if (ic->rotation)
6258c2ecf20Sopenharmony_ci		ipu_irt_enable(ic);
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	return 0;
6308c2ecf20Sopenharmony_ci}
6318c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ipu_ic_enable);
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ciint ipu_ic_disable(struct ipu_ic *ic)
6348c2ecf20Sopenharmony_ci{
6358c2ecf20Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
6368c2ecf20Sopenharmony_ci	unsigned long flags;
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci	priv->use_count--;
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci	if (!priv->use_count)
6438c2ecf20Sopenharmony_ci		ipu_module_disable(priv->ipu, IPU_CONF_IC_EN);
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ci	if (priv->use_count < 0)
6468c2ecf20Sopenharmony_ci		priv->use_count = 0;
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	if (ic->rotation)
6498c2ecf20Sopenharmony_ci		ipu_irt_disable(ic);
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	ic->rotation = ic->graphics = false;
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	return 0;
6568c2ecf20Sopenharmony_ci}
6578c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ipu_ic_disable);
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_cistruct ipu_ic *ipu_ic_get(struct ipu_soc *ipu, enum ipu_ic_task task)
6608c2ecf20Sopenharmony_ci{
6618c2ecf20Sopenharmony_ci	struct ipu_ic_priv *priv = ipu->ic_priv;
6628c2ecf20Sopenharmony_ci	unsigned long flags;
6638c2ecf20Sopenharmony_ci	struct ipu_ic *ic, *ret;
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	if (task >= IC_NUM_TASKS)
6668c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	ic = &priv->task[task];
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci	if (ic->in_use) {
6738c2ecf20Sopenharmony_ci		ret = ERR_PTR(-EBUSY);
6748c2ecf20Sopenharmony_ci		goto unlock;
6758c2ecf20Sopenharmony_ci	}
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	ic->in_use = true;
6788c2ecf20Sopenharmony_ci	ret = ic;
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ciunlock:
6818c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
6828c2ecf20Sopenharmony_ci	return ret;
6838c2ecf20Sopenharmony_ci}
6848c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ipu_ic_get);
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_civoid ipu_ic_put(struct ipu_ic *ic)
6878c2ecf20Sopenharmony_ci{
6888c2ecf20Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
6898c2ecf20Sopenharmony_ci	unsigned long flags;
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
6928c2ecf20Sopenharmony_ci	ic->in_use = false;
6938c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
6948c2ecf20Sopenharmony_ci}
6958c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ipu_ic_put);
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ciint ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
6988c2ecf20Sopenharmony_ci		unsigned long base, unsigned long tpmem_base)
6998c2ecf20Sopenharmony_ci{
7008c2ecf20Sopenharmony_ci	struct ipu_ic_priv *priv;
7018c2ecf20Sopenharmony_ci	int i;
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_ci	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
7048c2ecf20Sopenharmony_ci	if (!priv)
7058c2ecf20Sopenharmony_ci		return -ENOMEM;
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci	ipu->ic_priv = priv;
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	spin_lock_init(&priv->lock);
7108c2ecf20Sopenharmony_ci	priv->base = devm_ioremap(dev, base, PAGE_SIZE);
7118c2ecf20Sopenharmony_ci	if (!priv->base)
7128c2ecf20Sopenharmony_ci		return -ENOMEM;
7138c2ecf20Sopenharmony_ci	priv->tpmem_base = devm_ioremap(dev, tpmem_base, SZ_64K);
7148c2ecf20Sopenharmony_ci	if (!priv->tpmem_base)
7158c2ecf20Sopenharmony_ci		return -ENOMEM;
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	dev_dbg(dev, "IC base: 0x%08lx remapped to %p\n", base, priv->base);
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	priv->ipu = ipu;
7208c2ecf20Sopenharmony_ci
7218c2ecf20Sopenharmony_ci	for (i = 0; i < IC_NUM_TASKS; i++) {
7228c2ecf20Sopenharmony_ci		priv->task[i].task = i;
7238c2ecf20Sopenharmony_ci		priv->task[i].priv = priv;
7248c2ecf20Sopenharmony_ci		priv->task[i].reg = &ic_task_reg[i];
7258c2ecf20Sopenharmony_ci		priv->task[i].bit = &ic_task_bit[i];
7268c2ecf20Sopenharmony_ci	}
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci	return 0;
7298c2ecf20Sopenharmony_ci}
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_civoid ipu_ic_exit(struct ipu_soc *ipu)
7328c2ecf20Sopenharmony_ci{
7338c2ecf20Sopenharmony_ci}
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_civoid ipu_ic_dump(struct ipu_ic *ic)
7368c2ecf20Sopenharmony_ci{
7378c2ecf20Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
7388c2ecf20Sopenharmony_ci	struct ipu_soc *ipu = priv->ipu;
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci	dev_dbg(ipu->dev, "IC_CONF = \t0x%08X\n",
7418c2ecf20Sopenharmony_ci		ipu_ic_read(ic, IC_CONF));
7428c2ecf20Sopenharmony_ci	dev_dbg(ipu->dev, "IC_PRP_ENC_RSC = \t0x%08X\n",
7438c2ecf20Sopenharmony_ci		ipu_ic_read(ic, IC_PRP_ENC_RSC));
7448c2ecf20Sopenharmony_ci	dev_dbg(ipu->dev, "IC_PRP_VF_RSC = \t0x%08X\n",
7458c2ecf20Sopenharmony_ci		ipu_ic_read(ic, IC_PRP_VF_RSC));
7468c2ecf20Sopenharmony_ci	dev_dbg(ipu->dev, "IC_PP_RSC = \t0x%08X\n",
7478c2ecf20Sopenharmony_ci		ipu_ic_read(ic, IC_PP_RSC));
7488c2ecf20Sopenharmony_ci	dev_dbg(ipu->dev, "IC_CMBP_1 = \t0x%08X\n",
7498c2ecf20Sopenharmony_ci		ipu_ic_read(ic, IC_CMBP_1));
7508c2ecf20Sopenharmony_ci	dev_dbg(ipu->dev, "IC_CMBP_2 = \t0x%08X\n",
7518c2ecf20Sopenharmony_ci		ipu_ic_read(ic, IC_CMBP_2));
7528c2ecf20Sopenharmony_ci	dev_dbg(ipu->dev, "IC_IDMAC_1 = \t0x%08X\n",
7538c2ecf20Sopenharmony_ci		ipu_ic_read(ic, IC_IDMAC_1));
7548c2ecf20Sopenharmony_ci	dev_dbg(ipu->dev, "IC_IDMAC_2 = \t0x%08X\n",
7558c2ecf20Sopenharmony_ci		ipu_ic_read(ic, IC_IDMAC_2));
7568c2ecf20Sopenharmony_ci	dev_dbg(ipu->dev, "IC_IDMAC_3 = \t0x%08X\n",
7578c2ecf20Sopenharmony_ci		ipu_ic_read(ic, IC_IDMAC_3));
7588c2ecf20Sopenharmony_ci	dev_dbg(ipu->dev, "IC_IDMAC_4 = \t0x%08X\n",
7598c2ecf20Sopenharmony_ci		ipu_ic_read(ic, IC_IDMAC_4));
7608c2ecf20Sopenharmony_ci}
7618c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ipu_ic_dump);
762