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