cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ipu3-css.c (73303B)


      1// SPDX-License-Identifier: GPL-2.0
      2// Copyright (C) 2018 Intel Corporation
      3
      4#include <linux/device.h>
      5#include <linux/iopoll.h>
      6#include <linux/slab.h>
      7
      8#include "ipu3.h"
      9#include "ipu3-css.h"
     10#include "ipu3-css-fw.h"
     11#include "ipu3-css-params.h"
     12#include "ipu3-dmamap.h"
     13#include "ipu3-tables.h"
     14
     15/* IRQ configuration */
     16#define IMGU_IRQCTRL_IRQ_MASK	(IMGU_IRQCTRL_IRQ_SP1 | \
     17				 IMGU_IRQCTRL_IRQ_SP2 | \
     18				 IMGU_IRQCTRL_IRQ_SW_PIN(0) | \
     19				 IMGU_IRQCTRL_IRQ_SW_PIN(1))
     20
     21#define IPU3_CSS_FORMAT_BPP_DEN	50	/* Denominator */
     22
     23/* Some sane limits for resolutions */
     24#define IPU3_CSS_MIN_RES	32
     25#define IPU3_CSS_MAX_H		3136
     26#define IPU3_CSS_MAX_W		4224
     27
     28/* minimal envelope size(GDC in - out) should be 4 */
     29#define MIN_ENVELOPE            4
     30
     31/*
     32 * pre-allocated buffer size for CSS ABI, auxiliary frames
     33 * after BDS and before GDC. Those values should be tuned
     34 * to big enough to avoid buffer re-allocation when
     35 * streaming to lower streaming latency.
     36 */
     37#define CSS_ABI_SIZE    136
     38#define CSS_BDS_SIZE    (4480 * 3200 * 3)
     39#define CSS_GDC_SIZE    (4224 * 3200 * 12 / 8)
     40
     41#define IPU3_CSS_QUEUE_TO_FLAGS(q)	(1 << (q))
     42#define IPU3_CSS_FORMAT_FL_IN		\
     43			IPU3_CSS_QUEUE_TO_FLAGS(IPU3_CSS_QUEUE_IN)
     44#define IPU3_CSS_FORMAT_FL_OUT		\
     45			IPU3_CSS_QUEUE_TO_FLAGS(IPU3_CSS_QUEUE_OUT)
     46#define IPU3_CSS_FORMAT_FL_VF		\
     47			IPU3_CSS_QUEUE_TO_FLAGS(IPU3_CSS_QUEUE_VF)
     48
     49/* Formats supported by IPU3 Camera Sub System */
     50static const struct imgu_css_format imgu_css_formats[] = {
     51	{
     52		.pixelformat = V4L2_PIX_FMT_NV12,
     53		.colorspace = V4L2_COLORSPACE_SRGB,
     54		.frame_format = IMGU_ABI_FRAME_FORMAT_NV12,
     55		.osys_format = IMGU_ABI_OSYS_FORMAT_NV12,
     56		.osys_tiling = IMGU_ABI_OSYS_TILING_NONE,
     57		.chroma_decim = 4,
     58		.width_align = IPU3_UAPI_ISP_VEC_ELEMS,
     59		.flags = IPU3_CSS_FORMAT_FL_OUT | IPU3_CSS_FORMAT_FL_VF,
     60	}, {
     61		/* Each 32 bytes contains 25 10-bit pixels */
     62		.pixelformat = V4L2_PIX_FMT_IPU3_SBGGR10,
     63		.colorspace = V4L2_COLORSPACE_RAW,
     64		.frame_format = IMGU_ABI_FRAME_FORMAT_RAW_PACKED,
     65		.bayer_order = IMGU_ABI_BAYER_ORDER_BGGR,
     66		.bit_depth = 10,
     67		.width_align = 2 * IPU3_UAPI_ISP_VEC_ELEMS,
     68		.flags = IPU3_CSS_FORMAT_FL_IN,
     69	}, {
     70		.pixelformat = V4L2_PIX_FMT_IPU3_SGBRG10,
     71		.colorspace = V4L2_COLORSPACE_RAW,
     72		.frame_format = IMGU_ABI_FRAME_FORMAT_RAW_PACKED,
     73		.bayer_order = IMGU_ABI_BAYER_ORDER_GBRG,
     74		.bit_depth = 10,
     75		.width_align = 2 * IPU3_UAPI_ISP_VEC_ELEMS,
     76		.flags = IPU3_CSS_FORMAT_FL_IN,
     77	}, {
     78		.pixelformat = V4L2_PIX_FMT_IPU3_SGRBG10,
     79		.colorspace = V4L2_COLORSPACE_RAW,
     80		.frame_format = IMGU_ABI_FRAME_FORMAT_RAW_PACKED,
     81		.bayer_order = IMGU_ABI_BAYER_ORDER_GRBG,
     82		.bit_depth = 10,
     83		.width_align = 2 * IPU3_UAPI_ISP_VEC_ELEMS,
     84		.flags = IPU3_CSS_FORMAT_FL_IN,
     85	}, {
     86		.pixelformat = V4L2_PIX_FMT_IPU3_SRGGB10,
     87		.colorspace = V4L2_COLORSPACE_RAW,
     88		.frame_format = IMGU_ABI_FRAME_FORMAT_RAW_PACKED,
     89		.bayer_order = IMGU_ABI_BAYER_ORDER_RGGB,
     90		.bit_depth = 10,
     91		.width_align = 2 * IPU3_UAPI_ISP_VEC_ELEMS,
     92		.flags = IPU3_CSS_FORMAT_FL_IN,
     93	},
     94};
     95
     96static const struct {
     97	enum imgu_abi_queue_id qid;
     98	size_t ptr_ofs;
     99} imgu_css_queues[IPU3_CSS_QUEUES] = {
    100	[IPU3_CSS_QUEUE_IN] = {
    101		IMGU_ABI_QUEUE_C_ID,
    102		offsetof(struct imgu_abi_buffer, payload.frame.frame_data)
    103	},
    104	[IPU3_CSS_QUEUE_OUT] = {
    105		IMGU_ABI_QUEUE_D_ID,
    106		offsetof(struct imgu_abi_buffer, payload.frame.frame_data)
    107	},
    108	[IPU3_CSS_QUEUE_VF] = {
    109		IMGU_ABI_QUEUE_E_ID,
    110		offsetof(struct imgu_abi_buffer, payload.frame.frame_data)
    111	},
    112	[IPU3_CSS_QUEUE_STAT_3A] = {
    113		IMGU_ABI_QUEUE_F_ID,
    114		offsetof(struct imgu_abi_buffer, payload.s3a.data_ptr)
    115	},
    116};
    117
    118/* Initialize queue based on given format, adjust format as needed */
    119static int imgu_css_queue_init(struct imgu_css_queue *queue,
    120			       struct v4l2_pix_format_mplane *fmt, u32 flags)
    121{
    122	struct v4l2_pix_format_mplane *const f = &queue->fmt.mpix;
    123	unsigned int i;
    124	u32 sizeimage;
    125
    126	INIT_LIST_HEAD(&queue->bufs);
    127
    128	queue->css_fmt = NULL;	/* Disable */
    129	if (!fmt)
    130		return 0;
    131
    132	for (i = 0; i < ARRAY_SIZE(imgu_css_formats); i++) {
    133		if (!(imgu_css_formats[i].flags & flags))
    134			continue;
    135		queue->css_fmt = &imgu_css_formats[i];
    136		if (imgu_css_formats[i].pixelformat == fmt->pixelformat)
    137			break;
    138	}
    139	if (!queue->css_fmt)
    140		return -EINVAL;	/* Could not find any suitable format */
    141
    142	queue->fmt.mpix = *fmt;
    143
    144	f->width = ALIGN(clamp_t(u32, f->width,
    145				 IPU3_CSS_MIN_RES, IPU3_CSS_MAX_W), 2);
    146	f->height = ALIGN(clamp_t(u32, f->height,
    147				  IPU3_CSS_MIN_RES, IPU3_CSS_MAX_H), 2);
    148	queue->width_pad = ALIGN(f->width, queue->css_fmt->width_align);
    149	f->plane_fmt[0].bytesperline =
    150		imgu_bytesperline(f->width, queue->css_fmt->frame_format);
    151	sizeimage = f->height * f->plane_fmt[0].bytesperline;
    152	if (queue->css_fmt->chroma_decim)
    153		sizeimage += 2 * sizeimage / queue->css_fmt->chroma_decim;
    154
    155	f->plane_fmt[0].sizeimage = sizeimage;
    156	f->field = V4L2_FIELD_NONE;
    157	f->num_planes = 1;
    158	f->colorspace = queue->css_fmt->colorspace;
    159	f->flags = 0;
    160	f->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
    161	f->quantization = V4L2_QUANTIZATION_DEFAULT;
    162	f->xfer_func = V4L2_XFER_FUNC_DEFAULT;
    163	memset(f->reserved, 0, sizeof(f->reserved));
    164
    165	return 0;
    166}
    167
    168static bool imgu_css_queue_enabled(struct imgu_css_queue *q)
    169{
    170	return q->css_fmt;
    171}
    172
    173/******************* css hw *******************/
    174
    175/* In the style of writesl() defined in include/asm-generic/io.h */
    176static inline void writes(const void *mem, ssize_t count, void __iomem *addr)
    177{
    178	if (count >= 4) {
    179		const u32 *buf = mem;
    180
    181		count /= 4;
    182		do {
    183			writel(*buf++, addr);
    184			addr += 4;
    185		} while (--count);
    186	}
    187}
    188
    189/* Wait until register `reg', masked with `mask', becomes `cmp' */
    190static int imgu_hw_wait(void __iomem *base, int reg, u32 mask, u32 cmp)
    191{
    192	u32 val;
    193
    194	return readl_poll_timeout(base + reg, val, (val & mask) == cmp,
    195				  1000, 100 * 1000);
    196}
    197
    198/* Initialize the IPU3 CSS hardware and associated h/w blocks */
    199
    200int imgu_css_set_powerup(struct device *dev, void __iomem *base,
    201			 unsigned int freq)
    202{
    203	u32 pm_ctrl, state, val;
    204
    205	dev_dbg(dev, "%s with freq %u\n", __func__, freq);
    206	/* Clear the CSS busy signal */
    207	readl(base + IMGU_REG_GP_BUSY);
    208	writel(0, base + IMGU_REG_GP_BUSY);
    209
    210	/* Wait for idle signal */
    211	if (imgu_hw_wait(base, IMGU_REG_STATE, IMGU_STATE_IDLE_STS,
    212			 IMGU_STATE_IDLE_STS)) {
    213		dev_err(dev, "failed to set CSS idle\n");
    214		goto fail;
    215	}
    216
    217	/* Reset the css */
    218	writel(readl(base + IMGU_REG_PM_CTRL) | IMGU_PM_CTRL_FORCE_RESET,
    219	       base + IMGU_REG_PM_CTRL);
    220
    221	usleep_range(200, 300);
    222
    223	/** Prepare CSS */
    224
    225	pm_ctrl = readl(base + IMGU_REG_PM_CTRL);
    226	state = readl(base + IMGU_REG_STATE);
    227
    228	dev_dbg(dev, "CSS pm_ctrl 0x%x state 0x%x (power %s)\n",
    229		pm_ctrl, state, state & IMGU_STATE_POWER_DOWN ? "down" : "up");
    230
    231	/* Power up CSS using wrapper */
    232	if (state & IMGU_STATE_POWER_DOWN) {
    233		writel(IMGU_PM_CTRL_RACE_TO_HALT | IMGU_PM_CTRL_START,
    234		       base + IMGU_REG_PM_CTRL);
    235		if (imgu_hw_wait(base, IMGU_REG_PM_CTRL,
    236				 IMGU_PM_CTRL_START, 0)) {
    237			dev_err(dev, "failed to power up CSS\n");
    238			goto fail;
    239		}
    240		usleep_range(2000, 3000);
    241	} else {
    242		writel(IMGU_PM_CTRL_RACE_TO_HALT, base + IMGU_REG_PM_CTRL);
    243	}
    244
    245	/* Set the busy bit */
    246	writel(readl(base + IMGU_REG_GP_BUSY) | 1, base + IMGU_REG_GP_BUSY);
    247
    248	/* Set CSS clock frequency */
    249	pm_ctrl = readl(base + IMGU_REG_PM_CTRL);
    250	val = pm_ctrl & ~(IMGU_PM_CTRL_CSS_PWRDN | IMGU_PM_CTRL_RST_AT_EOF);
    251	writel(val, base + IMGU_REG_PM_CTRL);
    252	writel(0, base + IMGU_REG_GP_BUSY);
    253	if (imgu_hw_wait(base, IMGU_REG_STATE,
    254			 IMGU_STATE_PWRDNM_FSM_MASK, 0)) {
    255		dev_err(dev, "failed to pwrdn CSS\n");
    256		goto fail;
    257	}
    258	val = (freq / IMGU_SYSTEM_REQ_FREQ_DIVIDER) & IMGU_SYSTEM_REQ_FREQ_MASK;
    259	writel(val, base + IMGU_REG_SYSTEM_REQ);
    260	writel(1, base + IMGU_REG_GP_BUSY);
    261	writel(readl(base + IMGU_REG_PM_CTRL) | IMGU_PM_CTRL_FORCE_HALT,
    262	       base + IMGU_REG_PM_CTRL);
    263	if (imgu_hw_wait(base, IMGU_REG_STATE, IMGU_STATE_HALT_STS,
    264			 IMGU_STATE_HALT_STS)) {
    265		dev_err(dev, "failed to halt CSS\n");
    266		goto fail;
    267	}
    268
    269	writel(readl(base + IMGU_REG_PM_CTRL) | IMGU_PM_CTRL_START,
    270	       base + IMGU_REG_PM_CTRL);
    271	if (imgu_hw_wait(base, IMGU_REG_PM_CTRL, IMGU_PM_CTRL_START, 0)) {
    272		dev_err(dev, "failed to start CSS\n");
    273		goto fail;
    274	}
    275	writel(readl(base + IMGU_REG_PM_CTRL) | IMGU_PM_CTRL_FORCE_UNHALT,
    276	       base + IMGU_REG_PM_CTRL);
    277
    278	val = readl(base + IMGU_REG_PM_CTRL);	/* get pm_ctrl */
    279	val &= ~(IMGU_PM_CTRL_CSS_PWRDN | IMGU_PM_CTRL_RST_AT_EOF);
    280	val |= pm_ctrl & (IMGU_PM_CTRL_CSS_PWRDN | IMGU_PM_CTRL_RST_AT_EOF);
    281	writel(val, base + IMGU_REG_PM_CTRL);
    282
    283	return 0;
    284
    285fail:
    286	imgu_css_set_powerdown(dev, base);
    287	return -EIO;
    288}
    289
    290void imgu_css_set_powerdown(struct device *dev, void __iomem *base)
    291{
    292	dev_dbg(dev, "%s\n", __func__);
    293	/* wait for cio idle signal */
    294	if (imgu_hw_wait(base, IMGU_REG_CIO_GATE_BURST_STATE,
    295			 IMGU_CIO_GATE_BURST_MASK, 0))
    296		dev_warn(dev, "wait cio gate idle timeout");
    297
    298	/* wait for css idle signal */
    299	if (imgu_hw_wait(base, IMGU_REG_STATE, IMGU_STATE_IDLE_STS,
    300			 IMGU_STATE_IDLE_STS))
    301		dev_warn(dev, "wait css idle timeout\n");
    302
    303	/* do halt-halted handshake with css */
    304	writel(1, base + IMGU_REG_GP_HALT);
    305	if (imgu_hw_wait(base, IMGU_REG_STATE, IMGU_STATE_HALT_STS,
    306			 IMGU_STATE_HALT_STS))
    307		dev_warn(dev, "failed to halt css");
    308
    309	/* de-assert the busy bit */
    310	writel(0, base + IMGU_REG_GP_BUSY);
    311}
    312
    313static void imgu_css_hw_enable_irq(struct imgu_css *css)
    314{
    315	void __iomem *const base = css->base;
    316	u32 val, i;
    317
    318	/* Set up interrupts */
    319
    320	/*
    321	 * Enable IRQ on the SP which signals that SP goes to idle
    322	 * (aka ready state) and set trigger to pulse
    323	 */
    324	val = readl(base + IMGU_REG_SP_CTRL(0)) | IMGU_CTRL_IRQ_READY;
    325	writel(val, base + IMGU_REG_SP_CTRL(0));
    326	writel(val | IMGU_CTRL_IRQ_CLEAR, base + IMGU_REG_SP_CTRL(0));
    327
    328	/* Enable IRQs from the IMGU wrapper */
    329	writel(IMGU_REG_INT_CSS_IRQ, base + IMGU_REG_INT_ENABLE);
    330	/* Clear */
    331	writel(IMGU_REG_INT_CSS_IRQ, base + IMGU_REG_INT_STATUS);
    332
    333	/* Enable IRQs from main IRQ controller */
    334	writel(~0, base + IMGU_REG_IRQCTRL_EDGE_NOT_PULSE(IMGU_IRQCTRL_MAIN));
    335	writel(0, base + IMGU_REG_IRQCTRL_MASK(IMGU_IRQCTRL_MAIN));
    336	writel(IMGU_IRQCTRL_IRQ_MASK,
    337	       base + IMGU_REG_IRQCTRL_EDGE(IMGU_IRQCTRL_MAIN));
    338	writel(IMGU_IRQCTRL_IRQ_MASK,
    339	       base + IMGU_REG_IRQCTRL_ENABLE(IMGU_IRQCTRL_MAIN));
    340	writel(IMGU_IRQCTRL_IRQ_MASK,
    341	       base + IMGU_REG_IRQCTRL_CLEAR(IMGU_IRQCTRL_MAIN));
    342	writel(IMGU_IRQCTRL_IRQ_MASK,
    343	       base + IMGU_REG_IRQCTRL_MASK(IMGU_IRQCTRL_MAIN));
    344	/* Wait for write complete */
    345	readl(base + IMGU_REG_IRQCTRL_ENABLE(IMGU_IRQCTRL_MAIN));
    346
    347	/* Enable IRQs from SP0 and SP1 controllers */
    348	for (i = IMGU_IRQCTRL_SP0; i <= IMGU_IRQCTRL_SP1; i++) {
    349		writel(~0, base + IMGU_REG_IRQCTRL_EDGE_NOT_PULSE(i));
    350		writel(0, base + IMGU_REG_IRQCTRL_MASK(i));
    351		writel(IMGU_IRQCTRL_IRQ_MASK, base + IMGU_REG_IRQCTRL_EDGE(i));
    352		writel(IMGU_IRQCTRL_IRQ_MASK,
    353		       base + IMGU_REG_IRQCTRL_ENABLE(i));
    354		writel(IMGU_IRQCTRL_IRQ_MASK, base + IMGU_REG_IRQCTRL_CLEAR(i));
    355		writel(IMGU_IRQCTRL_IRQ_MASK, base + IMGU_REG_IRQCTRL_MASK(i));
    356		/* Wait for write complete */
    357		readl(base + IMGU_REG_IRQCTRL_ENABLE(i));
    358	}
    359}
    360
    361static int imgu_css_hw_init(struct imgu_css *css)
    362{
    363	/* For checking that streaming monitor statuses are valid */
    364	static const struct {
    365		u32 reg;
    366		u32 mask;
    367		const char *name;
    368	} stream_monitors[] = {
    369		{
    370			IMGU_REG_GP_SP1_STRMON_STAT,
    371			IMGU_GP_STRMON_STAT_ISP_PORT_SP12ISP,
    372			"ISP0 to SP0"
    373		}, {
    374			IMGU_REG_GP_ISP_STRMON_STAT,
    375			IMGU_GP_STRMON_STAT_SP1_PORT_ISP2SP1,
    376			"SP0 to ISP0"
    377		}, {
    378			IMGU_REG_GP_MOD_STRMON_STAT,
    379			IMGU_GP_STRMON_STAT_MOD_PORT_ISP2DMA,
    380			"ISP0 to DMA0"
    381		}, {
    382			IMGU_REG_GP_ISP_STRMON_STAT,
    383			IMGU_GP_STRMON_STAT_ISP_PORT_DMA2ISP,
    384			"DMA0 to ISP0"
    385		}, {
    386			IMGU_REG_GP_MOD_STRMON_STAT,
    387			IMGU_GP_STRMON_STAT_MOD_PORT_CELLS2GDC,
    388			"ISP0 to GDC0"
    389		}, {
    390			IMGU_REG_GP_MOD_STRMON_STAT,
    391			IMGU_GP_STRMON_STAT_MOD_PORT_GDC2CELLS,
    392			"GDC0 to ISP0"
    393		}, {
    394			IMGU_REG_GP_MOD_STRMON_STAT,
    395			IMGU_GP_STRMON_STAT_MOD_PORT_SP12DMA,
    396			"SP0 to DMA0"
    397		}, {
    398			IMGU_REG_GP_SP1_STRMON_STAT,
    399			IMGU_GP_STRMON_STAT_SP1_PORT_DMA2SP1,
    400			"DMA0 to SP0"
    401		}, {
    402			IMGU_REG_GP_MOD_STRMON_STAT,
    403			IMGU_GP_STRMON_STAT_MOD_PORT_CELLS2GDC,
    404			"SP0 to GDC0"
    405		}, {
    406			IMGU_REG_GP_MOD_STRMON_STAT,
    407			IMGU_GP_STRMON_STAT_MOD_PORT_GDC2CELLS,
    408			"GDC0 to SP0"
    409		},
    410	};
    411
    412	struct device *dev = css->dev;
    413	void __iomem *const base = css->base;
    414	u32 val, i;
    415
    416	/* Set instruction cache address and inv bit for ISP, SP, and SP1 */
    417	for (i = 0; i < IMGU_NUM_SP; i++) {
    418		struct imgu_fw_info *bi =
    419					&css->fwp->binary_header[css->fw_sp[i]];
    420
    421		writel(css->binary[css->fw_sp[i]].daddr,
    422		       base + IMGU_REG_SP_ICACHE_ADDR(bi->type));
    423		writel(readl(base + IMGU_REG_SP_CTRL(bi->type)) |
    424		       IMGU_CTRL_ICACHE_INV,
    425		       base + IMGU_REG_SP_CTRL(bi->type));
    426	}
    427	writel(css->binary[css->fw_bl].daddr, base + IMGU_REG_ISP_ICACHE_ADDR);
    428	writel(readl(base + IMGU_REG_ISP_CTRL) | IMGU_CTRL_ICACHE_INV,
    429	       base + IMGU_REG_ISP_CTRL);
    430
    431	/* Check that IMGU hardware is ready */
    432
    433	if (!(readl(base + IMGU_REG_SP_CTRL(0)) & IMGU_CTRL_IDLE)) {
    434		dev_err(dev, "SP is not idle\n");
    435		return -EIO;
    436	}
    437	if (!(readl(base + IMGU_REG_ISP_CTRL) & IMGU_CTRL_IDLE)) {
    438		dev_err(dev, "ISP is not idle\n");
    439		return -EIO;
    440	}
    441
    442	for (i = 0; i < ARRAY_SIZE(stream_monitors); i++) {
    443		val = readl(base + stream_monitors[i].reg);
    444		if (val & stream_monitors[i].mask) {
    445			dev_err(dev, "error: Stream monitor %s is valid\n",
    446				stream_monitors[i].name);
    447			return -EIO;
    448		}
    449	}
    450
    451	/* Initialize GDC with default values */
    452
    453	for (i = 0; i < ARRAY_SIZE(imgu_css_gdc_lut[0]); i++) {
    454		u32 val0 = imgu_css_gdc_lut[0][i] & IMGU_GDC_LUT_MASK;
    455		u32 val1 = imgu_css_gdc_lut[1][i] & IMGU_GDC_LUT_MASK;
    456		u32 val2 = imgu_css_gdc_lut[2][i] & IMGU_GDC_LUT_MASK;
    457		u32 val3 = imgu_css_gdc_lut[3][i] & IMGU_GDC_LUT_MASK;
    458
    459		writel(val0 | (val1 << 16),
    460		       base + IMGU_REG_GDC_LUT_BASE + i * 8);
    461		writel(val2 | (val3 << 16),
    462		       base + IMGU_REG_GDC_LUT_BASE + i * 8 + 4);
    463	}
    464
    465	return 0;
    466}
    467
    468/* Boot the given IPU3 CSS SP */
    469static int imgu_css_hw_start_sp(struct imgu_css *css, int sp)
    470{
    471	void __iomem *const base = css->base;
    472	struct imgu_fw_info *bi = &css->fwp->binary_header[css->fw_sp[sp]];
    473	struct imgu_abi_sp_init_dmem_cfg dmem_cfg = {
    474		.ddr_data_addr = css->binary[css->fw_sp[sp]].daddr
    475			+ bi->blob.data_source,
    476		.dmem_data_addr = bi->blob.data_target,
    477		.dmem_bss_addr = bi->blob.bss_target,
    478		.data_size = bi->blob.data_size,
    479		.bss_size = bi->blob.bss_size,
    480		.sp_id = sp,
    481	};
    482
    483	writes(&dmem_cfg, sizeof(dmem_cfg), base +
    484	       IMGU_REG_SP_DMEM_BASE(sp) + bi->info.sp.init_dmem_data);
    485
    486	writel(bi->info.sp.sp_entry, base + IMGU_REG_SP_START_ADDR(sp));
    487
    488	writel(readl(base + IMGU_REG_SP_CTRL(sp))
    489		| IMGU_CTRL_START | IMGU_CTRL_RUN, base + IMGU_REG_SP_CTRL(sp));
    490
    491	if (imgu_hw_wait(css->base, IMGU_REG_SP_DMEM_BASE(sp)
    492			 + bi->info.sp.sw_state,
    493			 ~0, IMGU_ABI_SP_SWSTATE_INITIALIZED))
    494		return -EIO;
    495
    496	return 0;
    497}
    498
    499/* Start the IPU3 CSS ImgU (Imaging Unit) and all the SPs */
    500static int imgu_css_hw_start(struct imgu_css *css)
    501{
    502	static const u32 event_mask =
    503		((1 << IMGU_ABI_EVTTYPE_OUT_FRAME_DONE) |
    504		(1 << IMGU_ABI_EVTTYPE_2ND_OUT_FRAME_DONE) |
    505		(1 << IMGU_ABI_EVTTYPE_VF_OUT_FRAME_DONE) |
    506		(1 << IMGU_ABI_EVTTYPE_2ND_VF_OUT_FRAME_DONE) |
    507		(1 << IMGU_ABI_EVTTYPE_3A_STATS_DONE) |
    508		(1 << IMGU_ABI_EVTTYPE_DIS_STATS_DONE) |
    509		(1 << IMGU_ABI_EVTTYPE_PIPELINE_DONE) |
    510		(1 << IMGU_ABI_EVTTYPE_FRAME_TAGGED) |
    511		(1 << IMGU_ABI_EVTTYPE_INPUT_FRAME_DONE) |
    512		(1 << IMGU_ABI_EVTTYPE_METADATA_DONE) |
    513		(1 << IMGU_ABI_EVTTYPE_ACC_STAGE_COMPLETE))
    514		<< IMGU_ABI_SP_COMM_EVENT_IRQ_MASK_OR_SHIFT;
    515
    516	void __iomem *const base = css->base;
    517	struct imgu_fw_info *bi, *bl = &css->fwp->binary_header[css->fw_bl];
    518	unsigned int i;
    519
    520	writel(IMGU_TLB_INVALIDATE, base + IMGU_REG_TLB_INVALIDATE);
    521
    522	/* Start bootloader */
    523
    524	writel(IMGU_ABI_BL_SWSTATE_BUSY,
    525	       base + IMGU_REG_ISP_DMEM_BASE + bl->info.bl.sw_state);
    526	writel(IMGU_NUM_SP,
    527	       base + IMGU_REG_ISP_DMEM_BASE + bl->info.bl.num_dma_cmds);
    528
    529	for (i = 0; i < IMGU_NUM_SP; i++) {
    530		int j = IMGU_NUM_SP - i - 1;	/* load sp1 first, then sp0 */
    531		struct imgu_fw_info *sp =
    532					&css->fwp->binary_header[css->fw_sp[j]];
    533		struct imgu_abi_bl_dma_cmd_entry dma_cmd = {
    534			.src_addr = css->binary[css->fw_sp[j]].daddr
    535				+ sp->blob.text_source,
    536			.size = sp->blob.text_size,
    537			.dst_type = IMGU_ABI_BL_DMACMD_TYPE_SP_PMEM,
    538			.dst_addr = IMGU_SP_PMEM_BASE(j),
    539		};
    540
    541		writes(&dma_cmd, sizeof(dma_cmd),
    542		       base + IMGU_REG_ISP_DMEM_BASE + i * sizeof(dma_cmd) +
    543		       bl->info.bl.dma_cmd_list);
    544	}
    545
    546	writel(bl->info.bl.bl_entry, base + IMGU_REG_ISP_START_ADDR);
    547
    548	writel(readl(base + IMGU_REG_ISP_CTRL)
    549		| IMGU_CTRL_START | IMGU_CTRL_RUN, base + IMGU_REG_ISP_CTRL);
    550	if (imgu_hw_wait(css->base, IMGU_REG_ISP_DMEM_BASE
    551			 + bl->info.bl.sw_state, ~0,
    552			 IMGU_ABI_BL_SWSTATE_OK)) {
    553		dev_err(css->dev, "failed to start bootloader\n");
    554		return -EIO;
    555	}
    556
    557	/* Start ISP */
    558
    559	memset(css->xmem_sp_group_ptrs.vaddr, 0,
    560	       sizeof(struct imgu_abi_sp_group));
    561
    562	bi = &css->fwp->binary_header[css->fw_sp[0]];
    563
    564	writel(css->xmem_sp_group_ptrs.daddr,
    565	       base + IMGU_REG_SP_DMEM_BASE(0) + bi->info.sp.per_frame_data);
    566
    567	writel(IMGU_ABI_SP_SWSTATE_TERMINATED,
    568	       base + IMGU_REG_SP_DMEM_BASE(0) + bi->info.sp.sw_state);
    569	writel(1, base + IMGU_REG_SP_DMEM_BASE(0) + bi->info.sp.invalidate_tlb);
    570
    571	if (imgu_css_hw_start_sp(css, 0))
    572		return -EIO;
    573
    574	writel(0, base + IMGU_REG_SP_DMEM_BASE(0) + bi->info.sp.isp_started);
    575	writel(0, base + IMGU_REG_SP_DMEM_BASE(0) +
    576		bi->info.sp.host_sp_queues_initialized);
    577	writel(0, base + IMGU_REG_SP_DMEM_BASE(0) + bi->info.sp.sleep_mode);
    578	writel(0, base + IMGU_REG_SP_DMEM_BASE(0) + bi->info.sp.invalidate_tlb);
    579	writel(IMGU_ABI_SP_COMM_COMMAND_READY, base + IMGU_REG_SP_DMEM_BASE(0)
    580		+ bi->info.sp.host_sp_com + IMGU_ABI_SP_COMM_COMMAND);
    581
    582	/* Enable all events for all queues */
    583
    584	for (i = 0; i < IPU3_CSS_PIPE_ID_NUM; i++)
    585		writel(event_mask, base + IMGU_REG_SP_DMEM_BASE(0)
    586			+ bi->info.sp.host_sp_com
    587			+ IMGU_ABI_SP_COMM_EVENT_IRQ_MASK(i));
    588	writel(1, base + IMGU_REG_SP_DMEM_BASE(0) +
    589		bi->info.sp.host_sp_queues_initialized);
    590
    591	/* Start SP1 */
    592
    593	bi = &css->fwp->binary_header[css->fw_sp[1]];
    594
    595	writel(IMGU_ABI_SP_SWSTATE_TERMINATED,
    596	       base + IMGU_REG_SP_DMEM_BASE(1) + bi->info.sp.sw_state);
    597
    598	if (imgu_css_hw_start_sp(css, 1))
    599		return -EIO;
    600
    601	writel(IMGU_ABI_SP_COMM_COMMAND_READY, base + IMGU_REG_SP_DMEM_BASE(1)
    602		+ bi->info.sp.host_sp_com + IMGU_ABI_SP_COMM_COMMAND);
    603
    604	return 0;
    605}
    606
    607static void imgu_css_hw_stop(struct imgu_css *css)
    608{
    609	void __iomem *const base = css->base;
    610	struct imgu_fw_info *bi = &css->fwp->binary_header[css->fw_sp[0]];
    611
    612	/* Stop fw */
    613	writel(IMGU_ABI_SP_COMM_COMMAND_TERMINATE,
    614	       base + IMGU_REG_SP_DMEM_BASE(0) +
    615	       bi->info.sp.host_sp_com + IMGU_ABI_SP_COMM_COMMAND);
    616	if (imgu_hw_wait(css->base, IMGU_REG_SP_CTRL(0),
    617			 IMGU_CTRL_IDLE, IMGU_CTRL_IDLE))
    618		dev_err(css->dev, "wait sp0 idle timeout.\n");
    619	if (readl(base + IMGU_REG_SP_DMEM_BASE(0) + bi->info.sp.sw_state) !=
    620		  IMGU_ABI_SP_SWSTATE_TERMINATED)
    621		dev_err(css->dev, "sp0 is not terminated.\n");
    622	if (imgu_hw_wait(css->base, IMGU_REG_ISP_CTRL,
    623			 IMGU_CTRL_IDLE, IMGU_CTRL_IDLE))
    624		dev_err(css->dev, "wait isp idle timeout\n");
    625}
    626
    627static void imgu_css_hw_cleanup(struct imgu_css *css)
    628{
    629	void __iomem *const base = css->base;
    630
    631	/** Reset CSS **/
    632
    633	/* Clear the CSS busy signal */
    634	readl(base + IMGU_REG_GP_BUSY);
    635	writel(0, base + IMGU_REG_GP_BUSY);
    636
    637	/* Wait for idle signal */
    638	if (imgu_hw_wait(css->base, IMGU_REG_STATE, IMGU_STATE_IDLE_STS,
    639			 IMGU_STATE_IDLE_STS))
    640		dev_err(css->dev, "failed to shut down hw cleanly\n");
    641
    642	/* Reset the css */
    643	writel(readl(base + IMGU_REG_PM_CTRL) | IMGU_PM_CTRL_FORCE_RESET,
    644	       base + IMGU_REG_PM_CTRL);
    645
    646	usleep_range(200, 300);
    647}
    648
    649static void imgu_css_pipeline_cleanup(struct imgu_css *css, unsigned int pipe)
    650{
    651	struct imgu_device *imgu = dev_get_drvdata(css->dev);
    652	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
    653	unsigned int i;
    654
    655	imgu_css_pool_cleanup(imgu, &css_pipe->pool.parameter_set_info);
    656	imgu_css_pool_cleanup(imgu, &css_pipe->pool.acc);
    657	imgu_css_pool_cleanup(imgu, &css_pipe->pool.gdc);
    658	imgu_css_pool_cleanup(imgu, &css_pipe->pool.obgrid);
    659
    660	for (i = 0; i < IMGU_ABI_NUM_MEMORIES; i++)
    661		imgu_css_pool_cleanup(imgu, &css_pipe->pool.binary_params_p[i]);
    662}
    663
    664/*
    665 * This function initializes various stages of the
    666 * IPU3 CSS ISP pipeline
    667 */
    668static int imgu_css_pipeline_init(struct imgu_css *css, unsigned int pipe)
    669{
    670	static const int BYPC = 2;	/* Bytes per component */
    671	static const struct imgu_abi_buffer_sp buffer_sp_init = {
    672		.buf_src = {.queue_id = IMGU_ABI_QUEUE_EVENT_ID},
    673		.buf_type = IMGU_ABI_BUFFER_TYPE_INVALID,
    674	};
    675
    676	struct imgu_abi_isp_iterator_config *cfg_iter;
    677	struct imgu_abi_isp_ref_config *cfg_ref;
    678	struct imgu_abi_isp_dvs_config *cfg_dvs;
    679	struct imgu_abi_isp_tnr3_config *cfg_tnr;
    680	struct imgu_abi_isp_ref_dmem_state *cfg_ref_state;
    681	struct imgu_abi_isp_tnr3_dmem_state *cfg_tnr_state;
    682
    683	const int stage = 0;
    684	unsigned int i, j;
    685
    686	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
    687	struct imgu_css_queue *css_queue_in =
    688			&css_pipe->queue[IPU3_CSS_QUEUE_IN];
    689	struct imgu_css_queue *css_queue_out =
    690			&css_pipe->queue[IPU3_CSS_QUEUE_OUT];
    691	struct imgu_css_queue *css_queue_vf =
    692			&css_pipe->queue[IPU3_CSS_QUEUE_VF];
    693	const struct imgu_fw_info *bi =
    694			&css->fwp->binary_header[css_pipe->bindex];
    695	const unsigned int stripes = bi->info.isp.sp.iterator.num_stripes;
    696
    697	struct imgu_fw_config_memory_offsets *cofs = (void *)css->fwp +
    698		bi->blob.memory_offsets.offsets[IMGU_ABI_PARAM_CLASS_CONFIG];
    699	struct imgu_fw_state_memory_offsets *sofs = (void *)css->fwp +
    700		bi->blob.memory_offsets.offsets[IMGU_ABI_PARAM_CLASS_STATE];
    701
    702	struct imgu_abi_isp_stage *isp_stage;
    703	struct imgu_abi_sp_stage *sp_stage;
    704	struct imgu_abi_sp_group *sp_group;
    705	struct imgu_abi_frames_sp *frames_sp;
    706	struct imgu_abi_frame_sp *frame_sp;
    707	struct imgu_abi_frame_sp_info *frame_sp_info;
    708
    709	const unsigned int bds_width_pad =
    710				ALIGN(css_pipe->rect[IPU3_CSS_RECT_BDS].width,
    711				      2 * IPU3_UAPI_ISP_VEC_ELEMS);
    712
    713	const enum imgu_abi_memories m0 = IMGU_ABI_MEM_ISP_DMEM0;
    714	enum imgu_abi_param_class cfg = IMGU_ABI_PARAM_CLASS_CONFIG;
    715	void *vaddr = css_pipe->binary_params_cs[cfg - 1][m0].vaddr;
    716
    717	struct imgu_device *imgu = dev_get_drvdata(css->dev);
    718
    719	dev_dbg(css->dev, "%s for pipe %d", __func__, pipe);
    720
    721	/* Configure iterator */
    722
    723	cfg_iter = imgu_css_fw_pipeline_params(css, pipe, cfg, m0,
    724					       &cofs->dmem.iterator,
    725					       sizeof(*cfg_iter), vaddr);
    726	if (!cfg_iter)
    727		goto bad_firmware;
    728
    729	frame_sp_info = &cfg_iter->input_info;
    730	frame_sp_info->res.width	= css_queue_in->fmt.mpix.width;
    731	frame_sp_info->res.height	= css_queue_in->fmt.mpix.height;
    732	frame_sp_info->padded_width	= css_queue_in->width_pad;
    733	frame_sp_info->format		= css_queue_in->css_fmt->frame_format;
    734	frame_sp_info->raw_bit_depth	= css_queue_in->css_fmt->bit_depth;
    735	frame_sp_info->raw_bayer_order	= css_queue_in->css_fmt->bayer_order;
    736	frame_sp_info->raw_type		= IMGU_ABI_RAW_TYPE_BAYER;
    737
    738	frame_sp_info = &cfg_iter->internal_info;
    739	frame_sp_info->res.width = css_pipe->rect[IPU3_CSS_RECT_BDS].width;
    740	frame_sp_info->res.height = css_pipe->rect[IPU3_CSS_RECT_BDS].height;
    741	frame_sp_info->padded_width	= bds_width_pad;
    742	frame_sp_info->format		= css_queue_out->css_fmt->frame_format;
    743	frame_sp_info->raw_bit_depth	= css_queue_out->css_fmt->bit_depth;
    744	frame_sp_info->raw_bayer_order	= css_queue_out->css_fmt->bayer_order;
    745	frame_sp_info->raw_type		= IMGU_ABI_RAW_TYPE_BAYER;
    746
    747	frame_sp_info = &cfg_iter->output_info;
    748	frame_sp_info->res.width	= css_queue_out->fmt.mpix.width;
    749	frame_sp_info->res.height	= css_queue_out->fmt.mpix.height;
    750	frame_sp_info->padded_width	= css_queue_out->width_pad;
    751	frame_sp_info->format		= css_queue_out->css_fmt->frame_format;
    752	frame_sp_info->raw_bit_depth	= css_queue_out->css_fmt->bit_depth;
    753	frame_sp_info->raw_bayer_order	= css_queue_out->css_fmt->bayer_order;
    754	frame_sp_info->raw_type		= IMGU_ABI_RAW_TYPE_BAYER;
    755
    756	frame_sp_info = &cfg_iter->vf_info;
    757	frame_sp_info->res.width	= css_queue_vf->fmt.mpix.width;
    758	frame_sp_info->res.height	= css_queue_vf->fmt.mpix.height;
    759	frame_sp_info->padded_width	= css_queue_vf->width_pad;
    760	frame_sp_info->format		= css_queue_vf->css_fmt->frame_format;
    761	frame_sp_info->raw_bit_depth	= css_queue_vf->css_fmt->bit_depth;
    762	frame_sp_info->raw_bayer_order	= css_queue_vf->css_fmt->bayer_order;
    763	frame_sp_info->raw_type		= IMGU_ABI_RAW_TYPE_BAYER;
    764
    765	cfg_iter->dvs_envelope.width =
    766				css_pipe->rect[IPU3_CSS_RECT_ENVELOPE].width;
    767	cfg_iter->dvs_envelope.height =
    768				css_pipe->rect[IPU3_CSS_RECT_ENVELOPE].height;
    769
    770	/* Configure reference (delay) frames */
    771
    772	cfg_ref = imgu_css_fw_pipeline_params(css, pipe, cfg, m0,
    773					      &cofs->dmem.ref,
    774					      sizeof(*cfg_ref), vaddr);
    775	if (!cfg_ref)
    776		goto bad_firmware;
    777
    778	cfg_ref->port_b.crop = 0;
    779	cfg_ref->port_b.elems = IMGU_ABI_ISP_DDR_WORD_BYTES / BYPC;
    780	cfg_ref->port_b.width =
    781		css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].width;
    782	cfg_ref->port_b.stride =
    783		css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].bytesperline;
    784	cfg_ref->width_a_over_b =
    785				IPU3_UAPI_ISP_VEC_ELEMS / cfg_ref->port_b.elems;
    786	cfg_ref->dvs_frame_delay = IPU3_CSS_AUX_FRAMES - 1;
    787	for (i = 0; i < IPU3_CSS_AUX_FRAMES; i++) {
    788		cfg_ref->ref_frame_addr_y[i] =
    789			css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].mem[i].daddr;
    790		cfg_ref->ref_frame_addr_c[i] =
    791			css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].mem[i].daddr +
    792			css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].bytesperline *
    793			css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].height;
    794	}
    795	for (; i < IMGU_ABI_FRAMES_REF; i++) {
    796		cfg_ref->ref_frame_addr_y[i] = 0;
    797		cfg_ref->ref_frame_addr_c[i] = 0;
    798	}
    799
    800	/* Configure DVS (digital video stabilization) */
    801
    802	cfg_dvs = imgu_css_fw_pipeline_params(css, pipe, cfg, m0,
    803					      &cofs->dmem.dvs, sizeof(*cfg_dvs),
    804					      vaddr);
    805	if (!cfg_dvs)
    806		goto bad_firmware;
    807
    808	cfg_dvs->num_horizontal_blocks =
    809			ALIGN(DIV_ROUND_UP(css_pipe->rect[IPU3_CSS_RECT_GDC].width,
    810					   IMGU_DVS_BLOCK_W), 2);
    811	cfg_dvs->num_vertical_blocks =
    812			DIV_ROUND_UP(css_pipe->rect[IPU3_CSS_RECT_GDC].height,
    813				     IMGU_DVS_BLOCK_H);
    814
    815	/* Configure TNR (temporal noise reduction) */
    816
    817	if (css_pipe->pipe_id == IPU3_CSS_PIPE_ID_VIDEO) {
    818		cfg_tnr = imgu_css_fw_pipeline_params(css, pipe, cfg, m0,
    819						      &cofs->dmem.tnr3,
    820						      sizeof(*cfg_tnr),
    821						      vaddr);
    822		if (!cfg_tnr)
    823			goto bad_firmware;
    824
    825		cfg_tnr->port_b.crop = 0;
    826		cfg_tnr->port_b.elems = IMGU_ABI_ISP_DDR_WORD_BYTES;
    827		cfg_tnr->port_b.width =
    828			css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].width;
    829		cfg_tnr->port_b.stride =
    830			css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].bytesperline;
    831		cfg_tnr->width_a_over_b =
    832			IPU3_UAPI_ISP_VEC_ELEMS / cfg_tnr->port_b.elems;
    833		cfg_tnr->frame_height =
    834			css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].height;
    835		cfg_tnr->delay_frame = IPU3_CSS_AUX_FRAMES - 1;
    836		for (i = 0; i < IPU3_CSS_AUX_FRAMES; i++)
    837			cfg_tnr->frame_addr[i] =
    838				css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR]
    839					.mem[i].daddr;
    840		for (; i < IMGU_ABI_FRAMES_TNR; i++)
    841			cfg_tnr->frame_addr[i] = 0;
    842	}
    843
    844	/* Configure ref dmem state parameters */
    845
    846	cfg = IMGU_ABI_PARAM_CLASS_STATE;
    847	vaddr = css_pipe->binary_params_cs[cfg - 1][m0].vaddr;
    848
    849	cfg_ref_state = imgu_css_fw_pipeline_params(css, pipe, cfg, m0,
    850						    &sofs->dmem.ref,
    851						    sizeof(*cfg_ref_state),
    852						    vaddr);
    853	if (!cfg_ref_state)
    854		goto bad_firmware;
    855
    856	cfg_ref_state->ref_in_buf_idx = 0;
    857	cfg_ref_state->ref_out_buf_idx = 1;
    858
    859	/* Configure tnr dmem state parameters */
    860	if (css_pipe->pipe_id == IPU3_CSS_PIPE_ID_VIDEO) {
    861		cfg_tnr_state =
    862			imgu_css_fw_pipeline_params(css, pipe, cfg, m0,
    863						    &sofs->dmem.tnr3,
    864						    sizeof(*cfg_tnr_state),
    865						    vaddr);
    866		if (!cfg_tnr_state)
    867			goto bad_firmware;
    868
    869		cfg_tnr_state->in_bufidx = 0;
    870		cfg_tnr_state->out_bufidx = 1;
    871		cfg_tnr_state->bypass_filter = 0;
    872		cfg_tnr_state->total_frame_counter = 0;
    873		for (i = 0; i < IMGU_ABI_BUF_SETS_TNR; i++)
    874			cfg_tnr_state->buffer_frame_counter[i] = 0;
    875	}
    876
    877	/* Configure ISP stage */
    878
    879	isp_stage = css_pipe->xmem_isp_stage_ptrs[pipe][stage].vaddr;
    880	memset(isp_stage, 0, sizeof(*isp_stage));
    881	isp_stage->blob_info = bi->blob;
    882	isp_stage->binary_info = bi->info.isp.sp;
    883	strscpy(isp_stage->binary_name,
    884		(char *)css->fwp + bi->blob.prog_name_offset,
    885		sizeof(isp_stage->binary_name));
    886	isp_stage->mem_initializers = bi->info.isp.sp.mem_initializers;
    887	for (i = IMGU_ABI_PARAM_CLASS_CONFIG; i < IMGU_ABI_PARAM_CLASS_NUM; i++)
    888		for (j = 0; j < IMGU_ABI_NUM_MEMORIES; j++)
    889			isp_stage->mem_initializers.params[i][j].address =
    890					css_pipe->binary_params_cs[i - 1][j].daddr;
    891
    892	/* Configure SP stage */
    893
    894	sp_stage = css_pipe->xmem_sp_stage_ptrs[pipe][stage].vaddr;
    895	memset(sp_stage, 0, sizeof(*sp_stage));
    896
    897	frames_sp = &sp_stage->frames;
    898	frames_sp->in.buf_attr = buffer_sp_init;
    899	for (i = 0; i < IMGU_ABI_BINARY_MAX_OUTPUT_PORTS; i++)
    900		frames_sp->out[i].buf_attr = buffer_sp_init;
    901	frames_sp->out_vf.buf_attr = buffer_sp_init;
    902	frames_sp->s3a_buf = buffer_sp_init;
    903	frames_sp->dvs_buf = buffer_sp_init;
    904
    905	sp_stage->stage_type = IMGU_ABI_STAGE_TYPE_ISP;
    906	sp_stage->num = stage;
    907	sp_stage->isp_online = 0;
    908	sp_stage->isp_copy_vf = 0;
    909	sp_stage->isp_copy_output = 0;
    910
    911	sp_stage->enable.vf_output = css_pipe->vf_output_en;
    912
    913	frames_sp->effective_in_res.width =
    914				css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].width;
    915	frames_sp->effective_in_res.height =
    916				css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].height;
    917
    918	frame_sp = &frames_sp->in;
    919	frame_sp->info.res.width	= css_queue_in->fmt.mpix.width;
    920	frame_sp->info.res.height	= css_queue_in->fmt.mpix.height;
    921	frame_sp->info.padded_width	= css_queue_in->width_pad;
    922	frame_sp->info.format		= css_queue_in->css_fmt->frame_format;
    923	frame_sp->info.raw_bit_depth	= css_queue_in->css_fmt->bit_depth;
    924	frame_sp->info.raw_bayer_order	= css_queue_in->css_fmt->bayer_order;
    925	frame_sp->info.raw_type		= IMGU_ABI_RAW_TYPE_BAYER;
    926	frame_sp->buf_attr.buf_src.queue_id = IMGU_ABI_QUEUE_C_ID;
    927	frame_sp->buf_attr.buf_type	= IMGU_ABI_BUFFER_TYPE_INPUT_FRAME;
    928
    929	frame_sp = &frames_sp->out[0];
    930	frame_sp->info.res.width	= css_queue_out->fmt.mpix.width;
    931	frame_sp->info.res.height	= css_queue_out->fmt.mpix.height;
    932	frame_sp->info.padded_width	= css_queue_out->width_pad;
    933	frame_sp->info.format		= css_queue_out->css_fmt->frame_format;
    934	frame_sp->info.raw_bit_depth	= css_queue_out->css_fmt->bit_depth;
    935	frame_sp->info.raw_bayer_order	= css_queue_out->css_fmt->bayer_order;
    936	frame_sp->info.raw_type		= IMGU_ABI_RAW_TYPE_BAYER;
    937	frame_sp->planes.nv.uv.offset	= css_queue_out->width_pad *
    938					  css_queue_out->fmt.mpix.height;
    939	frame_sp->buf_attr.buf_src.queue_id = IMGU_ABI_QUEUE_D_ID;
    940	frame_sp->buf_attr.buf_type	= IMGU_ABI_BUFFER_TYPE_OUTPUT_FRAME;
    941
    942	frame_sp = &frames_sp->out[1];
    943	frame_sp->buf_attr.buf_src.queue_id = IMGU_ABI_QUEUE_EVENT_ID;
    944
    945	frame_sp_info = &frames_sp->internal_frame_info;
    946	frame_sp_info->res.width = css_pipe->rect[IPU3_CSS_RECT_BDS].width;
    947	frame_sp_info->res.height = css_pipe->rect[IPU3_CSS_RECT_BDS].height;
    948	frame_sp_info->padded_width	= bds_width_pad;
    949	frame_sp_info->format		= css_queue_out->css_fmt->frame_format;
    950	frame_sp_info->raw_bit_depth	= css_queue_out->css_fmt->bit_depth;
    951	frame_sp_info->raw_bayer_order	= css_queue_out->css_fmt->bayer_order;
    952	frame_sp_info->raw_type		= IMGU_ABI_RAW_TYPE_BAYER;
    953
    954	frame_sp = &frames_sp->out_vf;
    955	frame_sp->info.res.width	= css_queue_vf->fmt.mpix.width;
    956	frame_sp->info.res.height	= css_queue_vf->fmt.mpix.height;
    957	frame_sp->info.padded_width	= css_queue_vf->width_pad;
    958	frame_sp->info.format		= css_queue_vf->css_fmt->frame_format;
    959	frame_sp->info.raw_bit_depth	= css_queue_vf->css_fmt->bit_depth;
    960	frame_sp->info.raw_bayer_order	= css_queue_vf->css_fmt->bayer_order;
    961	frame_sp->info.raw_type		= IMGU_ABI_RAW_TYPE_BAYER;
    962	frame_sp->planes.yuv.u.offset	= css_queue_vf->width_pad *
    963					  css_queue_vf->fmt.mpix.height;
    964	frame_sp->planes.yuv.v.offset	= css_queue_vf->width_pad *
    965					  css_queue_vf->fmt.mpix.height * 5 / 4;
    966	frame_sp->buf_attr.buf_src.queue_id = IMGU_ABI_QUEUE_E_ID;
    967	frame_sp->buf_attr.buf_type	= IMGU_ABI_BUFFER_TYPE_VF_OUTPUT_FRAME;
    968
    969	frames_sp->s3a_buf.buf_src.queue_id = IMGU_ABI_QUEUE_F_ID;
    970	frames_sp->s3a_buf.buf_type	= IMGU_ABI_BUFFER_TYPE_3A_STATISTICS;
    971
    972	frames_sp->dvs_buf.buf_src.queue_id = IMGU_ABI_QUEUE_G_ID;
    973	frames_sp->dvs_buf.buf_type	= IMGU_ABI_BUFFER_TYPE_DIS_STATISTICS;
    974
    975	sp_stage->dvs_envelope.width =
    976				css_pipe->rect[IPU3_CSS_RECT_ENVELOPE].width;
    977	sp_stage->dvs_envelope.height =
    978				css_pipe->rect[IPU3_CSS_RECT_ENVELOPE].height;
    979
    980	sp_stage->isp_pipe_version =
    981				bi->info.isp.sp.pipeline.isp_pipe_version;
    982	sp_stage->isp_deci_log_factor =
    983			clamp(max(fls(css_pipe->rect[IPU3_CSS_RECT_BDS].width /
    984				      IMGU_MAX_BQ_GRID_WIDTH),
    985				  fls(css_pipe->rect[IPU3_CSS_RECT_BDS].height /
    986				      IMGU_MAX_BQ_GRID_HEIGHT)) - 1, 3, 5);
    987	sp_stage->isp_vf_downscale_bits = 0;
    988	sp_stage->if_config_index = 255;
    989	sp_stage->sp_enable_xnr = 0;
    990	sp_stage->num_stripes = stripes;
    991	sp_stage->enable.s3a = 1;
    992	sp_stage->enable.dvs_stats = 0;
    993
    994	sp_stage->xmem_bin_addr = css->binary[css_pipe->bindex].daddr;
    995	sp_stage->xmem_map_addr = css_pipe->sp_ddr_ptrs.daddr;
    996	sp_stage->isp_stage_addr =
    997		css_pipe->xmem_isp_stage_ptrs[pipe][stage].daddr;
    998
    999	/* Configure SP group */
   1000
   1001	sp_group = css->xmem_sp_group_ptrs.vaddr;
   1002	memset(&sp_group->pipe[pipe], 0, sizeof(struct imgu_abi_sp_pipeline));
   1003
   1004	sp_group->pipe[pipe].num_stages = 1;
   1005	sp_group->pipe[pipe].pipe_id = css_pipe->pipe_id;
   1006	sp_group->pipe[pipe].thread_id = pipe;
   1007	sp_group->pipe[pipe].pipe_num = pipe;
   1008	sp_group->pipe[pipe].num_execs = -1;
   1009	sp_group->pipe[pipe].pipe_qos_config = -1;
   1010	sp_group->pipe[pipe].required_bds_factor = 0;
   1011	sp_group->pipe[pipe].dvs_frame_delay = IPU3_CSS_AUX_FRAMES - 1;
   1012	sp_group->pipe[pipe].inout_port_config =
   1013					IMGU_ABI_PORT_CONFIG_TYPE_INPUT_HOST |
   1014					IMGU_ABI_PORT_CONFIG_TYPE_OUTPUT_HOST;
   1015	sp_group->pipe[pipe].scaler_pp_lut = 0;
   1016	sp_group->pipe[pipe].shading.internal_frame_origin_x_bqs_on_sctbl = 0;
   1017	sp_group->pipe[pipe].shading.internal_frame_origin_y_bqs_on_sctbl = 0;
   1018	sp_group->pipe[pipe].sp_stage_addr[stage] =
   1019			css_pipe->xmem_sp_stage_ptrs[pipe][stage].daddr;
   1020	sp_group->pipe[pipe].pipe_config =
   1021			bi->info.isp.sp.enable.params ? (1 << pipe) : 0;
   1022	sp_group->pipe[pipe].pipe_config |= IMGU_ABI_PIPE_CONFIG_ACQUIRE_ISP;
   1023
   1024	/* Initialize parameter pools */
   1025
   1026	if (imgu_css_pool_init(imgu, &css_pipe->pool.parameter_set_info,
   1027			       sizeof(struct imgu_abi_parameter_set_info)) ||
   1028	    imgu_css_pool_init(imgu, &css_pipe->pool.acc,
   1029			       sizeof(struct imgu_abi_acc_param)) ||
   1030	    imgu_css_pool_init(imgu, &css_pipe->pool.gdc,
   1031			       sizeof(struct imgu_abi_gdc_warp_param) *
   1032			       3 * cfg_dvs->num_horizontal_blocks / 2 *
   1033			       cfg_dvs->num_vertical_blocks) ||
   1034	    imgu_css_pool_init(imgu, &css_pipe->pool.obgrid,
   1035			       imgu_css_fw_obgrid_size(
   1036			       &css->fwp->binary_header[css_pipe->bindex])))
   1037		goto out_of_memory;
   1038
   1039	for (i = 0; i < IMGU_ABI_NUM_MEMORIES; i++)
   1040		if (imgu_css_pool_init(imgu,
   1041				       &css_pipe->pool.binary_params_p[i],
   1042				       bi->info.isp.sp.mem_initializers.params
   1043				       [IMGU_ABI_PARAM_CLASS_PARAM][i].size))
   1044			goto out_of_memory;
   1045
   1046	return 0;
   1047
   1048bad_firmware:
   1049	imgu_css_pipeline_cleanup(css, pipe);
   1050	return -EPROTO;
   1051
   1052out_of_memory:
   1053	imgu_css_pipeline_cleanup(css, pipe);
   1054	return -ENOMEM;
   1055}
   1056
   1057static u8 imgu_css_queue_pos(struct imgu_css *css, int queue, int thread)
   1058{
   1059	static const unsigned int sp;
   1060	void __iomem *const base = css->base;
   1061	struct imgu_fw_info *bi = &css->fwp->binary_header[css->fw_sp[sp]];
   1062	struct imgu_abi_queues __iomem *q = base + IMGU_REG_SP_DMEM_BASE(sp) +
   1063						bi->info.sp.host_sp_queue;
   1064
   1065	return queue >= 0 ? readb(&q->host2sp_bufq_info[thread][queue].end) :
   1066			    readb(&q->host2sp_evtq_info.end);
   1067}
   1068
   1069/* Sent data to sp using given buffer queue, or if queue < 0, event queue. */
   1070static int imgu_css_queue_data(struct imgu_css *css,
   1071			       int queue, int thread, u32 data)
   1072{
   1073	static const unsigned int sp;
   1074	void __iomem *const base = css->base;
   1075	struct imgu_fw_info *bi = &css->fwp->binary_header[css->fw_sp[sp]];
   1076	struct imgu_abi_queues __iomem *q = base + IMGU_REG_SP_DMEM_BASE(sp) +
   1077						bi->info.sp.host_sp_queue;
   1078	u8 size, start, end, end2;
   1079
   1080	if (queue >= 0) {
   1081		size = readb(&q->host2sp_bufq_info[thread][queue].size);
   1082		start = readb(&q->host2sp_bufq_info[thread][queue].start);
   1083		end = readb(&q->host2sp_bufq_info[thread][queue].end);
   1084	} else {
   1085		size = readb(&q->host2sp_evtq_info.size);
   1086		start = readb(&q->host2sp_evtq_info.start);
   1087		end = readb(&q->host2sp_evtq_info.end);
   1088	}
   1089
   1090	if (size == 0)
   1091		return -EIO;
   1092
   1093	end2 = (end + 1) % size;
   1094	if (end2 == start)
   1095		return -EBUSY;	/* Queue full */
   1096
   1097	if (queue >= 0) {
   1098		writel(data, &q->host2sp_bufq[thread][queue][end]);
   1099		writeb(end2, &q->host2sp_bufq_info[thread][queue].end);
   1100	} else {
   1101		writel(data, &q->host2sp_evtq[end]);
   1102		writeb(end2, &q->host2sp_evtq_info.end);
   1103	}
   1104
   1105	return 0;
   1106}
   1107
   1108/* Receive data using given buffer queue, or if queue < 0, event queue. */
   1109static int imgu_css_dequeue_data(struct imgu_css *css, int queue, u32 *data)
   1110{
   1111	static const unsigned int sp;
   1112	void __iomem *const base = css->base;
   1113	struct imgu_fw_info *bi = &css->fwp->binary_header[css->fw_sp[sp]];
   1114	struct imgu_abi_queues __iomem *q = base + IMGU_REG_SP_DMEM_BASE(sp) +
   1115						bi->info.sp.host_sp_queue;
   1116	u8 size, start, end, start2;
   1117
   1118	if (queue >= 0) {
   1119		size = readb(&q->sp2host_bufq_info[queue].size);
   1120		start = readb(&q->sp2host_bufq_info[queue].start);
   1121		end = readb(&q->sp2host_bufq_info[queue].end);
   1122	} else {
   1123		size = readb(&q->sp2host_evtq_info.size);
   1124		start = readb(&q->sp2host_evtq_info.start);
   1125		end = readb(&q->sp2host_evtq_info.end);
   1126	}
   1127
   1128	if (size == 0)
   1129		return -EIO;
   1130
   1131	if (end == start)
   1132		return -EBUSY;	/* Queue empty */
   1133
   1134	start2 = (start + 1) % size;
   1135
   1136	if (queue >= 0) {
   1137		*data = readl(&q->sp2host_bufq[queue][start]);
   1138		writeb(start2, &q->sp2host_bufq_info[queue].start);
   1139	} else {
   1140		int r;
   1141
   1142		*data = readl(&q->sp2host_evtq[start]);
   1143		writeb(start2, &q->sp2host_evtq_info.start);
   1144
   1145		/* Acknowledge events dequeued from event queue */
   1146		r = imgu_css_queue_data(css, queue, 0,
   1147					IMGU_ABI_EVENT_EVENT_DEQUEUED);
   1148		if (r < 0)
   1149			return r;
   1150	}
   1151
   1152	return 0;
   1153}
   1154
   1155/* Free binary-specific resources */
   1156static void imgu_css_binary_cleanup(struct imgu_css *css, unsigned int pipe)
   1157{
   1158	struct imgu_device *imgu = dev_get_drvdata(css->dev);
   1159	unsigned int i, j;
   1160
   1161	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
   1162
   1163	for (j = 0; j < IMGU_ABI_PARAM_CLASS_NUM - 1; j++)
   1164		for (i = 0; i < IMGU_ABI_NUM_MEMORIES; i++)
   1165			imgu_dmamap_free(imgu,
   1166					 &css_pipe->binary_params_cs[j][i]);
   1167
   1168	j = IPU3_CSS_AUX_FRAME_REF;
   1169	for (i = 0; i < IPU3_CSS_AUX_FRAMES; i++)
   1170		imgu_dmamap_free(imgu,
   1171				 &css_pipe->aux_frames[j].mem[i]);
   1172
   1173	j = IPU3_CSS_AUX_FRAME_TNR;
   1174	for (i = 0; i < IPU3_CSS_AUX_FRAMES; i++)
   1175		imgu_dmamap_free(imgu,
   1176				 &css_pipe->aux_frames[j].mem[i]);
   1177}
   1178
   1179static int imgu_css_binary_preallocate(struct imgu_css *css, unsigned int pipe)
   1180{
   1181	struct imgu_device *imgu = dev_get_drvdata(css->dev);
   1182	unsigned int i, j;
   1183
   1184	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
   1185
   1186	for (j = IMGU_ABI_PARAM_CLASS_CONFIG;
   1187	     j < IMGU_ABI_PARAM_CLASS_NUM; j++)
   1188		for (i = 0; i < IMGU_ABI_NUM_MEMORIES; i++)
   1189			if (!imgu_dmamap_alloc(imgu,
   1190					       &css_pipe->binary_params_cs[j - 1][i],
   1191					       CSS_ABI_SIZE))
   1192				goto out_of_memory;
   1193
   1194	for (i = 0; i < IPU3_CSS_AUX_FRAMES; i++)
   1195		if (!imgu_dmamap_alloc(imgu,
   1196				       &css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].
   1197				       mem[i], CSS_BDS_SIZE))
   1198			goto out_of_memory;
   1199
   1200	for (i = 0; i < IPU3_CSS_AUX_FRAMES; i++)
   1201		if (!imgu_dmamap_alloc(imgu,
   1202				       &css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].
   1203				       mem[i], CSS_GDC_SIZE))
   1204			goto out_of_memory;
   1205
   1206	return 0;
   1207
   1208out_of_memory:
   1209	imgu_css_binary_cleanup(css, pipe);
   1210	return -ENOMEM;
   1211}
   1212
   1213/* allocate binary-specific resources */
   1214static int imgu_css_binary_setup(struct imgu_css *css, unsigned int pipe)
   1215{
   1216	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
   1217	struct imgu_fw_info *bi = &css->fwp->binary_header[css_pipe->bindex];
   1218	struct imgu_device *imgu = dev_get_drvdata(css->dev);
   1219	int i, j, size;
   1220	static const int BYPC = 2;	/* Bytes per component */
   1221	unsigned int w, h;
   1222
   1223	/* Allocate parameter memory blocks for this binary */
   1224
   1225	for (j = IMGU_ABI_PARAM_CLASS_CONFIG; j < IMGU_ABI_PARAM_CLASS_NUM; j++)
   1226		for (i = 0; i < IMGU_ABI_NUM_MEMORIES; i++) {
   1227			if (imgu_css_dma_buffer_resize(
   1228			    imgu,
   1229			    &css_pipe->binary_params_cs[j - 1][i],
   1230			    bi->info.isp.sp.mem_initializers.params[j][i].size))
   1231				goto out_of_memory;
   1232		}
   1233
   1234	/* Allocate internal frame buffers */
   1235
   1236	/* Reference frames for DVS, FRAME_FORMAT_YUV420_16 */
   1237	css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].bytesperpixel = BYPC;
   1238	css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].width =
   1239					css_pipe->rect[IPU3_CSS_RECT_BDS].width;
   1240	css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].height =
   1241				ALIGN(css_pipe->rect[IPU3_CSS_RECT_BDS].height,
   1242				      IMGU_DVS_BLOCK_H) + 2 * IMGU_GDC_BUF_Y;
   1243	h = css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].height;
   1244	w = ALIGN(css_pipe->rect[IPU3_CSS_RECT_BDS].width,
   1245		  2 * IPU3_UAPI_ISP_VEC_ELEMS) + 2 * IMGU_GDC_BUF_X;
   1246	css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].bytesperline =
   1247		css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].bytesperpixel * w;
   1248	size = w * h * BYPC + (w / 2) * (h / 2) * BYPC * 2;
   1249	for (i = 0; i < IPU3_CSS_AUX_FRAMES; i++)
   1250		if (imgu_css_dma_buffer_resize(
   1251			imgu,
   1252			&css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].mem[i],
   1253			size))
   1254			goto out_of_memory;
   1255
   1256	/* TNR frames for temporal noise reduction, FRAME_FORMAT_YUV_LINE */
   1257	css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].bytesperpixel = 1;
   1258	css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].width =
   1259			roundup(css_pipe->rect[IPU3_CSS_RECT_GDC].width,
   1260				bi->info.isp.sp.block.block_width *
   1261				IPU3_UAPI_ISP_VEC_ELEMS);
   1262	css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].height =
   1263			roundup(css_pipe->rect[IPU3_CSS_RECT_GDC].height,
   1264				bi->info.isp.sp.block.output_block_height);
   1265
   1266	w = css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].width;
   1267	css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].bytesperline = w;
   1268	h = css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].height;
   1269	size = w * ALIGN(h * 3 / 2 + 3, 2);	/* +3 for vf_pp prefetch */
   1270	for (i = 0; i < IPU3_CSS_AUX_FRAMES; i++)
   1271		if (imgu_css_dma_buffer_resize(
   1272			imgu,
   1273			&css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].mem[i],
   1274			size))
   1275			goto out_of_memory;
   1276
   1277	return 0;
   1278
   1279out_of_memory:
   1280	imgu_css_binary_cleanup(css, pipe);
   1281	return -ENOMEM;
   1282}
   1283
   1284int imgu_css_start_streaming(struct imgu_css *css)
   1285{
   1286	u32 data;
   1287	int r, pipe;
   1288
   1289	if (css->streaming)
   1290		return -EPROTO;
   1291
   1292	for_each_set_bit(pipe, css->enabled_pipes, IMGU_MAX_PIPE_NUM) {
   1293		r = imgu_css_binary_setup(css, pipe);
   1294		if (r < 0)
   1295			return r;
   1296	}
   1297
   1298	r = imgu_css_hw_init(css);
   1299	if (r < 0)
   1300		return r;
   1301
   1302	r = imgu_css_hw_start(css);
   1303	if (r < 0)
   1304		goto fail;
   1305
   1306	for_each_set_bit(pipe, css->enabled_pipes, IMGU_MAX_PIPE_NUM) {
   1307		r = imgu_css_pipeline_init(css, pipe);
   1308		if (r < 0)
   1309			goto fail;
   1310	}
   1311
   1312	css->streaming = true;
   1313
   1314	imgu_css_hw_enable_irq(css);
   1315
   1316	/* Initialize parameters to default */
   1317	for_each_set_bit(pipe, css->enabled_pipes, IMGU_MAX_PIPE_NUM) {
   1318		r = imgu_css_set_parameters(css, pipe, NULL);
   1319		if (r < 0)
   1320			goto fail;
   1321	}
   1322
   1323	while (!(r = imgu_css_dequeue_data(css, IMGU_ABI_QUEUE_A_ID, &data)))
   1324		;
   1325	if (r != -EBUSY)
   1326		goto fail;
   1327
   1328	while (!(r = imgu_css_dequeue_data(css, IMGU_ABI_QUEUE_B_ID, &data)))
   1329		;
   1330	if (r != -EBUSY)
   1331		goto fail;
   1332
   1333	for_each_set_bit(pipe, css->enabled_pipes, IMGU_MAX_PIPE_NUM) {
   1334		r = imgu_css_queue_data(css, IMGU_ABI_QUEUE_EVENT_ID, pipe,
   1335					IMGU_ABI_EVENT_START_STREAM |
   1336					pipe << 16);
   1337		if (r < 0)
   1338			goto fail;
   1339	}
   1340
   1341	return 0;
   1342
   1343fail:
   1344	css->streaming = false;
   1345	imgu_css_hw_cleanup(css);
   1346	for_each_set_bit(pipe, css->enabled_pipes, IMGU_MAX_PIPE_NUM) {
   1347		imgu_css_pipeline_cleanup(css, pipe);
   1348		imgu_css_binary_cleanup(css, pipe);
   1349	}
   1350
   1351	return r;
   1352}
   1353
   1354void imgu_css_stop_streaming(struct imgu_css *css)
   1355{
   1356	struct imgu_css_buffer *b, *b0;
   1357	int q, r, pipe;
   1358
   1359	for_each_set_bit(pipe, css->enabled_pipes, IMGU_MAX_PIPE_NUM) {
   1360		r = imgu_css_queue_data(css, IMGU_ABI_QUEUE_EVENT_ID, pipe,
   1361					IMGU_ABI_EVENT_STOP_STREAM);
   1362		if (r < 0)
   1363			dev_warn(css->dev, "failed on stop stream event\n");
   1364	}
   1365
   1366	if (!css->streaming)
   1367		return;
   1368
   1369	imgu_css_hw_stop(css);
   1370
   1371	imgu_css_hw_cleanup(css);
   1372
   1373	for_each_set_bit(pipe, css->enabled_pipes, IMGU_MAX_PIPE_NUM) {
   1374		struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
   1375
   1376		imgu_css_pipeline_cleanup(css, pipe);
   1377
   1378		spin_lock(&css_pipe->qlock);
   1379		for (q = 0; q < IPU3_CSS_QUEUES; q++)
   1380			list_for_each_entry_safe(b, b0,
   1381						 &css_pipe->queue[q].bufs,
   1382						 list) {
   1383				b->state = IPU3_CSS_BUFFER_FAILED;
   1384				list_del(&b->list);
   1385			}
   1386		spin_unlock(&css_pipe->qlock);
   1387	}
   1388
   1389	css->streaming = false;
   1390}
   1391
   1392bool imgu_css_pipe_queue_empty(struct imgu_css *css, unsigned int pipe)
   1393{
   1394	int q;
   1395	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
   1396
   1397	spin_lock(&css_pipe->qlock);
   1398	for (q = 0; q < IPU3_CSS_QUEUES; q++)
   1399		if (!list_empty(&css_pipe->queue[q].bufs))
   1400			break;
   1401	spin_unlock(&css_pipe->qlock);
   1402	return (q == IPU3_CSS_QUEUES);
   1403}
   1404
   1405bool imgu_css_queue_empty(struct imgu_css *css)
   1406{
   1407	unsigned int pipe;
   1408	bool ret = false;
   1409
   1410	for (pipe = 0; pipe < IMGU_MAX_PIPE_NUM; pipe++)
   1411		ret &= imgu_css_pipe_queue_empty(css, pipe);
   1412
   1413	return ret;
   1414}
   1415
   1416bool imgu_css_is_streaming(struct imgu_css *css)
   1417{
   1418	return css->streaming;
   1419}
   1420
   1421static int imgu_css_map_init(struct imgu_css *css, unsigned int pipe)
   1422{
   1423	struct imgu_device *imgu = dev_get_drvdata(css->dev);
   1424	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
   1425	unsigned int p, q, i;
   1426
   1427	/* Allocate and map common structures with imgu hardware */
   1428	for (p = 0; p < IPU3_CSS_PIPE_ID_NUM; p++)
   1429		for (i = 0; i < IMGU_ABI_MAX_STAGES; i++) {
   1430			if (!imgu_dmamap_alloc(imgu,
   1431					       &css_pipe->
   1432					       xmem_sp_stage_ptrs[p][i],
   1433					       sizeof(struct imgu_abi_sp_stage)))
   1434				return -ENOMEM;
   1435			if (!imgu_dmamap_alloc(imgu,
   1436					       &css_pipe->
   1437					       xmem_isp_stage_ptrs[p][i],
   1438					       sizeof(struct imgu_abi_isp_stage)))
   1439				return -ENOMEM;
   1440		}
   1441
   1442	if (!imgu_dmamap_alloc(imgu, &css_pipe->sp_ddr_ptrs,
   1443			       ALIGN(sizeof(struct imgu_abi_ddr_address_map),
   1444				     IMGU_ABI_ISP_DDR_WORD_BYTES)))
   1445		return -ENOMEM;
   1446
   1447	for (q = 0; q < IPU3_CSS_QUEUES; q++) {
   1448		unsigned int abi_buf_num = ARRAY_SIZE(css_pipe->abi_buffers[q]);
   1449
   1450		for (i = 0; i < abi_buf_num; i++)
   1451			if (!imgu_dmamap_alloc(imgu,
   1452					       &css_pipe->abi_buffers[q][i],
   1453					       sizeof(struct imgu_abi_buffer)))
   1454				return -ENOMEM;
   1455	}
   1456
   1457	if (imgu_css_binary_preallocate(css, pipe)) {
   1458		imgu_css_binary_cleanup(css, pipe);
   1459		return -ENOMEM;
   1460	}
   1461
   1462	return 0;
   1463}
   1464
   1465static void imgu_css_pipe_cleanup(struct imgu_css *css, unsigned int pipe)
   1466{
   1467	struct imgu_device *imgu = dev_get_drvdata(css->dev);
   1468	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
   1469	unsigned int p, q, i, abi_buf_num;
   1470
   1471	imgu_css_binary_cleanup(css, pipe);
   1472
   1473	for (q = 0; q < IPU3_CSS_QUEUES; q++) {
   1474		abi_buf_num = ARRAY_SIZE(css_pipe->abi_buffers[q]);
   1475		for (i = 0; i < abi_buf_num; i++)
   1476			imgu_dmamap_free(imgu, &css_pipe->abi_buffers[q][i]);
   1477	}
   1478
   1479	for (p = 0; p < IPU3_CSS_PIPE_ID_NUM; p++)
   1480		for (i = 0; i < IMGU_ABI_MAX_STAGES; i++) {
   1481			imgu_dmamap_free(imgu,
   1482					 &css_pipe->xmem_sp_stage_ptrs[p][i]);
   1483			imgu_dmamap_free(imgu,
   1484					 &css_pipe->xmem_isp_stage_ptrs[p][i]);
   1485		}
   1486
   1487	imgu_dmamap_free(imgu, &css_pipe->sp_ddr_ptrs);
   1488}
   1489
   1490void imgu_css_cleanup(struct imgu_css *css)
   1491{
   1492	struct imgu_device *imgu = dev_get_drvdata(css->dev);
   1493	unsigned int pipe;
   1494
   1495	imgu_css_stop_streaming(css);
   1496	for (pipe = 0; pipe < IMGU_MAX_PIPE_NUM; pipe++)
   1497		imgu_css_pipe_cleanup(css, pipe);
   1498	imgu_dmamap_free(imgu, &css->xmem_sp_group_ptrs);
   1499	imgu_css_fw_cleanup(css);
   1500}
   1501
   1502int imgu_css_init(struct device *dev, struct imgu_css *css,
   1503		  void __iomem *base, int length)
   1504{
   1505	struct imgu_device *imgu = dev_get_drvdata(dev);
   1506	int r, q, pipe;
   1507
   1508	/* Initialize main data structure */
   1509	css->dev = dev;
   1510	css->base = base;
   1511	css->iomem_length = length;
   1512
   1513	for (pipe = 0; pipe < IMGU_MAX_PIPE_NUM; pipe++) {
   1514		struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
   1515
   1516		css_pipe->vf_output_en = false;
   1517		spin_lock_init(&css_pipe->qlock);
   1518		css_pipe->bindex = IPU3_CSS_DEFAULT_BINARY;
   1519		css_pipe->pipe_id = IPU3_CSS_PIPE_ID_VIDEO;
   1520		for (q = 0; q < IPU3_CSS_QUEUES; q++) {
   1521			r = imgu_css_queue_init(&css_pipe->queue[q], NULL, 0);
   1522			if (r)
   1523				return r;
   1524		}
   1525		r = imgu_css_map_init(css, pipe);
   1526		if (r) {
   1527			imgu_css_cleanup(css);
   1528			return r;
   1529		}
   1530	}
   1531	if (!imgu_dmamap_alloc(imgu, &css->xmem_sp_group_ptrs,
   1532			       sizeof(struct imgu_abi_sp_group)))
   1533		return -ENOMEM;
   1534
   1535	r = imgu_css_fw_init(css);
   1536	if (r)
   1537		return r;
   1538
   1539	return 0;
   1540}
   1541
   1542static u32 imgu_css_adjust(u32 res, u32 align)
   1543{
   1544	u32 val = max_t(u32, IPU3_CSS_MIN_RES, res);
   1545
   1546	return DIV_ROUND_CLOSEST(val, align) * align;
   1547}
   1548
   1549/* Select a binary matching the required resolutions and formats */
   1550static int imgu_css_find_binary(struct imgu_css *css,
   1551				unsigned int pipe,
   1552				struct imgu_css_queue queue[IPU3_CSS_QUEUES],
   1553				struct v4l2_rect rects[IPU3_CSS_RECTS])
   1554{
   1555	const int binary_nr = css->fwp->file_header.binary_nr;
   1556	unsigned int binary_mode =
   1557		(css->pipes[pipe].pipe_id == IPU3_CSS_PIPE_ID_CAPTURE) ?
   1558		IA_CSS_BINARY_MODE_PRIMARY : IA_CSS_BINARY_MODE_VIDEO;
   1559	const struct v4l2_pix_format_mplane *in =
   1560					&queue[IPU3_CSS_QUEUE_IN].fmt.mpix;
   1561	const struct v4l2_pix_format_mplane *out =
   1562					&queue[IPU3_CSS_QUEUE_OUT].fmt.mpix;
   1563	const struct v4l2_pix_format_mplane *vf =
   1564					&queue[IPU3_CSS_QUEUE_VF].fmt.mpix;
   1565	u32 stripe_w = 0, stripe_h = 0;
   1566	const char *name;
   1567	int i, j;
   1568
   1569	if (!imgu_css_queue_enabled(&queue[IPU3_CSS_QUEUE_IN]))
   1570		return -EINVAL;
   1571
   1572	/* Find out the strip size boundary */
   1573	for (i = 0; i < binary_nr; i++) {
   1574		struct imgu_fw_info *bi = &css->fwp->binary_header[i];
   1575
   1576		u32 max_width = bi->info.isp.sp.output.max_width;
   1577		u32 max_height = bi->info.isp.sp.output.max_height;
   1578
   1579		if (bi->info.isp.sp.iterator.num_stripes <= 1) {
   1580			stripe_w = stripe_w ?
   1581				min(stripe_w, max_width) : max_width;
   1582			stripe_h = stripe_h ?
   1583				min(stripe_h, max_height) : max_height;
   1584		}
   1585	}
   1586
   1587	for (i = 0; i < binary_nr; i++) {
   1588		struct imgu_fw_info *bi = &css->fwp->binary_header[i];
   1589		enum imgu_abi_frame_format q_fmt;
   1590
   1591		name = (void *)css->fwp + bi->blob.prog_name_offset;
   1592
   1593		/* Check that binary supports memory-to-memory processing */
   1594		if (bi->info.isp.sp.input.source !=
   1595		    IMGU_ABI_BINARY_INPUT_SOURCE_MEMORY)
   1596			continue;
   1597
   1598		/* Check that binary supports raw10 input */
   1599		if (!bi->info.isp.sp.enable.input_feeder &&
   1600		    !bi->info.isp.sp.enable.input_raw)
   1601			continue;
   1602
   1603		/* Check binary mode */
   1604		if (bi->info.isp.sp.pipeline.mode != binary_mode)
   1605			continue;
   1606
   1607		/* Since input is RGGB bayer, need to process colors */
   1608		if (bi->info.isp.sp.enable.luma_only)
   1609			continue;
   1610
   1611		if (in->width < bi->info.isp.sp.input.min_width ||
   1612		    in->width > bi->info.isp.sp.input.max_width ||
   1613		    in->height < bi->info.isp.sp.input.min_height ||
   1614		    in->height > bi->info.isp.sp.input.max_height)
   1615			continue;
   1616
   1617		if (imgu_css_queue_enabled(&queue[IPU3_CSS_QUEUE_OUT])) {
   1618			if (bi->info.isp.num_output_pins <= 0)
   1619				continue;
   1620
   1621			q_fmt = queue[IPU3_CSS_QUEUE_OUT].css_fmt->frame_format;
   1622			for (j = 0; j < bi->info.isp.num_output_formats; j++)
   1623				if (bi->info.isp.output_formats[j] == q_fmt)
   1624					break;
   1625			if (j >= bi->info.isp.num_output_formats)
   1626				continue;
   1627
   1628			if (out->width < bi->info.isp.sp.output.min_width ||
   1629			    out->width > bi->info.isp.sp.output.max_width ||
   1630			    out->height < bi->info.isp.sp.output.min_height ||
   1631			    out->height > bi->info.isp.sp.output.max_height)
   1632				continue;
   1633
   1634			if (out->width > bi->info.isp.sp.internal.max_width ||
   1635			    out->height > bi->info.isp.sp.internal.max_height)
   1636				continue;
   1637		}
   1638
   1639		if (imgu_css_queue_enabled(&queue[IPU3_CSS_QUEUE_VF])) {
   1640			if (bi->info.isp.num_output_pins <= 1)
   1641				continue;
   1642
   1643			q_fmt = queue[IPU3_CSS_QUEUE_VF].css_fmt->frame_format;
   1644			for (j = 0; j < bi->info.isp.num_output_formats; j++)
   1645				if (bi->info.isp.output_formats[j] == q_fmt)
   1646					break;
   1647			if (j >= bi->info.isp.num_output_formats)
   1648				continue;
   1649
   1650			if (vf->width < bi->info.isp.sp.output.min_width ||
   1651			    vf->width > bi->info.isp.sp.output.max_width ||
   1652			    vf->height < bi->info.isp.sp.output.min_height ||
   1653			    vf->height > bi->info.isp.sp.output.max_height)
   1654				continue;
   1655		}
   1656
   1657		/* All checks passed, select the binary */
   1658		dev_dbg(css->dev, "using binary %s id = %u\n", name,
   1659			bi->info.isp.sp.id);
   1660		return i;
   1661	}
   1662
   1663	/* Can not find suitable binary for these parameters */
   1664	return -EINVAL;
   1665}
   1666
   1667/*
   1668 * Check that there is a binary matching requirements. Parameters may be
   1669 * NULL indicating disabled input/output. Return negative if given
   1670 * parameters can not be supported or on error, zero or positive indicating
   1671 * found binary number. May modify the given parameters if not exact match
   1672 * is found.
   1673 */
   1674int imgu_css_fmt_try(struct imgu_css *css,
   1675		     struct v4l2_pix_format_mplane *fmts[IPU3_CSS_QUEUES],
   1676		     struct v4l2_rect *rects[IPU3_CSS_RECTS],
   1677		     unsigned int pipe)
   1678{
   1679	static const u32 EFF_ALIGN_W = 2;
   1680	static const u32 BDS_ALIGN_W = 4;
   1681	static const u32 OUT_ALIGN_W = 8;
   1682	static const u32 OUT_ALIGN_H = 4;
   1683	static const u32 VF_ALIGN_W  = 2;
   1684	static const char *qnames[IPU3_CSS_QUEUES] = {
   1685		[IPU3_CSS_QUEUE_IN] = "in",
   1686		[IPU3_CSS_QUEUE_PARAMS]    = "params",
   1687		[IPU3_CSS_QUEUE_OUT] = "out",
   1688		[IPU3_CSS_QUEUE_VF] = "vf",
   1689		[IPU3_CSS_QUEUE_STAT_3A]   = "3a",
   1690	};
   1691	static const char *rnames[IPU3_CSS_RECTS] = {
   1692		[IPU3_CSS_RECT_EFFECTIVE] = "effective resolution",
   1693		[IPU3_CSS_RECT_BDS]       = "bayer-domain scaled resolution",
   1694		[IPU3_CSS_RECT_ENVELOPE]  = "DVS envelope size",
   1695		[IPU3_CSS_RECT_GDC]  = "GDC output res",
   1696	};
   1697	struct v4l2_rect r[IPU3_CSS_RECTS] = { };
   1698	struct v4l2_rect *const eff = &r[IPU3_CSS_RECT_EFFECTIVE];
   1699	struct v4l2_rect *const bds = &r[IPU3_CSS_RECT_BDS];
   1700	struct v4l2_rect *const env = &r[IPU3_CSS_RECT_ENVELOPE];
   1701	struct v4l2_rect *const gdc = &r[IPU3_CSS_RECT_GDC];
   1702	struct imgu_css_queue *q;
   1703	struct v4l2_pix_format_mplane *in, *out, *vf;
   1704	int i, s, ret;
   1705
   1706	q = kcalloc(IPU3_CSS_QUEUES, sizeof(struct imgu_css_queue), GFP_KERNEL);
   1707	if (!q)
   1708		return -ENOMEM;
   1709
   1710	in  = &q[IPU3_CSS_QUEUE_IN].fmt.mpix;
   1711	out = &q[IPU3_CSS_QUEUE_OUT].fmt.mpix;
   1712	vf  = &q[IPU3_CSS_QUEUE_VF].fmt.mpix;
   1713
   1714	/* Adjust all formats, get statistics buffer sizes and formats */
   1715	for (i = 0; i < IPU3_CSS_QUEUES; i++) {
   1716		if (fmts[i])
   1717			dev_dbg(css->dev, "%s %s: (%i,%i) fmt 0x%x\n", __func__,
   1718				qnames[i], fmts[i]->width, fmts[i]->height,
   1719				fmts[i]->pixelformat);
   1720		else
   1721			dev_dbg(css->dev, "%s %s: (not set)\n", __func__,
   1722				qnames[i]);
   1723		if (imgu_css_queue_init(&q[i], fmts[i],
   1724					IPU3_CSS_QUEUE_TO_FLAGS(i))) {
   1725			dev_notice(css->dev, "can not initialize queue %s\n",
   1726				   qnames[i]);
   1727			ret = -EINVAL;
   1728			goto out;
   1729		}
   1730	}
   1731	for (i = 0; i < IPU3_CSS_RECTS; i++) {
   1732		if (rects[i]) {
   1733			dev_dbg(css->dev, "%s %s: (%i,%i)\n", __func__,
   1734				rnames[i], rects[i]->width, rects[i]->height);
   1735			r[i].width  = rects[i]->width;
   1736			r[i].height = rects[i]->height;
   1737		} else {
   1738			dev_dbg(css->dev, "%s %s: (not set)\n", __func__,
   1739				rnames[i]);
   1740		}
   1741		/* For now, force known good resolutions */
   1742		r[i].left = 0;
   1743		r[i].top  = 0;
   1744	}
   1745
   1746	/* Always require one input and vf only if out is also enabled */
   1747	if (!imgu_css_queue_enabled(&q[IPU3_CSS_QUEUE_IN]) ||
   1748	    !imgu_css_queue_enabled(&q[IPU3_CSS_QUEUE_OUT])) {
   1749		dev_warn(css->dev, "required queues are disabled\n");
   1750		ret = -EINVAL;
   1751		goto out;
   1752	}
   1753
   1754	if (!imgu_css_queue_enabled(&q[IPU3_CSS_QUEUE_OUT])) {
   1755		out->width = in->width;
   1756		out->height = in->height;
   1757	}
   1758	if (eff->width <= 0 || eff->height <= 0) {
   1759		eff->width = in->width;
   1760		eff->height = in->height;
   1761	}
   1762	if (bds->width <= 0 || bds->height <= 0) {
   1763		bds->width = out->width;
   1764		bds->height = out->height;
   1765	}
   1766	if (gdc->width <= 0 || gdc->height <= 0) {
   1767		gdc->width = out->width;
   1768		gdc->height = out->height;
   1769	}
   1770
   1771	in->width   = imgu_css_adjust(in->width, 1);
   1772	in->height  = imgu_css_adjust(in->height, 1);
   1773	eff->width  = imgu_css_adjust(eff->width, EFF_ALIGN_W);
   1774	eff->height = imgu_css_adjust(eff->height, 1);
   1775	bds->width  = imgu_css_adjust(bds->width, BDS_ALIGN_W);
   1776	bds->height = imgu_css_adjust(bds->height, 1);
   1777	gdc->width  = imgu_css_adjust(gdc->width, OUT_ALIGN_W);
   1778	gdc->height = imgu_css_adjust(gdc->height, OUT_ALIGN_H);
   1779	out->width  = imgu_css_adjust(out->width, OUT_ALIGN_W);
   1780	out->height = imgu_css_adjust(out->height, OUT_ALIGN_H);
   1781	vf->width   = imgu_css_adjust(vf->width, VF_ALIGN_W);
   1782	vf->height  = imgu_css_adjust(vf->height, 1);
   1783
   1784	s = (bds->width - gdc->width) / 2;
   1785	env->width = s < MIN_ENVELOPE ? MIN_ENVELOPE : s;
   1786	s = (bds->height - gdc->height) / 2;
   1787	env->height = s < MIN_ENVELOPE ? MIN_ENVELOPE : s;
   1788
   1789	ret = imgu_css_find_binary(css, pipe, q, r);
   1790	if (ret < 0) {
   1791		dev_err(css->dev, "failed to find suitable binary\n");
   1792		ret = -EINVAL;
   1793		goto out;
   1794	}
   1795	css->pipes[pipe].bindex = ret;
   1796
   1797	dev_dbg(css->dev, "Binary index %d for pipe %d found.",
   1798		css->pipes[pipe].bindex, pipe);
   1799
   1800	/* Final adjustment and set back the queried formats */
   1801	for (i = 0; i < IPU3_CSS_QUEUES; i++) {
   1802		if (fmts[i]) {
   1803			if (imgu_css_queue_init(&q[i], &q[i].fmt.mpix,
   1804						IPU3_CSS_QUEUE_TO_FLAGS(i))) {
   1805				dev_err(css->dev,
   1806					"final resolution adjustment failed\n");
   1807				ret = -EINVAL;
   1808				goto out;
   1809			}
   1810			*fmts[i] = q[i].fmt.mpix;
   1811		}
   1812	}
   1813
   1814	for (i = 0; i < IPU3_CSS_RECTS; i++)
   1815		if (rects[i])
   1816			*rects[i] = r[i];
   1817
   1818	dev_dbg(css->dev,
   1819		"in(%u,%u) if(%u,%u) ds(%u,%u) gdc(%u,%u) out(%u,%u) vf(%u,%u)",
   1820		 in->width, in->height, eff->width, eff->height,
   1821		 bds->width, bds->height, gdc->width, gdc->height,
   1822		 out->width, out->height, vf->width, vf->height);
   1823
   1824	ret = 0;
   1825out:
   1826	kfree(q);
   1827	return ret;
   1828}
   1829
   1830int imgu_css_fmt_set(struct imgu_css *css,
   1831		     struct v4l2_pix_format_mplane *fmts[IPU3_CSS_QUEUES],
   1832		     struct v4l2_rect *rects[IPU3_CSS_RECTS],
   1833		     unsigned int pipe)
   1834{
   1835	struct v4l2_rect rect_data[IPU3_CSS_RECTS];
   1836	struct v4l2_rect *all_rects[IPU3_CSS_RECTS];
   1837	int i, r;
   1838	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
   1839
   1840	for (i = 0; i < IPU3_CSS_RECTS; i++) {
   1841		if (rects[i])
   1842			rect_data[i] = *rects[i];
   1843		else
   1844			memset(&rect_data[i], 0, sizeof(rect_data[i]));
   1845		all_rects[i] = &rect_data[i];
   1846	}
   1847	r = imgu_css_fmt_try(css, fmts, all_rects, pipe);
   1848	if (r < 0)
   1849		return r;
   1850
   1851	for (i = 0; i < IPU3_CSS_QUEUES; i++)
   1852		if (imgu_css_queue_init(&css_pipe->queue[i], fmts[i],
   1853					IPU3_CSS_QUEUE_TO_FLAGS(i)))
   1854			return -EINVAL;
   1855	for (i = 0; i < IPU3_CSS_RECTS; i++) {
   1856		css_pipe->rect[i] = rect_data[i];
   1857		if (rects[i])
   1858			*rects[i] = rect_data[i];
   1859	}
   1860
   1861	return 0;
   1862}
   1863
   1864int imgu_css_meta_fmt_set(struct v4l2_meta_format *fmt)
   1865{
   1866	switch (fmt->dataformat) {
   1867	case V4L2_META_FMT_IPU3_PARAMS:
   1868		fmt->buffersize = sizeof(struct ipu3_uapi_params);
   1869
   1870		/*
   1871		 * Sanity check for the parameter struct size. This must
   1872		 * not change!
   1873		 */
   1874		BUILD_BUG_ON(sizeof(struct ipu3_uapi_params) != 39328);
   1875
   1876		break;
   1877	case V4L2_META_FMT_IPU3_STAT_3A:
   1878		fmt->buffersize = sizeof(struct ipu3_uapi_stats_3a);
   1879		break;
   1880	default:
   1881		return -EINVAL;
   1882	}
   1883
   1884	return 0;
   1885}
   1886
   1887/*
   1888 * Queue given buffer to CSS. imgu_css_buf_prepare() must have been first
   1889 * called for the buffer. May be called from interrupt context.
   1890 * Returns 0 on success, -EBUSY if the buffer queue is full, or some other
   1891 * code on error conditions.
   1892 */
   1893int imgu_css_buf_queue(struct imgu_css *css, unsigned int pipe,
   1894		       struct imgu_css_buffer *b)
   1895{
   1896	struct imgu_abi_buffer *abi_buf;
   1897	struct imgu_addr_t *buf_addr;
   1898	u32 data;
   1899	int r;
   1900	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
   1901
   1902	if (!css->streaming)
   1903		return -EPROTO;	/* CSS or buffer in wrong state */
   1904
   1905	if (b->queue >= IPU3_CSS_QUEUES || !imgu_css_queues[b->queue].qid)
   1906		return -EINVAL;
   1907
   1908	b->queue_pos = imgu_css_queue_pos(css, imgu_css_queues[b->queue].qid,
   1909					  pipe);
   1910
   1911	if (b->queue_pos >= ARRAY_SIZE(css->pipes[pipe].abi_buffers[b->queue]))
   1912		return -EIO;
   1913	abi_buf = css->pipes[pipe].abi_buffers[b->queue][b->queue_pos].vaddr;
   1914
   1915	/* Fill struct abi_buffer for firmware */
   1916	memset(abi_buf, 0, sizeof(*abi_buf));
   1917
   1918	buf_addr = (void *)abi_buf + imgu_css_queues[b->queue].ptr_ofs;
   1919	*(imgu_addr_t *)buf_addr = b->daddr;
   1920
   1921	if (b->queue == IPU3_CSS_QUEUE_STAT_3A)
   1922		abi_buf->payload.s3a.data.dmem.s3a_tbl = b->daddr;
   1923
   1924	if (b->queue == IPU3_CSS_QUEUE_OUT)
   1925		abi_buf->payload.frame.padded_width =
   1926				css_pipe->queue[IPU3_CSS_QUEUE_OUT].width_pad;
   1927
   1928	if (b->queue == IPU3_CSS_QUEUE_VF)
   1929		abi_buf->payload.frame.padded_width =
   1930					css_pipe->queue[IPU3_CSS_QUEUE_VF].width_pad;
   1931
   1932	spin_lock(&css_pipe->qlock);
   1933	list_add_tail(&b->list, &css_pipe->queue[b->queue].bufs);
   1934	spin_unlock(&css_pipe->qlock);
   1935	b->state = IPU3_CSS_BUFFER_QUEUED;
   1936
   1937	data = css->pipes[pipe].abi_buffers[b->queue][b->queue_pos].daddr;
   1938	r = imgu_css_queue_data(css, imgu_css_queues[b->queue].qid,
   1939				pipe, data);
   1940	if (r < 0)
   1941		goto queueing_failed;
   1942
   1943	data = IMGU_ABI_EVENT_BUFFER_ENQUEUED(pipe,
   1944					      imgu_css_queues[b->queue].qid);
   1945	r = imgu_css_queue_data(css, IMGU_ABI_QUEUE_EVENT_ID, pipe, data);
   1946	if (r < 0)
   1947		goto queueing_failed;
   1948
   1949	dev_dbg(css->dev, "queued buffer %p to css queue %i in pipe %d\n",
   1950		b, b->queue, pipe);
   1951
   1952	return 0;
   1953
   1954queueing_failed:
   1955	b->state = (r == -EBUSY || r == -EAGAIN) ?
   1956		IPU3_CSS_BUFFER_NEW : IPU3_CSS_BUFFER_FAILED;
   1957	list_del(&b->list);
   1958
   1959	return r;
   1960}
   1961
   1962/*
   1963 * Get next ready CSS buffer. Returns -EAGAIN in which case the function
   1964 * should be called again, or -EBUSY which means that there are no more
   1965 * buffers available. May be called from interrupt context.
   1966 */
   1967struct imgu_css_buffer *imgu_css_buf_dequeue(struct imgu_css *css)
   1968{
   1969	static const unsigned char evtype_to_queue[] = {
   1970		[IMGU_ABI_EVTTYPE_INPUT_FRAME_DONE] = IPU3_CSS_QUEUE_IN,
   1971		[IMGU_ABI_EVTTYPE_OUT_FRAME_DONE] = IPU3_CSS_QUEUE_OUT,
   1972		[IMGU_ABI_EVTTYPE_VF_OUT_FRAME_DONE] = IPU3_CSS_QUEUE_VF,
   1973		[IMGU_ABI_EVTTYPE_3A_STATS_DONE] = IPU3_CSS_QUEUE_STAT_3A,
   1974	};
   1975	struct imgu_css_buffer *b = ERR_PTR(-EAGAIN);
   1976	u32 event, daddr;
   1977	int evtype, pipe, pipeid, queue, qid, r;
   1978	struct imgu_css_pipe *css_pipe;
   1979
   1980	if (!css->streaming)
   1981		return ERR_PTR(-EPROTO);
   1982
   1983	r = imgu_css_dequeue_data(css, IMGU_ABI_QUEUE_EVENT_ID, &event);
   1984	if (r < 0)
   1985		return ERR_PTR(r);
   1986
   1987	evtype = (event & IMGU_ABI_EVTTYPE_EVENT_MASK) >>
   1988		  IMGU_ABI_EVTTYPE_EVENT_SHIFT;
   1989
   1990	switch (evtype) {
   1991	case IMGU_ABI_EVTTYPE_OUT_FRAME_DONE:
   1992	case IMGU_ABI_EVTTYPE_VF_OUT_FRAME_DONE:
   1993	case IMGU_ABI_EVTTYPE_3A_STATS_DONE:
   1994	case IMGU_ABI_EVTTYPE_INPUT_FRAME_DONE:
   1995		pipe = (event & IMGU_ABI_EVTTYPE_PIPE_MASK) >>
   1996			IMGU_ABI_EVTTYPE_PIPE_SHIFT;
   1997		pipeid = (event & IMGU_ABI_EVTTYPE_PIPEID_MASK) >>
   1998			IMGU_ABI_EVTTYPE_PIPEID_SHIFT;
   1999		queue = evtype_to_queue[evtype];
   2000		qid = imgu_css_queues[queue].qid;
   2001
   2002		if (pipe >= IMGU_MAX_PIPE_NUM) {
   2003			dev_err(css->dev, "Invalid pipe: %i\n", pipe);
   2004			return ERR_PTR(-EIO);
   2005		}
   2006
   2007		if (qid >= IMGU_ABI_QUEUE_NUM) {
   2008			dev_err(css->dev, "Invalid qid: %i\n", qid);
   2009			return ERR_PTR(-EIO);
   2010		}
   2011		css_pipe = &css->pipes[pipe];
   2012		dev_dbg(css->dev,
   2013			"event: buffer done 0x%x queue %i pipe %i pipeid %i\n",
   2014			event, queue, pipe, pipeid);
   2015
   2016		r = imgu_css_dequeue_data(css, qid, &daddr);
   2017		if (r < 0) {
   2018			dev_err(css->dev, "failed to dequeue buffer\n");
   2019			/* Force real error, not -EBUSY */
   2020			return ERR_PTR(-EIO);
   2021		}
   2022
   2023		r = imgu_css_queue_data(css, IMGU_ABI_QUEUE_EVENT_ID, pipe,
   2024					IMGU_ABI_EVENT_BUFFER_DEQUEUED(qid));
   2025		if (r < 0) {
   2026			dev_err(css->dev, "failed to queue event\n");
   2027			return ERR_PTR(-EIO);
   2028		}
   2029
   2030		spin_lock(&css_pipe->qlock);
   2031		if (list_empty(&css_pipe->queue[queue].bufs)) {
   2032			spin_unlock(&css_pipe->qlock);
   2033			dev_err(css->dev, "event on empty queue\n");
   2034			return ERR_PTR(-EIO);
   2035		}
   2036		b = list_first_entry(&css_pipe->queue[queue].bufs,
   2037				     struct imgu_css_buffer, list);
   2038		if (queue != b->queue ||
   2039		    daddr != css_pipe->abi_buffers
   2040			[b->queue][b->queue_pos].daddr) {
   2041			spin_unlock(&css_pipe->qlock);
   2042			dev_err(css->dev, "dequeued bad buffer 0x%x\n", daddr);
   2043			return ERR_PTR(-EIO);
   2044		}
   2045
   2046		dev_dbg(css->dev, "buffer 0x%8x done from pipe %d\n", daddr, pipe);
   2047		b->pipe = pipe;
   2048		b->state = IPU3_CSS_BUFFER_DONE;
   2049		list_del(&b->list);
   2050		spin_unlock(&css_pipe->qlock);
   2051		break;
   2052	case IMGU_ABI_EVTTYPE_PIPELINE_DONE:
   2053		pipe = (event & IMGU_ABI_EVTTYPE_PIPE_MASK) >>
   2054			IMGU_ABI_EVTTYPE_PIPE_SHIFT;
   2055		if (pipe >= IMGU_MAX_PIPE_NUM) {
   2056			dev_err(css->dev, "Invalid pipe: %i\n", pipe);
   2057			return ERR_PTR(-EIO);
   2058		}
   2059
   2060		css_pipe = &css->pipes[pipe];
   2061		dev_dbg(css->dev, "event: pipeline done 0x%8x for pipe %d\n",
   2062			event, pipe);
   2063		break;
   2064	case IMGU_ABI_EVTTYPE_TIMER:
   2065		r = imgu_css_dequeue_data(css, IMGU_ABI_QUEUE_EVENT_ID, &event);
   2066		if (r < 0)
   2067			return ERR_PTR(r);
   2068
   2069		if ((event & IMGU_ABI_EVTTYPE_EVENT_MASK) >>
   2070		    IMGU_ABI_EVTTYPE_EVENT_SHIFT == IMGU_ABI_EVTTYPE_TIMER)
   2071			dev_dbg(css->dev, "event: timer\n");
   2072		else
   2073			dev_warn(css->dev, "half of timer event missing\n");
   2074		break;
   2075	case IMGU_ABI_EVTTYPE_FW_WARNING:
   2076		dev_warn(css->dev, "event: firmware warning 0x%x\n", event);
   2077		break;
   2078	case IMGU_ABI_EVTTYPE_FW_ASSERT:
   2079		dev_err(css->dev,
   2080			"event: firmware assert 0x%x module_id %i line_no %i\n",
   2081			event,
   2082			(event & IMGU_ABI_EVTTYPE_MODULEID_MASK) >>
   2083			IMGU_ABI_EVTTYPE_MODULEID_SHIFT,
   2084			swab16((event & IMGU_ABI_EVTTYPE_LINENO_MASK) >>
   2085			       IMGU_ABI_EVTTYPE_LINENO_SHIFT));
   2086		break;
   2087	default:
   2088		dev_warn(css->dev, "received unknown event 0x%x\n", event);
   2089	}
   2090
   2091	return b;
   2092}
   2093
   2094/*
   2095 * Get a new set of parameters from pool and initialize them based on
   2096 * the parameters params, gdc, and obgrid. Any of these may be NULL,
   2097 * in which case the previously set parameters are used.
   2098 * If parameters haven't been set previously, initialize from scratch.
   2099 *
   2100 * Return index to css->parameter_set_info which has the newly created
   2101 * parameters or negative value on error.
   2102 */
   2103int imgu_css_set_parameters(struct imgu_css *css, unsigned int pipe,
   2104			    struct ipu3_uapi_params *set_params)
   2105{
   2106	static const unsigned int queue_id = IMGU_ABI_QUEUE_A_ID;
   2107	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
   2108	const int stage = 0;
   2109	const struct imgu_fw_info *bi;
   2110	int obgrid_size;
   2111	unsigned int stripes, i;
   2112	struct ipu3_uapi_flags *use = set_params ? &set_params->use : NULL;
   2113
   2114	/* Destination buffers which are filled here */
   2115	struct imgu_abi_parameter_set_info *param_set;
   2116	struct imgu_abi_acc_param *acc = NULL;
   2117	struct imgu_abi_gdc_warp_param *gdc = NULL;
   2118	struct ipu3_uapi_obgrid_param *obgrid = NULL;
   2119	const struct imgu_css_map *map;
   2120	void *vmem0 = NULL;
   2121	void *dmem0 = NULL;
   2122
   2123	enum imgu_abi_memories m;
   2124	int r = -EBUSY;
   2125
   2126	if (!css->streaming)
   2127		return -EPROTO;
   2128
   2129	dev_dbg(css->dev, "%s for pipe %d", __func__, pipe);
   2130
   2131	bi = &css->fwp->binary_header[css_pipe->bindex];
   2132	obgrid_size = imgu_css_fw_obgrid_size(bi);
   2133	stripes = bi->info.isp.sp.iterator.num_stripes ? : 1;
   2134
   2135	imgu_css_pool_get(&css_pipe->pool.parameter_set_info);
   2136	param_set = imgu_css_pool_last(&css_pipe->pool.parameter_set_info,
   2137				       0)->vaddr;
   2138
   2139	/* Get a new acc only if new parameters given, or none yet */
   2140	map = imgu_css_pool_last(&css_pipe->pool.acc, 0);
   2141	if (set_params || !map->vaddr) {
   2142		imgu_css_pool_get(&css_pipe->pool.acc);
   2143		map = imgu_css_pool_last(&css_pipe->pool.acc, 0);
   2144		acc = map->vaddr;
   2145	}
   2146
   2147	/* Get new VMEM0 only if needed, or none yet */
   2148	m = IMGU_ABI_MEM_ISP_VMEM0;
   2149	map = imgu_css_pool_last(&css_pipe->pool.binary_params_p[m], 0);
   2150	if (!map->vaddr || (set_params && (set_params->use.lin_vmem_params ||
   2151					   set_params->use.tnr3_vmem_params ||
   2152					   set_params->use.xnr3_vmem_params))) {
   2153		imgu_css_pool_get(&css_pipe->pool.binary_params_p[m]);
   2154		map = imgu_css_pool_last(&css_pipe->pool.binary_params_p[m], 0);
   2155		vmem0 = map->vaddr;
   2156	}
   2157
   2158	/* Get new DMEM0 only if needed, or none yet */
   2159	m = IMGU_ABI_MEM_ISP_DMEM0;
   2160	map = imgu_css_pool_last(&css_pipe->pool.binary_params_p[m], 0);
   2161	if (!map->vaddr || (set_params && (set_params->use.tnr3_dmem_params ||
   2162					   set_params->use.xnr3_dmem_params))) {
   2163		imgu_css_pool_get(&css_pipe->pool.binary_params_p[m]);
   2164		map = imgu_css_pool_last(&css_pipe->pool.binary_params_p[m], 0);
   2165		dmem0 = map->vaddr;
   2166	}
   2167
   2168	/* Configure acc parameter cluster */
   2169	if (acc) {
   2170		/* get acc_old */
   2171		map = imgu_css_pool_last(&css_pipe->pool.acc, 1);
   2172		/* user acc */
   2173		r = imgu_css_cfg_acc(css, pipe, use, acc, map->vaddr,
   2174			set_params ? &set_params->acc_param : NULL);
   2175		if (r < 0)
   2176			goto fail;
   2177	}
   2178
   2179	/* Configure late binding parameters */
   2180	if (vmem0) {
   2181		m = IMGU_ABI_MEM_ISP_VMEM0;
   2182		map = imgu_css_pool_last(&css_pipe->pool.binary_params_p[m], 1);
   2183		r = imgu_css_cfg_vmem0(css, pipe, use, vmem0,
   2184				       map->vaddr, set_params);
   2185		if (r < 0)
   2186			goto fail;
   2187	}
   2188
   2189	if (dmem0) {
   2190		m = IMGU_ABI_MEM_ISP_DMEM0;
   2191		map = imgu_css_pool_last(&css_pipe->pool.binary_params_p[m], 1);
   2192		r = imgu_css_cfg_dmem0(css, pipe, use, dmem0,
   2193				       map->vaddr, set_params);
   2194		if (r < 0)
   2195			goto fail;
   2196	}
   2197
   2198	/* Get a new gdc only if a new gdc is given, or none yet */
   2199	if (bi->info.isp.sp.enable.dvs_6axis) {
   2200		unsigned int a = IPU3_CSS_AUX_FRAME_REF;
   2201		unsigned int g = IPU3_CSS_RECT_GDC;
   2202		unsigned int e = IPU3_CSS_RECT_ENVELOPE;
   2203
   2204		map = imgu_css_pool_last(&css_pipe->pool.gdc, 0);
   2205		if (!map->vaddr) {
   2206			imgu_css_pool_get(&css_pipe->pool.gdc);
   2207			map = imgu_css_pool_last(&css_pipe->pool.gdc, 0);
   2208			gdc = map->vaddr;
   2209			imgu_css_cfg_gdc_table(map->vaddr,
   2210				css_pipe->aux_frames[a].bytesperline /
   2211				css_pipe->aux_frames[a].bytesperpixel,
   2212				css_pipe->aux_frames[a].height,
   2213				css_pipe->rect[g].width,
   2214				css_pipe->rect[g].height,
   2215				css_pipe->rect[e].width,
   2216				css_pipe->rect[e].height);
   2217		}
   2218	}
   2219
   2220	/* Get a new obgrid only if a new obgrid is given, or none yet */
   2221	map = imgu_css_pool_last(&css_pipe->pool.obgrid, 0);
   2222	if (!map->vaddr || (set_params && set_params->use.obgrid_param)) {
   2223		imgu_css_pool_get(&css_pipe->pool.obgrid);
   2224		map = imgu_css_pool_last(&css_pipe->pool.obgrid, 0);
   2225		obgrid = map->vaddr;
   2226
   2227		/* Configure optical black level grid (obgrid) */
   2228		if (set_params && set_params->use.obgrid_param)
   2229			for (i = 0; i < obgrid_size / sizeof(*obgrid); i++)
   2230				obgrid[i] = set_params->obgrid_param;
   2231		else
   2232			memset(obgrid, 0, obgrid_size);
   2233	}
   2234
   2235	/* Configure parameter set info, queued to `queue_id' */
   2236
   2237	memset(param_set, 0, sizeof(*param_set));
   2238	map = imgu_css_pool_last(&css_pipe->pool.acc, 0);
   2239	param_set->mem_map.acc_cluster_params_for_sp = map->daddr;
   2240
   2241	map = imgu_css_pool_last(&css_pipe->pool.gdc, 0);
   2242	param_set->mem_map.dvs_6axis_params_y = map->daddr;
   2243
   2244	for (i = 0; i < stripes; i++) {
   2245		map = imgu_css_pool_last(&css_pipe->pool.obgrid, 0);
   2246		param_set->mem_map.obgrid_tbl[i] =
   2247			map->daddr + (obgrid_size / stripes) * i;
   2248	}
   2249
   2250	for (m = 0; m < IMGU_ABI_NUM_MEMORIES; m++) {
   2251		map = imgu_css_pool_last(&css_pipe->pool.binary_params_p[m], 0);
   2252		param_set->mem_map.isp_mem_param[stage][m] = map->daddr;
   2253	}
   2254
   2255	/* Then queue the new parameter buffer */
   2256	map = imgu_css_pool_last(&css_pipe->pool.parameter_set_info, 0);
   2257	r = imgu_css_queue_data(css, queue_id, pipe, map->daddr);
   2258	if (r < 0)
   2259		goto fail;
   2260
   2261	r = imgu_css_queue_data(css, IMGU_ABI_QUEUE_EVENT_ID, pipe,
   2262				IMGU_ABI_EVENT_BUFFER_ENQUEUED(pipe,
   2263							       queue_id));
   2264	if (r < 0)
   2265		goto fail_no_put;
   2266
   2267	/* Finally dequeue all old parameter buffers */
   2268
   2269	do {
   2270		u32 daddr;
   2271
   2272		r = imgu_css_dequeue_data(css, queue_id, &daddr);
   2273		if (r == -EBUSY)
   2274			break;
   2275		if (r)
   2276			goto fail_no_put;
   2277		r = imgu_css_queue_data(css, IMGU_ABI_QUEUE_EVENT_ID, pipe,
   2278					IMGU_ABI_EVENT_BUFFER_DEQUEUED
   2279					(queue_id));
   2280		if (r < 0) {
   2281			dev_err(css->dev, "failed to queue parameter event\n");
   2282			goto fail_no_put;
   2283		}
   2284	} while (1);
   2285
   2286	return 0;
   2287
   2288fail:
   2289	/*
   2290	 * A failure, most likely the parameter queue was full.
   2291	 * Return error but continue streaming. User can try submitting new
   2292	 * parameters again later.
   2293	 */
   2294
   2295	imgu_css_pool_put(&css_pipe->pool.parameter_set_info);
   2296	if (acc)
   2297		imgu_css_pool_put(&css_pipe->pool.acc);
   2298	if (gdc)
   2299		imgu_css_pool_put(&css_pipe->pool.gdc);
   2300	if (obgrid)
   2301		imgu_css_pool_put(&css_pipe->pool.obgrid);
   2302	if (vmem0)
   2303		imgu_css_pool_put(
   2304			&css_pipe->pool.binary_params_p
   2305			[IMGU_ABI_MEM_ISP_VMEM0]);
   2306	if (dmem0)
   2307		imgu_css_pool_put(
   2308			&css_pipe->pool.binary_params_p
   2309			[IMGU_ABI_MEM_ISP_DMEM0]);
   2310
   2311fail_no_put:
   2312	return r;
   2313}
   2314
   2315int imgu_css_irq_ack(struct imgu_css *css)
   2316{
   2317	static const int NUM_SWIRQS = 3;
   2318	struct imgu_fw_info *bi = &css->fwp->binary_header[css->fw_sp[0]];
   2319	void __iomem *const base = css->base;
   2320	u32 irq_status[IMGU_IRQCTRL_NUM];
   2321	int i;
   2322
   2323	u32 imgu_status = readl(base + IMGU_REG_INT_STATUS);
   2324
   2325	writel(imgu_status, base + IMGU_REG_INT_STATUS);
   2326	for (i = 0; i < IMGU_IRQCTRL_NUM; i++)
   2327		irq_status[i] = readl(base + IMGU_REG_IRQCTRL_STATUS(i));
   2328
   2329	for (i = 0; i < NUM_SWIRQS; i++) {
   2330		if (irq_status[IMGU_IRQCTRL_SP0] & IMGU_IRQCTRL_IRQ_SW_PIN(i)) {
   2331			/* SP SW interrupt */
   2332			u32 cnt = readl(base + IMGU_REG_SP_DMEM_BASE(0) +
   2333					bi->info.sp.output);
   2334			u32 val = readl(base + IMGU_REG_SP_DMEM_BASE(0) +
   2335					bi->info.sp.output + 4 + 4 * i);
   2336
   2337			dev_dbg(css->dev, "%s: swirq %i cnt %i val 0x%x\n",
   2338				__func__, i, cnt, val);
   2339		}
   2340	}
   2341
   2342	for (i = IMGU_IRQCTRL_NUM - 1; i >= 0; i--)
   2343		if (irq_status[i]) {
   2344			writel(irq_status[i], base + IMGU_REG_IRQCTRL_CLEAR(i));
   2345			/* Wait for write to complete */
   2346			readl(base + IMGU_REG_IRQCTRL_ENABLE(i));
   2347		}
   2348
   2349	dev_dbg(css->dev, "%s: imgu 0x%x main 0x%x sp0 0x%x sp1 0x%x\n",
   2350		__func__, imgu_status, irq_status[IMGU_IRQCTRL_MAIN],
   2351		irq_status[IMGU_IRQCTRL_SP0], irq_status[IMGU_IRQCTRL_SP1]);
   2352
   2353	if (!imgu_status && !irq_status[IMGU_IRQCTRL_MAIN])
   2354		return -ENOMSG;
   2355
   2356	return 0;
   2357}