root/drivers/staging/media/ipu3/ipu3-css.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. imgu_css_queue_init
  2. imgu_css_queue_enabled
  3. writes
  4. imgu_hw_wait
  5. imgu_css_set_powerup
  6. imgu_css_set_powerdown
  7. imgu_css_hw_enable_irq
  8. imgu_css_hw_init
  9. imgu_css_hw_start_sp
  10. imgu_css_hw_start
  11. imgu_css_hw_stop
  12. imgu_css_hw_cleanup
  13. imgu_css_pipeline_cleanup
  14. imgu_css_pipeline_init
  15. imgu_css_queue_pos
  16. imgu_css_queue_data
  17. imgu_css_dequeue_data
  18. imgu_css_binary_cleanup
  19. imgu_css_binary_preallocate
  20. imgu_css_binary_setup
  21. imgu_css_start_streaming
  22. imgu_css_stop_streaming
  23. imgu_css_pipe_queue_empty
  24. imgu_css_queue_empty
  25. imgu_css_is_streaming
  26. imgu_css_map_init
  27. imgu_css_pipe_cleanup
  28. imgu_css_cleanup
  29. imgu_css_init
  30. imgu_css_adjust
  31. imgu_css_find_binary
  32. imgu_css_fmt_try
  33. imgu_css_fmt_set
  34. imgu_css_meta_fmt_set
  35. imgu_css_buf_queue
  36. imgu_css_buf_dequeue
  37. imgu_css_set_parameters
  38. imgu_css_irq_ack

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

/* [<][>][^][v][top][bottom][index][help] */