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