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