0001
0002
0003
0004 #include <linux/device.h>
0005 #include <linux/iopoll.h>
0006 #include <linux/slab.h>
0007
0008 #include "ipu3.h"
0009 #include "ipu3-css.h"
0010 #include "ipu3-css-fw.h"
0011 #include "ipu3-css-params.h"
0012 #include "ipu3-dmamap.h"
0013 #include "ipu3-tables.h"
0014
0015
0016 #define IMGU_IRQCTRL_IRQ_MASK (IMGU_IRQCTRL_IRQ_SP1 | \
0017 IMGU_IRQCTRL_IRQ_SP2 | \
0018 IMGU_IRQCTRL_IRQ_SW_PIN(0) | \
0019 IMGU_IRQCTRL_IRQ_SW_PIN(1))
0020
0021 #define IPU3_CSS_FORMAT_BPP_DEN 50
0022
0023
0024 #define IPU3_CSS_MIN_RES 32
0025 #define IPU3_CSS_MAX_H 3136
0026 #define IPU3_CSS_MAX_W 4224
0027
0028
0029 #define MIN_ENVELOPE 4
0030
0031
0032
0033
0034
0035
0036
0037 #define CSS_ABI_SIZE 136
0038 #define CSS_BDS_SIZE (4480 * 3200 * 3)
0039 #define CSS_GDC_SIZE (4224 * 3200 * 12 / 8)
0040
0041 #define IPU3_CSS_QUEUE_TO_FLAGS(q) (1 << (q))
0042 #define IPU3_CSS_FORMAT_FL_IN \
0043 IPU3_CSS_QUEUE_TO_FLAGS(IPU3_CSS_QUEUE_IN)
0044 #define IPU3_CSS_FORMAT_FL_OUT \
0045 IPU3_CSS_QUEUE_TO_FLAGS(IPU3_CSS_QUEUE_OUT)
0046 #define IPU3_CSS_FORMAT_FL_VF \
0047 IPU3_CSS_QUEUE_TO_FLAGS(IPU3_CSS_QUEUE_VF)
0048
0049
0050 static const struct imgu_css_format imgu_css_formats[] = {
0051 {
0052 .pixelformat = V4L2_PIX_FMT_NV12,
0053 .colorspace = V4L2_COLORSPACE_SRGB,
0054 .frame_format = IMGU_ABI_FRAME_FORMAT_NV12,
0055 .osys_format = IMGU_ABI_OSYS_FORMAT_NV12,
0056 .osys_tiling = IMGU_ABI_OSYS_TILING_NONE,
0057 .chroma_decim = 4,
0058 .width_align = IPU3_UAPI_ISP_VEC_ELEMS,
0059 .flags = IPU3_CSS_FORMAT_FL_OUT | IPU3_CSS_FORMAT_FL_VF,
0060 }, {
0061
0062 .pixelformat = V4L2_PIX_FMT_IPU3_SBGGR10,
0063 .colorspace = V4L2_COLORSPACE_RAW,
0064 .frame_format = IMGU_ABI_FRAME_FORMAT_RAW_PACKED,
0065 .bayer_order = IMGU_ABI_BAYER_ORDER_BGGR,
0066 .bit_depth = 10,
0067 .width_align = 2 * IPU3_UAPI_ISP_VEC_ELEMS,
0068 .flags = IPU3_CSS_FORMAT_FL_IN,
0069 }, {
0070 .pixelformat = V4L2_PIX_FMT_IPU3_SGBRG10,
0071 .colorspace = V4L2_COLORSPACE_RAW,
0072 .frame_format = IMGU_ABI_FRAME_FORMAT_RAW_PACKED,
0073 .bayer_order = IMGU_ABI_BAYER_ORDER_GBRG,
0074 .bit_depth = 10,
0075 .width_align = 2 * IPU3_UAPI_ISP_VEC_ELEMS,
0076 .flags = IPU3_CSS_FORMAT_FL_IN,
0077 }, {
0078 .pixelformat = V4L2_PIX_FMT_IPU3_SGRBG10,
0079 .colorspace = V4L2_COLORSPACE_RAW,
0080 .frame_format = IMGU_ABI_FRAME_FORMAT_RAW_PACKED,
0081 .bayer_order = IMGU_ABI_BAYER_ORDER_GRBG,
0082 .bit_depth = 10,
0083 .width_align = 2 * IPU3_UAPI_ISP_VEC_ELEMS,
0084 .flags = IPU3_CSS_FORMAT_FL_IN,
0085 }, {
0086 .pixelformat = V4L2_PIX_FMT_IPU3_SRGGB10,
0087 .colorspace = V4L2_COLORSPACE_RAW,
0088 .frame_format = IMGU_ABI_FRAME_FORMAT_RAW_PACKED,
0089 .bayer_order = IMGU_ABI_BAYER_ORDER_RGGB,
0090 .bit_depth = 10,
0091 .width_align = 2 * IPU3_UAPI_ISP_VEC_ELEMS,
0092 .flags = IPU3_CSS_FORMAT_FL_IN,
0093 },
0094 };
0095
0096 static const struct {
0097 enum imgu_abi_queue_id qid;
0098 size_t ptr_ofs;
0099 } imgu_css_queues[IPU3_CSS_QUEUES] = {
0100 [IPU3_CSS_QUEUE_IN] = {
0101 IMGU_ABI_QUEUE_C_ID,
0102 offsetof(struct imgu_abi_buffer, payload.frame.frame_data)
0103 },
0104 [IPU3_CSS_QUEUE_OUT] = {
0105 IMGU_ABI_QUEUE_D_ID,
0106 offsetof(struct imgu_abi_buffer, payload.frame.frame_data)
0107 },
0108 [IPU3_CSS_QUEUE_VF] = {
0109 IMGU_ABI_QUEUE_E_ID,
0110 offsetof(struct imgu_abi_buffer, payload.frame.frame_data)
0111 },
0112 [IPU3_CSS_QUEUE_STAT_3A] = {
0113 IMGU_ABI_QUEUE_F_ID,
0114 offsetof(struct imgu_abi_buffer, payload.s3a.data_ptr)
0115 },
0116 };
0117
0118
0119 static int imgu_css_queue_init(struct imgu_css_queue *queue,
0120 struct v4l2_pix_format_mplane *fmt, u32 flags)
0121 {
0122 struct v4l2_pix_format_mplane *const f = &queue->fmt.mpix;
0123 unsigned int i;
0124 u32 sizeimage;
0125
0126 INIT_LIST_HEAD(&queue->bufs);
0127
0128 queue->css_fmt = NULL;
0129 if (!fmt)
0130 return 0;
0131
0132 for (i = 0; i < ARRAY_SIZE(imgu_css_formats); i++) {
0133 if (!(imgu_css_formats[i].flags & flags))
0134 continue;
0135 queue->css_fmt = &imgu_css_formats[i];
0136 if (imgu_css_formats[i].pixelformat == fmt->pixelformat)
0137 break;
0138 }
0139 if (!queue->css_fmt)
0140 return -EINVAL;
0141
0142 queue->fmt.mpix = *fmt;
0143
0144 f->width = ALIGN(clamp_t(u32, f->width,
0145 IPU3_CSS_MIN_RES, IPU3_CSS_MAX_W), 2);
0146 f->height = ALIGN(clamp_t(u32, f->height,
0147 IPU3_CSS_MIN_RES, IPU3_CSS_MAX_H), 2);
0148 queue->width_pad = ALIGN(f->width, queue->css_fmt->width_align);
0149 f->plane_fmt[0].bytesperline =
0150 imgu_bytesperline(f->width, queue->css_fmt->frame_format);
0151 sizeimage = f->height * f->plane_fmt[0].bytesperline;
0152 if (queue->css_fmt->chroma_decim)
0153 sizeimage += 2 * sizeimage / queue->css_fmt->chroma_decim;
0154
0155 f->plane_fmt[0].sizeimage = sizeimage;
0156 f->field = V4L2_FIELD_NONE;
0157 f->num_planes = 1;
0158 f->colorspace = queue->css_fmt->colorspace;
0159 f->flags = 0;
0160 f->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
0161 f->quantization = V4L2_QUANTIZATION_DEFAULT;
0162 f->xfer_func = V4L2_XFER_FUNC_DEFAULT;
0163 memset(f->reserved, 0, sizeof(f->reserved));
0164
0165 return 0;
0166 }
0167
0168 static bool imgu_css_queue_enabled(struct imgu_css_queue *q)
0169 {
0170 return q->css_fmt;
0171 }
0172
0173
0174
0175
0176 static inline void writes(const void *mem, ssize_t count, void __iomem *addr)
0177 {
0178 if (count >= 4) {
0179 const u32 *buf = mem;
0180
0181 count /= 4;
0182 do {
0183 writel(*buf++, addr);
0184 addr += 4;
0185 } while (--count);
0186 }
0187 }
0188
0189
0190 static int imgu_hw_wait(void __iomem *base, int reg, u32 mask, u32 cmp)
0191 {
0192 u32 val;
0193
0194 return readl_poll_timeout(base + reg, val, (val & mask) == cmp,
0195 1000, 100 * 1000);
0196 }
0197
0198
0199
0200 int imgu_css_set_powerup(struct device *dev, void __iomem *base,
0201 unsigned int freq)
0202 {
0203 u32 pm_ctrl, state, val;
0204
0205 dev_dbg(dev, "%s with freq %u\n", __func__, freq);
0206
0207 readl(base + IMGU_REG_GP_BUSY);
0208 writel(0, base + IMGU_REG_GP_BUSY);
0209
0210
0211 if (imgu_hw_wait(base, IMGU_REG_STATE, IMGU_STATE_IDLE_STS,
0212 IMGU_STATE_IDLE_STS)) {
0213 dev_err(dev, "failed to set CSS idle\n");
0214 goto fail;
0215 }
0216
0217
0218 writel(readl(base + IMGU_REG_PM_CTRL) | IMGU_PM_CTRL_FORCE_RESET,
0219 base + IMGU_REG_PM_CTRL);
0220
0221 usleep_range(200, 300);
0222
0223
0224
0225 pm_ctrl = readl(base + IMGU_REG_PM_CTRL);
0226 state = readl(base + IMGU_REG_STATE);
0227
0228 dev_dbg(dev, "CSS pm_ctrl 0x%x state 0x%x (power %s)\n",
0229 pm_ctrl, state, state & IMGU_STATE_POWER_DOWN ? "down" : "up");
0230
0231
0232 if (state & IMGU_STATE_POWER_DOWN) {
0233 writel(IMGU_PM_CTRL_RACE_TO_HALT | IMGU_PM_CTRL_START,
0234 base + IMGU_REG_PM_CTRL);
0235 if (imgu_hw_wait(base, IMGU_REG_PM_CTRL,
0236 IMGU_PM_CTRL_START, 0)) {
0237 dev_err(dev, "failed to power up CSS\n");
0238 goto fail;
0239 }
0240 usleep_range(2000, 3000);
0241 } else {
0242 writel(IMGU_PM_CTRL_RACE_TO_HALT, base + IMGU_REG_PM_CTRL);
0243 }
0244
0245
0246 writel(readl(base + IMGU_REG_GP_BUSY) | 1, base + IMGU_REG_GP_BUSY);
0247
0248
0249 pm_ctrl = readl(base + IMGU_REG_PM_CTRL);
0250 val = pm_ctrl & ~(IMGU_PM_CTRL_CSS_PWRDN | IMGU_PM_CTRL_RST_AT_EOF);
0251 writel(val, base + IMGU_REG_PM_CTRL);
0252 writel(0, base + IMGU_REG_GP_BUSY);
0253 if (imgu_hw_wait(base, IMGU_REG_STATE,
0254 IMGU_STATE_PWRDNM_FSM_MASK, 0)) {
0255 dev_err(dev, "failed to pwrdn CSS\n");
0256 goto fail;
0257 }
0258 val = (freq / IMGU_SYSTEM_REQ_FREQ_DIVIDER) & IMGU_SYSTEM_REQ_FREQ_MASK;
0259 writel(val, base + IMGU_REG_SYSTEM_REQ);
0260 writel(1, base + IMGU_REG_GP_BUSY);
0261 writel(readl(base + IMGU_REG_PM_CTRL) | IMGU_PM_CTRL_FORCE_HALT,
0262 base + IMGU_REG_PM_CTRL);
0263 if (imgu_hw_wait(base, IMGU_REG_STATE, IMGU_STATE_HALT_STS,
0264 IMGU_STATE_HALT_STS)) {
0265 dev_err(dev, "failed to halt CSS\n");
0266 goto fail;
0267 }
0268
0269 writel(readl(base + IMGU_REG_PM_CTRL) | IMGU_PM_CTRL_START,
0270 base + IMGU_REG_PM_CTRL);
0271 if (imgu_hw_wait(base, IMGU_REG_PM_CTRL, IMGU_PM_CTRL_START, 0)) {
0272 dev_err(dev, "failed to start CSS\n");
0273 goto fail;
0274 }
0275 writel(readl(base + IMGU_REG_PM_CTRL) | IMGU_PM_CTRL_FORCE_UNHALT,
0276 base + IMGU_REG_PM_CTRL);
0277
0278 val = readl(base + IMGU_REG_PM_CTRL);
0279 val &= ~(IMGU_PM_CTRL_CSS_PWRDN | IMGU_PM_CTRL_RST_AT_EOF);
0280 val |= pm_ctrl & (IMGU_PM_CTRL_CSS_PWRDN | IMGU_PM_CTRL_RST_AT_EOF);
0281 writel(val, base + IMGU_REG_PM_CTRL);
0282
0283 return 0;
0284
0285 fail:
0286 imgu_css_set_powerdown(dev, base);
0287 return -EIO;
0288 }
0289
0290 void imgu_css_set_powerdown(struct device *dev, void __iomem *base)
0291 {
0292 dev_dbg(dev, "%s\n", __func__);
0293
0294 if (imgu_hw_wait(base, IMGU_REG_CIO_GATE_BURST_STATE,
0295 IMGU_CIO_GATE_BURST_MASK, 0))
0296 dev_warn(dev, "wait cio gate idle timeout");
0297
0298
0299 if (imgu_hw_wait(base, IMGU_REG_STATE, IMGU_STATE_IDLE_STS,
0300 IMGU_STATE_IDLE_STS))
0301 dev_warn(dev, "wait css idle timeout\n");
0302
0303
0304 writel(1, base + IMGU_REG_GP_HALT);
0305 if (imgu_hw_wait(base, IMGU_REG_STATE, IMGU_STATE_HALT_STS,
0306 IMGU_STATE_HALT_STS))
0307 dev_warn(dev, "failed to halt css");
0308
0309
0310 writel(0, base + IMGU_REG_GP_BUSY);
0311 }
0312
0313 static void imgu_css_hw_enable_irq(struct imgu_css *css)
0314 {
0315 void __iomem *const base = css->base;
0316 u32 val, i;
0317
0318
0319
0320
0321
0322
0323
0324 val = readl(base + IMGU_REG_SP_CTRL(0)) | IMGU_CTRL_IRQ_READY;
0325 writel(val, base + IMGU_REG_SP_CTRL(0));
0326 writel(val | IMGU_CTRL_IRQ_CLEAR, base + IMGU_REG_SP_CTRL(0));
0327
0328
0329 writel(IMGU_REG_INT_CSS_IRQ, base + IMGU_REG_INT_ENABLE);
0330
0331 writel(IMGU_REG_INT_CSS_IRQ, base + IMGU_REG_INT_STATUS);
0332
0333
0334 writel(~0, base + IMGU_REG_IRQCTRL_EDGE_NOT_PULSE(IMGU_IRQCTRL_MAIN));
0335 writel(0, base + IMGU_REG_IRQCTRL_MASK(IMGU_IRQCTRL_MAIN));
0336 writel(IMGU_IRQCTRL_IRQ_MASK,
0337 base + IMGU_REG_IRQCTRL_EDGE(IMGU_IRQCTRL_MAIN));
0338 writel(IMGU_IRQCTRL_IRQ_MASK,
0339 base + IMGU_REG_IRQCTRL_ENABLE(IMGU_IRQCTRL_MAIN));
0340 writel(IMGU_IRQCTRL_IRQ_MASK,
0341 base + IMGU_REG_IRQCTRL_CLEAR(IMGU_IRQCTRL_MAIN));
0342 writel(IMGU_IRQCTRL_IRQ_MASK,
0343 base + IMGU_REG_IRQCTRL_MASK(IMGU_IRQCTRL_MAIN));
0344
0345 readl(base + IMGU_REG_IRQCTRL_ENABLE(IMGU_IRQCTRL_MAIN));
0346
0347
0348 for (i = IMGU_IRQCTRL_SP0; i <= IMGU_IRQCTRL_SP1; i++) {
0349 writel(~0, base + IMGU_REG_IRQCTRL_EDGE_NOT_PULSE(i));
0350 writel(0, base + IMGU_REG_IRQCTRL_MASK(i));
0351 writel(IMGU_IRQCTRL_IRQ_MASK, base + IMGU_REG_IRQCTRL_EDGE(i));
0352 writel(IMGU_IRQCTRL_IRQ_MASK,
0353 base + IMGU_REG_IRQCTRL_ENABLE(i));
0354 writel(IMGU_IRQCTRL_IRQ_MASK, base + IMGU_REG_IRQCTRL_CLEAR(i));
0355 writel(IMGU_IRQCTRL_IRQ_MASK, base + IMGU_REG_IRQCTRL_MASK(i));
0356
0357 readl(base + IMGU_REG_IRQCTRL_ENABLE(i));
0358 }
0359 }
0360
0361 static int imgu_css_hw_init(struct imgu_css *css)
0362 {
0363
0364 static const struct {
0365 u32 reg;
0366 u32 mask;
0367 const char *name;
0368 } stream_monitors[] = {
0369 {
0370 IMGU_REG_GP_SP1_STRMON_STAT,
0371 IMGU_GP_STRMON_STAT_ISP_PORT_SP12ISP,
0372 "ISP0 to SP0"
0373 }, {
0374 IMGU_REG_GP_ISP_STRMON_STAT,
0375 IMGU_GP_STRMON_STAT_SP1_PORT_ISP2SP1,
0376 "SP0 to ISP0"
0377 }, {
0378 IMGU_REG_GP_MOD_STRMON_STAT,
0379 IMGU_GP_STRMON_STAT_MOD_PORT_ISP2DMA,
0380 "ISP0 to DMA0"
0381 }, {
0382 IMGU_REG_GP_ISP_STRMON_STAT,
0383 IMGU_GP_STRMON_STAT_ISP_PORT_DMA2ISP,
0384 "DMA0 to ISP0"
0385 }, {
0386 IMGU_REG_GP_MOD_STRMON_STAT,
0387 IMGU_GP_STRMON_STAT_MOD_PORT_CELLS2GDC,
0388 "ISP0 to GDC0"
0389 }, {
0390 IMGU_REG_GP_MOD_STRMON_STAT,
0391 IMGU_GP_STRMON_STAT_MOD_PORT_GDC2CELLS,
0392 "GDC0 to ISP0"
0393 }, {
0394 IMGU_REG_GP_MOD_STRMON_STAT,
0395 IMGU_GP_STRMON_STAT_MOD_PORT_SP12DMA,
0396 "SP0 to DMA0"
0397 }, {
0398 IMGU_REG_GP_SP1_STRMON_STAT,
0399 IMGU_GP_STRMON_STAT_SP1_PORT_DMA2SP1,
0400 "DMA0 to SP0"
0401 }, {
0402 IMGU_REG_GP_MOD_STRMON_STAT,
0403 IMGU_GP_STRMON_STAT_MOD_PORT_CELLS2GDC,
0404 "SP0 to GDC0"
0405 }, {
0406 IMGU_REG_GP_MOD_STRMON_STAT,
0407 IMGU_GP_STRMON_STAT_MOD_PORT_GDC2CELLS,
0408 "GDC0 to SP0"
0409 },
0410 };
0411
0412 struct device *dev = css->dev;
0413 void __iomem *const base = css->base;
0414 u32 val, i;
0415
0416
0417 for (i = 0; i < IMGU_NUM_SP; i++) {
0418 struct imgu_fw_info *bi =
0419 &css->fwp->binary_header[css->fw_sp[i]];
0420
0421 writel(css->binary[css->fw_sp[i]].daddr,
0422 base + IMGU_REG_SP_ICACHE_ADDR(bi->type));
0423 writel(readl(base + IMGU_REG_SP_CTRL(bi->type)) |
0424 IMGU_CTRL_ICACHE_INV,
0425 base + IMGU_REG_SP_CTRL(bi->type));
0426 }
0427 writel(css->binary[css->fw_bl].daddr, base + IMGU_REG_ISP_ICACHE_ADDR);
0428 writel(readl(base + IMGU_REG_ISP_CTRL) | IMGU_CTRL_ICACHE_INV,
0429 base + IMGU_REG_ISP_CTRL);
0430
0431
0432
0433 if (!(readl(base + IMGU_REG_SP_CTRL(0)) & IMGU_CTRL_IDLE)) {
0434 dev_err(dev, "SP is not idle\n");
0435 return -EIO;
0436 }
0437 if (!(readl(base + IMGU_REG_ISP_CTRL) & IMGU_CTRL_IDLE)) {
0438 dev_err(dev, "ISP is not idle\n");
0439 return -EIO;
0440 }
0441
0442 for (i = 0; i < ARRAY_SIZE(stream_monitors); i++) {
0443 val = readl(base + stream_monitors[i].reg);
0444 if (val & stream_monitors[i].mask) {
0445 dev_err(dev, "error: Stream monitor %s is valid\n",
0446 stream_monitors[i].name);
0447 return -EIO;
0448 }
0449 }
0450
0451
0452
0453 for (i = 0; i < ARRAY_SIZE(imgu_css_gdc_lut[0]); i++) {
0454 u32 val0 = imgu_css_gdc_lut[0][i] & IMGU_GDC_LUT_MASK;
0455 u32 val1 = imgu_css_gdc_lut[1][i] & IMGU_GDC_LUT_MASK;
0456 u32 val2 = imgu_css_gdc_lut[2][i] & IMGU_GDC_LUT_MASK;
0457 u32 val3 = imgu_css_gdc_lut[3][i] & IMGU_GDC_LUT_MASK;
0458
0459 writel(val0 | (val1 << 16),
0460 base + IMGU_REG_GDC_LUT_BASE + i * 8);
0461 writel(val2 | (val3 << 16),
0462 base + IMGU_REG_GDC_LUT_BASE + i * 8 + 4);
0463 }
0464
0465 return 0;
0466 }
0467
0468
0469 static int imgu_css_hw_start_sp(struct imgu_css *css, int sp)
0470 {
0471 void __iomem *const base = css->base;
0472 struct imgu_fw_info *bi = &css->fwp->binary_header[css->fw_sp[sp]];
0473 struct imgu_abi_sp_init_dmem_cfg dmem_cfg = {
0474 .ddr_data_addr = css->binary[css->fw_sp[sp]].daddr
0475 + bi->blob.data_source,
0476 .dmem_data_addr = bi->blob.data_target,
0477 .dmem_bss_addr = bi->blob.bss_target,
0478 .data_size = bi->blob.data_size,
0479 .bss_size = bi->blob.bss_size,
0480 .sp_id = sp,
0481 };
0482
0483 writes(&dmem_cfg, sizeof(dmem_cfg), base +
0484 IMGU_REG_SP_DMEM_BASE(sp) + bi->info.sp.init_dmem_data);
0485
0486 writel(bi->info.sp.sp_entry, base + IMGU_REG_SP_START_ADDR(sp));
0487
0488 writel(readl(base + IMGU_REG_SP_CTRL(sp))
0489 | IMGU_CTRL_START | IMGU_CTRL_RUN, base + IMGU_REG_SP_CTRL(sp));
0490
0491 if (imgu_hw_wait(css->base, IMGU_REG_SP_DMEM_BASE(sp)
0492 + bi->info.sp.sw_state,
0493 ~0, IMGU_ABI_SP_SWSTATE_INITIALIZED))
0494 return -EIO;
0495
0496 return 0;
0497 }
0498
0499
0500 static int imgu_css_hw_start(struct imgu_css *css)
0501 {
0502 static const u32 event_mask =
0503 ((1 << IMGU_ABI_EVTTYPE_OUT_FRAME_DONE) |
0504 (1 << IMGU_ABI_EVTTYPE_2ND_OUT_FRAME_DONE) |
0505 (1 << IMGU_ABI_EVTTYPE_VF_OUT_FRAME_DONE) |
0506 (1 << IMGU_ABI_EVTTYPE_2ND_VF_OUT_FRAME_DONE) |
0507 (1 << IMGU_ABI_EVTTYPE_3A_STATS_DONE) |
0508 (1 << IMGU_ABI_EVTTYPE_DIS_STATS_DONE) |
0509 (1 << IMGU_ABI_EVTTYPE_PIPELINE_DONE) |
0510 (1 << IMGU_ABI_EVTTYPE_FRAME_TAGGED) |
0511 (1 << IMGU_ABI_EVTTYPE_INPUT_FRAME_DONE) |
0512 (1 << IMGU_ABI_EVTTYPE_METADATA_DONE) |
0513 (1 << IMGU_ABI_EVTTYPE_ACC_STAGE_COMPLETE))
0514 << IMGU_ABI_SP_COMM_EVENT_IRQ_MASK_OR_SHIFT;
0515
0516 void __iomem *const base = css->base;
0517 struct imgu_fw_info *bi, *bl = &css->fwp->binary_header[css->fw_bl];
0518 unsigned int i;
0519
0520 writel(IMGU_TLB_INVALIDATE, base + IMGU_REG_TLB_INVALIDATE);
0521
0522
0523
0524 writel(IMGU_ABI_BL_SWSTATE_BUSY,
0525 base + IMGU_REG_ISP_DMEM_BASE + bl->info.bl.sw_state);
0526 writel(IMGU_NUM_SP,
0527 base + IMGU_REG_ISP_DMEM_BASE + bl->info.bl.num_dma_cmds);
0528
0529 for (i = 0; i < IMGU_NUM_SP; i++) {
0530 int j = IMGU_NUM_SP - i - 1;
0531 struct imgu_fw_info *sp =
0532 &css->fwp->binary_header[css->fw_sp[j]];
0533 struct imgu_abi_bl_dma_cmd_entry dma_cmd = {
0534 .src_addr = css->binary[css->fw_sp[j]].daddr
0535 + sp->blob.text_source,
0536 .size = sp->blob.text_size,
0537 .dst_type = IMGU_ABI_BL_DMACMD_TYPE_SP_PMEM,
0538 .dst_addr = IMGU_SP_PMEM_BASE(j),
0539 };
0540
0541 writes(&dma_cmd, sizeof(dma_cmd),
0542 base + IMGU_REG_ISP_DMEM_BASE + i * sizeof(dma_cmd) +
0543 bl->info.bl.dma_cmd_list);
0544 }
0545
0546 writel(bl->info.bl.bl_entry, base + IMGU_REG_ISP_START_ADDR);
0547
0548 writel(readl(base + IMGU_REG_ISP_CTRL)
0549 | IMGU_CTRL_START | IMGU_CTRL_RUN, base + IMGU_REG_ISP_CTRL);
0550 if (imgu_hw_wait(css->base, IMGU_REG_ISP_DMEM_BASE
0551 + bl->info.bl.sw_state, ~0,
0552 IMGU_ABI_BL_SWSTATE_OK)) {
0553 dev_err(css->dev, "failed to start bootloader\n");
0554 return -EIO;
0555 }
0556
0557
0558
0559 memset(css->xmem_sp_group_ptrs.vaddr, 0,
0560 sizeof(struct imgu_abi_sp_group));
0561
0562 bi = &css->fwp->binary_header[css->fw_sp[0]];
0563
0564 writel(css->xmem_sp_group_ptrs.daddr,
0565 base + IMGU_REG_SP_DMEM_BASE(0) + bi->info.sp.per_frame_data);
0566
0567 writel(IMGU_ABI_SP_SWSTATE_TERMINATED,
0568 base + IMGU_REG_SP_DMEM_BASE(0) + bi->info.sp.sw_state);
0569 writel(1, base + IMGU_REG_SP_DMEM_BASE(0) + bi->info.sp.invalidate_tlb);
0570
0571 if (imgu_css_hw_start_sp(css, 0))
0572 return -EIO;
0573
0574 writel(0, base + IMGU_REG_SP_DMEM_BASE(0) + bi->info.sp.isp_started);
0575 writel(0, base + IMGU_REG_SP_DMEM_BASE(0) +
0576 bi->info.sp.host_sp_queues_initialized);
0577 writel(0, base + IMGU_REG_SP_DMEM_BASE(0) + bi->info.sp.sleep_mode);
0578 writel(0, base + IMGU_REG_SP_DMEM_BASE(0) + bi->info.sp.invalidate_tlb);
0579 writel(IMGU_ABI_SP_COMM_COMMAND_READY, base + IMGU_REG_SP_DMEM_BASE(0)
0580 + bi->info.sp.host_sp_com + IMGU_ABI_SP_COMM_COMMAND);
0581
0582
0583
0584 for (i = 0; i < IPU3_CSS_PIPE_ID_NUM; i++)
0585 writel(event_mask, base + IMGU_REG_SP_DMEM_BASE(0)
0586 + bi->info.sp.host_sp_com
0587 + IMGU_ABI_SP_COMM_EVENT_IRQ_MASK(i));
0588 writel(1, base + IMGU_REG_SP_DMEM_BASE(0) +
0589 bi->info.sp.host_sp_queues_initialized);
0590
0591
0592
0593 bi = &css->fwp->binary_header[css->fw_sp[1]];
0594
0595 writel(IMGU_ABI_SP_SWSTATE_TERMINATED,
0596 base + IMGU_REG_SP_DMEM_BASE(1) + bi->info.sp.sw_state);
0597
0598 if (imgu_css_hw_start_sp(css, 1))
0599 return -EIO;
0600
0601 writel(IMGU_ABI_SP_COMM_COMMAND_READY, base + IMGU_REG_SP_DMEM_BASE(1)
0602 + bi->info.sp.host_sp_com + IMGU_ABI_SP_COMM_COMMAND);
0603
0604 return 0;
0605 }
0606
0607 static void imgu_css_hw_stop(struct imgu_css *css)
0608 {
0609 void __iomem *const base = css->base;
0610 struct imgu_fw_info *bi = &css->fwp->binary_header[css->fw_sp[0]];
0611
0612
0613 writel(IMGU_ABI_SP_COMM_COMMAND_TERMINATE,
0614 base + IMGU_REG_SP_DMEM_BASE(0) +
0615 bi->info.sp.host_sp_com + IMGU_ABI_SP_COMM_COMMAND);
0616 if (imgu_hw_wait(css->base, IMGU_REG_SP_CTRL(0),
0617 IMGU_CTRL_IDLE, IMGU_CTRL_IDLE))
0618 dev_err(css->dev, "wait sp0 idle timeout.\n");
0619 if (readl(base + IMGU_REG_SP_DMEM_BASE(0) + bi->info.sp.sw_state) !=
0620 IMGU_ABI_SP_SWSTATE_TERMINATED)
0621 dev_err(css->dev, "sp0 is not terminated.\n");
0622 if (imgu_hw_wait(css->base, IMGU_REG_ISP_CTRL,
0623 IMGU_CTRL_IDLE, IMGU_CTRL_IDLE))
0624 dev_err(css->dev, "wait isp idle timeout\n");
0625 }
0626
0627 static void imgu_css_hw_cleanup(struct imgu_css *css)
0628 {
0629 void __iomem *const base = css->base;
0630
0631
0632
0633
0634 readl(base + IMGU_REG_GP_BUSY);
0635 writel(0, base + IMGU_REG_GP_BUSY);
0636
0637
0638 if (imgu_hw_wait(css->base, IMGU_REG_STATE, IMGU_STATE_IDLE_STS,
0639 IMGU_STATE_IDLE_STS))
0640 dev_err(css->dev, "failed to shut down hw cleanly\n");
0641
0642
0643 writel(readl(base + IMGU_REG_PM_CTRL) | IMGU_PM_CTRL_FORCE_RESET,
0644 base + IMGU_REG_PM_CTRL);
0645
0646 usleep_range(200, 300);
0647 }
0648
0649 static void imgu_css_pipeline_cleanup(struct imgu_css *css, unsigned int pipe)
0650 {
0651 struct imgu_device *imgu = dev_get_drvdata(css->dev);
0652 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
0653 unsigned int i;
0654
0655 imgu_css_pool_cleanup(imgu, &css_pipe->pool.parameter_set_info);
0656 imgu_css_pool_cleanup(imgu, &css_pipe->pool.acc);
0657 imgu_css_pool_cleanup(imgu, &css_pipe->pool.gdc);
0658 imgu_css_pool_cleanup(imgu, &css_pipe->pool.obgrid);
0659
0660 for (i = 0; i < IMGU_ABI_NUM_MEMORIES; i++)
0661 imgu_css_pool_cleanup(imgu, &css_pipe->pool.binary_params_p[i]);
0662 }
0663
0664
0665
0666
0667
0668 static int imgu_css_pipeline_init(struct imgu_css *css, unsigned int pipe)
0669 {
0670 static const int BYPC = 2;
0671 static const struct imgu_abi_buffer_sp buffer_sp_init = {
0672 .buf_src = {.queue_id = IMGU_ABI_QUEUE_EVENT_ID},
0673 .buf_type = IMGU_ABI_BUFFER_TYPE_INVALID,
0674 };
0675
0676 struct imgu_abi_isp_iterator_config *cfg_iter;
0677 struct imgu_abi_isp_ref_config *cfg_ref;
0678 struct imgu_abi_isp_dvs_config *cfg_dvs;
0679 struct imgu_abi_isp_tnr3_config *cfg_tnr;
0680 struct imgu_abi_isp_ref_dmem_state *cfg_ref_state;
0681 struct imgu_abi_isp_tnr3_dmem_state *cfg_tnr_state;
0682
0683 const int stage = 0;
0684 unsigned int i, j;
0685
0686 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
0687 struct imgu_css_queue *css_queue_in =
0688 &css_pipe->queue[IPU3_CSS_QUEUE_IN];
0689 struct imgu_css_queue *css_queue_out =
0690 &css_pipe->queue[IPU3_CSS_QUEUE_OUT];
0691 struct imgu_css_queue *css_queue_vf =
0692 &css_pipe->queue[IPU3_CSS_QUEUE_VF];
0693 const struct imgu_fw_info *bi =
0694 &css->fwp->binary_header[css_pipe->bindex];
0695 const unsigned int stripes = bi->info.isp.sp.iterator.num_stripes;
0696
0697 struct imgu_fw_config_memory_offsets *cofs = (void *)css->fwp +
0698 bi->blob.memory_offsets.offsets[IMGU_ABI_PARAM_CLASS_CONFIG];
0699 struct imgu_fw_state_memory_offsets *sofs = (void *)css->fwp +
0700 bi->blob.memory_offsets.offsets[IMGU_ABI_PARAM_CLASS_STATE];
0701
0702 struct imgu_abi_isp_stage *isp_stage;
0703 struct imgu_abi_sp_stage *sp_stage;
0704 struct imgu_abi_sp_group *sp_group;
0705 struct imgu_abi_frames_sp *frames_sp;
0706 struct imgu_abi_frame_sp *frame_sp;
0707 struct imgu_abi_frame_sp_info *frame_sp_info;
0708
0709 const unsigned int bds_width_pad =
0710 ALIGN(css_pipe->rect[IPU3_CSS_RECT_BDS].width,
0711 2 * IPU3_UAPI_ISP_VEC_ELEMS);
0712
0713 const enum imgu_abi_memories m0 = IMGU_ABI_MEM_ISP_DMEM0;
0714 enum imgu_abi_param_class cfg = IMGU_ABI_PARAM_CLASS_CONFIG;
0715 void *vaddr = css_pipe->binary_params_cs[cfg - 1][m0].vaddr;
0716
0717 struct imgu_device *imgu = dev_get_drvdata(css->dev);
0718
0719 dev_dbg(css->dev, "%s for pipe %d", __func__, pipe);
0720
0721
0722
0723 cfg_iter = imgu_css_fw_pipeline_params(css, pipe, cfg, m0,
0724 &cofs->dmem.iterator,
0725 sizeof(*cfg_iter), vaddr);
0726 if (!cfg_iter)
0727 goto bad_firmware;
0728
0729 frame_sp_info = &cfg_iter->input_info;
0730 frame_sp_info->res.width = css_queue_in->fmt.mpix.width;
0731 frame_sp_info->res.height = css_queue_in->fmt.mpix.height;
0732 frame_sp_info->padded_width = css_queue_in->width_pad;
0733 frame_sp_info->format = css_queue_in->css_fmt->frame_format;
0734 frame_sp_info->raw_bit_depth = css_queue_in->css_fmt->bit_depth;
0735 frame_sp_info->raw_bayer_order = css_queue_in->css_fmt->bayer_order;
0736 frame_sp_info->raw_type = IMGU_ABI_RAW_TYPE_BAYER;
0737
0738 frame_sp_info = &cfg_iter->internal_info;
0739 frame_sp_info->res.width = css_pipe->rect[IPU3_CSS_RECT_BDS].width;
0740 frame_sp_info->res.height = css_pipe->rect[IPU3_CSS_RECT_BDS].height;
0741 frame_sp_info->padded_width = bds_width_pad;
0742 frame_sp_info->format = css_queue_out->css_fmt->frame_format;
0743 frame_sp_info->raw_bit_depth = css_queue_out->css_fmt->bit_depth;
0744 frame_sp_info->raw_bayer_order = css_queue_out->css_fmt->bayer_order;
0745 frame_sp_info->raw_type = IMGU_ABI_RAW_TYPE_BAYER;
0746
0747 frame_sp_info = &cfg_iter->output_info;
0748 frame_sp_info->res.width = css_queue_out->fmt.mpix.width;
0749 frame_sp_info->res.height = css_queue_out->fmt.mpix.height;
0750 frame_sp_info->padded_width = css_queue_out->width_pad;
0751 frame_sp_info->format = css_queue_out->css_fmt->frame_format;
0752 frame_sp_info->raw_bit_depth = css_queue_out->css_fmt->bit_depth;
0753 frame_sp_info->raw_bayer_order = css_queue_out->css_fmt->bayer_order;
0754 frame_sp_info->raw_type = IMGU_ABI_RAW_TYPE_BAYER;
0755
0756 frame_sp_info = &cfg_iter->vf_info;
0757 frame_sp_info->res.width = css_queue_vf->fmt.mpix.width;
0758 frame_sp_info->res.height = css_queue_vf->fmt.mpix.height;
0759 frame_sp_info->padded_width = css_queue_vf->width_pad;
0760 frame_sp_info->format = css_queue_vf->css_fmt->frame_format;
0761 frame_sp_info->raw_bit_depth = css_queue_vf->css_fmt->bit_depth;
0762 frame_sp_info->raw_bayer_order = css_queue_vf->css_fmt->bayer_order;
0763 frame_sp_info->raw_type = IMGU_ABI_RAW_TYPE_BAYER;
0764
0765 cfg_iter->dvs_envelope.width =
0766 css_pipe->rect[IPU3_CSS_RECT_ENVELOPE].width;
0767 cfg_iter->dvs_envelope.height =
0768 css_pipe->rect[IPU3_CSS_RECT_ENVELOPE].height;
0769
0770
0771
0772 cfg_ref = imgu_css_fw_pipeline_params(css, pipe, cfg, m0,
0773 &cofs->dmem.ref,
0774 sizeof(*cfg_ref), vaddr);
0775 if (!cfg_ref)
0776 goto bad_firmware;
0777
0778 cfg_ref->port_b.crop = 0;
0779 cfg_ref->port_b.elems = IMGU_ABI_ISP_DDR_WORD_BYTES / BYPC;
0780 cfg_ref->port_b.width =
0781 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].width;
0782 cfg_ref->port_b.stride =
0783 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].bytesperline;
0784 cfg_ref->width_a_over_b =
0785 IPU3_UAPI_ISP_VEC_ELEMS / cfg_ref->port_b.elems;
0786 cfg_ref->dvs_frame_delay = IPU3_CSS_AUX_FRAMES - 1;
0787 for (i = 0; i < IPU3_CSS_AUX_FRAMES; i++) {
0788 cfg_ref->ref_frame_addr_y[i] =
0789 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].mem[i].daddr;
0790 cfg_ref->ref_frame_addr_c[i] =
0791 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].mem[i].daddr +
0792 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].bytesperline *
0793 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].height;
0794 }
0795 for (; i < IMGU_ABI_FRAMES_REF; i++) {
0796 cfg_ref->ref_frame_addr_y[i] = 0;
0797 cfg_ref->ref_frame_addr_c[i] = 0;
0798 }
0799
0800
0801
0802 cfg_dvs = imgu_css_fw_pipeline_params(css, pipe, cfg, m0,
0803 &cofs->dmem.dvs, sizeof(*cfg_dvs),
0804 vaddr);
0805 if (!cfg_dvs)
0806 goto bad_firmware;
0807
0808 cfg_dvs->num_horizontal_blocks =
0809 ALIGN(DIV_ROUND_UP(css_pipe->rect[IPU3_CSS_RECT_GDC].width,
0810 IMGU_DVS_BLOCK_W), 2);
0811 cfg_dvs->num_vertical_blocks =
0812 DIV_ROUND_UP(css_pipe->rect[IPU3_CSS_RECT_GDC].height,
0813 IMGU_DVS_BLOCK_H);
0814
0815
0816
0817 if (css_pipe->pipe_id == IPU3_CSS_PIPE_ID_VIDEO) {
0818 cfg_tnr = imgu_css_fw_pipeline_params(css, pipe, cfg, m0,
0819 &cofs->dmem.tnr3,
0820 sizeof(*cfg_tnr),
0821 vaddr);
0822 if (!cfg_tnr)
0823 goto bad_firmware;
0824
0825 cfg_tnr->port_b.crop = 0;
0826 cfg_tnr->port_b.elems = IMGU_ABI_ISP_DDR_WORD_BYTES;
0827 cfg_tnr->port_b.width =
0828 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].width;
0829 cfg_tnr->port_b.stride =
0830 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].bytesperline;
0831 cfg_tnr->width_a_over_b =
0832 IPU3_UAPI_ISP_VEC_ELEMS / cfg_tnr->port_b.elems;
0833 cfg_tnr->frame_height =
0834 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].height;
0835 cfg_tnr->delay_frame = IPU3_CSS_AUX_FRAMES - 1;
0836 for (i = 0; i < IPU3_CSS_AUX_FRAMES; i++)
0837 cfg_tnr->frame_addr[i] =
0838 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR]
0839 .mem[i].daddr;
0840 for (; i < IMGU_ABI_FRAMES_TNR; i++)
0841 cfg_tnr->frame_addr[i] = 0;
0842 }
0843
0844
0845
0846 cfg = IMGU_ABI_PARAM_CLASS_STATE;
0847 vaddr = css_pipe->binary_params_cs[cfg - 1][m0].vaddr;
0848
0849 cfg_ref_state = imgu_css_fw_pipeline_params(css, pipe, cfg, m0,
0850 &sofs->dmem.ref,
0851 sizeof(*cfg_ref_state),
0852 vaddr);
0853 if (!cfg_ref_state)
0854 goto bad_firmware;
0855
0856 cfg_ref_state->ref_in_buf_idx = 0;
0857 cfg_ref_state->ref_out_buf_idx = 1;
0858
0859
0860 if (css_pipe->pipe_id == IPU3_CSS_PIPE_ID_VIDEO) {
0861 cfg_tnr_state =
0862 imgu_css_fw_pipeline_params(css, pipe, cfg, m0,
0863 &sofs->dmem.tnr3,
0864 sizeof(*cfg_tnr_state),
0865 vaddr);
0866 if (!cfg_tnr_state)
0867 goto bad_firmware;
0868
0869 cfg_tnr_state->in_bufidx = 0;
0870 cfg_tnr_state->out_bufidx = 1;
0871 cfg_tnr_state->bypass_filter = 0;
0872 cfg_tnr_state->total_frame_counter = 0;
0873 for (i = 0; i < IMGU_ABI_BUF_SETS_TNR; i++)
0874 cfg_tnr_state->buffer_frame_counter[i] = 0;
0875 }
0876
0877
0878
0879 isp_stage = css_pipe->xmem_isp_stage_ptrs[pipe][stage].vaddr;
0880 memset(isp_stage, 0, sizeof(*isp_stage));
0881 isp_stage->blob_info = bi->blob;
0882 isp_stage->binary_info = bi->info.isp.sp;
0883 strscpy(isp_stage->binary_name,
0884 (char *)css->fwp + bi->blob.prog_name_offset,
0885 sizeof(isp_stage->binary_name));
0886 isp_stage->mem_initializers = bi->info.isp.sp.mem_initializers;
0887 for (i = IMGU_ABI_PARAM_CLASS_CONFIG; i < IMGU_ABI_PARAM_CLASS_NUM; i++)
0888 for (j = 0; j < IMGU_ABI_NUM_MEMORIES; j++)
0889 isp_stage->mem_initializers.params[i][j].address =
0890 css_pipe->binary_params_cs[i - 1][j].daddr;
0891
0892
0893
0894 sp_stage = css_pipe->xmem_sp_stage_ptrs[pipe][stage].vaddr;
0895 memset(sp_stage, 0, sizeof(*sp_stage));
0896
0897 frames_sp = &sp_stage->frames;
0898 frames_sp->in.buf_attr = buffer_sp_init;
0899 for (i = 0; i < IMGU_ABI_BINARY_MAX_OUTPUT_PORTS; i++)
0900 frames_sp->out[i].buf_attr = buffer_sp_init;
0901 frames_sp->out_vf.buf_attr = buffer_sp_init;
0902 frames_sp->s3a_buf = buffer_sp_init;
0903 frames_sp->dvs_buf = buffer_sp_init;
0904
0905 sp_stage->stage_type = IMGU_ABI_STAGE_TYPE_ISP;
0906 sp_stage->num = stage;
0907 sp_stage->isp_online = 0;
0908 sp_stage->isp_copy_vf = 0;
0909 sp_stage->isp_copy_output = 0;
0910
0911 sp_stage->enable.vf_output = css_pipe->vf_output_en;
0912
0913 frames_sp->effective_in_res.width =
0914 css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].width;
0915 frames_sp->effective_in_res.height =
0916 css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].height;
0917
0918 frame_sp = &frames_sp->in;
0919 frame_sp->info.res.width = css_queue_in->fmt.mpix.width;
0920 frame_sp->info.res.height = css_queue_in->fmt.mpix.height;
0921 frame_sp->info.padded_width = css_queue_in->width_pad;
0922 frame_sp->info.format = css_queue_in->css_fmt->frame_format;
0923 frame_sp->info.raw_bit_depth = css_queue_in->css_fmt->bit_depth;
0924 frame_sp->info.raw_bayer_order = css_queue_in->css_fmt->bayer_order;
0925 frame_sp->info.raw_type = IMGU_ABI_RAW_TYPE_BAYER;
0926 frame_sp->buf_attr.buf_src.queue_id = IMGU_ABI_QUEUE_C_ID;
0927 frame_sp->buf_attr.buf_type = IMGU_ABI_BUFFER_TYPE_INPUT_FRAME;
0928
0929 frame_sp = &frames_sp->out[0];
0930 frame_sp->info.res.width = css_queue_out->fmt.mpix.width;
0931 frame_sp->info.res.height = css_queue_out->fmt.mpix.height;
0932 frame_sp->info.padded_width = css_queue_out->width_pad;
0933 frame_sp->info.format = css_queue_out->css_fmt->frame_format;
0934 frame_sp->info.raw_bit_depth = css_queue_out->css_fmt->bit_depth;
0935 frame_sp->info.raw_bayer_order = css_queue_out->css_fmt->bayer_order;
0936 frame_sp->info.raw_type = IMGU_ABI_RAW_TYPE_BAYER;
0937 frame_sp->planes.nv.uv.offset = css_queue_out->width_pad *
0938 css_queue_out->fmt.mpix.height;
0939 frame_sp->buf_attr.buf_src.queue_id = IMGU_ABI_QUEUE_D_ID;
0940 frame_sp->buf_attr.buf_type = IMGU_ABI_BUFFER_TYPE_OUTPUT_FRAME;
0941
0942 frame_sp = &frames_sp->out[1];
0943 frame_sp->buf_attr.buf_src.queue_id = IMGU_ABI_QUEUE_EVENT_ID;
0944
0945 frame_sp_info = &frames_sp->internal_frame_info;
0946 frame_sp_info->res.width = css_pipe->rect[IPU3_CSS_RECT_BDS].width;
0947 frame_sp_info->res.height = css_pipe->rect[IPU3_CSS_RECT_BDS].height;
0948 frame_sp_info->padded_width = bds_width_pad;
0949 frame_sp_info->format = css_queue_out->css_fmt->frame_format;
0950 frame_sp_info->raw_bit_depth = css_queue_out->css_fmt->bit_depth;
0951 frame_sp_info->raw_bayer_order = css_queue_out->css_fmt->bayer_order;
0952 frame_sp_info->raw_type = IMGU_ABI_RAW_TYPE_BAYER;
0953
0954 frame_sp = &frames_sp->out_vf;
0955 frame_sp->info.res.width = css_queue_vf->fmt.mpix.width;
0956 frame_sp->info.res.height = css_queue_vf->fmt.mpix.height;
0957 frame_sp->info.padded_width = css_queue_vf->width_pad;
0958 frame_sp->info.format = css_queue_vf->css_fmt->frame_format;
0959 frame_sp->info.raw_bit_depth = css_queue_vf->css_fmt->bit_depth;
0960 frame_sp->info.raw_bayer_order = css_queue_vf->css_fmt->bayer_order;
0961 frame_sp->info.raw_type = IMGU_ABI_RAW_TYPE_BAYER;
0962 frame_sp->planes.yuv.u.offset = css_queue_vf->width_pad *
0963 css_queue_vf->fmt.mpix.height;
0964 frame_sp->planes.yuv.v.offset = css_queue_vf->width_pad *
0965 css_queue_vf->fmt.mpix.height * 5 / 4;
0966 frame_sp->buf_attr.buf_src.queue_id = IMGU_ABI_QUEUE_E_ID;
0967 frame_sp->buf_attr.buf_type = IMGU_ABI_BUFFER_TYPE_VF_OUTPUT_FRAME;
0968
0969 frames_sp->s3a_buf.buf_src.queue_id = IMGU_ABI_QUEUE_F_ID;
0970 frames_sp->s3a_buf.buf_type = IMGU_ABI_BUFFER_TYPE_3A_STATISTICS;
0971
0972 frames_sp->dvs_buf.buf_src.queue_id = IMGU_ABI_QUEUE_G_ID;
0973 frames_sp->dvs_buf.buf_type = IMGU_ABI_BUFFER_TYPE_DIS_STATISTICS;
0974
0975 sp_stage->dvs_envelope.width =
0976 css_pipe->rect[IPU3_CSS_RECT_ENVELOPE].width;
0977 sp_stage->dvs_envelope.height =
0978 css_pipe->rect[IPU3_CSS_RECT_ENVELOPE].height;
0979
0980 sp_stage->isp_pipe_version =
0981 bi->info.isp.sp.pipeline.isp_pipe_version;
0982 sp_stage->isp_deci_log_factor =
0983 clamp(max(fls(css_pipe->rect[IPU3_CSS_RECT_BDS].width /
0984 IMGU_MAX_BQ_GRID_WIDTH),
0985 fls(css_pipe->rect[IPU3_CSS_RECT_BDS].height /
0986 IMGU_MAX_BQ_GRID_HEIGHT)) - 1, 3, 5);
0987 sp_stage->isp_vf_downscale_bits = 0;
0988 sp_stage->if_config_index = 255;
0989 sp_stage->sp_enable_xnr = 0;
0990 sp_stage->num_stripes = stripes;
0991 sp_stage->enable.s3a = 1;
0992 sp_stage->enable.dvs_stats = 0;
0993
0994 sp_stage->xmem_bin_addr = css->binary[css_pipe->bindex].daddr;
0995 sp_stage->xmem_map_addr = css_pipe->sp_ddr_ptrs.daddr;
0996 sp_stage->isp_stage_addr =
0997 css_pipe->xmem_isp_stage_ptrs[pipe][stage].daddr;
0998
0999
1000
1001 sp_group = css->xmem_sp_group_ptrs.vaddr;
1002 memset(&sp_group->pipe[pipe], 0, sizeof(struct imgu_abi_sp_pipeline));
1003
1004 sp_group->pipe[pipe].num_stages = 1;
1005 sp_group->pipe[pipe].pipe_id = css_pipe->pipe_id;
1006 sp_group->pipe[pipe].thread_id = pipe;
1007 sp_group->pipe[pipe].pipe_num = pipe;
1008 sp_group->pipe[pipe].num_execs = -1;
1009 sp_group->pipe[pipe].pipe_qos_config = -1;
1010 sp_group->pipe[pipe].required_bds_factor = 0;
1011 sp_group->pipe[pipe].dvs_frame_delay = IPU3_CSS_AUX_FRAMES - 1;
1012 sp_group->pipe[pipe].inout_port_config =
1013 IMGU_ABI_PORT_CONFIG_TYPE_INPUT_HOST |
1014 IMGU_ABI_PORT_CONFIG_TYPE_OUTPUT_HOST;
1015 sp_group->pipe[pipe].scaler_pp_lut = 0;
1016 sp_group->pipe[pipe].shading.internal_frame_origin_x_bqs_on_sctbl = 0;
1017 sp_group->pipe[pipe].shading.internal_frame_origin_y_bqs_on_sctbl = 0;
1018 sp_group->pipe[pipe].sp_stage_addr[stage] =
1019 css_pipe->xmem_sp_stage_ptrs[pipe][stage].daddr;
1020 sp_group->pipe[pipe].pipe_config =
1021 bi->info.isp.sp.enable.params ? (1 << pipe) : 0;
1022 sp_group->pipe[pipe].pipe_config |= IMGU_ABI_PIPE_CONFIG_ACQUIRE_ISP;
1023
1024
1025
1026 if (imgu_css_pool_init(imgu, &css_pipe->pool.parameter_set_info,
1027 sizeof(struct imgu_abi_parameter_set_info)) ||
1028 imgu_css_pool_init(imgu, &css_pipe->pool.acc,
1029 sizeof(struct imgu_abi_acc_param)) ||
1030 imgu_css_pool_init(imgu, &css_pipe->pool.gdc,
1031 sizeof(struct imgu_abi_gdc_warp_param) *
1032 3 * cfg_dvs->num_horizontal_blocks / 2 *
1033 cfg_dvs->num_vertical_blocks) ||
1034 imgu_css_pool_init(imgu, &css_pipe->pool.obgrid,
1035 imgu_css_fw_obgrid_size(
1036 &css->fwp->binary_header[css_pipe->bindex])))
1037 goto out_of_memory;
1038
1039 for (i = 0; i < IMGU_ABI_NUM_MEMORIES; i++)
1040 if (imgu_css_pool_init(imgu,
1041 &css_pipe->pool.binary_params_p[i],
1042 bi->info.isp.sp.mem_initializers.params
1043 [IMGU_ABI_PARAM_CLASS_PARAM][i].size))
1044 goto out_of_memory;
1045
1046 return 0;
1047
1048 bad_firmware:
1049 imgu_css_pipeline_cleanup(css, pipe);
1050 return -EPROTO;
1051
1052 out_of_memory:
1053 imgu_css_pipeline_cleanup(css, pipe);
1054 return -ENOMEM;
1055 }
1056
1057 static u8 imgu_css_queue_pos(struct imgu_css *css, int queue, int thread)
1058 {
1059 static const unsigned int sp;
1060 void __iomem *const base = css->base;
1061 struct imgu_fw_info *bi = &css->fwp->binary_header[css->fw_sp[sp]];
1062 struct imgu_abi_queues __iomem *q = base + IMGU_REG_SP_DMEM_BASE(sp) +
1063 bi->info.sp.host_sp_queue;
1064
1065 return queue >= 0 ? readb(&q->host2sp_bufq_info[thread][queue].end) :
1066 readb(&q->host2sp_evtq_info.end);
1067 }
1068
1069
1070 static int imgu_css_queue_data(struct imgu_css *css,
1071 int queue, int thread, u32 data)
1072 {
1073 static const unsigned int sp;
1074 void __iomem *const base = css->base;
1075 struct imgu_fw_info *bi = &css->fwp->binary_header[css->fw_sp[sp]];
1076 struct imgu_abi_queues __iomem *q = base + IMGU_REG_SP_DMEM_BASE(sp) +
1077 bi->info.sp.host_sp_queue;
1078 u8 size, start, end, end2;
1079
1080 if (queue >= 0) {
1081 size = readb(&q->host2sp_bufq_info[thread][queue].size);
1082 start = readb(&q->host2sp_bufq_info[thread][queue].start);
1083 end = readb(&q->host2sp_bufq_info[thread][queue].end);
1084 } else {
1085 size = readb(&q->host2sp_evtq_info.size);
1086 start = readb(&q->host2sp_evtq_info.start);
1087 end = readb(&q->host2sp_evtq_info.end);
1088 }
1089
1090 if (size == 0)
1091 return -EIO;
1092
1093 end2 = (end + 1) % size;
1094 if (end2 == start)
1095 return -EBUSY;
1096
1097 if (queue >= 0) {
1098 writel(data, &q->host2sp_bufq[thread][queue][end]);
1099 writeb(end2, &q->host2sp_bufq_info[thread][queue].end);
1100 } else {
1101 writel(data, &q->host2sp_evtq[end]);
1102 writeb(end2, &q->host2sp_evtq_info.end);
1103 }
1104
1105 return 0;
1106 }
1107
1108
1109 static int imgu_css_dequeue_data(struct imgu_css *css, int queue, u32 *data)
1110 {
1111 static const unsigned int sp;
1112 void __iomem *const base = css->base;
1113 struct imgu_fw_info *bi = &css->fwp->binary_header[css->fw_sp[sp]];
1114 struct imgu_abi_queues __iomem *q = base + IMGU_REG_SP_DMEM_BASE(sp) +
1115 bi->info.sp.host_sp_queue;
1116 u8 size, start, end, start2;
1117
1118 if (queue >= 0) {
1119 size = readb(&q->sp2host_bufq_info[queue].size);
1120 start = readb(&q->sp2host_bufq_info[queue].start);
1121 end = readb(&q->sp2host_bufq_info[queue].end);
1122 } else {
1123 size = readb(&q->sp2host_evtq_info.size);
1124 start = readb(&q->sp2host_evtq_info.start);
1125 end = readb(&q->sp2host_evtq_info.end);
1126 }
1127
1128 if (size == 0)
1129 return -EIO;
1130
1131 if (end == start)
1132 return -EBUSY;
1133
1134 start2 = (start + 1) % size;
1135
1136 if (queue >= 0) {
1137 *data = readl(&q->sp2host_bufq[queue][start]);
1138 writeb(start2, &q->sp2host_bufq_info[queue].start);
1139 } else {
1140 int r;
1141
1142 *data = readl(&q->sp2host_evtq[start]);
1143 writeb(start2, &q->sp2host_evtq_info.start);
1144
1145
1146 r = imgu_css_queue_data(css, queue, 0,
1147 IMGU_ABI_EVENT_EVENT_DEQUEUED);
1148 if (r < 0)
1149 return r;
1150 }
1151
1152 return 0;
1153 }
1154
1155
1156 static void imgu_css_binary_cleanup(struct imgu_css *css, unsigned int pipe)
1157 {
1158 struct imgu_device *imgu = dev_get_drvdata(css->dev);
1159 unsigned int i, j;
1160
1161 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1162
1163 for (j = 0; j < IMGU_ABI_PARAM_CLASS_NUM - 1; j++)
1164 for (i = 0; i < IMGU_ABI_NUM_MEMORIES; i++)
1165 imgu_dmamap_free(imgu,
1166 &css_pipe->binary_params_cs[j][i]);
1167
1168 j = IPU3_CSS_AUX_FRAME_REF;
1169 for (i = 0; i < IPU3_CSS_AUX_FRAMES; i++)
1170 imgu_dmamap_free(imgu,
1171 &css_pipe->aux_frames[j].mem[i]);
1172
1173 j = IPU3_CSS_AUX_FRAME_TNR;
1174 for (i = 0; i < IPU3_CSS_AUX_FRAMES; i++)
1175 imgu_dmamap_free(imgu,
1176 &css_pipe->aux_frames[j].mem[i]);
1177 }
1178
1179 static int imgu_css_binary_preallocate(struct imgu_css *css, unsigned int pipe)
1180 {
1181 struct imgu_device *imgu = dev_get_drvdata(css->dev);
1182 unsigned int i, j;
1183
1184 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1185
1186 for (j = IMGU_ABI_PARAM_CLASS_CONFIG;
1187 j < IMGU_ABI_PARAM_CLASS_NUM; j++)
1188 for (i = 0; i < IMGU_ABI_NUM_MEMORIES; i++)
1189 if (!imgu_dmamap_alloc(imgu,
1190 &css_pipe->binary_params_cs[j - 1][i],
1191 CSS_ABI_SIZE))
1192 goto out_of_memory;
1193
1194 for (i = 0; i < IPU3_CSS_AUX_FRAMES; i++)
1195 if (!imgu_dmamap_alloc(imgu,
1196 &css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].
1197 mem[i], CSS_BDS_SIZE))
1198 goto out_of_memory;
1199
1200 for (i = 0; i < IPU3_CSS_AUX_FRAMES; i++)
1201 if (!imgu_dmamap_alloc(imgu,
1202 &css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].
1203 mem[i], CSS_GDC_SIZE))
1204 goto out_of_memory;
1205
1206 return 0;
1207
1208 out_of_memory:
1209 imgu_css_binary_cleanup(css, pipe);
1210 return -ENOMEM;
1211 }
1212
1213
1214 static int imgu_css_binary_setup(struct imgu_css *css, unsigned int pipe)
1215 {
1216 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1217 struct imgu_fw_info *bi = &css->fwp->binary_header[css_pipe->bindex];
1218 struct imgu_device *imgu = dev_get_drvdata(css->dev);
1219 int i, j, size;
1220 static const int BYPC = 2;
1221 unsigned int w, h;
1222
1223
1224
1225 for (j = IMGU_ABI_PARAM_CLASS_CONFIG; j < IMGU_ABI_PARAM_CLASS_NUM; j++)
1226 for (i = 0; i < IMGU_ABI_NUM_MEMORIES; i++) {
1227 if (imgu_css_dma_buffer_resize(
1228 imgu,
1229 &css_pipe->binary_params_cs[j - 1][i],
1230 bi->info.isp.sp.mem_initializers.params[j][i].size))
1231 goto out_of_memory;
1232 }
1233
1234
1235
1236
1237 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].bytesperpixel = BYPC;
1238 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].width =
1239 css_pipe->rect[IPU3_CSS_RECT_BDS].width;
1240 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].height =
1241 ALIGN(css_pipe->rect[IPU3_CSS_RECT_BDS].height,
1242 IMGU_DVS_BLOCK_H) + 2 * IMGU_GDC_BUF_Y;
1243 h = css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].height;
1244 w = ALIGN(css_pipe->rect[IPU3_CSS_RECT_BDS].width,
1245 2 * IPU3_UAPI_ISP_VEC_ELEMS) + 2 * IMGU_GDC_BUF_X;
1246 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].bytesperline =
1247 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].bytesperpixel * w;
1248 size = w * h * BYPC + (w / 2) * (h / 2) * BYPC * 2;
1249 for (i = 0; i < IPU3_CSS_AUX_FRAMES; i++)
1250 if (imgu_css_dma_buffer_resize(
1251 imgu,
1252 &css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].mem[i],
1253 size))
1254 goto out_of_memory;
1255
1256
1257 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].bytesperpixel = 1;
1258 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].width =
1259 roundup(css_pipe->rect[IPU3_CSS_RECT_GDC].width,
1260 bi->info.isp.sp.block.block_width *
1261 IPU3_UAPI_ISP_VEC_ELEMS);
1262 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].height =
1263 roundup(css_pipe->rect[IPU3_CSS_RECT_GDC].height,
1264 bi->info.isp.sp.block.output_block_height);
1265
1266 w = css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].width;
1267 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].bytesperline = w;
1268 h = css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].height;
1269 size = w * ALIGN(h * 3 / 2 + 3, 2);
1270 for (i = 0; i < IPU3_CSS_AUX_FRAMES; i++)
1271 if (imgu_css_dma_buffer_resize(
1272 imgu,
1273 &css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_TNR].mem[i],
1274 size))
1275 goto out_of_memory;
1276
1277 return 0;
1278
1279 out_of_memory:
1280 imgu_css_binary_cleanup(css, pipe);
1281 return -ENOMEM;
1282 }
1283
1284 int imgu_css_start_streaming(struct imgu_css *css)
1285 {
1286 u32 data;
1287 int r, pipe;
1288
1289 if (css->streaming)
1290 return -EPROTO;
1291
1292 for_each_set_bit(pipe, css->enabled_pipes, IMGU_MAX_PIPE_NUM) {
1293 r = imgu_css_binary_setup(css, pipe);
1294 if (r < 0)
1295 return r;
1296 }
1297
1298 r = imgu_css_hw_init(css);
1299 if (r < 0)
1300 return r;
1301
1302 r = imgu_css_hw_start(css);
1303 if (r < 0)
1304 goto fail;
1305
1306 for_each_set_bit(pipe, css->enabled_pipes, IMGU_MAX_PIPE_NUM) {
1307 r = imgu_css_pipeline_init(css, pipe);
1308 if (r < 0)
1309 goto fail;
1310 }
1311
1312 css->streaming = true;
1313
1314 imgu_css_hw_enable_irq(css);
1315
1316
1317 for_each_set_bit(pipe, css->enabled_pipes, IMGU_MAX_PIPE_NUM) {
1318 r = imgu_css_set_parameters(css, pipe, NULL);
1319 if (r < 0)
1320 goto fail;
1321 }
1322
1323 while (!(r = imgu_css_dequeue_data(css, IMGU_ABI_QUEUE_A_ID, &data)))
1324 ;
1325 if (r != -EBUSY)
1326 goto fail;
1327
1328 while (!(r = imgu_css_dequeue_data(css, IMGU_ABI_QUEUE_B_ID, &data)))
1329 ;
1330 if (r != -EBUSY)
1331 goto fail;
1332
1333 for_each_set_bit(pipe, css->enabled_pipes, IMGU_MAX_PIPE_NUM) {
1334 r = imgu_css_queue_data(css, IMGU_ABI_QUEUE_EVENT_ID, pipe,
1335 IMGU_ABI_EVENT_START_STREAM |
1336 pipe << 16);
1337 if (r < 0)
1338 goto fail;
1339 }
1340
1341 return 0;
1342
1343 fail:
1344 css->streaming = false;
1345 imgu_css_hw_cleanup(css);
1346 for_each_set_bit(pipe, css->enabled_pipes, IMGU_MAX_PIPE_NUM) {
1347 imgu_css_pipeline_cleanup(css, pipe);
1348 imgu_css_binary_cleanup(css, pipe);
1349 }
1350
1351 return r;
1352 }
1353
1354 void imgu_css_stop_streaming(struct imgu_css *css)
1355 {
1356 struct imgu_css_buffer *b, *b0;
1357 int q, r, pipe;
1358
1359 for_each_set_bit(pipe, css->enabled_pipes, IMGU_MAX_PIPE_NUM) {
1360 r = imgu_css_queue_data(css, IMGU_ABI_QUEUE_EVENT_ID, pipe,
1361 IMGU_ABI_EVENT_STOP_STREAM);
1362 if (r < 0)
1363 dev_warn(css->dev, "failed on stop stream event\n");
1364 }
1365
1366 if (!css->streaming)
1367 return;
1368
1369 imgu_css_hw_stop(css);
1370
1371 imgu_css_hw_cleanup(css);
1372
1373 for_each_set_bit(pipe, css->enabled_pipes, IMGU_MAX_PIPE_NUM) {
1374 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1375
1376 imgu_css_pipeline_cleanup(css, pipe);
1377
1378 spin_lock(&css_pipe->qlock);
1379 for (q = 0; q < IPU3_CSS_QUEUES; q++)
1380 list_for_each_entry_safe(b, b0,
1381 &css_pipe->queue[q].bufs,
1382 list) {
1383 b->state = IPU3_CSS_BUFFER_FAILED;
1384 list_del(&b->list);
1385 }
1386 spin_unlock(&css_pipe->qlock);
1387 }
1388
1389 css->streaming = false;
1390 }
1391
1392 bool imgu_css_pipe_queue_empty(struct imgu_css *css, unsigned int pipe)
1393 {
1394 int q;
1395 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1396
1397 spin_lock(&css_pipe->qlock);
1398 for (q = 0; q < IPU3_CSS_QUEUES; q++)
1399 if (!list_empty(&css_pipe->queue[q].bufs))
1400 break;
1401 spin_unlock(&css_pipe->qlock);
1402 return (q == IPU3_CSS_QUEUES);
1403 }
1404
1405 bool imgu_css_queue_empty(struct imgu_css *css)
1406 {
1407 unsigned int pipe;
1408 bool ret = false;
1409
1410 for (pipe = 0; pipe < IMGU_MAX_PIPE_NUM; pipe++)
1411 ret &= imgu_css_pipe_queue_empty(css, pipe);
1412
1413 return ret;
1414 }
1415
1416 bool imgu_css_is_streaming(struct imgu_css *css)
1417 {
1418 return css->streaming;
1419 }
1420
1421 static int imgu_css_map_init(struct imgu_css *css, unsigned int pipe)
1422 {
1423 struct imgu_device *imgu = dev_get_drvdata(css->dev);
1424 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1425 unsigned int p, q, i;
1426
1427
1428 for (p = 0; p < IPU3_CSS_PIPE_ID_NUM; p++)
1429 for (i = 0; i < IMGU_ABI_MAX_STAGES; i++) {
1430 if (!imgu_dmamap_alloc(imgu,
1431 &css_pipe->
1432 xmem_sp_stage_ptrs[p][i],
1433 sizeof(struct imgu_abi_sp_stage)))
1434 return -ENOMEM;
1435 if (!imgu_dmamap_alloc(imgu,
1436 &css_pipe->
1437 xmem_isp_stage_ptrs[p][i],
1438 sizeof(struct imgu_abi_isp_stage)))
1439 return -ENOMEM;
1440 }
1441
1442 if (!imgu_dmamap_alloc(imgu, &css_pipe->sp_ddr_ptrs,
1443 ALIGN(sizeof(struct imgu_abi_ddr_address_map),
1444 IMGU_ABI_ISP_DDR_WORD_BYTES)))
1445 return -ENOMEM;
1446
1447 for (q = 0; q < IPU3_CSS_QUEUES; q++) {
1448 unsigned int abi_buf_num = ARRAY_SIZE(css_pipe->abi_buffers[q]);
1449
1450 for (i = 0; i < abi_buf_num; i++)
1451 if (!imgu_dmamap_alloc(imgu,
1452 &css_pipe->abi_buffers[q][i],
1453 sizeof(struct imgu_abi_buffer)))
1454 return -ENOMEM;
1455 }
1456
1457 if (imgu_css_binary_preallocate(css, pipe)) {
1458 imgu_css_binary_cleanup(css, pipe);
1459 return -ENOMEM;
1460 }
1461
1462 return 0;
1463 }
1464
1465 static void imgu_css_pipe_cleanup(struct imgu_css *css, unsigned int pipe)
1466 {
1467 struct imgu_device *imgu = dev_get_drvdata(css->dev);
1468 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1469 unsigned int p, q, i, abi_buf_num;
1470
1471 imgu_css_binary_cleanup(css, pipe);
1472
1473 for (q = 0; q < IPU3_CSS_QUEUES; q++) {
1474 abi_buf_num = ARRAY_SIZE(css_pipe->abi_buffers[q]);
1475 for (i = 0; i < abi_buf_num; i++)
1476 imgu_dmamap_free(imgu, &css_pipe->abi_buffers[q][i]);
1477 }
1478
1479 for (p = 0; p < IPU3_CSS_PIPE_ID_NUM; p++)
1480 for (i = 0; i < IMGU_ABI_MAX_STAGES; i++) {
1481 imgu_dmamap_free(imgu,
1482 &css_pipe->xmem_sp_stage_ptrs[p][i]);
1483 imgu_dmamap_free(imgu,
1484 &css_pipe->xmem_isp_stage_ptrs[p][i]);
1485 }
1486
1487 imgu_dmamap_free(imgu, &css_pipe->sp_ddr_ptrs);
1488 }
1489
1490 void imgu_css_cleanup(struct imgu_css *css)
1491 {
1492 struct imgu_device *imgu = dev_get_drvdata(css->dev);
1493 unsigned int pipe;
1494
1495 imgu_css_stop_streaming(css);
1496 for (pipe = 0; pipe < IMGU_MAX_PIPE_NUM; pipe++)
1497 imgu_css_pipe_cleanup(css, pipe);
1498 imgu_dmamap_free(imgu, &css->xmem_sp_group_ptrs);
1499 imgu_css_fw_cleanup(css);
1500 }
1501
1502 int imgu_css_init(struct device *dev, struct imgu_css *css,
1503 void __iomem *base, int length)
1504 {
1505 struct imgu_device *imgu = dev_get_drvdata(dev);
1506 int r, q, pipe;
1507
1508
1509 css->dev = dev;
1510 css->base = base;
1511 css->iomem_length = length;
1512
1513 for (pipe = 0; pipe < IMGU_MAX_PIPE_NUM; pipe++) {
1514 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1515
1516 css_pipe->vf_output_en = false;
1517 spin_lock_init(&css_pipe->qlock);
1518 css_pipe->bindex = IPU3_CSS_DEFAULT_BINARY;
1519 css_pipe->pipe_id = IPU3_CSS_PIPE_ID_VIDEO;
1520 for (q = 0; q < IPU3_CSS_QUEUES; q++) {
1521 r = imgu_css_queue_init(&css_pipe->queue[q], NULL, 0);
1522 if (r)
1523 return r;
1524 }
1525 r = imgu_css_map_init(css, pipe);
1526 if (r) {
1527 imgu_css_cleanup(css);
1528 return r;
1529 }
1530 }
1531 if (!imgu_dmamap_alloc(imgu, &css->xmem_sp_group_ptrs,
1532 sizeof(struct imgu_abi_sp_group)))
1533 return -ENOMEM;
1534
1535 r = imgu_css_fw_init(css);
1536 if (r)
1537 return r;
1538
1539 return 0;
1540 }
1541
1542 static u32 imgu_css_adjust(u32 res, u32 align)
1543 {
1544 u32 val = max_t(u32, IPU3_CSS_MIN_RES, res);
1545
1546 return DIV_ROUND_CLOSEST(val, align) * align;
1547 }
1548
1549
1550 static int imgu_css_find_binary(struct imgu_css *css,
1551 unsigned int pipe,
1552 struct imgu_css_queue queue[IPU3_CSS_QUEUES],
1553 struct v4l2_rect rects[IPU3_CSS_RECTS])
1554 {
1555 const int binary_nr = css->fwp->file_header.binary_nr;
1556 unsigned int binary_mode =
1557 (css->pipes[pipe].pipe_id == IPU3_CSS_PIPE_ID_CAPTURE) ?
1558 IA_CSS_BINARY_MODE_PRIMARY : IA_CSS_BINARY_MODE_VIDEO;
1559 const struct v4l2_pix_format_mplane *in =
1560 &queue[IPU3_CSS_QUEUE_IN].fmt.mpix;
1561 const struct v4l2_pix_format_mplane *out =
1562 &queue[IPU3_CSS_QUEUE_OUT].fmt.mpix;
1563 const struct v4l2_pix_format_mplane *vf =
1564 &queue[IPU3_CSS_QUEUE_VF].fmt.mpix;
1565 u32 stripe_w = 0, stripe_h = 0;
1566 const char *name;
1567 int i, j;
1568
1569 if (!imgu_css_queue_enabled(&queue[IPU3_CSS_QUEUE_IN]))
1570 return -EINVAL;
1571
1572
1573 for (i = 0; i < binary_nr; i++) {
1574 struct imgu_fw_info *bi = &css->fwp->binary_header[i];
1575
1576 u32 max_width = bi->info.isp.sp.output.max_width;
1577 u32 max_height = bi->info.isp.sp.output.max_height;
1578
1579 if (bi->info.isp.sp.iterator.num_stripes <= 1) {
1580 stripe_w = stripe_w ?
1581 min(stripe_w, max_width) : max_width;
1582 stripe_h = stripe_h ?
1583 min(stripe_h, max_height) : max_height;
1584 }
1585 }
1586
1587 for (i = 0; i < binary_nr; i++) {
1588 struct imgu_fw_info *bi = &css->fwp->binary_header[i];
1589 enum imgu_abi_frame_format q_fmt;
1590
1591 name = (void *)css->fwp + bi->blob.prog_name_offset;
1592
1593
1594 if (bi->info.isp.sp.input.source !=
1595 IMGU_ABI_BINARY_INPUT_SOURCE_MEMORY)
1596 continue;
1597
1598
1599 if (!bi->info.isp.sp.enable.input_feeder &&
1600 !bi->info.isp.sp.enable.input_raw)
1601 continue;
1602
1603
1604 if (bi->info.isp.sp.pipeline.mode != binary_mode)
1605 continue;
1606
1607
1608 if (bi->info.isp.sp.enable.luma_only)
1609 continue;
1610
1611 if (in->width < bi->info.isp.sp.input.min_width ||
1612 in->width > bi->info.isp.sp.input.max_width ||
1613 in->height < bi->info.isp.sp.input.min_height ||
1614 in->height > bi->info.isp.sp.input.max_height)
1615 continue;
1616
1617 if (imgu_css_queue_enabled(&queue[IPU3_CSS_QUEUE_OUT])) {
1618 if (bi->info.isp.num_output_pins <= 0)
1619 continue;
1620
1621 q_fmt = queue[IPU3_CSS_QUEUE_OUT].css_fmt->frame_format;
1622 for (j = 0; j < bi->info.isp.num_output_formats; j++)
1623 if (bi->info.isp.output_formats[j] == q_fmt)
1624 break;
1625 if (j >= bi->info.isp.num_output_formats)
1626 continue;
1627
1628 if (out->width < bi->info.isp.sp.output.min_width ||
1629 out->width > bi->info.isp.sp.output.max_width ||
1630 out->height < bi->info.isp.sp.output.min_height ||
1631 out->height > bi->info.isp.sp.output.max_height)
1632 continue;
1633
1634 if (out->width > bi->info.isp.sp.internal.max_width ||
1635 out->height > bi->info.isp.sp.internal.max_height)
1636 continue;
1637 }
1638
1639 if (imgu_css_queue_enabled(&queue[IPU3_CSS_QUEUE_VF])) {
1640 if (bi->info.isp.num_output_pins <= 1)
1641 continue;
1642
1643 q_fmt = queue[IPU3_CSS_QUEUE_VF].css_fmt->frame_format;
1644 for (j = 0; j < bi->info.isp.num_output_formats; j++)
1645 if (bi->info.isp.output_formats[j] == q_fmt)
1646 break;
1647 if (j >= bi->info.isp.num_output_formats)
1648 continue;
1649
1650 if (vf->width < bi->info.isp.sp.output.min_width ||
1651 vf->width > bi->info.isp.sp.output.max_width ||
1652 vf->height < bi->info.isp.sp.output.min_height ||
1653 vf->height > bi->info.isp.sp.output.max_height)
1654 continue;
1655 }
1656
1657
1658 dev_dbg(css->dev, "using binary %s id = %u\n", name,
1659 bi->info.isp.sp.id);
1660 return i;
1661 }
1662
1663
1664 return -EINVAL;
1665 }
1666
1667
1668
1669
1670
1671
1672
1673
1674 int imgu_css_fmt_try(struct imgu_css *css,
1675 struct v4l2_pix_format_mplane *fmts[IPU3_CSS_QUEUES],
1676 struct v4l2_rect *rects[IPU3_CSS_RECTS],
1677 unsigned int pipe)
1678 {
1679 static const u32 EFF_ALIGN_W = 2;
1680 static const u32 BDS_ALIGN_W = 4;
1681 static const u32 OUT_ALIGN_W = 8;
1682 static const u32 OUT_ALIGN_H = 4;
1683 static const u32 VF_ALIGN_W = 2;
1684 static const char *qnames[IPU3_CSS_QUEUES] = {
1685 [IPU3_CSS_QUEUE_IN] = "in",
1686 [IPU3_CSS_QUEUE_PARAMS] = "params",
1687 [IPU3_CSS_QUEUE_OUT] = "out",
1688 [IPU3_CSS_QUEUE_VF] = "vf",
1689 [IPU3_CSS_QUEUE_STAT_3A] = "3a",
1690 };
1691 static const char *rnames[IPU3_CSS_RECTS] = {
1692 [IPU3_CSS_RECT_EFFECTIVE] = "effective resolution",
1693 [IPU3_CSS_RECT_BDS] = "bayer-domain scaled resolution",
1694 [IPU3_CSS_RECT_ENVELOPE] = "DVS envelope size",
1695 [IPU3_CSS_RECT_GDC] = "GDC output res",
1696 };
1697 struct v4l2_rect r[IPU3_CSS_RECTS] = { };
1698 struct v4l2_rect *const eff = &r[IPU3_CSS_RECT_EFFECTIVE];
1699 struct v4l2_rect *const bds = &r[IPU3_CSS_RECT_BDS];
1700 struct v4l2_rect *const env = &r[IPU3_CSS_RECT_ENVELOPE];
1701 struct v4l2_rect *const gdc = &r[IPU3_CSS_RECT_GDC];
1702 struct imgu_css_queue *q;
1703 struct v4l2_pix_format_mplane *in, *out, *vf;
1704 int i, s, ret;
1705
1706 q = kcalloc(IPU3_CSS_QUEUES, sizeof(struct imgu_css_queue), GFP_KERNEL);
1707 if (!q)
1708 return -ENOMEM;
1709
1710 in = &q[IPU3_CSS_QUEUE_IN].fmt.mpix;
1711 out = &q[IPU3_CSS_QUEUE_OUT].fmt.mpix;
1712 vf = &q[IPU3_CSS_QUEUE_VF].fmt.mpix;
1713
1714
1715 for (i = 0; i < IPU3_CSS_QUEUES; i++) {
1716 if (fmts[i])
1717 dev_dbg(css->dev, "%s %s: (%i,%i) fmt 0x%x\n", __func__,
1718 qnames[i], fmts[i]->width, fmts[i]->height,
1719 fmts[i]->pixelformat);
1720 else
1721 dev_dbg(css->dev, "%s %s: (not set)\n", __func__,
1722 qnames[i]);
1723 if (imgu_css_queue_init(&q[i], fmts[i],
1724 IPU3_CSS_QUEUE_TO_FLAGS(i))) {
1725 dev_notice(css->dev, "can not initialize queue %s\n",
1726 qnames[i]);
1727 ret = -EINVAL;
1728 goto out;
1729 }
1730 }
1731 for (i = 0; i < IPU3_CSS_RECTS; i++) {
1732 if (rects[i]) {
1733 dev_dbg(css->dev, "%s %s: (%i,%i)\n", __func__,
1734 rnames[i], rects[i]->width, rects[i]->height);
1735 r[i].width = rects[i]->width;
1736 r[i].height = rects[i]->height;
1737 } else {
1738 dev_dbg(css->dev, "%s %s: (not set)\n", __func__,
1739 rnames[i]);
1740 }
1741
1742 r[i].left = 0;
1743 r[i].top = 0;
1744 }
1745
1746
1747 if (!imgu_css_queue_enabled(&q[IPU3_CSS_QUEUE_IN]) ||
1748 !imgu_css_queue_enabled(&q[IPU3_CSS_QUEUE_OUT])) {
1749 dev_warn(css->dev, "required queues are disabled\n");
1750 ret = -EINVAL;
1751 goto out;
1752 }
1753
1754 if (!imgu_css_queue_enabled(&q[IPU3_CSS_QUEUE_OUT])) {
1755 out->width = in->width;
1756 out->height = in->height;
1757 }
1758 if (eff->width <= 0 || eff->height <= 0) {
1759 eff->width = in->width;
1760 eff->height = in->height;
1761 }
1762 if (bds->width <= 0 || bds->height <= 0) {
1763 bds->width = out->width;
1764 bds->height = out->height;
1765 }
1766 if (gdc->width <= 0 || gdc->height <= 0) {
1767 gdc->width = out->width;
1768 gdc->height = out->height;
1769 }
1770
1771 in->width = imgu_css_adjust(in->width, 1);
1772 in->height = imgu_css_adjust(in->height, 1);
1773 eff->width = imgu_css_adjust(eff->width, EFF_ALIGN_W);
1774 eff->height = imgu_css_adjust(eff->height, 1);
1775 bds->width = imgu_css_adjust(bds->width, BDS_ALIGN_W);
1776 bds->height = imgu_css_adjust(bds->height, 1);
1777 gdc->width = imgu_css_adjust(gdc->width, OUT_ALIGN_W);
1778 gdc->height = imgu_css_adjust(gdc->height, OUT_ALIGN_H);
1779 out->width = imgu_css_adjust(out->width, OUT_ALIGN_W);
1780 out->height = imgu_css_adjust(out->height, OUT_ALIGN_H);
1781 vf->width = imgu_css_adjust(vf->width, VF_ALIGN_W);
1782 vf->height = imgu_css_adjust(vf->height, 1);
1783
1784 s = (bds->width - gdc->width) / 2;
1785 env->width = s < MIN_ENVELOPE ? MIN_ENVELOPE : s;
1786 s = (bds->height - gdc->height) / 2;
1787 env->height = s < MIN_ENVELOPE ? MIN_ENVELOPE : s;
1788
1789 ret = imgu_css_find_binary(css, pipe, q, r);
1790 if (ret < 0) {
1791 dev_err(css->dev, "failed to find suitable binary\n");
1792 ret = -EINVAL;
1793 goto out;
1794 }
1795 css->pipes[pipe].bindex = ret;
1796
1797 dev_dbg(css->dev, "Binary index %d for pipe %d found.",
1798 css->pipes[pipe].bindex, pipe);
1799
1800
1801 for (i = 0; i < IPU3_CSS_QUEUES; i++) {
1802 if (fmts[i]) {
1803 if (imgu_css_queue_init(&q[i], &q[i].fmt.mpix,
1804 IPU3_CSS_QUEUE_TO_FLAGS(i))) {
1805 dev_err(css->dev,
1806 "final resolution adjustment failed\n");
1807 ret = -EINVAL;
1808 goto out;
1809 }
1810 *fmts[i] = q[i].fmt.mpix;
1811 }
1812 }
1813
1814 for (i = 0; i < IPU3_CSS_RECTS; i++)
1815 if (rects[i])
1816 *rects[i] = r[i];
1817
1818 dev_dbg(css->dev,
1819 "in(%u,%u) if(%u,%u) ds(%u,%u) gdc(%u,%u) out(%u,%u) vf(%u,%u)",
1820 in->width, in->height, eff->width, eff->height,
1821 bds->width, bds->height, gdc->width, gdc->height,
1822 out->width, out->height, vf->width, vf->height);
1823
1824 ret = 0;
1825 out:
1826 kfree(q);
1827 return ret;
1828 }
1829
1830 int imgu_css_fmt_set(struct imgu_css *css,
1831 struct v4l2_pix_format_mplane *fmts[IPU3_CSS_QUEUES],
1832 struct v4l2_rect *rects[IPU3_CSS_RECTS],
1833 unsigned int pipe)
1834 {
1835 struct v4l2_rect rect_data[IPU3_CSS_RECTS];
1836 struct v4l2_rect *all_rects[IPU3_CSS_RECTS];
1837 int i, r;
1838 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1839
1840 for (i = 0; i < IPU3_CSS_RECTS; i++) {
1841 if (rects[i])
1842 rect_data[i] = *rects[i];
1843 else
1844 memset(&rect_data[i], 0, sizeof(rect_data[i]));
1845 all_rects[i] = &rect_data[i];
1846 }
1847 r = imgu_css_fmt_try(css, fmts, all_rects, pipe);
1848 if (r < 0)
1849 return r;
1850
1851 for (i = 0; i < IPU3_CSS_QUEUES; i++)
1852 if (imgu_css_queue_init(&css_pipe->queue[i], fmts[i],
1853 IPU3_CSS_QUEUE_TO_FLAGS(i)))
1854 return -EINVAL;
1855 for (i = 0; i < IPU3_CSS_RECTS; i++) {
1856 css_pipe->rect[i] = rect_data[i];
1857 if (rects[i])
1858 *rects[i] = rect_data[i];
1859 }
1860
1861 return 0;
1862 }
1863
1864 int imgu_css_meta_fmt_set(struct v4l2_meta_format *fmt)
1865 {
1866 switch (fmt->dataformat) {
1867 case V4L2_META_FMT_IPU3_PARAMS:
1868 fmt->buffersize = sizeof(struct ipu3_uapi_params);
1869
1870
1871
1872
1873
1874 BUILD_BUG_ON(sizeof(struct ipu3_uapi_params) != 39328);
1875
1876 break;
1877 case V4L2_META_FMT_IPU3_STAT_3A:
1878 fmt->buffersize = sizeof(struct ipu3_uapi_stats_3a);
1879 break;
1880 default:
1881 return -EINVAL;
1882 }
1883
1884 return 0;
1885 }
1886
1887
1888
1889
1890
1891
1892
1893 int imgu_css_buf_queue(struct imgu_css *css, unsigned int pipe,
1894 struct imgu_css_buffer *b)
1895 {
1896 struct imgu_abi_buffer *abi_buf;
1897 struct imgu_addr_t *buf_addr;
1898 u32 data;
1899 int r;
1900 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1901
1902 if (!css->streaming)
1903 return -EPROTO;
1904
1905 if (b->queue >= IPU3_CSS_QUEUES || !imgu_css_queues[b->queue].qid)
1906 return -EINVAL;
1907
1908 b->queue_pos = imgu_css_queue_pos(css, imgu_css_queues[b->queue].qid,
1909 pipe);
1910
1911 if (b->queue_pos >= ARRAY_SIZE(css->pipes[pipe].abi_buffers[b->queue]))
1912 return -EIO;
1913 abi_buf = css->pipes[pipe].abi_buffers[b->queue][b->queue_pos].vaddr;
1914
1915
1916 memset(abi_buf, 0, sizeof(*abi_buf));
1917
1918 buf_addr = (void *)abi_buf + imgu_css_queues[b->queue].ptr_ofs;
1919 *(imgu_addr_t *)buf_addr = b->daddr;
1920
1921 if (b->queue == IPU3_CSS_QUEUE_STAT_3A)
1922 abi_buf->payload.s3a.data.dmem.s3a_tbl = b->daddr;
1923
1924 if (b->queue == IPU3_CSS_QUEUE_OUT)
1925 abi_buf->payload.frame.padded_width =
1926 css_pipe->queue[IPU3_CSS_QUEUE_OUT].width_pad;
1927
1928 if (b->queue == IPU3_CSS_QUEUE_VF)
1929 abi_buf->payload.frame.padded_width =
1930 css_pipe->queue[IPU3_CSS_QUEUE_VF].width_pad;
1931
1932 spin_lock(&css_pipe->qlock);
1933 list_add_tail(&b->list, &css_pipe->queue[b->queue].bufs);
1934 spin_unlock(&css_pipe->qlock);
1935 b->state = IPU3_CSS_BUFFER_QUEUED;
1936
1937 data = css->pipes[pipe].abi_buffers[b->queue][b->queue_pos].daddr;
1938 r = imgu_css_queue_data(css, imgu_css_queues[b->queue].qid,
1939 pipe, data);
1940 if (r < 0)
1941 goto queueing_failed;
1942
1943 data = IMGU_ABI_EVENT_BUFFER_ENQUEUED(pipe,
1944 imgu_css_queues[b->queue].qid);
1945 r = imgu_css_queue_data(css, IMGU_ABI_QUEUE_EVENT_ID, pipe, data);
1946 if (r < 0)
1947 goto queueing_failed;
1948
1949 dev_dbg(css->dev, "queued buffer %p to css queue %i in pipe %d\n",
1950 b, b->queue, pipe);
1951
1952 return 0;
1953
1954 queueing_failed:
1955 b->state = (r == -EBUSY || r == -EAGAIN) ?
1956 IPU3_CSS_BUFFER_NEW : IPU3_CSS_BUFFER_FAILED;
1957 list_del(&b->list);
1958
1959 return r;
1960 }
1961
1962
1963
1964
1965
1966
1967 struct imgu_css_buffer *imgu_css_buf_dequeue(struct imgu_css *css)
1968 {
1969 static const unsigned char evtype_to_queue[] = {
1970 [IMGU_ABI_EVTTYPE_INPUT_FRAME_DONE] = IPU3_CSS_QUEUE_IN,
1971 [IMGU_ABI_EVTTYPE_OUT_FRAME_DONE] = IPU3_CSS_QUEUE_OUT,
1972 [IMGU_ABI_EVTTYPE_VF_OUT_FRAME_DONE] = IPU3_CSS_QUEUE_VF,
1973 [IMGU_ABI_EVTTYPE_3A_STATS_DONE] = IPU3_CSS_QUEUE_STAT_3A,
1974 };
1975 struct imgu_css_buffer *b = ERR_PTR(-EAGAIN);
1976 u32 event, daddr;
1977 int evtype, pipe, pipeid, queue, qid, r;
1978 struct imgu_css_pipe *css_pipe;
1979
1980 if (!css->streaming)
1981 return ERR_PTR(-EPROTO);
1982
1983 r = imgu_css_dequeue_data(css, IMGU_ABI_QUEUE_EVENT_ID, &event);
1984 if (r < 0)
1985 return ERR_PTR(r);
1986
1987 evtype = (event & IMGU_ABI_EVTTYPE_EVENT_MASK) >>
1988 IMGU_ABI_EVTTYPE_EVENT_SHIFT;
1989
1990 switch (evtype) {
1991 case IMGU_ABI_EVTTYPE_OUT_FRAME_DONE:
1992 case IMGU_ABI_EVTTYPE_VF_OUT_FRAME_DONE:
1993 case IMGU_ABI_EVTTYPE_3A_STATS_DONE:
1994 case IMGU_ABI_EVTTYPE_INPUT_FRAME_DONE:
1995 pipe = (event & IMGU_ABI_EVTTYPE_PIPE_MASK) >>
1996 IMGU_ABI_EVTTYPE_PIPE_SHIFT;
1997 pipeid = (event & IMGU_ABI_EVTTYPE_PIPEID_MASK) >>
1998 IMGU_ABI_EVTTYPE_PIPEID_SHIFT;
1999 queue = evtype_to_queue[evtype];
2000 qid = imgu_css_queues[queue].qid;
2001
2002 if (pipe >= IMGU_MAX_PIPE_NUM) {
2003 dev_err(css->dev, "Invalid pipe: %i\n", pipe);
2004 return ERR_PTR(-EIO);
2005 }
2006
2007 if (qid >= IMGU_ABI_QUEUE_NUM) {
2008 dev_err(css->dev, "Invalid qid: %i\n", qid);
2009 return ERR_PTR(-EIO);
2010 }
2011 css_pipe = &css->pipes[pipe];
2012 dev_dbg(css->dev,
2013 "event: buffer done 0x%x queue %i pipe %i pipeid %i\n",
2014 event, queue, pipe, pipeid);
2015
2016 r = imgu_css_dequeue_data(css, qid, &daddr);
2017 if (r < 0) {
2018 dev_err(css->dev, "failed to dequeue buffer\n");
2019
2020 return ERR_PTR(-EIO);
2021 }
2022
2023 r = imgu_css_queue_data(css, IMGU_ABI_QUEUE_EVENT_ID, pipe,
2024 IMGU_ABI_EVENT_BUFFER_DEQUEUED(qid));
2025 if (r < 0) {
2026 dev_err(css->dev, "failed to queue event\n");
2027 return ERR_PTR(-EIO);
2028 }
2029
2030 spin_lock(&css_pipe->qlock);
2031 if (list_empty(&css_pipe->queue[queue].bufs)) {
2032 spin_unlock(&css_pipe->qlock);
2033 dev_err(css->dev, "event on empty queue\n");
2034 return ERR_PTR(-EIO);
2035 }
2036 b = list_first_entry(&css_pipe->queue[queue].bufs,
2037 struct imgu_css_buffer, list);
2038 if (queue != b->queue ||
2039 daddr != css_pipe->abi_buffers
2040 [b->queue][b->queue_pos].daddr) {
2041 spin_unlock(&css_pipe->qlock);
2042 dev_err(css->dev, "dequeued bad buffer 0x%x\n", daddr);
2043 return ERR_PTR(-EIO);
2044 }
2045
2046 dev_dbg(css->dev, "buffer 0x%8x done from pipe %d\n", daddr, pipe);
2047 b->pipe = pipe;
2048 b->state = IPU3_CSS_BUFFER_DONE;
2049 list_del(&b->list);
2050 spin_unlock(&css_pipe->qlock);
2051 break;
2052 case IMGU_ABI_EVTTYPE_PIPELINE_DONE:
2053 pipe = (event & IMGU_ABI_EVTTYPE_PIPE_MASK) >>
2054 IMGU_ABI_EVTTYPE_PIPE_SHIFT;
2055 if (pipe >= IMGU_MAX_PIPE_NUM) {
2056 dev_err(css->dev, "Invalid pipe: %i\n", pipe);
2057 return ERR_PTR(-EIO);
2058 }
2059
2060 css_pipe = &css->pipes[pipe];
2061 dev_dbg(css->dev, "event: pipeline done 0x%8x for pipe %d\n",
2062 event, pipe);
2063 break;
2064 case IMGU_ABI_EVTTYPE_TIMER:
2065 r = imgu_css_dequeue_data(css, IMGU_ABI_QUEUE_EVENT_ID, &event);
2066 if (r < 0)
2067 return ERR_PTR(r);
2068
2069 if ((event & IMGU_ABI_EVTTYPE_EVENT_MASK) >>
2070 IMGU_ABI_EVTTYPE_EVENT_SHIFT == IMGU_ABI_EVTTYPE_TIMER)
2071 dev_dbg(css->dev, "event: timer\n");
2072 else
2073 dev_warn(css->dev, "half of timer event missing\n");
2074 break;
2075 case IMGU_ABI_EVTTYPE_FW_WARNING:
2076 dev_warn(css->dev, "event: firmware warning 0x%x\n", event);
2077 break;
2078 case IMGU_ABI_EVTTYPE_FW_ASSERT:
2079 dev_err(css->dev,
2080 "event: firmware assert 0x%x module_id %i line_no %i\n",
2081 event,
2082 (event & IMGU_ABI_EVTTYPE_MODULEID_MASK) >>
2083 IMGU_ABI_EVTTYPE_MODULEID_SHIFT,
2084 swab16((event & IMGU_ABI_EVTTYPE_LINENO_MASK) >>
2085 IMGU_ABI_EVTTYPE_LINENO_SHIFT));
2086 break;
2087 default:
2088 dev_warn(css->dev, "received unknown event 0x%x\n", event);
2089 }
2090
2091 return b;
2092 }
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103 int imgu_css_set_parameters(struct imgu_css *css, unsigned int pipe,
2104 struct ipu3_uapi_params *set_params)
2105 {
2106 static const unsigned int queue_id = IMGU_ABI_QUEUE_A_ID;
2107 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
2108 const int stage = 0;
2109 const struct imgu_fw_info *bi;
2110 int obgrid_size;
2111 unsigned int stripes, i;
2112 struct ipu3_uapi_flags *use = set_params ? &set_params->use : NULL;
2113
2114
2115 struct imgu_abi_parameter_set_info *param_set;
2116 struct imgu_abi_acc_param *acc = NULL;
2117 struct imgu_abi_gdc_warp_param *gdc = NULL;
2118 struct ipu3_uapi_obgrid_param *obgrid = NULL;
2119 const struct imgu_css_map *map;
2120 void *vmem0 = NULL;
2121 void *dmem0 = NULL;
2122
2123 enum imgu_abi_memories m;
2124 int r = -EBUSY;
2125
2126 if (!css->streaming)
2127 return -EPROTO;
2128
2129 dev_dbg(css->dev, "%s for pipe %d", __func__, pipe);
2130
2131 bi = &css->fwp->binary_header[css_pipe->bindex];
2132 obgrid_size = imgu_css_fw_obgrid_size(bi);
2133 stripes = bi->info.isp.sp.iterator.num_stripes ? : 1;
2134
2135 imgu_css_pool_get(&css_pipe->pool.parameter_set_info);
2136 param_set = imgu_css_pool_last(&css_pipe->pool.parameter_set_info,
2137 0)->vaddr;
2138
2139
2140 map = imgu_css_pool_last(&css_pipe->pool.acc, 0);
2141 if (set_params || !map->vaddr) {
2142 imgu_css_pool_get(&css_pipe->pool.acc);
2143 map = imgu_css_pool_last(&css_pipe->pool.acc, 0);
2144 acc = map->vaddr;
2145 }
2146
2147
2148 m = IMGU_ABI_MEM_ISP_VMEM0;
2149 map = imgu_css_pool_last(&css_pipe->pool.binary_params_p[m], 0);
2150 if (!map->vaddr || (set_params && (set_params->use.lin_vmem_params ||
2151 set_params->use.tnr3_vmem_params ||
2152 set_params->use.xnr3_vmem_params))) {
2153 imgu_css_pool_get(&css_pipe->pool.binary_params_p[m]);
2154 map = imgu_css_pool_last(&css_pipe->pool.binary_params_p[m], 0);
2155 vmem0 = map->vaddr;
2156 }
2157
2158
2159 m = IMGU_ABI_MEM_ISP_DMEM0;
2160 map = imgu_css_pool_last(&css_pipe->pool.binary_params_p[m], 0);
2161 if (!map->vaddr || (set_params && (set_params->use.tnr3_dmem_params ||
2162 set_params->use.xnr3_dmem_params))) {
2163 imgu_css_pool_get(&css_pipe->pool.binary_params_p[m]);
2164 map = imgu_css_pool_last(&css_pipe->pool.binary_params_p[m], 0);
2165 dmem0 = map->vaddr;
2166 }
2167
2168
2169 if (acc) {
2170
2171 map = imgu_css_pool_last(&css_pipe->pool.acc, 1);
2172
2173 r = imgu_css_cfg_acc(css, pipe, use, acc, map->vaddr,
2174 set_params ? &set_params->acc_param : NULL);
2175 if (r < 0)
2176 goto fail;
2177 }
2178
2179
2180 if (vmem0) {
2181 m = IMGU_ABI_MEM_ISP_VMEM0;
2182 map = imgu_css_pool_last(&css_pipe->pool.binary_params_p[m], 1);
2183 r = imgu_css_cfg_vmem0(css, pipe, use, vmem0,
2184 map->vaddr, set_params);
2185 if (r < 0)
2186 goto fail;
2187 }
2188
2189 if (dmem0) {
2190 m = IMGU_ABI_MEM_ISP_DMEM0;
2191 map = imgu_css_pool_last(&css_pipe->pool.binary_params_p[m], 1);
2192 r = imgu_css_cfg_dmem0(css, pipe, use, dmem0,
2193 map->vaddr, set_params);
2194 if (r < 0)
2195 goto fail;
2196 }
2197
2198
2199 if (bi->info.isp.sp.enable.dvs_6axis) {
2200 unsigned int a = IPU3_CSS_AUX_FRAME_REF;
2201 unsigned int g = IPU3_CSS_RECT_GDC;
2202 unsigned int e = IPU3_CSS_RECT_ENVELOPE;
2203
2204 map = imgu_css_pool_last(&css_pipe->pool.gdc, 0);
2205 if (!map->vaddr) {
2206 imgu_css_pool_get(&css_pipe->pool.gdc);
2207 map = imgu_css_pool_last(&css_pipe->pool.gdc, 0);
2208 gdc = map->vaddr;
2209 imgu_css_cfg_gdc_table(map->vaddr,
2210 css_pipe->aux_frames[a].bytesperline /
2211 css_pipe->aux_frames[a].bytesperpixel,
2212 css_pipe->aux_frames[a].height,
2213 css_pipe->rect[g].width,
2214 css_pipe->rect[g].height,
2215 css_pipe->rect[e].width,
2216 css_pipe->rect[e].height);
2217 }
2218 }
2219
2220
2221 map = imgu_css_pool_last(&css_pipe->pool.obgrid, 0);
2222 if (!map->vaddr || (set_params && set_params->use.obgrid_param)) {
2223 imgu_css_pool_get(&css_pipe->pool.obgrid);
2224 map = imgu_css_pool_last(&css_pipe->pool.obgrid, 0);
2225 obgrid = map->vaddr;
2226
2227
2228 if (set_params && set_params->use.obgrid_param)
2229 for (i = 0; i < obgrid_size / sizeof(*obgrid); i++)
2230 obgrid[i] = set_params->obgrid_param;
2231 else
2232 memset(obgrid, 0, obgrid_size);
2233 }
2234
2235
2236
2237 memset(param_set, 0, sizeof(*param_set));
2238 map = imgu_css_pool_last(&css_pipe->pool.acc, 0);
2239 param_set->mem_map.acc_cluster_params_for_sp = map->daddr;
2240
2241 map = imgu_css_pool_last(&css_pipe->pool.gdc, 0);
2242 param_set->mem_map.dvs_6axis_params_y = map->daddr;
2243
2244 for (i = 0; i < stripes; i++) {
2245 map = imgu_css_pool_last(&css_pipe->pool.obgrid, 0);
2246 param_set->mem_map.obgrid_tbl[i] =
2247 map->daddr + (obgrid_size / stripes) * i;
2248 }
2249
2250 for (m = 0; m < IMGU_ABI_NUM_MEMORIES; m++) {
2251 map = imgu_css_pool_last(&css_pipe->pool.binary_params_p[m], 0);
2252 param_set->mem_map.isp_mem_param[stage][m] = map->daddr;
2253 }
2254
2255
2256 map = imgu_css_pool_last(&css_pipe->pool.parameter_set_info, 0);
2257 r = imgu_css_queue_data(css, queue_id, pipe, map->daddr);
2258 if (r < 0)
2259 goto fail;
2260
2261 r = imgu_css_queue_data(css, IMGU_ABI_QUEUE_EVENT_ID, pipe,
2262 IMGU_ABI_EVENT_BUFFER_ENQUEUED(pipe,
2263 queue_id));
2264 if (r < 0)
2265 goto fail_no_put;
2266
2267
2268
2269 do {
2270 u32 daddr;
2271
2272 r = imgu_css_dequeue_data(css, queue_id, &daddr);
2273 if (r == -EBUSY)
2274 break;
2275 if (r)
2276 goto fail_no_put;
2277 r = imgu_css_queue_data(css, IMGU_ABI_QUEUE_EVENT_ID, pipe,
2278 IMGU_ABI_EVENT_BUFFER_DEQUEUED
2279 (queue_id));
2280 if (r < 0) {
2281 dev_err(css->dev, "failed to queue parameter event\n");
2282 goto fail_no_put;
2283 }
2284 } while (1);
2285
2286 return 0;
2287
2288 fail:
2289
2290
2291
2292
2293
2294
2295 imgu_css_pool_put(&css_pipe->pool.parameter_set_info);
2296 if (acc)
2297 imgu_css_pool_put(&css_pipe->pool.acc);
2298 if (gdc)
2299 imgu_css_pool_put(&css_pipe->pool.gdc);
2300 if (obgrid)
2301 imgu_css_pool_put(&css_pipe->pool.obgrid);
2302 if (vmem0)
2303 imgu_css_pool_put(
2304 &css_pipe->pool.binary_params_p
2305 [IMGU_ABI_MEM_ISP_VMEM0]);
2306 if (dmem0)
2307 imgu_css_pool_put(
2308 &css_pipe->pool.binary_params_p
2309 [IMGU_ABI_MEM_ISP_DMEM0]);
2310
2311 fail_no_put:
2312 return r;
2313 }
2314
2315 int imgu_css_irq_ack(struct imgu_css *css)
2316 {
2317 static const int NUM_SWIRQS = 3;
2318 struct imgu_fw_info *bi = &css->fwp->binary_header[css->fw_sp[0]];
2319 void __iomem *const base = css->base;
2320 u32 irq_status[IMGU_IRQCTRL_NUM];
2321 int i;
2322
2323 u32 imgu_status = readl(base + IMGU_REG_INT_STATUS);
2324
2325 writel(imgu_status, base + IMGU_REG_INT_STATUS);
2326 for (i = 0; i < IMGU_IRQCTRL_NUM; i++)
2327 irq_status[i] = readl(base + IMGU_REG_IRQCTRL_STATUS(i));
2328
2329 for (i = 0; i < NUM_SWIRQS; i++) {
2330 if (irq_status[IMGU_IRQCTRL_SP0] & IMGU_IRQCTRL_IRQ_SW_PIN(i)) {
2331
2332 u32 cnt = readl(base + IMGU_REG_SP_DMEM_BASE(0) +
2333 bi->info.sp.output);
2334 u32 val = readl(base + IMGU_REG_SP_DMEM_BASE(0) +
2335 bi->info.sp.output + 4 + 4 * i);
2336
2337 dev_dbg(css->dev, "%s: swirq %i cnt %i val 0x%x\n",
2338 __func__, i, cnt, val);
2339 }
2340 }
2341
2342 for (i = IMGU_IRQCTRL_NUM - 1; i >= 0; i--)
2343 if (irq_status[i]) {
2344 writel(irq_status[i], base + IMGU_REG_IRQCTRL_CLEAR(i));
2345
2346 readl(base + IMGU_REG_IRQCTRL_ENABLE(i));
2347 }
2348
2349 dev_dbg(css->dev, "%s: imgu 0x%x main 0x%x sp0 0x%x sp1 0x%x\n",
2350 __func__, imgu_status, irq_status[IMGU_IRQCTRL_MAIN],
2351 irq_status[IMGU_IRQCTRL_SP0], irq_status[IMGU_IRQCTRL_SP1]);
2352
2353 if (!imgu_status && !irq_status[IMGU_IRQCTRL_MAIN])
2354 return -ENOMSG;
2355
2356 return 0;
2357 }