1 /* 2 * Copyright (C) 2012-2016 Mentor Graphics Inc. 3 * 4 * Queued image conversion support, with tiling and rotation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2 of the License, or (at your 9 * option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * for more details. 15 */ 16 17 #include <linux/interrupt.h> 18 #include <linux/dma-mapping.h> 19 #include <video/imx-ipu-image-convert.h> 20 #include "ipu-prv.h" 21 22 /* 23 * The IC Resizer has a restriction that the output frame from the 24 * resizer must be 1024 or less in both width (pixels) and height 25 * (lines). 26 * 27 * The image converter attempts to split up a conversion when 28 * the desired output (converted) frame resolution exceeds the 29 * IC resizer limit of 1024 in either dimension. 30 * 31 * If either dimension of the output frame exceeds the limit, the 32 * dimension is split into 1, 2, or 4 equal stripes, for a maximum 33 * of 4*4 or 16 tiles. A conversion is then carried out for each 34 * tile (but taking care to pass the full frame stride length to 35 * the DMA channel's parameter memory!). IDMA double-buffering is used 36 * to convert each tile back-to-back when possible (see note below 37 * when double_buffering boolean is set). 38 * 39 * Note that the input frame must be split up into the same number 40 * of tiles as the output frame: 41 * 42 * +---------+-----+ 43 * +-----+---+ | A | B | 44 * | A | B | | | | 45 * +-----+---+ --> +---------+-----+ 46 * | C | D | | C | D | 47 * +-----+---+ | | | 48 * +---------+-----+ 49 * 50 * Clockwise 90° rotations are handled by first rescaling into a 51 * reusable temporary tile buffer and then rotating with the 8x8 52 * block rotator, writing to the correct destination: 53 * 54 * +-----+-----+ 55 * | | | 56 * +-----+---+ +---------+ | C | A | 57 * | A | B | | A,B, | | | | | 58 * +-----+---+ --> | C,D | | --> | | | 59 * | C | D | +---------+ +-----+-----+ 60 * +-----+---+ | D | B | 61 * | | | 62 * +-----+-----+ 63 * 64 * If the 8x8 block rotator is used, horizontal or vertical flipping 65 * is done during the rotation step, otherwise flipping is done 66 * during the scaling step. 67 * With rotation or flipping, tile order changes between input and 68 * output image. Tiles are numbered row major from top left to bottom 69 * right for both input and output image. 70 */ 71 72 #define MAX_STRIPES_W 4 73 #define MAX_STRIPES_H 4 74 #define MAX_TILES (MAX_STRIPES_W * MAX_STRIPES_H) 75 76 #define MIN_W 16 77 #define MIN_H 8 78 #define MAX_W 4096 79 #define MAX_H 4096 80 81 enum ipu_image_convert_type { 82 IMAGE_CONVERT_IN = 0, 83 IMAGE_CONVERT_OUT, 84 }; 85 86 struct ipu_image_convert_dma_buf { 87 void *virt; 88 dma_addr_t phys; 89 unsigned long len; 90 }; 91 92 struct ipu_image_convert_dma_chan { 93 int in; 94 int out; 95 int rot_in; 96 int rot_out; 97 int vdi_in_p; 98 int vdi_in; 99 int vdi_in_n; 100 }; 101 102 /* dimensions of one tile */ 103 struct ipu_image_tile { 104 u32 width; 105 u32 height; 106 u32 left; 107 u32 top; 108 /* size and strides are in bytes */ 109 u32 size; 110 u32 stride; 111 u32 rot_stride; 112 /* start Y or packed offset of this tile */ 113 u32 offset; 114 /* offset from start to tile in U plane, for planar formats */ 115 u32 u_off; 116 /* offset from start to tile in V plane, for planar formats */ 117 u32 v_off; 118 }; 119 120 struct ipu_image_convert_image { 121 struct ipu_image base; 122 enum ipu_image_convert_type type; 123 124 const struct ipu_image_pixfmt *fmt; 125 unsigned int stride; 126 127 /* # of rows (horizontal stripes) if dest height is > 1024 */ 128 unsigned int num_rows; 129 /* # of columns (vertical stripes) if dest width is > 1024 */ 130 unsigned int num_cols; 131 132 struct ipu_image_tile tile[MAX_TILES]; 133 }; 134 135 struct ipu_image_pixfmt { 136 u32 fourcc; /* V4L2 fourcc */ 137 int bpp; /* total bpp */ 138 int uv_width_dec; /* decimation in width for U/V planes */ 139 int uv_height_dec; /* decimation in height for U/V planes */ 140 bool planar; /* planar format */ 141 bool uv_swapped; /* U and V planes are swapped */ 142 bool uv_packed; /* partial planar (U and V in same plane) */ 143 }; 144 145 struct ipu_image_convert_ctx; 146 struct ipu_image_convert_chan; 147 struct ipu_image_convert_priv; 148 149 struct ipu_image_convert_ctx { 150 struct ipu_image_convert_chan *chan; 151 152 ipu_image_convert_cb_t complete; 153 void *complete_context; 154 155 /* Source/destination image data and rotation mode */ 156 struct ipu_image_convert_image in; 157 struct ipu_image_convert_image out; 158 enum ipu_rotate_mode rot_mode; 159 u32 downsize_coeff_h; 160 u32 downsize_coeff_v; 161 u32 image_resize_coeff_h; 162 u32 image_resize_coeff_v; 163 u32 resize_coeffs_h[MAX_STRIPES_W]; 164 u32 resize_coeffs_v[MAX_STRIPES_H]; 165 166 /* intermediate buffer for rotation */ 167 struct ipu_image_convert_dma_buf rot_intermediate[2]; 168 169 /* current buffer number for double buffering */ 170 int cur_buf_num; 171 172 bool aborting; 173 struct completion aborted; 174 175 /* can we use double-buffering for this conversion operation? */ 176 bool double_buffering; 177 /* num_rows * num_cols */ 178 unsigned int num_tiles; 179 /* next tile to process */ 180 unsigned int next_tile; 181 /* where to place converted tile in dest image */ 182 unsigned int out_tile_map[MAX_TILES]; 183 184 struct list_head list; 185 }; 186 187 struct ipu_image_convert_chan { 188 struct ipu_image_convert_priv *priv; 189 190 enum ipu_ic_task ic_task; 191 const struct ipu_image_convert_dma_chan *dma_ch; 192 193 struct ipu_ic *ic; 194 struct ipuv3_channel *in_chan; 195 struct ipuv3_channel *out_chan; 196 struct ipuv3_channel *rotation_in_chan; 197 struct ipuv3_channel *rotation_out_chan; 198 199 /* the IPU end-of-frame irqs */ 200 int out_eof_irq; 201 int rot_out_eof_irq; 202 203 spinlock_t irqlock; 204 205 /* list of convert contexts */ 206 struct list_head ctx_list; 207 /* queue of conversion runs */ 208 struct list_head pending_q; 209 /* queue of completed runs */ 210 struct list_head done_q; 211 212 /* the current conversion run */ 213 struct ipu_image_convert_run *current_run; 214 }; 215 216 struct ipu_image_convert_priv { 217 struct ipu_image_convert_chan chan[IC_NUM_TASKS]; 218 struct ipu_soc *ipu; 219 }; 220 221 static const struct ipu_image_convert_dma_chan 222 image_convert_dma_chan[IC_NUM_TASKS] = { 223 [IC_TASK_VIEWFINDER] = { 224 .in = IPUV3_CHANNEL_MEM_IC_PRP_VF, 225 .out = IPUV3_CHANNEL_IC_PRP_VF_MEM, 226 .rot_in = IPUV3_CHANNEL_MEM_ROT_VF, 227 .rot_out = IPUV3_CHANNEL_ROT_VF_MEM, 228 .vdi_in_p = IPUV3_CHANNEL_MEM_VDI_PREV, 229 .vdi_in = IPUV3_CHANNEL_MEM_VDI_CUR, 230 .vdi_in_n = IPUV3_CHANNEL_MEM_VDI_NEXT, 231 }, 232 [IC_TASK_POST_PROCESSOR] = { 233 .in = IPUV3_CHANNEL_MEM_IC_PP, 234 .out = IPUV3_CHANNEL_IC_PP_MEM, 235 .rot_in = IPUV3_CHANNEL_MEM_ROT_PP, 236 .rot_out = IPUV3_CHANNEL_ROT_PP_MEM, 237 }, 238 }; 239 240 static const struct ipu_image_pixfmt image_convert_formats[] = { 241 { 242 .fourcc = V4L2_PIX_FMT_RGB565, 243 .bpp = 16, 244 }, { 245 .fourcc = V4L2_PIX_FMT_RGB24, 246 .bpp = 24, 247 }, { 248 .fourcc = V4L2_PIX_FMT_BGR24, 249 .bpp = 24, 250 }, { 251 .fourcc = V4L2_PIX_FMT_RGB32, 252 .bpp = 32, 253 }, { 254 .fourcc = V4L2_PIX_FMT_BGR32, 255 .bpp = 32, 256 }, { 257 .fourcc = V4L2_PIX_FMT_XRGB32, 258 .bpp = 32, 259 }, { 260 .fourcc = V4L2_PIX_FMT_XBGR32, 261 .bpp = 32, 262 }, { 263 .fourcc = V4L2_PIX_FMT_YUYV, 264 .bpp = 16, 265 .uv_width_dec = 2, 266 .uv_height_dec = 1, 267 }, { 268 .fourcc = V4L2_PIX_FMT_UYVY, 269 .bpp = 16, 270 .uv_width_dec = 2, 271 .uv_height_dec = 1, 272 }, { 273 .fourcc = V4L2_PIX_FMT_YUV420, 274 .bpp = 12, 275 .planar = true, 276 .uv_width_dec = 2, 277 .uv_height_dec = 2, 278 }, { 279 .fourcc = V4L2_PIX_FMT_YVU420, 280 .bpp = 12, 281 .planar = true, 282 .uv_width_dec = 2, 283 .uv_height_dec = 2, 284 .uv_swapped = true, 285 }, { 286 .fourcc = V4L2_PIX_FMT_NV12, 287 .bpp = 12, 288 .planar = true, 289 .uv_width_dec = 2, 290 .uv_height_dec = 2, 291 .uv_packed = true, 292 }, { 293 .fourcc = V4L2_PIX_FMT_YUV422P, 294 .bpp = 16, 295 .planar = true, 296 .uv_width_dec = 2, 297 .uv_height_dec = 1, 298 }, { 299 .fourcc = V4L2_PIX_FMT_NV16, 300 .bpp = 16, 301 .planar = true, 302 .uv_width_dec = 2, 303 .uv_height_dec = 1, 304 .uv_packed = true, 305 }, 306 }; 307 308 static const struct ipu_image_pixfmt *get_format(u32 fourcc) 309 { 310 const struct ipu_image_pixfmt *ret = NULL; 311 unsigned int i; 312 313 for (i = 0; i < ARRAY_SIZE(image_convert_formats); i++) { 314 if (image_convert_formats[i].fourcc == fourcc) { 315 ret = &image_convert_formats[i]; 316 break; 317 } 318 } 319 320 return ret; 321 } 322 323 static void dump_format(struct ipu_image_convert_ctx *ctx, 324 struct ipu_image_convert_image *ic_image) 325 { 326 struct ipu_image_convert_chan *chan = ctx->chan; 327 struct ipu_image_convert_priv *priv = chan->priv; 328 329 dev_dbg(priv->ipu->dev, 330 "task %u: ctx %p: %s format: %dx%d (%dx%d tiles), %c%c%c%c\n", 331 chan->ic_task, ctx, 332 ic_image->type == IMAGE_CONVERT_OUT ? "Output" : "Input", 333 ic_image->base.pix.width, ic_image->base.pix.height, 334 ic_image->num_cols, ic_image->num_rows, 335 ic_image->fmt->fourcc & 0xff, 336 (ic_image->fmt->fourcc >> 8) & 0xff, 337 (ic_image->fmt->fourcc >> 16) & 0xff, 338 (ic_image->fmt->fourcc >> 24) & 0xff); 339 } 340 341 int ipu_image_convert_enum_format(int index, u32 *fourcc) 342 { 343 const struct ipu_image_pixfmt *fmt; 344 345 if (index >= (int)ARRAY_SIZE(image_convert_formats)) 346 return -EINVAL; 347 348 /* Format found */ 349 fmt = &image_convert_formats[index]; 350 *fourcc = fmt->fourcc; 351 return 0; 352 } 353 EXPORT_SYMBOL_GPL(ipu_image_convert_enum_format); 354 355 static void free_dma_buf(struct ipu_image_convert_priv *priv, 356 struct ipu_image_convert_dma_buf *buf) 357 { 358 if (buf->virt) 359 dma_free_coherent(priv->ipu->dev, 360 buf->len, buf->virt, buf->phys); 361 buf->virt = NULL; 362 buf->phys = 0; 363 } 364 365 static int alloc_dma_buf(struct ipu_image_convert_priv *priv, 366 struct ipu_image_convert_dma_buf *buf, 367 int size) 368 { 369 buf->len = PAGE_ALIGN(size); 370 buf->virt = dma_alloc_coherent(priv->ipu->dev, buf->len, &buf->phys, 371 GFP_DMA | GFP_KERNEL); 372 if (!buf->virt) { 373 dev_err(priv->ipu->dev, "failed to alloc dma buffer\n"); 374 return -ENOMEM; 375 } 376 377 return 0; 378 } 379 380 static inline int num_stripes(int dim) 381 { 382 return (dim - 1) / 1024 + 1; 383 } 384 385 /* 386 * Calculate downsizing coefficients, which are the same for all tiles, 387 * and bilinear resizing coefficients, which are used to find the best 388 * seam positions. 389 */ 390 static int calc_image_resize_coefficients(struct ipu_image_convert_ctx *ctx, 391 struct ipu_image *in, 392 struct ipu_image *out) 393 { 394 u32 downsized_width = in->rect.width; 395 u32 downsized_height = in->rect.height; 396 u32 downsize_coeff_v = 0; 397 u32 downsize_coeff_h = 0; 398 u32 resized_width = out->rect.width; 399 u32 resized_height = out->rect.height; 400 u32 resize_coeff_h; 401 u32 resize_coeff_v; 402 403 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { 404 resized_width = out->rect.height; 405 resized_height = out->rect.width; 406 } 407 408 /* Do not let invalid input lead to an endless loop below */ 409 if (WARN_ON(resized_width == 0 || resized_height == 0)) 410 return -EINVAL; 411 412 while (downsized_width >= resized_width * 2) { 413 downsized_width >>= 1; 414 downsize_coeff_h++; 415 } 416 417 while (downsized_height >= resized_height * 2) { 418 downsized_height >>= 1; 419 downsize_coeff_v++; 420 } 421 422 /* 423 * Calculate the bilinear resizing coefficients that could be used if 424 * we were converting with a single tile. The bottom right output pixel 425 * should sample as close as possible to the bottom right input pixel 426 * out of the decimator, but not overshoot it: 427 */ 428 resize_coeff_h = 8192 * (downsized_width - 1) / (resized_width - 1); 429 resize_coeff_v = 8192 * (downsized_height - 1) / (resized_height - 1); 430 431 dev_dbg(ctx->chan->priv->ipu->dev, 432 "%s: hscale: >>%u, *8192/%u vscale: >>%u, *8192/%u, %ux%u tiles\n", 433 __func__, downsize_coeff_h, resize_coeff_h, downsize_coeff_v, 434 resize_coeff_v, ctx->in.num_cols, ctx->in.num_rows); 435 436 if (downsize_coeff_h > 2 || downsize_coeff_v > 2 || 437 resize_coeff_h > 0x3fff || resize_coeff_v > 0x3fff) 438 return -EINVAL; 439 440 ctx->downsize_coeff_h = downsize_coeff_h; 441 ctx->downsize_coeff_v = downsize_coeff_v; 442 ctx->image_resize_coeff_h = resize_coeff_h; 443 ctx->image_resize_coeff_v = resize_coeff_v; 444 445 return 0; 446 } 447 448 #define round_closest(x, y) round_down((x) + (y)/2, (y)) 449 450 /* 451 * Find the best aligned seam position in the inverval [out_start, out_end]. 452 * Rotation and image offsets are out of scope. 453 * 454 * @out_start: start of inverval, must be within 1024 pixels / lines 455 * of out_end 456 * @out_end: end of interval, smaller than or equal to out_edge 457 * @in_edge: input right / bottom edge 458 * @out_edge: output right / bottom edge 459 * @in_align: input alignment, either horizontal 8-byte line start address 460 * alignment, or pixel alignment due to image format 461 * @out_align: output alignment, either horizontal 8-byte line start address 462 * alignment, or pixel alignment due to image format or rotator 463 * block size 464 * @in_burst: horizontal input burst size in case of horizontal flip 465 * @out_burst: horizontal output burst size or rotator block size 466 * @downsize_coeff: downsizing section coefficient 467 * @resize_coeff: main processing section resizing coefficient 468 * @_in_seam: aligned input seam position return value 469 * @_out_seam: aligned output seam position return value 470 */ 471 static void find_best_seam(struct ipu_image_convert_ctx *ctx, 472 unsigned int out_start, 473 unsigned int out_end, 474 unsigned int in_edge, 475 unsigned int out_edge, 476 unsigned int in_align, 477 unsigned int out_align, 478 unsigned int in_burst, 479 unsigned int out_burst, 480 unsigned int downsize_coeff, 481 unsigned int resize_coeff, 482 u32 *_in_seam, 483 u32 *_out_seam) 484 { 485 struct device *dev = ctx->chan->priv->ipu->dev; 486 unsigned int out_pos; 487 /* Input / output seam position candidates */ 488 unsigned int out_seam = 0; 489 unsigned int in_seam = 0; 490 unsigned int min_diff = UINT_MAX; 491 492 /* 493 * Output tiles must start at a multiple of 8 bytes horizontally and 494 * possibly at an even line horizontally depending on the pixel format. 495 * Only consider output aligned positions for the seam. 496 */ 497 out_start = round_up(out_start, out_align); 498 for (out_pos = out_start; out_pos < out_end; out_pos += out_align) { 499 unsigned int in_pos; 500 unsigned int in_pos_aligned; 501 unsigned int abs_diff; 502 503 /* 504 * Tiles in the right row / bottom column may not be allowed to 505 * overshoot horizontally / vertically. out_burst may be the 506 * actual DMA burst size, or the rotator block size. 507 */ 508 if ((out_burst > 1) && (out_edge - out_pos) % out_burst) 509 continue; 510 511 /* 512 * Input sample position, corresponding to out_pos, 19.13 fixed 513 * point. 514 */ 515 in_pos = (out_pos * resize_coeff) << downsize_coeff; 516 /* 517 * The closest input sample position that we could actually 518 * start the input tile at, 19.13 fixed point. 519 */ 520 in_pos_aligned = round_closest(in_pos, 8192U * in_align); 521 522 if ((in_burst > 1) && 523 (in_edge - in_pos_aligned / 8192U) % in_burst) 524 continue; 525 526 if (in_pos < in_pos_aligned) 527 abs_diff = in_pos_aligned - in_pos; 528 else 529 abs_diff = in_pos - in_pos_aligned; 530 531 if (abs_diff < min_diff) { 532 in_seam = in_pos_aligned; 533 out_seam = out_pos; 534 min_diff = abs_diff; 535 } 536 } 537 538 *_out_seam = out_seam; 539 /* Convert 19.13 fixed point to integer seam position */ 540 *_in_seam = DIV_ROUND_CLOSEST(in_seam, 8192U); 541 542 dev_dbg(dev, "%s: out_seam %u(%u) in [%u, %u], in_seam %u(%u) diff %u.%03u\n", 543 __func__, out_seam, out_align, out_start, out_end, 544 *_in_seam, in_align, min_diff / 8192, 545 DIV_ROUND_CLOSEST(min_diff % 8192 * 1000, 8192)); 546 } 547 548 /* 549 * Tile left edges are required to be aligned to multiples of 8 bytes 550 * by the IDMAC. 551 */ 552 static inline u32 tile_left_align(const struct ipu_image_pixfmt *fmt) 553 { 554 if (fmt->planar) 555 return fmt->uv_packed ? 8 : 8 * fmt->uv_width_dec; 556 else 557 return fmt->bpp == 32 ? 2 : fmt->bpp == 16 ? 4 : 8; 558 } 559 560 /* 561 * Tile top edge alignment is only limited by chroma subsampling. 562 */ 563 static inline u32 tile_top_align(const struct ipu_image_pixfmt *fmt) 564 { 565 return fmt->uv_height_dec > 1 ? 2 : 1; 566 } 567 568 static inline u32 tile_width_align(enum ipu_image_convert_type type, 569 const struct ipu_image_pixfmt *fmt, 570 enum ipu_rotate_mode rot_mode) 571 { 572 if (type == IMAGE_CONVERT_IN) { 573 /* 574 * The IC burst reads 8 pixels at a time. Reading beyond the 575 * end of the line is usually acceptable. Those pixels are 576 * ignored, unless the IC has to write the scaled line in 577 * reverse. 578 */ 579 return (!ipu_rot_mode_is_irt(rot_mode) && 580 (rot_mode & IPU_ROT_BIT_HFLIP)) ? 8 : 2; 581 } 582 583 /* 584 * Align to 16x16 pixel blocks for planar 4:2:0 chroma subsampled 585 * formats to guarantee 8-byte aligned line start addresses in the 586 * chroma planes when IRT is used. Align to 8x8 pixel IRT block size 587 * for all other formats. 588 */ 589 return (ipu_rot_mode_is_irt(rot_mode) && 590 fmt->planar && !fmt->uv_packed) ? 591 8 * fmt->uv_width_dec : 8; 592 } 593 594 static inline u32 tile_height_align(enum ipu_image_convert_type type, 595 const struct ipu_image_pixfmt *fmt, 596 enum ipu_rotate_mode rot_mode) 597 { 598 if (type == IMAGE_CONVERT_IN || !ipu_rot_mode_is_irt(rot_mode)) 599 return 2; 600 601 /* 602 * Align to 16x16 pixel blocks for planar 4:2:0 chroma subsampled 603 * formats to guarantee 8-byte aligned line start addresses in the 604 * chroma planes when IRT is used. Align to 8x8 pixel IRT block size 605 * for all other formats. 606 */ 607 return (fmt->planar && !fmt->uv_packed) ? 8 * fmt->uv_width_dec : 8; 608 } 609 610 /* 611 * Fill in left position and width and for all tiles in an input column, and 612 * for all corresponding output tiles. If the 90° rotator is used, the output 613 * tiles are in a row, and output tile top position and height are set. 614 */ 615 static void fill_tile_column(struct ipu_image_convert_ctx *ctx, 616 unsigned int col, 617 struct ipu_image_convert_image *in, 618 unsigned int in_left, unsigned int in_width, 619 struct ipu_image_convert_image *out, 620 unsigned int out_left, unsigned int out_width) 621 { 622 unsigned int row, tile_idx; 623 struct ipu_image_tile *in_tile, *out_tile; 624 625 for (row = 0; row < in->num_rows; row++) { 626 tile_idx = in->num_cols * row + col; 627 in_tile = &in->tile[tile_idx]; 628 out_tile = &out->tile[ctx->out_tile_map[tile_idx]]; 629 630 in_tile->left = in_left; 631 in_tile->width = in_width; 632 633 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { 634 out_tile->top = out_left; 635 out_tile->height = out_width; 636 } else { 637 out_tile->left = out_left; 638 out_tile->width = out_width; 639 } 640 } 641 } 642 643 /* 644 * Fill in top position and height and for all tiles in an input row, and 645 * for all corresponding output tiles. If the 90° rotator is used, the output 646 * tiles are in a column, and output tile left position and width are set. 647 */ 648 static void fill_tile_row(struct ipu_image_convert_ctx *ctx, unsigned int row, 649 struct ipu_image_convert_image *in, 650 unsigned int in_top, unsigned int in_height, 651 struct ipu_image_convert_image *out, 652 unsigned int out_top, unsigned int out_height) 653 { 654 unsigned int col, tile_idx; 655 struct ipu_image_tile *in_tile, *out_tile; 656 657 for (col = 0; col < in->num_cols; col++) { 658 tile_idx = in->num_cols * row + col; 659 in_tile = &in->tile[tile_idx]; 660 out_tile = &out->tile[ctx->out_tile_map[tile_idx]]; 661 662 in_tile->top = in_top; 663 in_tile->height = in_height; 664 665 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { 666 out_tile->left = out_top; 667 out_tile->width = out_height; 668 } else { 669 out_tile->top = out_top; 670 out_tile->height = out_height; 671 } 672 } 673 } 674 675 /* 676 * Find the best horizontal and vertical seam positions to split into tiles. 677 * Minimize the fractional part of the input sampling position for the 678 * top / left pixels of each tile. 679 */ 680 static void find_seams(struct ipu_image_convert_ctx *ctx, 681 struct ipu_image_convert_image *in, 682 struct ipu_image_convert_image *out) 683 { 684 struct device *dev = ctx->chan->priv->ipu->dev; 685 unsigned int resized_width = out->base.rect.width; 686 unsigned int resized_height = out->base.rect.height; 687 unsigned int col; 688 unsigned int row; 689 unsigned int in_left_align = tile_left_align(in->fmt); 690 unsigned int in_top_align = tile_top_align(in->fmt); 691 unsigned int out_left_align = tile_left_align(out->fmt); 692 unsigned int out_top_align = tile_top_align(out->fmt); 693 unsigned int out_width_align = tile_width_align(out->type, out->fmt, 694 ctx->rot_mode); 695 unsigned int out_height_align = tile_height_align(out->type, out->fmt, 696 ctx->rot_mode); 697 unsigned int in_right = in->base.rect.width; 698 unsigned int in_bottom = in->base.rect.height; 699 unsigned int out_right = out->base.rect.width; 700 unsigned int out_bottom = out->base.rect.height; 701 unsigned int flipped_out_left; 702 unsigned int flipped_out_top; 703 704 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { 705 /* Switch width/height and align top left to IRT block size */ 706 resized_width = out->base.rect.height; 707 resized_height = out->base.rect.width; 708 out_left_align = out_height_align; 709 out_top_align = out_width_align; 710 out_width_align = out_left_align; 711 out_height_align = out_top_align; 712 out_right = out->base.rect.height; 713 out_bottom = out->base.rect.width; 714 } 715 716 for (col = in->num_cols - 1; col > 0; col--) { 717 bool allow_in_overshoot = ipu_rot_mode_is_irt(ctx->rot_mode) || 718 !(ctx->rot_mode & IPU_ROT_BIT_HFLIP); 719 bool allow_out_overshoot = (col < in->num_cols - 1) && 720 !(ctx->rot_mode & IPU_ROT_BIT_HFLIP); 721 unsigned int out_start; 722 unsigned int out_end; 723 unsigned int in_left; 724 unsigned int out_left; 725 726 /* 727 * Align input width to burst length if the scaling step flips 728 * horizontally. 729 */ 730 731 /* Start within 1024 pixels of the right edge */ 732 out_start = max_t(int, 0, out_right - 1024); 733 /* End before having to add more columns to the left */ 734 out_end = min_t(unsigned int, out_right, col * 1024); 735 736 find_best_seam(ctx, out_start, out_end, 737 in_right, out_right, 738 in_left_align, out_left_align, 739 allow_in_overshoot ? 1 : 8 /* burst length */, 740 allow_out_overshoot ? 1 : out_width_align, 741 ctx->downsize_coeff_h, ctx->image_resize_coeff_h, 742 &in_left, &out_left); 743 744 if (ctx->rot_mode & IPU_ROT_BIT_HFLIP) 745 flipped_out_left = resized_width - out_right; 746 else 747 flipped_out_left = out_left; 748 749 fill_tile_column(ctx, col, in, in_left, in_right - in_left, 750 out, flipped_out_left, out_right - out_left); 751 752 dev_dbg(dev, "%s: col %u: %u, %u -> %u, %u\n", __func__, col, 753 in_left, in_right - in_left, 754 flipped_out_left, out_right - out_left); 755 756 in_right = in_left; 757 out_right = out_left; 758 } 759 760 flipped_out_left = (ctx->rot_mode & IPU_ROT_BIT_HFLIP) ? 761 resized_width - out_right : 0; 762 763 fill_tile_column(ctx, 0, in, 0, in_right, 764 out, flipped_out_left, out_right); 765 766 dev_dbg(dev, "%s: col 0: 0, %u -> %u, %u\n", __func__, 767 in_right, flipped_out_left, out_right); 768 769 for (row = in->num_rows - 1; row > 0; row--) { 770 bool allow_overshoot = row < in->num_rows - 1; 771 unsigned int out_start; 772 unsigned int out_end; 773 unsigned int in_top; 774 unsigned int out_top; 775 776 /* Start within 1024 lines of the bottom edge */ 777 out_start = max_t(int, 0, out_bottom - 1024); 778 /* End before having to add more rows above */ 779 out_end = min_t(unsigned int, out_bottom, row * 1024); 780 781 find_best_seam(ctx, out_start, out_end, 782 in_bottom, out_bottom, 783 in_top_align, out_top_align, 784 1, allow_overshoot ? 1 : out_height_align, 785 ctx->downsize_coeff_v, ctx->image_resize_coeff_v, 786 &in_top, &out_top); 787 788 if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^ 789 ipu_rot_mode_is_irt(ctx->rot_mode)) 790 flipped_out_top = resized_height - out_bottom; 791 else 792 flipped_out_top = out_top; 793 794 fill_tile_row(ctx, row, in, in_top, in_bottom - in_top, 795 out, flipped_out_top, out_bottom - out_top); 796 797 dev_dbg(dev, "%s: row %u: %u, %u -> %u, %u\n", __func__, row, 798 in_top, in_bottom - in_top, 799 flipped_out_top, out_bottom - out_top); 800 801 in_bottom = in_top; 802 out_bottom = out_top; 803 } 804 805 if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^ 806 ipu_rot_mode_is_irt(ctx->rot_mode)) 807 flipped_out_top = resized_height - out_bottom; 808 else 809 flipped_out_top = 0; 810 811 fill_tile_row(ctx, 0, in, 0, in_bottom, 812 out, flipped_out_top, out_bottom); 813 814 dev_dbg(dev, "%s: row 0: 0, %u -> %u, %u\n", __func__, 815 in_bottom, flipped_out_top, out_bottom); 816 } 817 818 static void calc_tile_dimensions(struct ipu_image_convert_ctx *ctx, 819 struct ipu_image_convert_image *image) 820 { 821 struct ipu_image_convert_chan *chan = ctx->chan; 822 struct ipu_image_convert_priv *priv = chan->priv; 823 unsigned int i; 824 825 for (i = 0; i < ctx->num_tiles; i++) { 826 struct ipu_image_tile *tile; 827 const unsigned int row = i / image->num_cols; 828 const unsigned int col = i % image->num_cols; 829 830 if (image->type == IMAGE_CONVERT_OUT) 831 tile = &image->tile[ctx->out_tile_map[i]]; 832 else 833 tile = &image->tile[i]; 834 835 tile->size = ((tile->height * image->fmt->bpp) >> 3) * 836 tile->width; 837 838 if (image->fmt->planar) { 839 tile->stride = tile->width; 840 tile->rot_stride = tile->height; 841 } else { 842 tile->stride = 843 (image->fmt->bpp * tile->width) >> 3; 844 tile->rot_stride = 845 (image->fmt->bpp * tile->height) >> 3; 846 } 847 848 dev_dbg(priv->ipu->dev, 849 "task %u: ctx %p: %s@[%u,%u]: %ux%u@%u,%u\n", 850 chan->ic_task, ctx, 851 image->type == IMAGE_CONVERT_IN ? "Input" : "Output", 852 row, col, 853 tile->width, tile->height, tile->left, tile->top); 854 } 855 } 856 857 /* 858 * Use the rotation transformation to find the tile coordinates 859 * (row, col) of a tile in the destination frame that corresponds 860 * to the given tile coordinates of a source frame. The destination 861 * coordinate is then converted to a tile index. 862 */ 863 static int transform_tile_index(struct ipu_image_convert_ctx *ctx, 864 int src_row, int src_col) 865 { 866 struct ipu_image_convert_chan *chan = ctx->chan; 867 struct ipu_image_convert_priv *priv = chan->priv; 868 struct ipu_image_convert_image *s_image = &ctx->in; 869 struct ipu_image_convert_image *d_image = &ctx->out; 870 int dst_row, dst_col; 871 872 /* with no rotation it's a 1:1 mapping */ 873 if (ctx->rot_mode == IPU_ROTATE_NONE) 874 return src_row * s_image->num_cols + src_col; 875 876 /* 877 * before doing the transform, first we have to translate 878 * source row,col for an origin in the center of s_image 879 */ 880 src_row = src_row * 2 - (s_image->num_rows - 1); 881 src_col = src_col * 2 - (s_image->num_cols - 1); 882 883 /* do the rotation transform */ 884 if (ctx->rot_mode & IPU_ROT_BIT_90) { 885 dst_col = -src_row; 886 dst_row = src_col; 887 } else { 888 dst_col = src_col; 889 dst_row = src_row; 890 } 891 892 /* apply flip */ 893 if (ctx->rot_mode & IPU_ROT_BIT_HFLIP) 894 dst_col = -dst_col; 895 if (ctx->rot_mode & IPU_ROT_BIT_VFLIP) 896 dst_row = -dst_row; 897 898 dev_dbg(priv->ipu->dev, "task %u: ctx %p: [%d,%d] --> [%d,%d]\n", 899 chan->ic_task, ctx, src_col, src_row, dst_col, dst_row); 900 901 /* 902 * finally translate dest row,col using an origin in upper 903 * left of d_image 904 */ 905 dst_row += d_image->num_rows - 1; 906 dst_col += d_image->num_cols - 1; 907 dst_row /= 2; 908 dst_col /= 2; 909 910 return dst_row * d_image->num_cols + dst_col; 911 } 912 913 /* 914 * Fill the out_tile_map[] with transformed destination tile indeces. 915 */ 916 static void calc_out_tile_map(struct ipu_image_convert_ctx *ctx) 917 { 918 struct ipu_image_convert_image *s_image = &ctx->in; 919 unsigned int row, col, tile = 0; 920 921 for (row = 0; row < s_image->num_rows; row++) { 922 for (col = 0; col < s_image->num_cols; col++) { 923 ctx->out_tile_map[tile] = 924 transform_tile_index(ctx, row, col); 925 tile++; 926 } 927 } 928 } 929 930 static int calc_tile_offsets_planar(struct ipu_image_convert_ctx *ctx, 931 struct ipu_image_convert_image *image) 932 { 933 struct ipu_image_convert_chan *chan = ctx->chan; 934 struct ipu_image_convert_priv *priv = chan->priv; 935 const struct ipu_image_pixfmt *fmt = image->fmt; 936 unsigned int row, col, tile = 0; 937 u32 H, top, y_stride, uv_stride; 938 u32 uv_row_off, uv_col_off, uv_off, u_off, v_off, tmp; 939 u32 y_row_off, y_col_off, y_off; 940 u32 y_size, uv_size; 941 942 /* setup some convenience vars */ 943 H = image->base.pix.height; 944 945 y_stride = image->stride; 946 uv_stride = y_stride / fmt->uv_width_dec; 947 if (fmt->uv_packed) 948 uv_stride *= 2; 949 950 y_size = H * y_stride; 951 uv_size = y_size / (fmt->uv_width_dec * fmt->uv_height_dec); 952 953 for (row = 0; row < image->num_rows; row++) { 954 top = image->tile[tile].top; 955 y_row_off = top * y_stride; 956 uv_row_off = (top * uv_stride) / fmt->uv_height_dec; 957 958 for (col = 0; col < image->num_cols; col++) { 959 y_col_off = image->tile[tile].left; 960 uv_col_off = y_col_off / fmt->uv_width_dec; 961 if (fmt->uv_packed) 962 uv_col_off *= 2; 963 964 y_off = y_row_off + y_col_off; 965 uv_off = uv_row_off + uv_col_off; 966 967 u_off = y_size - y_off + uv_off; 968 v_off = (fmt->uv_packed) ? 0 : u_off + uv_size; 969 if (fmt->uv_swapped) { 970 tmp = u_off; 971 u_off = v_off; 972 v_off = tmp; 973 } 974 975 image->tile[tile].offset = y_off; 976 image->tile[tile].u_off = u_off; 977 image->tile[tile++].v_off = v_off; 978 979 if ((y_off & 0x7) || (u_off & 0x7) || (v_off & 0x7)) { 980 dev_err(priv->ipu->dev, 981 "task %u: ctx %p: %s@[%d,%d]: " 982 "y_off %08x, u_off %08x, v_off %08x\n", 983 chan->ic_task, ctx, 984 image->type == IMAGE_CONVERT_IN ? 985 "Input" : "Output", row, col, 986 y_off, u_off, v_off); 987 return -EINVAL; 988 } 989 } 990 } 991 992 return 0; 993 } 994 995 static int calc_tile_offsets_packed(struct ipu_image_convert_ctx *ctx, 996 struct ipu_image_convert_image *image) 997 { 998 struct ipu_image_convert_chan *chan = ctx->chan; 999 struct ipu_image_convert_priv *priv = chan->priv; 1000 const struct ipu_image_pixfmt *fmt = image->fmt; 1001 unsigned int row, col, tile = 0; 1002 u32 bpp, stride, offset; 1003 u32 row_off, col_off; 1004 1005 /* setup some convenience vars */ 1006 stride = image->stride; 1007 bpp = fmt->bpp; 1008 1009 for (row = 0; row < image->num_rows; row++) { 1010 row_off = image->tile[tile].top * stride; 1011 1012 for (col = 0; col < image->num_cols; col++) { 1013 col_off = (image->tile[tile].left * bpp) >> 3; 1014 1015 offset = row_off + col_off; 1016 1017 image->tile[tile].offset = offset; 1018 image->tile[tile].u_off = 0; 1019 image->tile[tile++].v_off = 0; 1020 1021 if (offset & 0x7) { 1022 dev_err(priv->ipu->dev, 1023 "task %u: ctx %p: %s@[%d,%d]: " 1024 "phys %08x\n", 1025 chan->ic_task, ctx, 1026 image->type == IMAGE_CONVERT_IN ? 1027 "Input" : "Output", row, col, 1028 row_off + col_off); 1029 return -EINVAL; 1030 } 1031 } 1032 } 1033 1034 return 0; 1035 } 1036 1037 static int calc_tile_offsets(struct ipu_image_convert_ctx *ctx, 1038 struct ipu_image_convert_image *image) 1039 { 1040 if (image->fmt->planar) 1041 return calc_tile_offsets_planar(ctx, image); 1042 1043 return calc_tile_offsets_packed(ctx, image); 1044 } 1045 1046 /* 1047 * Calculate the resizing ratio for the IC main processing section given input 1048 * size, fixed downsizing coefficient, and output size. 1049 * Either round to closest for the next tile's first pixel to minimize seams 1050 * and distortion (for all but right column / bottom row), or round down to 1051 * avoid sampling beyond the edges of the input image for this tile's last 1052 * pixel. 1053 * Returns the resizing coefficient, resizing ratio is 8192.0 / resize_coeff. 1054 */ 1055 static u32 calc_resize_coeff(u32 input_size, u32 downsize_coeff, 1056 u32 output_size, bool allow_overshoot) 1057 { 1058 u32 downsized = input_size >> downsize_coeff; 1059 1060 if (allow_overshoot) 1061 return DIV_ROUND_CLOSEST(8192 * downsized, output_size); 1062 else 1063 return 8192 * (downsized - 1) / (output_size - 1); 1064 } 1065 1066 /* 1067 * Slightly modify resize coefficients per tile to hide the bilinear 1068 * interpolator reset at tile borders, shifting the right / bottom edge 1069 * by up to a half input pixel. This removes noticeable seams between 1070 * tiles at higher upscaling factors. 1071 */ 1072 static void calc_tile_resize_coefficients(struct ipu_image_convert_ctx *ctx) 1073 { 1074 struct ipu_image_convert_chan *chan = ctx->chan; 1075 struct ipu_image_convert_priv *priv = chan->priv; 1076 struct ipu_image_tile *in_tile, *out_tile; 1077 unsigned int col, row, tile_idx; 1078 unsigned int last_output; 1079 1080 for (col = 0; col < ctx->in.num_cols; col++) { 1081 bool closest = (col < ctx->in.num_cols - 1) && 1082 !(ctx->rot_mode & IPU_ROT_BIT_HFLIP); 1083 u32 resized_width; 1084 u32 resize_coeff_h; 1085 1086 tile_idx = col; 1087 in_tile = &ctx->in.tile[tile_idx]; 1088 out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]]; 1089 1090 if (ipu_rot_mode_is_irt(ctx->rot_mode)) 1091 resized_width = out_tile->height; 1092 else 1093 resized_width = out_tile->width; 1094 1095 resize_coeff_h = calc_resize_coeff(in_tile->width, 1096 ctx->downsize_coeff_h, 1097 resized_width, closest); 1098 1099 dev_dbg(priv->ipu->dev, "%s: column %u hscale: *8192/%u\n", 1100 __func__, col, resize_coeff_h); 1101 1102 1103 for (row = 0; row < ctx->in.num_rows; row++) { 1104 tile_idx = row * ctx->in.num_cols + col; 1105 in_tile = &ctx->in.tile[tile_idx]; 1106 out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]]; 1107 1108 /* 1109 * With the horizontal scaling factor known, round up 1110 * resized width (output width or height) to burst size. 1111 */ 1112 if (ipu_rot_mode_is_irt(ctx->rot_mode)) 1113 out_tile->height = round_up(resized_width, 8); 1114 else 1115 out_tile->width = round_up(resized_width, 8); 1116 1117 /* 1118 * Calculate input width from the last accessed input 1119 * pixel given resized width and scaling coefficients. 1120 * Round up to burst size. 1121 */ 1122 last_output = round_up(resized_width, 8) - 1; 1123 if (closest) 1124 last_output++; 1125 in_tile->width = round_up( 1126 (DIV_ROUND_UP(last_output * resize_coeff_h, 1127 8192) + 1) 1128 << ctx->downsize_coeff_h, 8); 1129 } 1130 1131 ctx->resize_coeffs_h[col] = resize_coeff_h; 1132 } 1133 1134 for (row = 0; row < ctx->in.num_rows; row++) { 1135 bool closest = (row < ctx->in.num_rows - 1) && 1136 !(ctx->rot_mode & IPU_ROT_BIT_VFLIP); 1137 u32 resized_height; 1138 u32 resize_coeff_v; 1139 1140 tile_idx = row * ctx->in.num_cols; 1141 in_tile = &ctx->in.tile[tile_idx]; 1142 out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]]; 1143 1144 if (ipu_rot_mode_is_irt(ctx->rot_mode)) 1145 resized_height = out_tile->width; 1146 else 1147 resized_height = out_tile->height; 1148 1149 resize_coeff_v = calc_resize_coeff(in_tile->height, 1150 ctx->downsize_coeff_v, 1151 resized_height, closest); 1152 1153 dev_dbg(priv->ipu->dev, "%s: row %u vscale: *8192/%u\n", 1154 __func__, row, resize_coeff_v); 1155 1156 for (col = 0; col < ctx->in.num_cols; col++) { 1157 tile_idx = row * ctx->in.num_cols + col; 1158 in_tile = &ctx->in.tile[tile_idx]; 1159 out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]]; 1160 1161 /* 1162 * With the vertical scaling factor known, round up 1163 * resized height (output width or height) to IDMAC 1164 * limitations. 1165 */ 1166 if (ipu_rot_mode_is_irt(ctx->rot_mode)) 1167 out_tile->width = round_up(resized_height, 2); 1168 else 1169 out_tile->height = round_up(resized_height, 2); 1170 1171 /* 1172 * Calculate input width from the last accessed input 1173 * pixel given resized height and scaling coefficients. 1174 * Align to IDMAC restrictions. 1175 */ 1176 last_output = round_up(resized_height, 2) - 1; 1177 if (closest) 1178 last_output++; 1179 in_tile->height = round_up( 1180 (DIV_ROUND_UP(last_output * resize_coeff_v, 1181 8192) + 1) 1182 << ctx->downsize_coeff_v, 2); 1183 } 1184 1185 ctx->resize_coeffs_v[row] = resize_coeff_v; 1186 } 1187 } 1188 1189 /* 1190 * return the number of runs in given queue (pending_q or done_q) 1191 * for this context. hold irqlock when calling. 1192 */ 1193 static int get_run_count(struct ipu_image_convert_ctx *ctx, 1194 struct list_head *q) 1195 { 1196 struct ipu_image_convert_run *run; 1197 int count = 0; 1198 1199 lockdep_assert_held(&ctx->chan->irqlock); 1200 1201 list_for_each_entry(run, q, list) { 1202 if (run->ctx == ctx) 1203 count++; 1204 } 1205 1206 return count; 1207 } 1208 1209 static void convert_stop(struct ipu_image_convert_run *run) 1210 { 1211 struct ipu_image_convert_ctx *ctx = run->ctx; 1212 struct ipu_image_convert_chan *chan = ctx->chan; 1213 struct ipu_image_convert_priv *priv = chan->priv; 1214 1215 dev_dbg(priv->ipu->dev, "%s: task %u: stopping ctx %p run %p\n", 1216 __func__, chan->ic_task, ctx, run); 1217 1218 /* disable IC tasks and the channels */ 1219 ipu_ic_task_disable(chan->ic); 1220 ipu_idmac_disable_channel(chan->in_chan); 1221 ipu_idmac_disable_channel(chan->out_chan); 1222 1223 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { 1224 ipu_idmac_disable_channel(chan->rotation_in_chan); 1225 ipu_idmac_disable_channel(chan->rotation_out_chan); 1226 ipu_idmac_unlink(chan->out_chan, chan->rotation_in_chan); 1227 } 1228 1229 ipu_ic_disable(chan->ic); 1230 } 1231 1232 static void init_idmac_channel(struct ipu_image_convert_ctx *ctx, 1233 struct ipuv3_channel *channel, 1234 struct ipu_image_convert_image *image, 1235 enum ipu_rotate_mode rot_mode, 1236 bool rot_swap_width_height, 1237 unsigned int tile) 1238 { 1239 struct ipu_image_convert_chan *chan = ctx->chan; 1240 unsigned int burst_size; 1241 u32 width, height, stride; 1242 dma_addr_t addr0, addr1 = 0; 1243 struct ipu_image tile_image; 1244 unsigned int tile_idx[2]; 1245 1246 if (image->type == IMAGE_CONVERT_OUT) { 1247 tile_idx[0] = ctx->out_tile_map[tile]; 1248 tile_idx[1] = ctx->out_tile_map[1]; 1249 } else { 1250 tile_idx[0] = tile; 1251 tile_idx[1] = 1; 1252 } 1253 1254 if (rot_swap_width_height) { 1255 width = image->tile[tile_idx[0]].height; 1256 height = image->tile[tile_idx[0]].width; 1257 stride = image->tile[tile_idx[0]].rot_stride; 1258 addr0 = ctx->rot_intermediate[0].phys; 1259 if (ctx->double_buffering) 1260 addr1 = ctx->rot_intermediate[1].phys; 1261 } else { 1262 width = image->tile[tile_idx[0]].width; 1263 height = image->tile[tile_idx[0]].height; 1264 stride = image->stride; 1265 addr0 = image->base.phys0 + 1266 image->tile[tile_idx[0]].offset; 1267 if (ctx->double_buffering) 1268 addr1 = image->base.phys0 + 1269 image->tile[tile_idx[1]].offset; 1270 } 1271 1272 ipu_cpmem_zero(channel); 1273 1274 memset(&tile_image, 0, sizeof(tile_image)); 1275 tile_image.pix.width = tile_image.rect.width = width; 1276 tile_image.pix.height = tile_image.rect.height = height; 1277 tile_image.pix.bytesperline = stride; 1278 tile_image.pix.pixelformat = image->fmt->fourcc; 1279 tile_image.phys0 = addr0; 1280 tile_image.phys1 = addr1; 1281 if (image->fmt->planar && !rot_swap_width_height) { 1282 tile_image.u_offset = image->tile[tile_idx[0]].u_off; 1283 tile_image.v_offset = image->tile[tile_idx[0]].v_off; 1284 } 1285 1286 ipu_cpmem_set_image(channel, &tile_image); 1287 1288 if (rot_mode) 1289 ipu_cpmem_set_rotation(channel, rot_mode); 1290 1291 if (channel == chan->rotation_in_chan || 1292 channel == chan->rotation_out_chan) { 1293 burst_size = 8; 1294 ipu_cpmem_set_block_mode(channel); 1295 } else 1296 burst_size = (width % 16) ? 8 : 16; 1297 1298 ipu_cpmem_set_burstsize(channel, burst_size); 1299 1300 ipu_ic_task_idma_init(chan->ic, channel, width, height, 1301 burst_size, rot_mode); 1302 1303 /* 1304 * Setting a non-zero AXI ID collides with the PRG AXI snooping, so 1305 * only do this when there is no PRG present. 1306 */ 1307 if (!channel->ipu->prg_priv) 1308 ipu_cpmem_set_axi_id(channel, 1); 1309 1310 ipu_idmac_set_double_buffer(channel, ctx->double_buffering); 1311 } 1312 1313 static int convert_start(struct ipu_image_convert_run *run, unsigned int tile) 1314 { 1315 struct ipu_image_convert_ctx *ctx = run->ctx; 1316 struct ipu_image_convert_chan *chan = ctx->chan; 1317 struct ipu_image_convert_priv *priv = chan->priv; 1318 struct ipu_image_convert_image *s_image = &ctx->in; 1319 struct ipu_image_convert_image *d_image = &ctx->out; 1320 enum ipu_color_space src_cs, dest_cs; 1321 unsigned int dst_tile = ctx->out_tile_map[tile]; 1322 unsigned int dest_width, dest_height; 1323 unsigned int col, row; 1324 u32 rsc; 1325 int ret; 1326 1327 dev_dbg(priv->ipu->dev, "%s: task %u: starting ctx %p run %p tile %u -> %u\n", 1328 __func__, chan->ic_task, ctx, run, tile, dst_tile); 1329 1330 src_cs = ipu_pixelformat_to_colorspace(s_image->fmt->fourcc); 1331 dest_cs = ipu_pixelformat_to_colorspace(d_image->fmt->fourcc); 1332 1333 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { 1334 /* swap width/height for resizer */ 1335 dest_width = d_image->tile[dst_tile].height; 1336 dest_height = d_image->tile[dst_tile].width; 1337 } else { 1338 dest_width = d_image->tile[dst_tile].width; 1339 dest_height = d_image->tile[dst_tile].height; 1340 } 1341 1342 row = tile / s_image->num_cols; 1343 col = tile % s_image->num_cols; 1344 1345 rsc = (ctx->downsize_coeff_v << 30) | 1346 (ctx->resize_coeffs_v[row] << 16) | 1347 (ctx->downsize_coeff_h << 14) | 1348 (ctx->resize_coeffs_h[col]); 1349 1350 dev_dbg(priv->ipu->dev, "%s: %ux%u -> %ux%u (rsc = 0x%x)\n", 1351 __func__, s_image->tile[tile].width, 1352 s_image->tile[tile].height, dest_width, dest_height, rsc); 1353 1354 /* setup the IC resizer and CSC */ 1355 ret = ipu_ic_task_init_rsc(chan->ic, 1356 s_image->tile[tile].width, 1357 s_image->tile[tile].height, 1358 dest_width, 1359 dest_height, 1360 src_cs, dest_cs, 1361 rsc); 1362 if (ret) { 1363 dev_err(priv->ipu->dev, "ipu_ic_task_init failed, %d\n", ret); 1364 return ret; 1365 } 1366 1367 /* init the source MEM-->IC PP IDMAC channel */ 1368 init_idmac_channel(ctx, chan->in_chan, s_image, 1369 IPU_ROTATE_NONE, false, tile); 1370 1371 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { 1372 /* init the IC PP-->MEM IDMAC channel */ 1373 init_idmac_channel(ctx, chan->out_chan, d_image, 1374 IPU_ROTATE_NONE, true, tile); 1375 1376 /* init the MEM-->IC PP ROT IDMAC channel */ 1377 init_idmac_channel(ctx, chan->rotation_in_chan, d_image, 1378 ctx->rot_mode, true, tile); 1379 1380 /* init the destination IC PP ROT-->MEM IDMAC channel */ 1381 init_idmac_channel(ctx, chan->rotation_out_chan, d_image, 1382 IPU_ROTATE_NONE, false, tile); 1383 1384 /* now link IC PP-->MEM to MEM-->IC PP ROT */ 1385 ipu_idmac_link(chan->out_chan, chan->rotation_in_chan); 1386 } else { 1387 /* init the destination IC PP-->MEM IDMAC channel */ 1388 init_idmac_channel(ctx, chan->out_chan, d_image, 1389 ctx->rot_mode, false, tile); 1390 } 1391 1392 /* enable the IC */ 1393 ipu_ic_enable(chan->ic); 1394 1395 /* set buffers ready */ 1396 ipu_idmac_select_buffer(chan->in_chan, 0); 1397 ipu_idmac_select_buffer(chan->out_chan, 0); 1398 if (ipu_rot_mode_is_irt(ctx->rot_mode)) 1399 ipu_idmac_select_buffer(chan->rotation_out_chan, 0); 1400 if (ctx->double_buffering) { 1401 ipu_idmac_select_buffer(chan->in_chan, 1); 1402 ipu_idmac_select_buffer(chan->out_chan, 1); 1403 if (ipu_rot_mode_is_irt(ctx->rot_mode)) 1404 ipu_idmac_select_buffer(chan->rotation_out_chan, 1); 1405 } 1406 1407 /* enable the channels! */ 1408 ipu_idmac_enable_channel(chan->in_chan); 1409 ipu_idmac_enable_channel(chan->out_chan); 1410 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { 1411 ipu_idmac_enable_channel(chan->rotation_in_chan); 1412 ipu_idmac_enable_channel(chan->rotation_out_chan); 1413 } 1414 1415 ipu_ic_task_enable(chan->ic); 1416 1417 ipu_cpmem_dump(chan->in_chan); 1418 ipu_cpmem_dump(chan->out_chan); 1419 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { 1420 ipu_cpmem_dump(chan->rotation_in_chan); 1421 ipu_cpmem_dump(chan->rotation_out_chan); 1422 } 1423 1424 ipu_dump(priv->ipu); 1425 1426 return 0; 1427 } 1428 1429 /* hold irqlock when calling */ 1430 static int do_run(struct ipu_image_convert_run *run) 1431 { 1432 struct ipu_image_convert_ctx *ctx = run->ctx; 1433 struct ipu_image_convert_chan *chan = ctx->chan; 1434 1435 lockdep_assert_held(&chan->irqlock); 1436 1437 ctx->in.base.phys0 = run->in_phys; 1438 ctx->out.base.phys0 = run->out_phys; 1439 1440 ctx->cur_buf_num = 0; 1441 ctx->next_tile = 1; 1442 1443 /* remove run from pending_q and set as current */ 1444 list_del(&run->list); 1445 chan->current_run = run; 1446 1447 return convert_start(run, 0); 1448 } 1449 1450 /* hold irqlock when calling */ 1451 static void run_next(struct ipu_image_convert_chan *chan) 1452 { 1453 struct ipu_image_convert_priv *priv = chan->priv; 1454 struct ipu_image_convert_run *run, *tmp; 1455 int ret; 1456 1457 lockdep_assert_held(&chan->irqlock); 1458 1459 list_for_each_entry_safe(run, tmp, &chan->pending_q, list) { 1460 /* skip contexts that are aborting */ 1461 if (run->ctx->aborting) { 1462 dev_dbg(priv->ipu->dev, 1463 "%s: task %u: skipping aborting ctx %p run %p\n", 1464 __func__, chan->ic_task, run->ctx, run); 1465 continue; 1466 } 1467 1468 ret = do_run(run); 1469 if (!ret) 1470 break; 1471 1472 /* 1473 * something went wrong with start, add the run 1474 * to done q and continue to the next run in the 1475 * pending q. 1476 */ 1477 run->status = ret; 1478 list_add_tail(&run->list, &chan->done_q); 1479 chan->current_run = NULL; 1480 } 1481 } 1482 1483 static void empty_done_q(struct ipu_image_convert_chan *chan) 1484 { 1485 struct ipu_image_convert_priv *priv = chan->priv; 1486 struct ipu_image_convert_run *run; 1487 unsigned long flags; 1488 1489 spin_lock_irqsave(&chan->irqlock, flags); 1490 1491 while (!list_empty(&chan->done_q)) { 1492 run = list_entry(chan->done_q.next, 1493 struct ipu_image_convert_run, 1494 list); 1495 1496 list_del(&run->list); 1497 1498 dev_dbg(priv->ipu->dev, 1499 "%s: task %u: completing ctx %p run %p with %d\n", 1500 __func__, chan->ic_task, run->ctx, run, run->status); 1501 1502 /* call the completion callback and free the run */ 1503 spin_unlock_irqrestore(&chan->irqlock, flags); 1504 run->ctx->complete(run, run->ctx->complete_context); 1505 spin_lock_irqsave(&chan->irqlock, flags); 1506 } 1507 1508 spin_unlock_irqrestore(&chan->irqlock, flags); 1509 } 1510 1511 /* 1512 * the bottom half thread clears out the done_q, calling the 1513 * completion handler for each. 1514 */ 1515 static irqreturn_t do_bh(int irq, void *dev_id) 1516 { 1517 struct ipu_image_convert_chan *chan = dev_id; 1518 struct ipu_image_convert_priv *priv = chan->priv; 1519 struct ipu_image_convert_ctx *ctx; 1520 unsigned long flags; 1521 1522 dev_dbg(priv->ipu->dev, "%s: task %u: enter\n", __func__, 1523 chan->ic_task); 1524 1525 empty_done_q(chan); 1526 1527 spin_lock_irqsave(&chan->irqlock, flags); 1528 1529 /* 1530 * the done_q is cleared out, signal any contexts 1531 * that are aborting that abort can complete. 1532 */ 1533 list_for_each_entry(ctx, &chan->ctx_list, list) { 1534 if (ctx->aborting) { 1535 dev_dbg(priv->ipu->dev, 1536 "%s: task %u: signaling abort for ctx %p\n", 1537 __func__, chan->ic_task, ctx); 1538 complete_all(&ctx->aborted); 1539 } 1540 } 1541 1542 spin_unlock_irqrestore(&chan->irqlock, flags); 1543 1544 dev_dbg(priv->ipu->dev, "%s: task %u: exit\n", __func__, 1545 chan->ic_task); 1546 1547 return IRQ_HANDLED; 1548 } 1549 1550 static bool ic_settings_changed(struct ipu_image_convert_ctx *ctx) 1551 { 1552 unsigned int cur_tile = ctx->next_tile - 1; 1553 unsigned int next_tile = ctx->next_tile; 1554 1555 if (ctx->resize_coeffs_h[cur_tile % ctx->in.num_cols] != 1556 ctx->resize_coeffs_h[next_tile % ctx->in.num_cols] || 1557 ctx->resize_coeffs_v[cur_tile / ctx->in.num_cols] != 1558 ctx->resize_coeffs_v[next_tile / ctx->in.num_cols] || 1559 ctx->in.tile[cur_tile].width != ctx->in.tile[next_tile].width || 1560 ctx->in.tile[cur_tile].height != ctx->in.tile[next_tile].height || 1561 ctx->out.tile[cur_tile].width != ctx->out.tile[next_tile].width || 1562 ctx->out.tile[cur_tile].height != ctx->out.tile[next_tile].height) 1563 return true; 1564 1565 return false; 1566 } 1567 1568 /* hold irqlock when calling */ 1569 static irqreturn_t do_irq(struct ipu_image_convert_run *run) 1570 { 1571 struct ipu_image_convert_ctx *ctx = run->ctx; 1572 struct ipu_image_convert_chan *chan = ctx->chan; 1573 struct ipu_image_tile *src_tile, *dst_tile; 1574 struct ipu_image_convert_image *s_image = &ctx->in; 1575 struct ipu_image_convert_image *d_image = &ctx->out; 1576 struct ipuv3_channel *outch; 1577 unsigned int dst_idx; 1578 1579 lockdep_assert_held(&chan->irqlock); 1580 1581 outch = ipu_rot_mode_is_irt(ctx->rot_mode) ? 1582 chan->rotation_out_chan : chan->out_chan; 1583 1584 /* 1585 * It is difficult to stop the channel DMA before the channels 1586 * enter the paused state. Without double-buffering the channels 1587 * are always in a paused state when the EOF irq occurs, so it 1588 * is safe to stop the channels now. For double-buffering we 1589 * just ignore the abort until the operation completes, when it 1590 * is safe to shut down. 1591 */ 1592 if (ctx->aborting && !ctx->double_buffering) { 1593 convert_stop(run); 1594 run->status = -EIO; 1595 goto done; 1596 } 1597 1598 if (ctx->next_tile == ctx->num_tiles) { 1599 /* 1600 * the conversion is complete 1601 */ 1602 convert_stop(run); 1603 run->status = 0; 1604 goto done; 1605 } 1606 1607 /* 1608 * not done, place the next tile buffers. 1609 */ 1610 if (!ctx->double_buffering) { 1611 if (ic_settings_changed(ctx)) { 1612 convert_stop(run); 1613 convert_start(run, ctx->next_tile); 1614 } else { 1615 src_tile = &s_image->tile[ctx->next_tile]; 1616 dst_idx = ctx->out_tile_map[ctx->next_tile]; 1617 dst_tile = &d_image->tile[dst_idx]; 1618 1619 ipu_cpmem_set_buffer(chan->in_chan, 0, 1620 s_image->base.phys0 + 1621 src_tile->offset); 1622 ipu_cpmem_set_buffer(outch, 0, 1623 d_image->base.phys0 + 1624 dst_tile->offset); 1625 if (s_image->fmt->planar) 1626 ipu_cpmem_set_uv_offset(chan->in_chan, 1627 src_tile->u_off, 1628 src_tile->v_off); 1629 if (d_image->fmt->planar) 1630 ipu_cpmem_set_uv_offset(outch, 1631 dst_tile->u_off, 1632 dst_tile->v_off); 1633 1634 ipu_idmac_select_buffer(chan->in_chan, 0); 1635 ipu_idmac_select_buffer(outch, 0); 1636 } 1637 } else if (ctx->next_tile < ctx->num_tiles - 1) { 1638 1639 src_tile = &s_image->tile[ctx->next_tile + 1]; 1640 dst_idx = ctx->out_tile_map[ctx->next_tile + 1]; 1641 dst_tile = &d_image->tile[dst_idx]; 1642 1643 ipu_cpmem_set_buffer(chan->in_chan, ctx->cur_buf_num, 1644 s_image->base.phys0 + src_tile->offset); 1645 ipu_cpmem_set_buffer(outch, ctx->cur_buf_num, 1646 d_image->base.phys0 + dst_tile->offset); 1647 1648 ipu_idmac_select_buffer(chan->in_chan, ctx->cur_buf_num); 1649 ipu_idmac_select_buffer(outch, ctx->cur_buf_num); 1650 1651 ctx->cur_buf_num ^= 1; 1652 } 1653 1654 ctx->next_tile++; 1655 return IRQ_HANDLED; 1656 done: 1657 list_add_tail(&run->list, &chan->done_q); 1658 chan->current_run = NULL; 1659 run_next(chan); 1660 return IRQ_WAKE_THREAD; 1661 } 1662 1663 static irqreturn_t norotate_irq(int irq, void *data) 1664 { 1665 struct ipu_image_convert_chan *chan = data; 1666 struct ipu_image_convert_ctx *ctx; 1667 struct ipu_image_convert_run *run; 1668 unsigned long flags; 1669 irqreturn_t ret; 1670 1671 spin_lock_irqsave(&chan->irqlock, flags); 1672 1673 /* get current run and its context */ 1674 run = chan->current_run; 1675 if (!run) { 1676 ret = IRQ_NONE; 1677 goto out; 1678 } 1679 1680 ctx = run->ctx; 1681 1682 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { 1683 /* this is a rotation operation, just ignore */ 1684 spin_unlock_irqrestore(&chan->irqlock, flags); 1685 return IRQ_HANDLED; 1686 } 1687 1688 ret = do_irq(run); 1689 out: 1690 spin_unlock_irqrestore(&chan->irqlock, flags); 1691 return ret; 1692 } 1693 1694 static irqreturn_t rotate_irq(int irq, void *data) 1695 { 1696 struct ipu_image_convert_chan *chan = data; 1697 struct ipu_image_convert_priv *priv = chan->priv; 1698 struct ipu_image_convert_ctx *ctx; 1699 struct ipu_image_convert_run *run; 1700 unsigned long flags; 1701 irqreturn_t ret; 1702 1703 spin_lock_irqsave(&chan->irqlock, flags); 1704 1705 /* get current run and its context */ 1706 run = chan->current_run; 1707 if (!run) { 1708 ret = IRQ_NONE; 1709 goto out; 1710 } 1711 1712 ctx = run->ctx; 1713 1714 if (!ipu_rot_mode_is_irt(ctx->rot_mode)) { 1715 /* this was NOT a rotation operation, shouldn't happen */ 1716 dev_err(priv->ipu->dev, "Unexpected rotation interrupt\n"); 1717 spin_unlock_irqrestore(&chan->irqlock, flags); 1718 return IRQ_HANDLED; 1719 } 1720 1721 ret = do_irq(run); 1722 out: 1723 spin_unlock_irqrestore(&chan->irqlock, flags); 1724 return ret; 1725 } 1726 1727 /* 1728 * try to force the completion of runs for this ctx. Called when 1729 * abort wait times out in ipu_image_convert_abort(). 1730 */ 1731 static void force_abort(struct ipu_image_convert_ctx *ctx) 1732 { 1733 struct ipu_image_convert_chan *chan = ctx->chan; 1734 struct ipu_image_convert_run *run; 1735 unsigned long flags; 1736 1737 spin_lock_irqsave(&chan->irqlock, flags); 1738 1739 run = chan->current_run; 1740 if (run && run->ctx == ctx) { 1741 convert_stop(run); 1742 run->status = -EIO; 1743 list_add_tail(&run->list, &chan->done_q); 1744 chan->current_run = NULL; 1745 run_next(chan); 1746 } 1747 1748 spin_unlock_irqrestore(&chan->irqlock, flags); 1749 1750 empty_done_q(chan); 1751 } 1752 1753 static void release_ipu_resources(struct ipu_image_convert_chan *chan) 1754 { 1755 if (chan->out_eof_irq >= 0) 1756 free_irq(chan->out_eof_irq, chan); 1757 if (chan->rot_out_eof_irq >= 0) 1758 free_irq(chan->rot_out_eof_irq, chan); 1759 1760 if (!IS_ERR_OR_NULL(chan->in_chan)) 1761 ipu_idmac_put(chan->in_chan); 1762 if (!IS_ERR_OR_NULL(chan->out_chan)) 1763 ipu_idmac_put(chan->out_chan); 1764 if (!IS_ERR_OR_NULL(chan->rotation_in_chan)) 1765 ipu_idmac_put(chan->rotation_in_chan); 1766 if (!IS_ERR_OR_NULL(chan->rotation_out_chan)) 1767 ipu_idmac_put(chan->rotation_out_chan); 1768 if (!IS_ERR_OR_NULL(chan->ic)) 1769 ipu_ic_put(chan->ic); 1770 1771 chan->in_chan = chan->out_chan = chan->rotation_in_chan = 1772 chan->rotation_out_chan = NULL; 1773 chan->out_eof_irq = chan->rot_out_eof_irq = -1; 1774 } 1775 1776 static int get_ipu_resources(struct ipu_image_convert_chan *chan) 1777 { 1778 const struct ipu_image_convert_dma_chan *dma = chan->dma_ch; 1779 struct ipu_image_convert_priv *priv = chan->priv; 1780 int ret; 1781 1782 /* get IC */ 1783 chan->ic = ipu_ic_get(priv->ipu, chan->ic_task); 1784 if (IS_ERR(chan->ic)) { 1785 dev_err(priv->ipu->dev, "could not acquire IC\n"); 1786 ret = PTR_ERR(chan->ic); 1787 goto err; 1788 } 1789 1790 /* get IDMAC channels */ 1791 chan->in_chan = ipu_idmac_get(priv->ipu, dma->in); 1792 chan->out_chan = ipu_idmac_get(priv->ipu, dma->out); 1793 if (IS_ERR(chan->in_chan) || IS_ERR(chan->out_chan)) { 1794 dev_err(priv->ipu->dev, "could not acquire idmac channels\n"); 1795 ret = -EBUSY; 1796 goto err; 1797 } 1798 1799 chan->rotation_in_chan = ipu_idmac_get(priv->ipu, dma->rot_in); 1800 chan->rotation_out_chan = ipu_idmac_get(priv->ipu, dma->rot_out); 1801 if (IS_ERR(chan->rotation_in_chan) || IS_ERR(chan->rotation_out_chan)) { 1802 dev_err(priv->ipu->dev, 1803 "could not acquire idmac rotation channels\n"); 1804 ret = -EBUSY; 1805 goto err; 1806 } 1807 1808 /* acquire the EOF interrupts */ 1809 chan->out_eof_irq = ipu_idmac_channel_irq(priv->ipu, 1810 chan->out_chan, 1811 IPU_IRQ_EOF); 1812 1813 ret = request_threaded_irq(chan->out_eof_irq, norotate_irq, do_bh, 1814 0, "ipu-ic", chan); 1815 if (ret < 0) { 1816 dev_err(priv->ipu->dev, "could not acquire irq %d\n", 1817 chan->out_eof_irq); 1818 chan->out_eof_irq = -1; 1819 goto err; 1820 } 1821 1822 chan->rot_out_eof_irq = ipu_idmac_channel_irq(priv->ipu, 1823 chan->rotation_out_chan, 1824 IPU_IRQ_EOF); 1825 1826 ret = request_threaded_irq(chan->rot_out_eof_irq, rotate_irq, do_bh, 1827 0, "ipu-ic", chan); 1828 if (ret < 0) { 1829 dev_err(priv->ipu->dev, "could not acquire irq %d\n", 1830 chan->rot_out_eof_irq); 1831 chan->rot_out_eof_irq = -1; 1832 goto err; 1833 } 1834 1835 return 0; 1836 err: 1837 release_ipu_resources(chan); 1838 return ret; 1839 } 1840 1841 static int fill_image(struct ipu_image_convert_ctx *ctx, 1842 struct ipu_image_convert_image *ic_image, 1843 struct ipu_image *image, 1844 enum ipu_image_convert_type type) 1845 { 1846 struct ipu_image_convert_priv *priv = ctx->chan->priv; 1847 1848 ic_image->base = *image; 1849 ic_image->type = type; 1850 1851 ic_image->fmt = get_format(image->pix.pixelformat); 1852 if (!ic_image->fmt) { 1853 dev_err(priv->ipu->dev, "pixelformat not supported for %s\n", 1854 type == IMAGE_CONVERT_OUT ? "Output" : "Input"); 1855 return -EINVAL; 1856 } 1857 1858 if (ic_image->fmt->planar) 1859 ic_image->stride = ic_image->base.pix.width; 1860 else 1861 ic_image->stride = ic_image->base.pix.bytesperline; 1862 1863 return 0; 1864 } 1865 1866 /* borrowed from drivers/media/v4l2-core/v4l2-common.c */ 1867 static unsigned int clamp_align(unsigned int x, unsigned int min, 1868 unsigned int max, unsigned int align) 1869 { 1870 /* Bits that must be zero to be aligned */ 1871 unsigned int mask = ~((1 << align) - 1); 1872 1873 /* Clamp to aligned min and max */ 1874 x = clamp(x, (min + ~mask) & mask, max & mask); 1875 1876 /* Round to nearest aligned value */ 1877 if (align) 1878 x = (x + (1 << (align - 1))) & mask; 1879 1880 return x; 1881 } 1882 1883 /* Adjusts input/output images to IPU restrictions */ 1884 void ipu_image_convert_adjust(struct ipu_image *in, struct ipu_image *out, 1885 enum ipu_rotate_mode rot_mode) 1886 { 1887 const struct ipu_image_pixfmt *infmt, *outfmt; 1888 u32 w_align, h_align; 1889 1890 infmt = get_format(in->pix.pixelformat); 1891 outfmt = get_format(out->pix.pixelformat); 1892 1893 /* set some default pixel formats if needed */ 1894 if (!infmt) { 1895 in->pix.pixelformat = V4L2_PIX_FMT_RGB24; 1896 infmt = get_format(V4L2_PIX_FMT_RGB24); 1897 } 1898 if (!outfmt) { 1899 out->pix.pixelformat = V4L2_PIX_FMT_RGB24; 1900 outfmt = get_format(V4L2_PIX_FMT_RGB24); 1901 } 1902 1903 /* image converter does not handle fields */ 1904 in->pix.field = out->pix.field = V4L2_FIELD_NONE; 1905 1906 /* resizer cannot downsize more than 4:1 */ 1907 if (ipu_rot_mode_is_irt(rot_mode)) { 1908 out->pix.height = max_t(__u32, out->pix.height, 1909 in->pix.width / 4); 1910 out->pix.width = max_t(__u32, out->pix.width, 1911 in->pix.height / 4); 1912 } else { 1913 out->pix.width = max_t(__u32, out->pix.width, 1914 in->pix.width / 4); 1915 out->pix.height = max_t(__u32, out->pix.height, 1916 in->pix.height / 4); 1917 } 1918 1919 /* align input width/height */ 1920 w_align = ilog2(tile_width_align(IMAGE_CONVERT_IN, infmt, rot_mode)); 1921 h_align = ilog2(tile_height_align(IMAGE_CONVERT_IN, infmt, rot_mode)); 1922 in->pix.width = clamp_align(in->pix.width, MIN_W, MAX_W, w_align); 1923 in->pix.height = clamp_align(in->pix.height, MIN_H, MAX_H, h_align); 1924 1925 /* align output width/height */ 1926 w_align = ilog2(tile_width_align(IMAGE_CONVERT_OUT, outfmt, rot_mode)); 1927 h_align = ilog2(tile_height_align(IMAGE_CONVERT_OUT, outfmt, rot_mode)); 1928 out->pix.width = clamp_align(out->pix.width, MIN_W, MAX_W, w_align); 1929 out->pix.height = clamp_align(out->pix.height, MIN_H, MAX_H, h_align); 1930 1931 /* set input/output strides and image sizes */ 1932 in->pix.bytesperline = infmt->planar ? 1933 clamp_align(in->pix.width, 2 << w_align, MAX_W, w_align) : 1934 clamp_align((in->pix.width * infmt->bpp) >> 3, 1935 2 << w_align, MAX_W, w_align); 1936 in->pix.sizeimage = infmt->planar ? 1937 (in->pix.height * in->pix.bytesperline * infmt->bpp) >> 3 : 1938 in->pix.height * in->pix.bytesperline; 1939 out->pix.bytesperline = outfmt->planar ? out->pix.width : 1940 (out->pix.width * outfmt->bpp) >> 3; 1941 out->pix.sizeimage = outfmt->planar ? 1942 (out->pix.height * out->pix.bytesperline * outfmt->bpp) >> 3 : 1943 out->pix.height * out->pix.bytesperline; 1944 } 1945 EXPORT_SYMBOL_GPL(ipu_image_convert_adjust); 1946 1947 /* 1948 * this is used by ipu_image_convert_prepare() to verify set input and 1949 * output images are valid before starting the conversion. Clients can 1950 * also call it before calling ipu_image_convert_prepare(). 1951 */ 1952 int ipu_image_convert_verify(struct ipu_image *in, struct ipu_image *out, 1953 enum ipu_rotate_mode rot_mode) 1954 { 1955 struct ipu_image testin, testout; 1956 1957 testin = *in; 1958 testout = *out; 1959 1960 ipu_image_convert_adjust(&testin, &testout, rot_mode); 1961 1962 if (testin.pix.width != in->pix.width || 1963 testin.pix.height != in->pix.height || 1964 testout.pix.width != out->pix.width || 1965 testout.pix.height != out->pix.height) 1966 return -EINVAL; 1967 1968 return 0; 1969 } 1970 EXPORT_SYMBOL_GPL(ipu_image_convert_verify); 1971 1972 /* 1973 * Call ipu_image_convert_prepare() to prepare for the conversion of 1974 * given images and rotation mode. Returns a new conversion context. 1975 */ 1976 struct ipu_image_convert_ctx * 1977 ipu_image_convert_prepare(struct ipu_soc *ipu, enum ipu_ic_task ic_task, 1978 struct ipu_image *in, struct ipu_image *out, 1979 enum ipu_rotate_mode rot_mode, 1980 ipu_image_convert_cb_t complete, 1981 void *complete_context) 1982 { 1983 struct ipu_image_convert_priv *priv = ipu->image_convert_priv; 1984 struct ipu_image_convert_image *s_image, *d_image; 1985 struct ipu_image_convert_chan *chan; 1986 struct ipu_image_convert_ctx *ctx; 1987 unsigned long flags; 1988 unsigned int i; 1989 bool get_res; 1990 int ret; 1991 1992 if (!in || !out || !complete || 1993 (ic_task != IC_TASK_VIEWFINDER && 1994 ic_task != IC_TASK_POST_PROCESSOR)) 1995 return ERR_PTR(-EINVAL); 1996 1997 /* verify the in/out images before continuing */ 1998 ret = ipu_image_convert_verify(in, out, rot_mode); 1999 if (ret) { 2000 dev_err(priv->ipu->dev, "%s: in/out formats invalid\n", 2001 __func__); 2002 return ERR_PTR(ret); 2003 } 2004 2005 chan = &priv->chan[ic_task]; 2006 2007 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 2008 if (!ctx) 2009 return ERR_PTR(-ENOMEM); 2010 2011 dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p\n", __func__, 2012 chan->ic_task, ctx); 2013 2014 ctx->chan = chan; 2015 init_completion(&ctx->aborted); 2016 2017 s_image = &ctx->in; 2018 d_image = &ctx->out; 2019 2020 /* set tiling and rotation */ 2021 d_image->num_rows = num_stripes(out->pix.height); 2022 d_image->num_cols = num_stripes(out->pix.width); 2023 if (ipu_rot_mode_is_irt(rot_mode)) { 2024 s_image->num_rows = d_image->num_cols; 2025 s_image->num_cols = d_image->num_rows; 2026 } else { 2027 s_image->num_rows = d_image->num_rows; 2028 s_image->num_cols = d_image->num_cols; 2029 } 2030 2031 ctx->num_tiles = d_image->num_cols * d_image->num_rows; 2032 ctx->rot_mode = rot_mode; 2033 2034 ret = fill_image(ctx, s_image, in, IMAGE_CONVERT_IN); 2035 if (ret) 2036 goto out_free; 2037 ret = fill_image(ctx, d_image, out, IMAGE_CONVERT_OUT); 2038 if (ret) 2039 goto out_free; 2040 2041 ret = calc_image_resize_coefficients(ctx, in, out); 2042 if (ret) 2043 goto out_free; 2044 2045 calc_out_tile_map(ctx); 2046 2047 find_seams(ctx, s_image, d_image); 2048 2049 calc_tile_dimensions(ctx, s_image); 2050 ret = calc_tile_offsets(ctx, s_image); 2051 if (ret) 2052 goto out_free; 2053 2054 calc_tile_dimensions(ctx, d_image); 2055 ret = calc_tile_offsets(ctx, d_image); 2056 if (ret) 2057 goto out_free; 2058 2059 calc_tile_resize_coefficients(ctx); 2060 2061 dump_format(ctx, s_image); 2062 dump_format(ctx, d_image); 2063 2064 ctx->complete = complete; 2065 ctx->complete_context = complete_context; 2066 2067 /* 2068 * Can we use double-buffering for this operation? If there is 2069 * only one tile (the whole image can be converted in a single 2070 * operation) there's no point in using double-buffering. Also, 2071 * the IPU's IDMAC channels allow only a single U and V plane 2072 * offset shared between both buffers, but these offsets change 2073 * for every tile, and therefore would have to be updated for 2074 * each buffer which is not possible. So double-buffering is 2075 * impossible when either the source or destination images are 2076 * a planar format (YUV420, YUV422P, etc.). Further, differently 2077 * sized tiles or different resizing coefficients per tile 2078 * prevent double-buffering as well. 2079 */ 2080 ctx->double_buffering = (ctx->num_tiles > 1 && 2081 !s_image->fmt->planar && 2082 !d_image->fmt->planar); 2083 for (i = 1; i < ctx->num_tiles; i++) { 2084 if (ctx->in.tile[i].width != ctx->in.tile[0].width || 2085 ctx->in.tile[i].height != ctx->in.tile[0].height || 2086 ctx->out.tile[i].width != ctx->out.tile[0].width || 2087 ctx->out.tile[i].height != ctx->out.tile[0].height) { 2088 ctx->double_buffering = false; 2089 break; 2090 } 2091 } 2092 for (i = 1; i < ctx->in.num_cols; i++) { 2093 if (ctx->resize_coeffs_h[i] != ctx->resize_coeffs_h[0]) { 2094 ctx->double_buffering = false; 2095 break; 2096 } 2097 } 2098 for (i = 1; i < ctx->in.num_rows; i++) { 2099 if (ctx->resize_coeffs_v[i] != ctx->resize_coeffs_v[0]) { 2100 ctx->double_buffering = false; 2101 break; 2102 } 2103 } 2104 2105 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { 2106 unsigned long intermediate_size = d_image->tile[0].size; 2107 2108 for (i = 1; i < ctx->num_tiles; i++) { 2109 if (d_image->tile[i].size > intermediate_size) 2110 intermediate_size = d_image->tile[i].size; 2111 } 2112 2113 ret = alloc_dma_buf(priv, &ctx->rot_intermediate[0], 2114 intermediate_size); 2115 if (ret) 2116 goto out_free; 2117 if (ctx->double_buffering) { 2118 ret = alloc_dma_buf(priv, 2119 &ctx->rot_intermediate[1], 2120 intermediate_size); 2121 if (ret) 2122 goto out_free_dmabuf0; 2123 } 2124 } 2125 2126 spin_lock_irqsave(&chan->irqlock, flags); 2127 2128 get_res = list_empty(&chan->ctx_list); 2129 2130 list_add_tail(&ctx->list, &chan->ctx_list); 2131 2132 spin_unlock_irqrestore(&chan->irqlock, flags); 2133 2134 if (get_res) { 2135 ret = get_ipu_resources(chan); 2136 if (ret) 2137 goto out_free_dmabuf1; 2138 } 2139 2140 return ctx; 2141 2142 out_free_dmabuf1: 2143 free_dma_buf(priv, &ctx->rot_intermediate[1]); 2144 spin_lock_irqsave(&chan->irqlock, flags); 2145 list_del(&ctx->list); 2146 spin_unlock_irqrestore(&chan->irqlock, flags); 2147 out_free_dmabuf0: 2148 free_dma_buf(priv, &ctx->rot_intermediate[0]); 2149 out_free: 2150 kfree(ctx); 2151 return ERR_PTR(ret); 2152 } 2153 EXPORT_SYMBOL_GPL(ipu_image_convert_prepare); 2154 2155 /* 2156 * Carry out a single image conversion run. Only the physaddr's of the input 2157 * and output image buffers are needed. The conversion context must have 2158 * been created previously with ipu_image_convert_prepare(). 2159 */ 2160 int ipu_image_convert_queue(struct ipu_image_convert_run *run) 2161 { 2162 struct ipu_image_convert_chan *chan; 2163 struct ipu_image_convert_priv *priv; 2164 struct ipu_image_convert_ctx *ctx; 2165 unsigned long flags; 2166 int ret = 0; 2167 2168 if (!run || !run->ctx || !run->in_phys || !run->out_phys) 2169 return -EINVAL; 2170 2171 ctx = run->ctx; 2172 chan = ctx->chan; 2173 priv = chan->priv; 2174 2175 dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p run %p\n", __func__, 2176 chan->ic_task, ctx, run); 2177 2178 INIT_LIST_HEAD(&run->list); 2179 2180 spin_lock_irqsave(&chan->irqlock, flags); 2181 2182 if (ctx->aborting) { 2183 ret = -EIO; 2184 goto unlock; 2185 } 2186 2187 list_add_tail(&run->list, &chan->pending_q); 2188 2189 if (!chan->current_run) { 2190 ret = do_run(run); 2191 if (ret) 2192 chan->current_run = NULL; 2193 } 2194 unlock: 2195 spin_unlock_irqrestore(&chan->irqlock, flags); 2196 return ret; 2197 } 2198 EXPORT_SYMBOL_GPL(ipu_image_convert_queue); 2199 2200 /* Abort any active or pending conversions for this context */ 2201 static void __ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx) 2202 { 2203 struct ipu_image_convert_chan *chan = ctx->chan; 2204 struct ipu_image_convert_priv *priv = chan->priv; 2205 struct ipu_image_convert_run *run, *active_run, *tmp; 2206 unsigned long flags; 2207 int run_count, ret; 2208 2209 spin_lock_irqsave(&chan->irqlock, flags); 2210 2211 /* move all remaining pending runs in this context to done_q */ 2212 list_for_each_entry_safe(run, tmp, &chan->pending_q, list) { 2213 if (run->ctx != ctx) 2214 continue; 2215 run->status = -EIO; 2216 list_move_tail(&run->list, &chan->done_q); 2217 } 2218 2219 run_count = get_run_count(ctx, &chan->done_q); 2220 active_run = (chan->current_run && chan->current_run->ctx == ctx) ? 2221 chan->current_run : NULL; 2222 2223 if (active_run) 2224 reinit_completion(&ctx->aborted); 2225 2226 ctx->aborting = true; 2227 2228 spin_unlock_irqrestore(&chan->irqlock, flags); 2229 2230 if (!run_count && !active_run) { 2231 dev_dbg(priv->ipu->dev, 2232 "%s: task %u: no abort needed for ctx %p\n", 2233 __func__, chan->ic_task, ctx); 2234 return; 2235 } 2236 2237 if (!active_run) { 2238 empty_done_q(chan); 2239 return; 2240 } 2241 2242 dev_dbg(priv->ipu->dev, 2243 "%s: task %u: wait for completion: %d runs\n", 2244 __func__, chan->ic_task, run_count); 2245 2246 ret = wait_for_completion_timeout(&ctx->aborted, 2247 msecs_to_jiffies(10000)); 2248 if (ret == 0) { 2249 dev_warn(priv->ipu->dev, "%s: timeout\n", __func__); 2250 force_abort(ctx); 2251 } 2252 } 2253 2254 void ipu_image_convert_abort(struct ipu_image_convert_ctx *ctx) 2255 { 2256 __ipu_image_convert_abort(ctx); 2257 ctx->aborting = false; 2258 } 2259 EXPORT_SYMBOL_GPL(ipu_image_convert_abort); 2260 2261 /* Unprepare image conversion context */ 2262 void ipu_image_convert_unprepare(struct ipu_image_convert_ctx *ctx) 2263 { 2264 struct ipu_image_convert_chan *chan = ctx->chan; 2265 struct ipu_image_convert_priv *priv = chan->priv; 2266 unsigned long flags; 2267 bool put_res; 2268 2269 /* make sure no runs are hanging around */ 2270 __ipu_image_convert_abort(ctx); 2271 2272 dev_dbg(priv->ipu->dev, "%s: task %u: removing ctx %p\n", __func__, 2273 chan->ic_task, ctx); 2274 2275 spin_lock_irqsave(&chan->irqlock, flags); 2276 2277 list_del(&ctx->list); 2278 2279 put_res = list_empty(&chan->ctx_list); 2280 2281 spin_unlock_irqrestore(&chan->irqlock, flags); 2282 2283 if (put_res) 2284 release_ipu_resources(chan); 2285 2286 free_dma_buf(priv, &ctx->rot_intermediate[1]); 2287 free_dma_buf(priv, &ctx->rot_intermediate[0]); 2288 2289 kfree(ctx); 2290 } 2291 EXPORT_SYMBOL_GPL(ipu_image_convert_unprepare); 2292 2293 /* 2294 * "Canned" asynchronous single image conversion. Allocates and returns 2295 * a new conversion run. On successful return the caller must free the 2296 * run and call ipu_image_convert_unprepare() after conversion completes. 2297 */ 2298 struct ipu_image_convert_run * 2299 ipu_image_convert(struct ipu_soc *ipu, enum ipu_ic_task ic_task, 2300 struct ipu_image *in, struct ipu_image *out, 2301 enum ipu_rotate_mode rot_mode, 2302 ipu_image_convert_cb_t complete, 2303 void *complete_context) 2304 { 2305 struct ipu_image_convert_ctx *ctx; 2306 struct ipu_image_convert_run *run; 2307 int ret; 2308 2309 ctx = ipu_image_convert_prepare(ipu, ic_task, in, out, rot_mode, 2310 complete, complete_context); 2311 if (IS_ERR(ctx)) 2312 return ERR_CAST(ctx); 2313 2314 run = kzalloc(sizeof(*run), GFP_KERNEL); 2315 if (!run) { 2316 ipu_image_convert_unprepare(ctx); 2317 return ERR_PTR(-ENOMEM); 2318 } 2319 2320 run->ctx = ctx; 2321 run->in_phys = in->phys0; 2322 run->out_phys = out->phys0; 2323 2324 ret = ipu_image_convert_queue(run); 2325 if (ret) { 2326 ipu_image_convert_unprepare(ctx); 2327 kfree(run); 2328 return ERR_PTR(ret); 2329 } 2330 2331 return run; 2332 } 2333 EXPORT_SYMBOL_GPL(ipu_image_convert); 2334 2335 /* "Canned" synchronous single image conversion */ 2336 static void image_convert_sync_complete(struct ipu_image_convert_run *run, 2337 void *data) 2338 { 2339 struct completion *comp = data; 2340 2341 complete(comp); 2342 } 2343 2344 int ipu_image_convert_sync(struct ipu_soc *ipu, enum ipu_ic_task ic_task, 2345 struct ipu_image *in, struct ipu_image *out, 2346 enum ipu_rotate_mode rot_mode) 2347 { 2348 struct ipu_image_convert_run *run; 2349 struct completion comp; 2350 int ret; 2351 2352 init_completion(&comp); 2353 2354 run = ipu_image_convert(ipu, ic_task, in, out, rot_mode, 2355 image_convert_sync_complete, &comp); 2356 if (IS_ERR(run)) 2357 return PTR_ERR(run); 2358 2359 ret = wait_for_completion_timeout(&comp, msecs_to_jiffies(10000)); 2360 ret = (ret == 0) ? -ETIMEDOUT : 0; 2361 2362 ipu_image_convert_unprepare(run->ctx); 2363 kfree(run); 2364 2365 return ret; 2366 } 2367 EXPORT_SYMBOL_GPL(ipu_image_convert_sync); 2368 2369 int ipu_image_convert_init(struct ipu_soc *ipu, struct device *dev) 2370 { 2371 struct ipu_image_convert_priv *priv; 2372 int i; 2373 2374 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 2375 if (!priv) 2376 return -ENOMEM; 2377 2378 ipu->image_convert_priv = priv; 2379 priv->ipu = ipu; 2380 2381 for (i = 0; i < IC_NUM_TASKS; i++) { 2382 struct ipu_image_convert_chan *chan = &priv->chan[i]; 2383 2384 chan->ic_task = i; 2385 chan->priv = priv; 2386 chan->dma_ch = &image_convert_dma_chan[i]; 2387 chan->out_eof_irq = -1; 2388 chan->rot_out_eof_irq = -1; 2389 2390 spin_lock_init(&chan->irqlock); 2391 INIT_LIST_HEAD(&chan->ctx_list); 2392 INIT_LIST_HEAD(&chan->pending_q); 2393 INIT_LIST_HEAD(&chan->done_q); 2394 } 2395 2396 return 0; 2397 } 2398 2399 void ipu_image_convert_exit(struct ipu_soc *ipu) 2400 { 2401 } 2402