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