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