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