162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2012-2014 Mentor Graphics Inc.
462306a36Sopenharmony_ci * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/types.h>
862306a36Sopenharmony_ci#include <linux/init.h>
962306a36Sopenharmony_ci#include <linux/errno.h>
1062306a36Sopenharmony_ci#include <linux/spinlock.h>
1162306a36Sopenharmony_ci#include <linux/bitrev.h>
1262306a36Sopenharmony_ci#include <linux/io.h>
1362306a36Sopenharmony_ci#include <linux/err.h>
1462306a36Sopenharmony_ci#include <linux/sizes.h>
1562306a36Sopenharmony_ci#include "ipu-prv.h"
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci/* IC Register Offsets */
1862306a36Sopenharmony_ci#define IC_CONF                 0x0000
1962306a36Sopenharmony_ci#define IC_PRP_ENC_RSC          0x0004
2062306a36Sopenharmony_ci#define IC_PRP_VF_RSC           0x0008
2162306a36Sopenharmony_ci#define IC_PP_RSC               0x000C
2262306a36Sopenharmony_ci#define IC_CMBP_1               0x0010
2362306a36Sopenharmony_ci#define IC_CMBP_2               0x0014
2462306a36Sopenharmony_ci#define IC_IDMAC_1              0x0018
2562306a36Sopenharmony_ci#define IC_IDMAC_2              0x001C
2662306a36Sopenharmony_ci#define IC_IDMAC_3              0x0020
2762306a36Sopenharmony_ci#define IC_IDMAC_4              0x0024
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/* IC Register Fields */
3062306a36Sopenharmony_ci#define IC_CONF_PRPENC_EN       (1 << 0)
3162306a36Sopenharmony_ci#define IC_CONF_PRPENC_CSC1     (1 << 1)
3262306a36Sopenharmony_ci#define IC_CONF_PRPENC_ROT_EN   (1 << 2)
3362306a36Sopenharmony_ci#define IC_CONF_PRPVF_EN        (1 << 8)
3462306a36Sopenharmony_ci#define IC_CONF_PRPVF_CSC1      (1 << 9)
3562306a36Sopenharmony_ci#define IC_CONF_PRPVF_CSC2      (1 << 10)
3662306a36Sopenharmony_ci#define IC_CONF_PRPVF_CMB       (1 << 11)
3762306a36Sopenharmony_ci#define IC_CONF_PRPVF_ROT_EN    (1 << 12)
3862306a36Sopenharmony_ci#define IC_CONF_PP_EN           (1 << 16)
3962306a36Sopenharmony_ci#define IC_CONF_PP_CSC1         (1 << 17)
4062306a36Sopenharmony_ci#define IC_CONF_PP_CSC2         (1 << 18)
4162306a36Sopenharmony_ci#define IC_CONF_PP_CMB          (1 << 19)
4262306a36Sopenharmony_ci#define IC_CONF_PP_ROT_EN       (1 << 20)
4362306a36Sopenharmony_ci#define IC_CONF_IC_GLB_LOC_A    (1 << 28)
4462306a36Sopenharmony_ci#define IC_CONF_KEY_COLOR_EN    (1 << 29)
4562306a36Sopenharmony_ci#define IC_CONF_RWS_EN          (1 << 30)
4662306a36Sopenharmony_ci#define IC_CONF_CSI_MEM_WR_EN   (1 << 31)
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci#define IC_IDMAC_1_CB0_BURST_16         (1 << 0)
4962306a36Sopenharmony_ci#define IC_IDMAC_1_CB1_BURST_16         (1 << 1)
5062306a36Sopenharmony_ci#define IC_IDMAC_1_CB2_BURST_16         (1 << 2)
5162306a36Sopenharmony_ci#define IC_IDMAC_1_CB3_BURST_16         (1 << 3)
5262306a36Sopenharmony_ci#define IC_IDMAC_1_CB4_BURST_16         (1 << 4)
5362306a36Sopenharmony_ci#define IC_IDMAC_1_CB5_BURST_16         (1 << 5)
5462306a36Sopenharmony_ci#define IC_IDMAC_1_CB6_BURST_16         (1 << 6)
5562306a36Sopenharmony_ci#define IC_IDMAC_1_CB7_BURST_16         (1 << 7)
5662306a36Sopenharmony_ci#define IC_IDMAC_1_PRPENC_ROT_MASK      (0x7 << 11)
5762306a36Sopenharmony_ci#define IC_IDMAC_1_PRPENC_ROT_OFFSET    11
5862306a36Sopenharmony_ci#define IC_IDMAC_1_PRPVF_ROT_MASK       (0x7 << 14)
5962306a36Sopenharmony_ci#define IC_IDMAC_1_PRPVF_ROT_OFFSET     14
6062306a36Sopenharmony_ci#define IC_IDMAC_1_PP_ROT_MASK          (0x7 << 17)
6162306a36Sopenharmony_ci#define IC_IDMAC_1_PP_ROT_OFFSET        17
6262306a36Sopenharmony_ci#define IC_IDMAC_1_PP_FLIP_RS           (1 << 22)
6362306a36Sopenharmony_ci#define IC_IDMAC_1_PRPVF_FLIP_RS        (1 << 21)
6462306a36Sopenharmony_ci#define IC_IDMAC_1_PRPENC_FLIP_RS       (1 << 20)
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci#define IC_IDMAC_2_PRPENC_HEIGHT_MASK   (0x3ff << 0)
6762306a36Sopenharmony_ci#define IC_IDMAC_2_PRPENC_HEIGHT_OFFSET 0
6862306a36Sopenharmony_ci#define IC_IDMAC_2_PRPVF_HEIGHT_MASK    (0x3ff << 10)
6962306a36Sopenharmony_ci#define IC_IDMAC_2_PRPVF_HEIGHT_OFFSET  10
7062306a36Sopenharmony_ci#define IC_IDMAC_2_PP_HEIGHT_MASK       (0x3ff << 20)
7162306a36Sopenharmony_ci#define IC_IDMAC_2_PP_HEIGHT_OFFSET     20
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci#define IC_IDMAC_3_PRPENC_WIDTH_MASK    (0x3ff << 0)
7462306a36Sopenharmony_ci#define IC_IDMAC_3_PRPENC_WIDTH_OFFSET  0
7562306a36Sopenharmony_ci#define IC_IDMAC_3_PRPVF_WIDTH_MASK     (0x3ff << 10)
7662306a36Sopenharmony_ci#define IC_IDMAC_3_PRPVF_WIDTH_OFFSET   10
7762306a36Sopenharmony_ci#define IC_IDMAC_3_PP_WIDTH_MASK        (0x3ff << 20)
7862306a36Sopenharmony_ci#define IC_IDMAC_3_PP_WIDTH_OFFSET      20
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cistruct ic_task_regoffs {
8162306a36Sopenharmony_ci	u32 rsc;
8262306a36Sopenharmony_ci	u32 tpmem_csc[2];
8362306a36Sopenharmony_ci};
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_cistruct ic_task_bitfields {
8662306a36Sopenharmony_ci	u32 ic_conf_en;
8762306a36Sopenharmony_ci	u32 ic_conf_rot_en;
8862306a36Sopenharmony_ci	u32 ic_conf_cmb_en;
8962306a36Sopenharmony_ci	u32 ic_conf_csc1_en;
9062306a36Sopenharmony_ci	u32 ic_conf_csc2_en;
9162306a36Sopenharmony_ci	u32 ic_cmb_galpha_bit;
9262306a36Sopenharmony_ci};
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistatic const struct ic_task_regoffs ic_task_reg[IC_NUM_TASKS] = {
9562306a36Sopenharmony_ci	[IC_TASK_ENCODER] = {
9662306a36Sopenharmony_ci		.rsc = IC_PRP_ENC_RSC,
9762306a36Sopenharmony_ci		.tpmem_csc = {0x2008, 0},
9862306a36Sopenharmony_ci	},
9962306a36Sopenharmony_ci	[IC_TASK_VIEWFINDER] = {
10062306a36Sopenharmony_ci		.rsc = IC_PRP_VF_RSC,
10162306a36Sopenharmony_ci		.tpmem_csc = {0x4028, 0x4040},
10262306a36Sopenharmony_ci	},
10362306a36Sopenharmony_ci	[IC_TASK_POST_PROCESSOR] = {
10462306a36Sopenharmony_ci		.rsc = IC_PP_RSC,
10562306a36Sopenharmony_ci		.tpmem_csc = {0x6060, 0x6078},
10662306a36Sopenharmony_ci	},
10762306a36Sopenharmony_ci};
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cistatic const struct ic_task_bitfields ic_task_bit[IC_NUM_TASKS] = {
11062306a36Sopenharmony_ci	[IC_TASK_ENCODER] = {
11162306a36Sopenharmony_ci		.ic_conf_en = IC_CONF_PRPENC_EN,
11262306a36Sopenharmony_ci		.ic_conf_rot_en = IC_CONF_PRPENC_ROT_EN,
11362306a36Sopenharmony_ci		.ic_conf_cmb_en = 0,    /* NA */
11462306a36Sopenharmony_ci		.ic_conf_csc1_en = IC_CONF_PRPENC_CSC1,
11562306a36Sopenharmony_ci		.ic_conf_csc2_en = 0,   /* NA */
11662306a36Sopenharmony_ci		.ic_cmb_galpha_bit = 0, /* NA */
11762306a36Sopenharmony_ci	},
11862306a36Sopenharmony_ci	[IC_TASK_VIEWFINDER] = {
11962306a36Sopenharmony_ci		.ic_conf_en = IC_CONF_PRPVF_EN,
12062306a36Sopenharmony_ci		.ic_conf_rot_en = IC_CONF_PRPVF_ROT_EN,
12162306a36Sopenharmony_ci		.ic_conf_cmb_en = IC_CONF_PRPVF_CMB,
12262306a36Sopenharmony_ci		.ic_conf_csc1_en = IC_CONF_PRPVF_CSC1,
12362306a36Sopenharmony_ci		.ic_conf_csc2_en = IC_CONF_PRPVF_CSC2,
12462306a36Sopenharmony_ci		.ic_cmb_galpha_bit = 0,
12562306a36Sopenharmony_ci	},
12662306a36Sopenharmony_ci	[IC_TASK_POST_PROCESSOR] = {
12762306a36Sopenharmony_ci		.ic_conf_en = IC_CONF_PP_EN,
12862306a36Sopenharmony_ci		.ic_conf_rot_en = IC_CONF_PP_ROT_EN,
12962306a36Sopenharmony_ci		.ic_conf_cmb_en = IC_CONF_PP_CMB,
13062306a36Sopenharmony_ci		.ic_conf_csc1_en = IC_CONF_PP_CSC1,
13162306a36Sopenharmony_ci		.ic_conf_csc2_en = IC_CONF_PP_CSC2,
13262306a36Sopenharmony_ci		.ic_cmb_galpha_bit = 8,
13362306a36Sopenharmony_ci	},
13462306a36Sopenharmony_ci};
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_cistruct ipu_ic_priv;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_cistruct ipu_ic {
13962306a36Sopenharmony_ci	enum ipu_ic_task task;
14062306a36Sopenharmony_ci	const struct ic_task_regoffs *reg;
14162306a36Sopenharmony_ci	const struct ic_task_bitfields *bit;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	struct ipu_ic_colorspace in_cs;
14462306a36Sopenharmony_ci	struct ipu_ic_colorspace g_in_cs;
14562306a36Sopenharmony_ci	struct ipu_ic_colorspace out_cs;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	bool graphics;
14862306a36Sopenharmony_ci	bool rotation;
14962306a36Sopenharmony_ci	bool in_use;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	struct ipu_ic_priv *priv;
15262306a36Sopenharmony_ci};
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_cistruct ipu_ic_priv {
15562306a36Sopenharmony_ci	void __iomem *base;
15662306a36Sopenharmony_ci	void __iomem *tpmem_base;
15762306a36Sopenharmony_ci	spinlock_t lock;
15862306a36Sopenharmony_ci	struct ipu_soc *ipu;
15962306a36Sopenharmony_ci	int use_count;
16062306a36Sopenharmony_ci	int irt_use_count;
16162306a36Sopenharmony_ci	struct ipu_ic task[IC_NUM_TASKS];
16262306a36Sopenharmony_ci};
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_cistatic inline u32 ipu_ic_read(struct ipu_ic *ic, unsigned offset)
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	return readl(ic->priv->base + offset);
16762306a36Sopenharmony_ci}
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_cistatic inline void ipu_ic_write(struct ipu_ic *ic, u32 value, unsigned offset)
17062306a36Sopenharmony_ci{
17162306a36Sopenharmony_ci	writel(value, ic->priv->base + offset);
17262306a36Sopenharmony_ci}
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_cistatic int init_csc(struct ipu_ic *ic,
17562306a36Sopenharmony_ci		    const struct ipu_ic_csc *csc,
17662306a36Sopenharmony_ci		    int csc_index)
17762306a36Sopenharmony_ci{
17862306a36Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
17962306a36Sopenharmony_ci	u32 __iomem *base;
18062306a36Sopenharmony_ci	const u16 (*c)[3];
18162306a36Sopenharmony_ci	const u16 *a;
18262306a36Sopenharmony_ci	u32 param;
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	base = (u32 __iomem *)
18562306a36Sopenharmony_ci		(priv->tpmem_base + ic->reg->tpmem_csc[csc_index]);
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	/* Cast to unsigned */
18862306a36Sopenharmony_ci	c = (const u16 (*)[3])csc->params.coeff;
18962306a36Sopenharmony_ci	a = (const u16 *)csc->params.offset;
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	param = ((a[0] & 0x1f) << 27) | ((c[0][0] & 0x1ff) << 18) |
19262306a36Sopenharmony_ci		((c[1][1] & 0x1ff) << 9) | (c[2][2] & 0x1ff);
19362306a36Sopenharmony_ci	writel(param, base++);
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	param = ((a[0] & 0x1fe0) >> 5) | (csc->params.scale << 8) |
19662306a36Sopenharmony_ci		(csc->params.sat << 10);
19762306a36Sopenharmony_ci	writel(param, base++);
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	param = ((a[1] & 0x1f) << 27) | ((c[0][1] & 0x1ff) << 18) |
20062306a36Sopenharmony_ci		((c[1][0] & 0x1ff) << 9) | (c[2][0] & 0x1ff);
20162306a36Sopenharmony_ci	writel(param, base++);
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	param = ((a[1] & 0x1fe0) >> 5);
20462306a36Sopenharmony_ci	writel(param, base++);
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	param = ((a[2] & 0x1f) << 27) | ((c[0][2] & 0x1ff) << 18) |
20762306a36Sopenharmony_ci		((c[1][2] & 0x1ff) << 9) | (c[2][1] & 0x1ff);
20862306a36Sopenharmony_ci	writel(param, base++);
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	param = ((a[2] & 0x1fe0) >> 5);
21162306a36Sopenharmony_ci	writel(param, base++);
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	return 0;
21462306a36Sopenharmony_ci}
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_cistatic int calc_resize_coeffs(struct ipu_ic *ic,
21762306a36Sopenharmony_ci			      u32 in_size, u32 out_size,
21862306a36Sopenharmony_ci			      u32 *resize_coeff,
21962306a36Sopenharmony_ci			      u32 *downsize_coeff)
22062306a36Sopenharmony_ci{
22162306a36Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
22262306a36Sopenharmony_ci	struct ipu_soc *ipu = priv->ipu;
22362306a36Sopenharmony_ci	u32 temp_size, temp_downsize;
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	/*
22662306a36Sopenharmony_ci	 * Input size cannot be more than 4096, and output size cannot
22762306a36Sopenharmony_ci	 * be more than 1024
22862306a36Sopenharmony_ci	 */
22962306a36Sopenharmony_ci	if (in_size > 4096) {
23062306a36Sopenharmony_ci		dev_err(ipu->dev, "Unsupported resize (in_size > 4096)\n");
23162306a36Sopenharmony_ci		return -EINVAL;
23262306a36Sopenharmony_ci	}
23362306a36Sopenharmony_ci	if (out_size > 1024) {
23462306a36Sopenharmony_ci		dev_err(ipu->dev, "Unsupported resize (out_size > 1024)\n");
23562306a36Sopenharmony_ci		return -EINVAL;
23662306a36Sopenharmony_ci	}
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	/* Cannot downsize more than 4:1 */
23962306a36Sopenharmony_ci	if ((out_size << 2) < in_size) {
24062306a36Sopenharmony_ci		dev_err(ipu->dev, "Unsupported downsize\n");
24162306a36Sopenharmony_ci		return -EINVAL;
24262306a36Sopenharmony_ci	}
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	/* Compute downsizing coefficient */
24562306a36Sopenharmony_ci	temp_downsize = 0;
24662306a36Sopenharmony_ci	temp_size = in_size;
24762306a36Sopenharmony_ci	while (((temp_size > 1024) || (temp_size >= out_size * 2)) &&
24862306a36Sopenharmony_ci	       (temp_downsize < 2)) {
24962306a36Sopenharmony_ci		temp_size >>= 1;
25062306a36Sopenharmony_ci		temp_downsize++;
25162306a36Sopenharmony_ci	}
25262306a36Sopenharmony_ci	*downsize_coeff = temp_downsize;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	/*
25562306a36Sopenharmony_ci	 * compute resizing coefficient using the following equation:
25662306a36Sopenharmony_ci	 * resize_coeff = M * (SI - 1) / (SO - 1)
25762306a36Sopenharmony_ci	 * where M = 2^13, SI = input size, SO = output size
25862306a36Sopenharmony_ci	 */
25962306a36Sopenharmony_ci	*resize_coeff = (8192L * (temp_size - 1)) / (out_size - 1);
26062306a36Sopenharmony_ci	if (*resize_coeff >= 16384L) {
26162306a36Sopenharmony_ci		dev_err(ipu->dev, "Warning! Overflow on resize coeff.\n");
26262306a36Sopenharmony_ci		*resize_coeff = 0x3FFF;
26362306a36Sopenharmony_ci	}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	return 0;
26662306a36Sopenharmony_ci}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_civoid ipu_ic_task_enable(struct ipu_ic *ic)
26962306a36Sopenharmony_ci{
27062306a36Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
27162306a36Sopenharmony_ci	unsigned long flags;
27262306a36Sopenharmony_ci	u32 ic_conf;
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	ic_conf = ipu_ic_read(ic, IC_CONF);
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	ic_conf |= ic->bit->ic_conf_en;
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	if (ic->rotation)
28162306a36Sopenharmony_ci		ic_conf |= ic->bit->ic_conf_rot_en;
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	if (ic->in_cs.cs != ic->out_cs.cs)
28462306a36Sopenharmony_ci		ic_conf |= ic->bit->ic_conf_csc1_en;
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	if (ic->graphics) {
28762306a36Sopenharmony_ci		ic_conf |= ic->bit->ic_conf_cmb_en;
28862306a36Sopenharmony_ci		ic_conf |= ic->bit->ic_conf_csc1_en;
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci		if (ic->g_in_cs.cs != ic->out_cs.cs)
29162306a36Sopenharmony_ci			ic_conf |= ic->bit->ic_conf_csc2_en;
29262306a36Sopenharmony_ci	}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	ipu_ic_write(ic, ic_conf, IC_CONF);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
29762306a36Sopenharmony_ci}
29862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ipu_ic_task_enable);
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_civoid ipu_ic_task_disable(struct ipu_ic *ic)
30162306a36Sopenharmony_ci{
30262306a36Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
30362306a36Sopenharmony_ci	unsigned long flags;
30462306a36Sopenharmony_ci	u32 ic_conf;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	ic_conf = ipu_ic_read(ic, IC_CONF);
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	ic_conf &= ~(ic->bit->ic_conf_en |
31162306a36Sopenharmony_ci		     ic->bit->ic_conf_csc1_en |
31262306a36Sopenharmony_ci		     ic->bit->ic_conf_rot_en);
31362306a36Sopenharmony_ci	if (ic->bit->ic_conf_csc2_en)
31462306a36Sopenharmony_ci		ic_conf &= ~ic->bit->ic_conf_csc2_en;
31562306a36Sopenharmony_ci	if (ic->bit->ic_conf_cmb_en)
31662306a36Sopenharmony_ci		ic_conf &= ~ic->bit->ic_conf_cmb_en;
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	ipu_ic_write(ic, ic_conf, IC_CONF);
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
32162306a36Sopenharmony_ci}
32262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ipu_ic_task_disable);
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ciint ipu_ic_task_graphics_init(struct ipu_ic *ic,
32562306a36Sopenharmony_ci			      const struct ipu_ic_colorspace *g_in_cs,
32662306a36Sopenharmony_ci			      bool galpha_en, u32 galpha,
32762306a36Sopenharmony_ci			      bool colorkey_en, u32 colorkey)
32862306a36Sopenharmony_ci{
32962306a36Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
33062306a36Sopenharmony_ci	struct ipu_ic_csc csc2;
33162306a36Sopenharmony_ci	unsigned long flags;
33262306a36Sopenharmony_ci	u32 reg, ic_conf;
33362306a36Sopenharmony_ci	int ret = 0;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	if (ic->task == IC_TASK_ENCODER)
33662306a36Sopenharmony_ci		return -EINVAL;
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	ic_conf = ipu_ic_read(ic, IC_CONF);
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	if (!(ic_conf & ic->bit->ic_conf_csc1_en)) {
34362306a36Sopenharmony_ci		struct ipu_ic_csc csc1;
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci		ret = ipu_ic_calc_csc(&csc1,
34662306a36Sopenharmony_ci				      V4L2_YCBCR_ENC_601,
34762306a36Sopenharmony_ci				      V4L2_QUANTIZATION_FULL_RANGE,
34862306a36Sopenharmony_ci				      IPUV3_COLORSPACE_RGB,
34962306a36Sopenharmony_ci				      V4L2_YCBCR_ENC_601,
35062306a36Sopenharmony_ci				      V4L2_QUANTIZATION_FULL_RANGE,
35162306a36Sopenharmony_ci				      IPUV3_COLORSPACE_RGB);
35262306a36Sopenharmony_ci		if (ret)
35362306a36Sopenharmony_ci			goto unlock;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci		/* need transparent CSC1 conversion */
35662306a36Sopenharmony_ci		ret = init_csc(ic, &csc1, 0);
35762306a36Sopenharmony_ci		if (ret)
35862306a36Sopenharmony_ci			goto unlock;
35962306a36Sopenharmony_ci	}
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	ic->g_in_cs = *g_in_cs;
36262306a36Sopenharmony_ci	csc2.in_cs = ic->g_in_cs;
36362306a36Sopenharmony_ci	csc2.out_cs = ic->out_cs;
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	ret = __ipu_ic_calc_csc(&csc2);
36662306a36Sopenharmony_ci	if (ret)
36762306a36Sopenharmony_ci		goto unlock;
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	ret = init_csc(ic, &csc2, 1);
37062306a36Sopenharmony_ci	if (ret)
37162306a36Sopenharmony_ci		goto unlock;
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	if (galpha_en) {
37462306a36Sopenharmony_ci		ic_conf |= IC_CONF_IC_GLB_LOC_A;
37562306a36Sopenharmony_ci		reg = ipu_ic_read(ic, IC_CMBP_1);
37662306a36Sopenharmony_ci		reg &= ~(0xff << ic->bit->ic_cmb_galpha_bit);
37762306a36Sopenharmony_ci		reg |= (galpha << ic->bit->ic_cmb_galpha_bit);
37862306a36Sopenharmony_ci		ipu_ic_write(ic, reg, IC_CMBP_1);
37962306a36Sopenharmony_ci	} else
38062306a36Sopenharmony_ci		ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	if (colorkey_en) {
38362306a36Sopenharmony_ci		ic_conf |= IC_CONF_KEY_COLOR_EN;
38462306a36Sopenharmony_ci		ipu_ic_write(ic, colorkey, IC_CMBP_2);
38562306a36Sopenharmony_ci	} else
38662306a36Sopenharmony_ci		ic_conf &= ~IC_CONF_KEY_COLOR_EN;
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	ipu_ic_write(ic, ic_conf, IC_CONF);
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	ic->graphics = true;
39162306a36Sopenharmony_ciunlock:
39262306a36Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
39362306a36Sopenharmony_ci	return ret;
39462306a36Sopenharmony_ci}
39562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ipu_ic_task_graphics_init);
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ciint ipu_ic_task_init_rsc(struct ipu_ic *ic,
39862306a36Sopenharmony_ci			 const struct ipu_ic_csc *csc,
39962306a36Sopenharmony_ci			 int in_width, int in_height,
40062306a36Sopenharmony_ci			 int out_width, int out_height,
40162306a36Sopenharmony_ci			 u32 rsc)
40262306a36Sopenharmony_ci{
40362306a36Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
40462306a36Sopenharmony_ci	u32 downsize_coeff, resize_coeff;
40562306a36Sopenharmony_ci	unsigned long flags;
40662306a36Sopenharmony_ci	int ret = 0;
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	if (!rsc) {
40962306a36Sopenharmony_ci		/* Setup vertical resizing */
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci		ret = calc_resize_coeffs(ic, in_height, out_height,
41262306a36Sopenharmony_ci					 &resize_coeff, &downsize_coeff);
41362306a36Sopenharmony_ci		if (ret)
41462306a36Sopenharmony_ci			return ret;
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci		rsc = (downsize_coeff << 30) | (resize_coeff << 16);
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci		/* Setup horizontal resizing */
41962306a36Sopenharmony_ci		ret = calc_resize_coeffs(ic, in_width, out_width,
42062306a36Sopenharmony_ci					 &resize_coeff, &downsize_coeff);
42162306a36Sopenharmony_ci		if (ret)
42262306a36Sopenharmony_ci			return ret;
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci		rsc |= (downsize_coeff << 14) | resize_coeff;
42562306a36Sopenharmony_ci	}
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	ipu_ic_write(ic, rsc, ic->reg->rsc);
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	/* Setup color space conversion */
43262306a36Sopenharmony_ci	ic->in_cs = csc->in_cs;
43362306a36Sopenharmony_ci	ic->out_cs = csc->out_cs;
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	ret = init_csc(ic, csc, 0);
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
43862306a36Sopenharmony_ci	return ret;
43962306a36Sopenharmony_ci}
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ciint ipu_ic_task_init(struct ipu_ic *ic,
44262306a36Sopenharmony_ci		     const struct ipu_ic_csc *csc,
44362306a36Sopenharmony_ci		     int in_width, int in_height,
44462306a36Sopenharmony_ci		     int out_width, int out_height)
44562306a36Sopenharmony_ci{
44662306a36Sopenharmony_ci	return ipu_ic_task_init_rsc(ic, csc,
44762306a36Sopenharmony_ci				    in_width, in_height,
44862306a36Sopenharmony_ci				    out_width, out_height, 0);
44962306a36Sopenharmony_ci}
45062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ipu_ic_task_init);
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ciint ipu_ic_task_idma_init(struct ipu_ic *ic, struct ipuv3_channel *channel,
45362306a36Sopenharmony_ci			  u32 width, u32 height, int burst_size,
45462306a36Sopenharmony_ci			  enum ipu_rotate_mode rot)
45562306a36Sopenharmony_ci{
45662306a36Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
45762306a36Sopenharmony_ci	struct ipu_soc *ipu = priv->ipu;
45862306a36Sopenharmony_ci	u32 ic_idmac_1, ic_idmac_2, ic_idmac_3;
45962306a36Sopenharmony_ci	u32 temp_rot = bitrev8(rot) >> 5;
46062306a36Sopenharmony_ci	bool need_hor_flip = false;
46162306a36Sopenharmony_ci	unsigned long flags;
46262306a36Sopenharmony_ci	int ret = 0;
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	if ((burst_size != 8) && (burst_size != 16)) {
46562306a36Sopenharmony_ci		dev_err(ipu->dev, "Illegal burst length for IC\n");
46662306a36Sopenharmony_ci		return -EINVAL;
46762306a36Sopenharmony_ci	}
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	width--;
47062306a36Sopenharmony_ci	height--;
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	if (temp_rot & 0x2)	/* Need horizontal flip */
47362306a36Sopenharmony_ci		need_hor_flip = true;
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	ic_idmac_1 = ipu_ic_read(ic, IC_IDMAC_1);
47862306a36Sopenharmony_ci	ic_idmac_2 = ipu_ic_read(ic, IC_IDMAC_2);
47962306a36Sopenharmony_ci	ic_idmac_3 = ipu_ic_read(ic, IC_IDMAC_3);
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	switch (channel->num) {
48262306a36Sopenharmony_ci	case IPUV3_CHANNEL_IC_PP_MEM:
48362306a36Sopenharmony_ci		if (burst_size == 16)
48462306a36Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_CB2_BURST_16;
48562306a36Sopenharmony_ci		else
48662306a36Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_CB2_BURST_16;
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci		if (need_hor_flip)
48962306a36Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_PP_FLIP_RS;
49062306a36Sopenharmony_ci		else
49162306a36Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_PP_FLIP_RS;
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci		ic_idmac_2 &= ~IC_IDMAC_2_PP_HEIGHT_MASK;
49462306a36Sopenharmony_ci		ic_idmac_2 |= height << IC_IDMAC_2_PP_HEIGHT_OFFSET;
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci		ic_idmac_3 &= ~IC_IDMAC_3_PP_WIDTH_MASK;
49762306a36Sopenharmony_ci		ic_idmac_3 |= width << IC_IDMAC_3_PP_WIDTH_OFFSET;
49862306a36Sopenharmony_ci		break;
49962306a36Sopenharmony_ci	case IPUV3_CHANNEL_MEM_IC_PP:
50062306a36Sopenharmony_ci		if (burst_size == 16)
50162306a36Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_CB5_BURST_16;
50262306a36Sopenharmony_ci		else
50362306a36Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_CB5_BURST_16;
50462306a36Sopenharmony_ci		break;
50562306a36Sopenharmony_ci	case IPUV3_CHANNEL_MEM_ROT_PP:
50662306a36Sopenharmony_ci		ic_idmac_1 &= ~IC_IDMAC_1_PP_ROT_MASK;
50762306a36Sopenharmony_ci		ic_idmac_1 |= temp_rot << IC_IDMAC_1_PP_ROT_OFFSET;
50862306a36Sopenharmony_ci		break;
50962306a36Sopenharmony_ci	case IPUV3_CHANNEL_MEM_IC_PRP_VF:
51062306a36Sopenharmony_ci		if (burst_size == 16)
51162306a36Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_CB6_BURST_16;
51262306a36Sopenharmony_ci		else
51362306a36Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_CB6_BURST_16;
51462306a36Sopenharmony_ci		break;
51562306a36Sopenharmony_ci	case IPUV3_CHANNEL_IC_PRP_ENC_MEM:
51662306a36Sopenharmony_ci		if (burst_size == 16)
51762306a36Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_CB0_BURST_16;
51862306a36Sopenharmony_ci		else
51962306a36Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_CB0_BURST_16;
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci		if (need_hor_flip)
52262306a36Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_PRPENC_FLIP_RS;
52362306a36Sopenharmony_ci		else
52462306a36Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_FLIP_RS;
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci		ic_idmac_2 &= ~IC_IDMAC_2_PRPENC_HEIGHT_MASK;
52762306a36Sopenharmony_ci		ic_idmac_2 |= height << IC_IDMAC_2_PRPENC_HEIGHT_OFFSET;
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci		ic_idmac_3 &= ~IC_IDMAC_3_PRPENC_WIDTH_MASK;
53062306a36Sopenharmony_ci		ic_idmac_3 |= width << IC_IDMAC_3_PRPENC_WIDTH_OFFSET;
53162306a36Sopenharmony_ci		break;
53262306a36Sopenharmony_ci	case IPUV3_CHANNEL_MEM_ROT_ENC:
53362306a36Sopenharmony_ci		ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_ROT_MASK;
53462306a36Sopenharmony_ci		ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPENC_ROT_OFFSET;
53562306a36Sopenharmony_ci		break;
53662306a36Sopenharmony_ci	case IPUV3_CHANNEL_IC_PRP_VF_MEM:
53762306a36Sopenharmony_ci		if (burst_size == 16)
53862306a36Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_CB1_BURST_16;
53962306a36Sopenharmony_ci		else
54062306a36Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_CB1_BURST_16;
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci		if (need_hor_flip)
54362306a36Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_PRPVF_FLIP_RS;
54462306a36Sopenharmony_ci		else
54562306a36Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_FLIP_RS;
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci		ic_idmac_2 &= ~IC_IDMAC_2_PRPVF_HEIGHT_MASK;
54862306a36Sopenharmony_ci		ic_idmac_2 |= height << IC_IDMAC_2_PRPVF_HEIGHT_OFFSET;
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci		ic_idmac_3 &= ~IC_IDMAC_3_PRPVF_WIDTH_MASK;
55162306a36Sopenharmony_ci		ic_idmac_3 |= width << IC_IDMAC_3_PRPVF_WIDTH_OFFSET;
55262306a36Sopenharmony_ci		break;
55362306a36Sopenharmony_ci	case IPUV3_CHANNEL_MEM_ROT_VF:
55462306a36Sopenharmony_ci		ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_ROT_MASK;
55562306a36Sopenharmony_ci		ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPVF_ROT_OFFSET;
55662306a36Sopenharmony_ci		break;
55762306a36Sopenharmony_ci	case IPUV3_CHANNEL_G_MEM_IC_PRP_VF:
55862306a36Sopenharmony_ci		if (burst_size == 16)
55962306a36Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_CB3_BURST_16;
56062306a36Sopenharmony_ci		else
56162306a36Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_CB3_BURST_16;
56262306a36Sopenharmony_ci		break;
56362306a36Sopenharmony_ci	case IPUV3_CHANNEL_G_MEM_IC_PP:
56462306a36Sopenharmony_ci		if (burst_size == 16)
56562306a36Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_CB4_BURST_16;
56662306a36Sopenharmony_ci		else
56762306a36Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_CB4_BURST_16;
56862306a36Sopenharmony_ci		break;
56962306a36Sopenharmony_ci	case IPUV3_CHANNEL_VDI_MEM_IC_VF:
57062306a36Sopenharmony_ci		if (burst_size == 16)
57162306a36Sopenharmony_ci			ic_idmac_1 |= IC_IDMAC_1_CB7_BURST_16;
57262306a36Sopenharmony_ci		else
57362306a36Sopenharmony_ci			ic_idmac_1 &= ~IC_IDMAC_1_CB7_BURST_16;
57462306a36Sopenharmony_ci		break;
57562306a36Sopenharmony_ci	default:
57662306a36Sopenharmony_ci		goto unlock;
57762306a36Sopenharmony_ci	}
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	ipu_ic_write(ic, ic_idmac_1, IC_IDMAC_1);
58062306a36Sopenharmony_ci	ipu_ic_write(ic, ic_idmac_2, IC_IDMAC_2);
58162306a36Sopenharmony_ci	ipu_ic_write(ic, ic_idmac_3, IC_IDMAC_3);
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci	if (ipu_rot_mode_is_irt(rot))
58462306a36Sopenharmony_ci		ic->rotation = true;
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ciunlock:
58762306a36Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
58862306a36Sopenharmony_ci	return ret;
58962306a36Sopenharmony_ci}
59062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ipu_ic_task_idma_init);
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_cistatic void ipu_irt_enable(struct ipu_ic *ic)
59362306a36Sopenharmony_ci{
59462306a36Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	if (!priv->irt_use_count)
59762306a36Sopenharmony_ci		ipu_module_enable(priv->ipu, IPU_CONF_ROT_EN);
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	priv->irt_use_count++;
60062306a36Sopenharmony_ci}
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_cistatic void ipu_irt_disable(struct ipu_ic *ic)
60362306a36Sopenharmony_ci{
60462306a36Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci	if (priv->irt_use_count) {
60762306a36Sopenharmony_ci		if (!--priv->irt_use_count)
60862306a36Sopenharmony_ci			ipu_module_disable(priv->ipu, IPU_CONF_ROT_EN);
60962306a36Sopenharmony_ci	}
61062306a36Sopenharmony_ci}
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ciint ipu_ic_enable(struct ipu_ic *ic)
61362306a36Sopenharmony_ci{
61462306a36Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
61562306a36Sopenharmony_ci	unsigned long flags;
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	if (!priv->use_count)
62062306a36Sopenharmony_ci		ipu_module_enable(priv->ipu, IPU_CONF_IC_EN);
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci	priv->use_count++;
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_ci	if (ic->rotation)
62562306a36Sopenharmony_ci		ipu_irt_enable(ic);
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci	return 0;
63062306a36Sopenharmony_ci}
63162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ipu_ic_enable);
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ciint ipu_ic_disable(struct ipu_ic *ic)
63462306a36Sopenharmony_ci{
63562306a36Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
63662306a36Sopenharmony_ci	unsigned long flags;
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci	priv->use_count--;
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci	if (!priv->use_count)
64362306a36Sopenharmony_ci		ipu_module_disable(priv->ipu, IPU_CONF_IC_EN);
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	if (priv->use_count < 0)
64662306a36Sopenharmony_ci		priv->use_count = 0;
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	if (ic->rotation)
64962306a36Sopenharmony_ci		ipu_irt_disable(ic);
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci	ic->rotation = ic->graphics = false;
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci	return 0;
65662306a36Sopenharmony_ci}
65762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ipu_ic_disable);
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_cistruct ipu_ic *ipu_ic_get(struct ipu_soc *ipu, enum ipu_ic_task task)
66062306a36Sopenharmony_ci{
66162306a36Sopenharmony_ci	struct ipu_ic_priv *priv = ipu->ic_priv;
66262306a36Sopenharmony_ci	unsigned long flags;
66362306a36Sopenharmony_ci	struct ipu_ic *ic, *ret;
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ci	if (task >= IC_NUM_TASKS)
66662306a36Sopenharmony_ci		return ERR_PTR(-EINVAL);
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci	ic = &priv->task[task];
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci	if (ic->in_use) {
67362306a36Sopenharmony_ci		ret = ERR_PTR(-EBUSY);
67462306a36Sopenharmony_ci		goto unlock;
67562306a36Sopenharmony_ci	}
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci	ic->in_use = true;
67862306a36Sopenharmony_ci	ret = ic;
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ciunlock:
68162306a36Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
68262306a36Sopenharmony_ci	return ret;
68362306a36Sopenharmony_ci}
68462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ipu_ic_get);
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_civoid ipu_ic_put(struct ipu_ic *ic)
68762306a36Sopenharmony_ci{
68862306a36Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
68962306a36Sopenharmony_ci	unsigned long flags;
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
69262306a36Sopenharmony_ci	ic->in_use = false;
69362306a36Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
69462306a36Sopenharmony_ci}
69562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ipu_ic_put);
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ciint ipu_ic_init(struct ipu_soc *ipu, struct device *dev,
69862306a36Sopenharmony_ci		unsigned long base, unsigned long tpmem_base)
69962306a36Sopenharmony_ci{
70062306a36Sopenharmony_ci	struct ipu_ic_priv *priv;
70162306a36Sopenharmony_ci	int i;
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
70462306a36Sopenharmony_ci	if (!priv)
70562306a36Sopenharmony_ci		return -ENOMEM;
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci	ipu->ic_priv = priv;
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci	spin_lock_init(&priv->lock);
71062306a36Sopenharmony_ci	priv->base = devm_ioremap(dev, base, PAGE_SIZE);
71162306a36Sopenharmony_ci	if (!priv->base)
71262306a36Sopenharmony_ci		return -ENOMEM;
71362306a36Sopenharmony_ci	priv->tpmem_base = devm_ioremap(dev, tpmem_base, SZ_64K);
71462306a36Sopenharmony_ci	if (!priv->tpmem_base)
71562306a36Sopenharmony_ci		return -ENOMEM;
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_ci	dev_dbg(dev, "IC base: 0x%08lx remapped to %p\n", base, priv->base);
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci	priv->ipu = ipu;
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ci	for (i = 0; i < IC_NUM_TASKS; i++) {
72262306a36Sopenharmony_ci		priv->task[i].task = i;
72362306a36Sopenharmony_ci		priv->task[i].priv = priv;
72462306a36Sopenharmony_ci		priv->task[i].reg = &ic_task_reg[i];
72562306a36Sopenharmony_ci		priv->task[i].bit = &ic_task_bit[i];
72662306a36Sopenharmony_ci	}
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_ci	return 0;
72962306a36Sopenharmony_ci}
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_civoid ipu_ic_exit(struct ipu_soc *ipu)
73262306a36Sopenharmony_ci{
73362306a36Sopenharmony_ci}
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_civoid ipu_ic_dump(struct ipu_ic *ic)
73662306a36Sopenharmony_ci{
73762306a36Sopenharmony_ci	struct ipu_ic_priv *priv = ic->priv;
73862306a36Sopenharmony_ci	struct ipu_soc *ipu = priv->ipu;
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci	dev_dbg(ipu->dev, "IC_CONF = \t0x%08X\n",
74162306a36Sopenharmony_ci		ipu_ic_read(ic, IC_CONF));
74262306a36Sopenharmony_ci	dev_dbg(ipu->dev, "IC_PRP_ENC_RSC = \t0x%08X\n",
74362306a36Sopenharmony_ci		ipu_ic_read(ic, IC_PRP_ENC_RSC));
74462306a36Sopenharmony_ci	dev_dbg(ipu->dev, "IC_PRP_VF_RSC = \t0x%08X\n",
74562306a36Sopenharmony_ci		ipu_ic_read(ic, IC_PRP_VF_RSC));
74662306a36Sopenharmony_ci	dev_dbg(ipu->dev, "IC_PP_RSC = \t0x%08X\n",
74762306a36Sopenharmony_ci		ipu_ic_read(ic, IC_PP_RSC));
74862306a36Sopenharmony_ci	dev_dbg(ipu->dev, "IC_CMBP_1 = \t0x%08X\n",
74962306a36Sopenharmony_ci		ipu_ic_read(ic, IC_CMBP_1));
75062306a36Sopenharmony_ci	dev_dbg(ipu->dev, "IC_CMBP_2 = \t0x%08X\n",
75162306a36Sopenharmony_ci		ipu_ic_read(ic, IC_CMBP_2));
75262306a36Sopenharmony_ci	dev_dbg(ipu->dev, "IC_IDMAC_1 = \t0x%08X\n",
75362306a36Sopenharmony_ci		ipu_ic_read(ic, IC_IDMAC_1));
75462306a36Sopenharmony_ci	dev_dbg(ipu->dev, "IC_IDMAC_2 = \t0x%08X\n",
75562306a36Sopenharmony_ci		ipu_ic_read(ic, IC_IDMAC_2));
75662306a36Sopenharmony_ci	dev_dbg(ipu->dev, "IC_IDMAC_3 = \t0x%08X\n",
75762306a36Sopenharmony_ci		ipu_ic_read(ic, IC_IDMAC_3));
75862306a36Sopenharmony_ci	dev_dbg(ipu->dev, "IC_IDMAC_4 = \t0x%08X\n",
75962306a36Sopenharmony_ci		ipu_ic_read(ic, IC_IDMAC_4));
76062306a36Sopenharmony_ci}
76162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ipu_ic_dump);
762