1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2012-2016 Mentor Graphics Inc.
5 * Queued image conversion support, with tiling and rotation.
8 #include <linux/interrupt.h>
9 #include <linux/dma-mapping.h>
10 #include <video/imx-ipu-image-convert.h>
14 * The IC Resizer has a restriction that the output frame from the
15 * resizer must be 1024 or less in both width (pixels) and height
18 * The image converter attempts to split up a conversion when
19 * the desired output (converted) frame resolution exceeds the
20 * IC resizer limit of 1024 in either dimension.
22 * If either dimension of the output frame exceeds the limit, the
23 * dimension is split into 1, 2, or 4 equal stripes, for a maximum
24 * of 4*4 or 16 tiles. A conversion is then carried out for each
25 * tile (but taking care to pass the full frame stride length to
26 * the DMA channel's parameter memory!). IDMA double-buffering is used
27 * to convert each tile back-to-back when possible (see note below
28 * when double_buffering boolean is set).
30 * Note that the input frame must be split up into the same number
31 * of tiles as the output frame:
34 * +-----+---+ | A | B |
36 * +-----+---+ --> +---------+-----+
41 * Clockwise 90° rotations are handled by first rescaling into a
42 * reusable temporary tile buffer and then rotating with the 8x8
43 * block rotator, writing to the correct destination:
47 * +-----+---+ +---------+ | C | A |
48 * | A | B | | A,B, | | | | |
49 * +-----+---+ --> | C,D | | --> | | |
50 * | C | D | +---------+ +-----+-----+
51 * +-----+---+ | D | B |
55 * If the 8x8 block rotator is used, horizontal or vertical flipping
56 * is done during the rotation step, otherwise flipping is done
57 * during the scaling step.
58 * With rotation or flipping, tile order changes between input and
59 * output image. Tiles are numbered row major from top left to bottom
60 * right for both input and output image.
63 #define MAX_STRIPES_W 4
64 #define MAX_STRIPES_H 4
65 #define MAX_TILES (MAX_STRIPES_W * MAX_STRIPES_H)
72 enum ipu_image_convert_type
{
77 struct ipu_image_convert_dma_buf
{
83 struct ipu_image_convert_dma_chan
{
93 /* dimensions of one tile */
94 struct ipu_image_tile
{
99 /* size and strides are in bytes */
103 /* start Y or packed offset of this tile */
105 /* offset from start to tile in U plane, for planar formats */
107 /* offset from start to tile in V plane, for planar formats */
111 struct ipu_image_convert_image
{
112 struct ipu_image base
;
113 enum ipu_image_convert_type type
;
115 const struct ipu_image_pixfmt
*fmt
;
118 /* # of rows (horizontal stripes) if dest height is > 1024 */
119 unsigned int num_rows
;
120 /* # of columns (vertical stripes) if dest width is > 1024 */
121 unsigned int num_cols
;
123 struct ipu_image_tile tile
[MAX_TILES
];
126 struct ipu_image_pixfmt
{
127 u32 fourcc
; /* V4L2 fourcc */
128 int bpp
; /* total bpp */
129 int uv_width_dec
; /* decimation in width for U/V planes */
130 int uv_height_dec
; /* decimation in height for U/V planes */
131 bool planar
; /* planar format */
132 bool uv_swapped
; /* U and V planes are swapped */
133 bool uv_packed
; /* partial planar (U and V in same plane) */
136 struct ipu_image_convert_ctx
;
137 struct ipu_image_convert_chan
;
138 struct ipu_image_convert_priv
;
140 struct ipu_image_convert_ctx
{
141 struct ipu_image_convert_chan
*chan
;
143 ipu_image_convert_cb_t complete
;
144 void *complete_context
;
146 /* Source/destination image data and rotation mode */
147 struct ipu_image_convert_image in
;
148 struct ipu_image_convert_image out
;
149 struct ipu_ic_csc csc
;
150 enum ipu_rotate_mode rot_mode
;
151 u32 downsize_coeff_h
;
152 u32 downsize_coeff_v
;
153 u32 image_resize_coeff_h
;
154 u32 image_resize_coeff_v
;
155 u32 resize_coeffs_h
[MAX_STRIPES_W
];
156 u32 resize_coeffs_v
[MAX_STRIPES_H
];
158 /* intermediate buffer for rotation */
159 struct ipu_image_convert_dma_buf rot_intermediate
[2];
161 /* current buffer number for double buffering */
165 struct completion aborted
;
167 /* can we use double-buffering for this conversion operation? */
168 bool double_buffering
;
169 /* num_rows * num_cols */
170 unsigned int num_tiles
;
171 /* next tile to process */
172 unsigned int next_tile
;
173 /* where to place converted tile in dest image */
174 unsigned int out_tile_map
[MAX_TILES
];
176 struct list_head list
;
179 struct ipu_image_convert_chan
{
180 struct ipu_image_convert_priv
*priv
;
182 enum ipu_ic_task ic_task
;
183 const struct ipu_image_convert_dma_chan
*dma_ch
;
186 struct ipuv3_channel
*in_chan
;
187 struct ipuv3_channel
*out_chan
;
188 struct ipuv3_channel
*rotation_in_chan
;
189 struct ipuv3_channel
*rotation_out_chan
;
191 /* the IPU end-of-frame irqs */
197 /* list of convert contexts */
198 struct list_head ctx_list
;
199 /* queue of conversion runs */
200 struct list_head pending_q
;
201 /* queue of completed runs */
202 struct list_head done_q
;
204 /* the current conversion run */
205 struct ipu_image_convert_run
*current_run
;
208 struct ipu_image_convert_priv
{
209 struct ipu_image_convert_chan chan
[IC_NUM_TASKS
];
213 static const struct ipu_image_convert_dma_chan
214 image_convert_dma_chan
[IC_NUM_TASKS
] = {
215 [IC_TASK_VIEWFINDER
] = {
216 .in
= IPUV3_CHANNEL_MEM_IC_PRP_VF
,
217 .out
= IPUV3_CHANNEL_IC_PRP_VF_MEM
,
218 .rot_in
= IPUV3_CHANNEL_MEM_ROT_VF
,
219 .rot_out
= IPUV3_CHANNEL_ROT_VF_MEM
,
220 .vdi_in_p
= IPUV3_CHANNEL_MEM_VDI_PREV
,
221 .vdi_in
= IPUV3_CHANNEL_MEM_VDI_CUR
,
222 .vdi_in_n
= IPUV3_CHANNEL_MEM_VDI_NEXT
,
224 [IC_TASK_POST_PROCESSOR
] = {
225 .in
= IPUV3_CHANNEL_MEM_IC_PP
,
226 .out
= IPUV3_CHANNEL_IC_PP_MEM
,
227 .rot_in
= IPUV3_CHANNEL_MEM_ROT_PP
,
228 .rot_out
= IPUV3_CHANNEL_ROT_PP_MEM
,
232 static const struct ipu_image_pixfmt image_convert_formats
[] = {
234 .fourcc
= V4L2_PIX_FMT_RGB565
,
237 .fourcc
= V4L2_PIX_FMT_RGB24
,
240 .fourcc
= V4L2_PIX_FMT_BGR24
,
243 .fourcc
= V4L2_PIX_FMT_RGB32
,
246 .fourcc
= V4L2_PIX_FMT_BGR32
,
249 .fourcc
= V4L2_PIX_FMT_XRGB32
,
252 .fourcc
= V4L2_PIX_FMT_XBGR32
,
255 .fourcc
= V4L2_PIX_FMT_BGRX32
,
258 .fourcc
= V4L2_PIX_FMT_RGBX32
,
261 .fourcc
= V4L2_PIX_FMT_YUYV
,
266 .fourcc
= V4L2_PIX_FMT_UYVY
,
271 .fourcc
= V4L2_PIX_FMT_YUV420
,
277 .fourcc
= V4L2_PIX_FMT_YVU420
,
284 .fourcc
= V4L2_PIX_FMT_NV12
,
291 .fourcc
= V4L2_PIX_FMT_YUV422P
,
297 .fourcc
= V4L2_PIX_FMT_NV16
,
306 static const struct ipu_image_pixfmt
*get_format(u32 fourcc
)
308 const struct ipu_image_pixfmt
*ret
= NULL
;
311 for (i
= 0; i
< ARRAY_SIZE(image_convert_formats
); i
++) {
312 if (image_convert_formats
[i
].fourcc
== fourcc
) {
313 ret
= &image_convert_formats
[i
];
321 static void dump_format(struct ipu_image_convert_ctx
*ctx
,
322 struct ipu_image_convert_image
*ic_image
)
324 struct ipu_image_convert_chan
*chan
= ctx
->chan
;
325 struct ipu_image_convert_priv
*priv
= chan
->priv
;
327 dev_dbg(priv
->ipu
->dev
,
328 "task %u: ctx %p: %s format: %dx%d (%dx%d tiles), %c%c%c%c\n",
330 ic_image
->type
== IMAGE_CONVERT_OUT
? "Output" : "Input",
331 ic_image
->base
.pix
.width
, ic_image
->base
.pix
.height
,
332 ic_image
->num_cols
, ic_image
->num_rows
,
333 ic_image
->fmt
->fourcc
& 0xff,
334 (ic_image
->fmt
->fourcc
>> 8) & 0xff,
335 (ic_image
->fmt
->fourcc
>> 16) & 0xff,
336 (ic_image
->fmt
->fourcc
>> 24) & 0xff);
339 int ipu_image_convert_enum_format(int index
, u32
*fourcc
)
341 const struct ipu_image_pixfmt
*fmt
;
343 if (index
>= (int)ARRAY_SIZE(image_convert_formats
))
347 fmt
= &image_convert_formats
[index
];
348 *fourcc
= fmt
->fourcc
;
351 EXPORT_SYMBOL_GPL(ipu_image_convert_enum_format
);
353 static void free_dma_buf(struct ipu_image_convert_priv
*priv
,
354 struct ipu_image_convert_dma_buf
*buf
)
357 dma_free_coherent(priv
->ipu
->dev
,
358 buf
->len
, buf
->virt
, buf
->phys
);
363 static int alloc_dma_buf(struct ipu_image_convert_priv
*priv
,
364 struct ipu_image_convert_dma_buf
*buf
,
367 buf
->len
= PAGE_ALIGN(size
);
368 buf
->virt
= dma_alloc_coherent(priv
->ipu
->dev
, buf
->len
, &buf
->phys
,
369 GFP_DMA
| GFP_KERNEL
);
371 dev_err(priv
->ipu
->dev
, "failed to alloc dma buffer\n");
378 static inline int num_stripes(int dim
)
380 return (dim
- 1) / 1024 + 1;
384 * Calculate downsizing coefficients, which are the same for all tiles,
385 * and initial bilinear resizing coefficients, which are used to find the
386 * best seam positions.
387 * Also determine the number of tiles necessary to guarantee that no tile
388 * is larger than 1024 pixels in either dimension at the output and between
389 * IC downsizing and main processing sections.
391 static int calc_image_resize_coefficients(struct ipu_image_convert_ctx
*ctx
,
392 struct ipu_image
*in
,
393 struct ipu_image
*out
)
395 u32 downsized_width
= in
->rect
.width
;
396 u32 downsized_height
= in
->rect
.height
;
397 u32 downsize_coeff_v
= 0;
398 u32 downsize_coeff_h
= 0;
399 u32 resized_width
= out
->rect
.width
;
400 u32 resized_height
= out
->rect
.height
;
406 if (ipu_rot_mode_is_irt(ctx
->rot_mode
)) {
407 resized_width
= out
->rect
.height
;
408 resized_height
= out
->rect
.width
;
411 /* Do not let invalid input lead to an endless loop below */
412 if (WARN_ON(resized_width
== 0 || resized_height
== 0))
415 while (downsized_width
>= resized_width
* 2) {
416 downsized_width
>>= 1;
420 while (downsized_height
>= resized_height
* 2) {
421 downsized_height
>>= 1;
426 * Calculate the bilinear resizing coefficients that could be used if
427 * we were converting with a single tile. The bottom right output pixel
428 * should sample as close as possible to the bottom right input pixel
429 * out of the decimator, but not overshoot it:
431 resize_coeff_h
= 8192 * (downsized_width
- 1) / (resized_width
- 1);
432 resize_coeff_v
= 8192 * (downsized_height
- 1) / (resized_height
- 1);
435 * Both the output of the IC downsizing section before being passed to
436 * the IC main processing section and the final output of the IC main
437 * processing section must be <= 1024 pixels in both dimensions.
439 cols
= num_stripes(max_t(u32
, downsized_width
, resized_width
));
440 rows
= num_stripes(max_t(u32
, downsized_height
, resized_height
));
442 dev_dbg(ctx
->chan
->priv
->ipu
->dev
,
443 "%s: hscale: >>%u, *8192/%u vscale: >>%u, *8192/%u, %ux%u tiles\n",
444 __func__
, downsize_coeff_h
, resize_coeff_h
, downsize_coeff_v
,
445 resize_coeff_v
, cols
, rows
);
447 if (downsize_coeff_h
> 2 || downsize_coeff_v
> 2 ||
448 resize_coeff_h
> 0x3fff || resize_coeff_v
> 0x3fff)
451 ctx
->downsize_coeff_h
= downsize_coeff_h
;
452 ctx
->downsize_coeff_v
= downsize_coeff_v
;
453 ctx
->image_resize_coeff_h
= resize_coeff_h
;
454 ctx
->image_resize_coeff_v
= resize_coeff_v
;
455 ctx
->in
.num_cols
= cols
;
456 ctx
->in
.num_rows
= rows
;
461 #define round_closest(x, y) round_down((x) + (y)/2, (y))
464 * Find the best aligned seam position for the given column / row index.
465 * Rotation and image offsets are out of scope.
467 * @index: column / row index, used to calculate valid interval
468 * @in_edge: input right / bottom edge
469 * @out_edge: output right / bottom edge
470 * @in_align: input alignment, either horizontal 8-byte line start address
471 * alignment, or pixel alignment due to image format
472 * @out_align: output alignment, either horizontal 8-byte line start address
473 * alignment, or pixel alignment due to image format or rotator
475 * @in_burst: horizontal input burst size in case of horizontal flip
476 * @out_burst: horizontal output burst size or rotator block size
477 * @downsize_coeff: downsizing section coefficient
478 * @resize_coeff: main processing section resizing coefficient
479 * @_in_seam: aligned input seam position return value
480 * @_out_seam: aligned output seam position return value
482 static void find_best_seam(struct ipu_image_convert_ctx
*ctx
,
484 unsigned int in_edge
,
485 unsigned int out_edge
,
486 unsigned int in_align
,
487 unsigned int out_align
,
488 unsigned int in_burst
,
489 unsigned int out_burst
,
490 unsigned int downsize_coeff
,
491 unsigned int resize_coeff
,
495 struct device
*dev
= ctx
->chan
->priv
->ipu
->dev
;
496 unsigned int out_pos
;
497 /* Input / output seam position candidates */
498 unsigned int out_seam
= 0;
499 unsigned int in_seam
= 0;
500 unsigned int min_diff
= UINT_MAX
;
501 unsigned int out_start
;
502 unsigned int out_end
;
503 unsigned int in_start
;
506 /* Start within 1024 pixels of the right / bottom edge */
507 out_start
= max_t(int, index
* out_align
, out_edge
- 1024);
508 /* End before having to add more columns to the left / rows above */
509 out_end
= min_t(unsigned int, out_edge
, index
* 1024 + 1);
512 * Limit input seam position to make sure that the downsized input tile
513 * to the right or bottom does not exceed 1024 pixels.
515 in_start
= max_t(int, index
* in_align
,
516 in_edge
- (1024 << downsize_coeff
));
517 in_end
= min_t(unsigned int, in_edge
,
518 index
* (1024 << downsize_coeff
) + 1);
521 * Output tiles must start at a multiple of 8 bytes horizontally and
522 * possibly at an even line horizontally depending on the pixel format.
523 * Only consider output aligned positions for the seam.
525 out_start
= round_up(out_start
, out_align
);
526 for (out_pos
= out_start
; out_pos
< out_end
; out_pos
+= out_align
) {
528 unsigned int in_pos_aligned
;
529 unsigned int in_pos_rounded
;
530 unsigned int abs_diff
;
533 * Tiles in the right row / bottom column may not be allowed to
534 * overshoot horizontally / vertically. out_burst may be the
535 * actual DMA burst size, or the rotator block size.
537 if ((out_burst
> 1) && (out_edge
- out_pos
) % out_burst
)
541 * Input sample position, corresponding to out_pos, 19.13 fixed
544 in_pos
= (out_pos
* resize_coeff
) << downsize_coeff
;
546 * The closest input sample position that we could actually
547 * start the input tile at, 19.13 fixed point.
549 in_pos_aligned
= round_closest(in_pos
, 8192U * in_align
);
550 /* Convert 19.13 fixed point to integer */
551 in_pos_rounded
= in_pos_aligned
/ 8192U;
553 if (in_pos_rounded
< in_start
)
555 if (in_pos_rounded
>= in_end
)
558 if ((in_burst
> 1) &&
559 (in_edge
- in_pos_rounded
) % in_burst
)
562 if (in_pos
< in_pos_aligned
)
563 abs_diff
= in_pos_aligned
- in_pos
;
565 abs_diff
= in_pos
- in_pos_aligned
;
567 if (abs_diff
< min_diff
) {
568 in_seam
= in_pos_rounded
;
574 *_out_seam
= out_seam
;
577 dev_dbg(dev
, "%s: out_seam %u(%u) in [%u, %u], in_seam %u(%u) in [%u, %u] diff %u.%03u\n",
578 __func__
, out_seam
, out_align
, out_start
, out_end
,
579 in_seam
, in_align
, in_start
, in_end
, min_diff
/ 8192,
580 DIV_ROUND_CLOSEST(min_diff
% 8192 * 1000, 8192));
584 * Tile left edges are required to be aligned to multiples of 8 bytes
587 static inline u32
tile_left_align(const struct ipu_image_pixfmt
*fmt
)
590 return fmt
->uv_packed
? 8 : 8 * fmt
->uv_width_dec
;
592 return fmt
->bpp
== 32 ? 2 : fmt
->bpp
== 16 ? 4 : 8;
596 * Tile top edge alignment is only limited by chroma subsampling.
598 static inline u32
tile_top_align(const struct ipu_image_pixfmt
*fmt
)
600 return fmt
->uv_height_dec
> 1 ? 2 : 1;
603 static inline u32
tile_width_align(enum ipu_image_convert_type type
,
604 const struct ipu_image_pixfmt
*fmt
,
605 enum ipu_rotate_mode rot_mode
)
607 if (type
== IMAGE_CONVERT_IN
) {
609 * The IC burst reads 8 pixels at a time. Reading beyond the
610 * end of the line is usually acceptable. Those pixels are
611 * ignored, unless the IC has to write the scaled line in
614 return (!ipu_rot_mode_is_irt(rot_mode
) &&
615 (rot_mode
& IPU_ROT_BIT_HFLIP
)) ? 8 : 2;
619 * Align to 16x16 pixel blocks for planar 4:2:0 chroma subsampled
620 * formats to guarantee 8-byte aligned line start addresses in the
621 * chroma planes when IRT is used. Align to 8x8 pixel IRT block size
622 * for all other formats.
624 return (ipu_rot_mode_is_irt(rot_mode
) &&
625 fmt
->planar
&& !fmt
->uv_packed
) ?
626 8 * fmt
->uv_width_dec
: 8;
629 static inline u32
tile_height_align(enum ipu_image_convert_type type
,
630 const struct ipu_image_pixfmt
*fmt
,
631 enum ipu_rotate_mode rot_mode
)
633 if (type
== IMAGE_CONVERT_IN
|| !ipu_rot_mode_is_irt(rot_mode
))
637 * Align to 16x16 pixel blocks for planar 4:2:0 chroma subsampled
638 * formats to guarantee 8-byte aligned line start addresses in the
639 * chroma planes when IRT is used. Align to 8x8 pixel IRT block size
640 * for all other formats.
642 return (fmt
->planar
&& !fmt
->uv_packed
) ? 8 * fmt
->uv_width_dec
: 8;
646 * Fill in left position and width and for all tiles in an input column, and
647 * for all corresponding output tiles. If the 90° rotator is used, the output
648 * tiles are in a row, and output tile top position and height are set.
650 static void fill_tile_column(struct ipu_image_convert_ctx
*ctx
,
652 struct ipu_image_convert_image
*in
,
653 unsigned int in_left
, unsigned int in_width
,
654 struct ipu_image_convert_image
*out
,
655 unsigned int out_left
, unsigned int out_width
)
657 unsigned int row
, tile_idx
;
658 struct ipu_image_tile
*in_tile
, *out_tile
;
660 for (row
= 0; row
< in
->num_rows
; row
++) {
661 tile_idx
= in
->num_cols
* row
+ col
;
662 in_tile
= &in
->tile
[tile_idx
];
663 out_tile
= &out
->tile
[ctx
->out_tile_map
[tile_idx
]];
665 in_tile
->left
= in_left
;
666 in_tile
->width
= in_width
;
668 if (ipu_rot_mode_is_irt(ctx
->rot_mode
)) {
669 out_tile
->top
= out_left
;
670 out_tile
->height
= out_width
;
672 out_tile
->left
= out_left
;
673 out_tile
->width
= out_width
;
679 * Fill in top position and height and for all tiles in an input row, and
680 * for all corresponding output tiles. If the 90° rotator is used, the output
681 * tiles are in a column, and output tile left position and width are set.
683 static void fill_tile_row(struct ipu_image_convert_ctx
*ctx
, unsigned int row
,
684 struct ipu_image_convert_image
*in
,
685 unsigned int in_top
, unsigned int in_height
,
686 struct ipu_image_convert_image
*out
,
687 unsigned int out_top
, unsigned int out_height
)
689 unsigned int col
, tile_idx
;
690 struct ipu_image_tile
*in_tile
, *out_tile
;
692 for (col
= 0; col
< in
->num_cols
; col
++) {
693 tile_idx
= in
->num_cols
* row
+ col
;
694 in_tile
= &in
->tile
[tile_idx
];
695 out_tile
= &out
->tile
[ctx
->out_tile_map
[tile_idx
]];
697 in_tile
->top
= in_top
;
698 in_tile
->height
= in_height
;
700 if (ipu_rot_mode_is_irt(ctx
->rot_mode
)) {
701 out_tile
->left
= out_top
;
702 out_tile
->width
= out_height
;
704 out_tile
->top
= out_top
;
705 out_tile
->height
= out_height
;
711 * Find the best horizontal and vertical seam positions to split into tiles.
712 * Minimize the fractional part of the input sampling position for the
713 * top / left pixels of each tile.
715 static void find_seams(struct ipu_image_convert_ctx
*ctx
,
716 struct ipu_image_convert_image
*in
,
717 struct ipu_image_convert_image
*out
)
719 struct device
*dev
= ctx
->chan
->priv
->ipu
->dev
;
720 unsigned int resized_width
= out
->base
.rect
.width
;
721 unsigned int resized_height
= out
->base
.rect
.height
;
724 unsigned int in_left_align
= tile_left_align(in
->fmt
);
725 unsigned int in_top_align
= tile_top_align(in
->fmt
);
726 unsigned int out_left_align
= tile_left_align(out
->fmt
);
727 unsigned int out_top_align
= tile_top_align(out
->fmt
);
728 unsigned int out_width_align
= tile_width_align(out
->type
, out
->fmt
,
730 unsigned int out_height_align
= tile_height_align(out
->type
, out
->fmt
,
732 unsigned int in_right
= in
->base
.rect
.width
;
733 unsigned int in_bottom
= in
->base
.rect
.height
;
734 unsigned int out_right
= out
->base
.rect
.width
;
735 unsigned int out_bottom
= out
->base
.rect
.height
;
736 unsigned int flipped_out_left
;
737 unsigned int flipped_out_top
;
739 if (ipu_rot_mode_is_irt(ctx
->rot_mode
)) {
740 /* Switch width/height and align top left to IRT block size */
741 resized_width
= out
->base
.rect
.height
;
742 resized_height
= out
->base
.rect
.width
;
743 out_left_align
= out_height_align
;
744 out_top_align
= out_width_align
;
745 out_width_align
= out_left_align
;
746 out_height_align
= out_top_align
;
747 out_right
= out
->base
.rect
.height
;
748 out_bottom
= out
->base
.rect
.width
;
751 for (col
= in
->num_cols
- 1; col
> 0; col
--) {
752 bool allow_in_overshoot
= ipu_rot_mode_is_irt(ctx
->rot_mode
) ||
753 !(ctx
->rot_mode
& IPU_ROT_BIT_HFLIP
);
754 bool allow_out_overshoot
= (col
< in
->num_cols
- 1) &&
755 !(ctx
->rot_mode
& IPU_ROT_BIT_HFLIP
);
756 unsigned int in_left
;
757 unsigned int out_left
;
760 * Align input width to burst length if the scaling step flips
764 find_best_seam(ctx
, col
,
766 in_left_align
, out_left_align
,
767 allow_in_overshoot
? 1 : 8 /* burst length */,
768 allow_out_overshoot
? 1 : out_width_align
,
769 ctx
->downsize_coeff_h
, ctx
->image_resize_coeff_h
,
770 &in_left
, &out_left
);
772 if (ctx
->rot_mode
& IPU_ROT_BIT_HFLIP
)
773 flipped_out_left
= resized_width
- out_right
;
775 flipped_out_left
= out_left
;
777 fill_tile_column(ctx
, col
, in
, in_left
, in_right
- in_left
,
778 out
, flipped_out_left
, out_right
- out_left
);
780 dev_dbg(dev
, "%s: col %u: %u, %u -> %u, %u\n", __func__
, col
,
781 in_left
, in_right
- in_left
,
782 flipped_out_left
, out_right
- out_left
);
785 out_right
= out_left
;
788 flipped_out_left
= (ctx
->rot_mode
& IPU_ROT_BIT_HFLIP
) ?
789 resized_width
- out_right
: 0;
791 fill_tile_column(ctx
, 0, in
, 0, in_right
,
792 out
, flipped_out_left
, out_right
);
794 dev_dbg(dev
, "%s: col 0: 0, %u -> %u, %u\n", __func__
,
795 in_right
, flipped_out_left
, out_right
);
797 for (row
= in
->num_rows
- 1; row
> 0; row
--) {
798 bool allow_overshoot
= row
< in
->num_rows
- 1;
800 unsigned int out_top
;
802 find_best_seam(ctx
, row
,
803 in_bottom
, out_bottom
,
804 in_top_align
, out_top_align
,
805 1, allow_overshoot
? 1 : out_height_align
,
806 ctx
->downsize_coeff_v
, ctx
->image_resize_coeff_v
,
809 if ((ctx
->rot_mode
& IPU_ROT_BIT_VFLIP
) ^
810 ipu_rot_mode_is_irt(ctx
->rot_mode
))
811 flipped_out_top
= resized_height
- out_bottom
;
813 flipped_out_top
= out_top
;
815 fill_tile_row(ctx
, row
, in
, in_top
, in_bottom
- in_top
,
816 out
, flipped_out_top
, out_bottom
- out_top
);
818 dev_dbg(dev
, "%s: row %u: %u, %u -> %u, %u\n", __func__
, row
,
819 in_top
, in_bottom
- in_top
,
820 flipped_out_top
, out_bottom
- out_top
);
823 out_bottom
= out_top
;
826 if ((ctx
->rot_mode
& IPU_ROT_BIT_VFLIP
) ^
827 ipu_rot_mode_is_irt(ctx
->rot_mode
))
828 flipped_out_top
= resized_height
- out_bottom
;
832 fill_tile_row(ctx
, 0, in
, 0, in_bottom
,
833 out
, flipped_out_top
, out_bottom
);
835 dev_dbg(dev
, "%s: row 0: 0, %u -> %u, %u\n", __func__
,
836 in_bottom
, flipped_out_top
, out_bottom
);
839 static int calc_tile_dimensions(struct ipu_image_convert_ctx
*ctx
,
840 struct ipu_image_convert_image
*image
)
842 struct ipu_image_convert_chan
*chan
= ctx
->chan
;
843 struct ipu_image_convert_priv
*priv
= chan
->priv
;
844 unsigned int max_width
= 1024;
845 unsigned int max_height
= 1024;
848 if (image
->type
== IMAGE_CONVERT_IN
) {
849 /* Up to 4096x4096 input tile size */
850 max_width
<<= ctx
->downsize_coeff_h
;
851 max_height
<<= ctx
->downsize_coeff_v
;
854 for (i
= 0; i
< ctx
->num_tiles
; i
++) {
855 struct ipu_image_tile
*tile
;
856 const unsigned int row
= i
/ image
->num_cols
;
857 const unsigned int col
= i
% image
->num_cols
;
859 if (image
->type
== IMAGE_CONVERT_OUT
)
860 tile
= &image
->tile
[ctx
->out_tile_map
[i
]];
862 tile
= &image
->tile
[i
];
864 tile
->size
= ((tile
->height
* image
->fmt
->bpp
) >> 3) *
867 if (image
->fmt
->planar
) {
868 tile
->stride
= tile
->width
;
869 tile
->rot_stride
= tile
->height
;
872 (image
->fmt
->bpp
* tile
->width
) >> 3;
874 (image
->fmt
->bpp
* tile
->height
) >> 3;
877 dev_dbg(priv
->ipu
->dev
,
878 "task %u: ctx %p: %s@[%u,%u]: %ux%u@%u,%u\n",
880 image
->type
== IMAGE_CONVERT_IN
? "Input" : "Output",
882 tile
->width
, tile
->height
, tile
->left
, tile
->top
);
884 if (!tile
->width
|| tile
->width
> max_width
||
885 !tile
->height
|| tile
->height
> max_height
) {
886 dev_err(priv
->ipu
->dev
, "invalid %s tile size: %ux%u\n",
887 image
->type
== IMAGE_CONVERT_IN
? "input" :
888 "output", tile
->width
, tile
->height
);
897 * Use the rotation transformation to find the tile coordinates
898 * (row, col) of a tile in the destination frame that corresponds
899 * to the given tile coordinates of a source frame. The destination
900 * coordinate is then converted to a tile index.
902 static int transform_tile_index(struct ipu_image_convert_ctx
*ctx
,
903 int src_row
, int src_col
)
905 struct ipu_image_convert_chan
*chan
= ctx
->chan
;
906 struct ipu_image_convert_priv
*priv
= chan
->priv
;
907 struct ipu_image_convert_image
*s_image
= &ctx
->in
;
908 struct ipu_image_convert_image
*d_image
= &ctx
->out
;
909 int dst_row
, dst_col
;
911 /* with no rotation it's a 1:1 mapping */
912 if (ctx
->rot_mode
== IPU_ROTATE_NONE
)
913 return src_row
* s_image
->num_cols
+ src_col
;
916 * before doing the transform, first we have to translate
917 * source row,col for an origin in the center of s_image
919 src_row
= src_row
* 2 - (s_image
->num_rows
- 1);
920 src_col
= src_col
* 2 - (s_image
->num_cols
- 1);
922 /* do the rotation transform */
923 if (ctx
->rot_mode
& IPU_ROT_BIT_90
) {
932 if (ctx
->rot_mode
& IPU_ROT_BIT_HFLIP
)
934 if (ctx
->rot_mode
& IPU_ROT_BIT_VFLIP
)
937 dev_dbg(priv
->ipu
->dev
, "task %u: ctx %p: [%d,%d] --> [%d,%d]\n",
938 chan
->ic_task
, ctx
, src_col
, src_row
, dst_col
, dst_row
);
941 * finally translate dest row,col using an origin in upper
944 dst_row
+= d_image
->num_rows
- 1;
945 dst_col
+= d_image
->num_cols
- 1;
949 return dst_row
* d_image
->num_cols
+ dst_col
;
953 * Fill the out_tile_map[] with transformed destination tile indeces.
955 static void calc_out_tile_map(struct ipu_image_convert_ctx
*ctx
)
957 struct ipu_image_convert_image
*s_image
= &ctx
->in
;
958 unsigned int row
, col
, tile
= 0;
960 for (row
= 0; row
< s_image
->num_rows
; row
++) {
961 for (col
= 0; col
< s_image
->num_cols
; col
++) {
962 ctx
->out_tile_map
[tile
] =
963 transform_tile_index(ctx
, row
, col
);
969 static int calc_tile_offsets_planar(struct ipu_image_convert_ctx
*ctx
,
970 struct ipu_image_convert_image
*image
)
972 struct ipu_image_convert_chan
*chan
= ctx
->chan
;
973 struct ipu_image_convert_priv
*priv
= chan
->priv
;
974 const struct ipu_image_pixfmt
*fmt
= image
->fmt
;
975 unsigned int row
, col
, tile
= 0;
976 u32 H
, top
, y_stride
, uv_stride
;
977 u32 uv_row_off
, uv_col_off
, uv_off
, u_off
, v_off
, tmp
;
978 u32 y_row_off
, y_col_off
, y_off
;
981 /* setup some convenience vars */
982 H
= image
->base
.pix
.height
;
984 y_stride
= image
->stride
;
985 uv_stride
= y_stride
/ fmt
->uv_width_dec
;
989 y_size
= H
* y_stride
;
990 uv_size
= y_size
/ (fmt
->uv_width_dec
* fmt
->uv_height_dec
);
992 for (row
= 0; row
< image
->num_rows
; row
++) {
993 top
= image
->tile
[tile
].top
;
994 y_row_off
= top
* y_stride
;
995 uv_row_off
= (top
* uv_stride
) / fmt
->uv_height_dec
;
997 for (col
= 0; col
< image
->num_cols
; col
++) {
998 y_col_off
= image
->tile
[tile
].left
;
999 uv_col_off
= y_col_off
/ fmt
->uv_width_dec
;
1003 y_off
= y_row_off
+ y_col_off
;
1004 uv_off
= uv_row_off
+ uv_col_off
;
1006 u_off
= y_size
- y_off
+ uv_off
;
1007 v_off
= (fmt
->uv_packed
) ? 0 : u_off
+ uv_size
;
1008 if (fmt
->uv_swapped
) {
1014 image
->tile
[tile
].offset
= y_off
;
1015 image
->tile
[tile
].u_off
= u_off
;
1016 image
->tile
[tile
++].v_off
= v_off
;
1018 if ((y_off
& 0x7) || (u_off
& 0x7) || (v_off
& 0x7)) {
1019 dev_err(priv
->ipu
->dev
,
1020 "task %u: ctx %p: %s@[%d,%d]: "
1021 "y_off %08x, u_off %08x, v_off %08x\n",
1023 image
->type
== IMAGE_CONVERT_IN
?
1024 "Input" : "Output", row
, col
,
1025 y_off
, u_off
, v_off
);
1034 static int calc_tile_offsets_packed(struct ipu_image_convert_ctx
*ctx
,
1035 struct ipu_image_convert_image
*image
)
1037 struct ipu_image_convert_chan
*chan
= ctx
->chan
;
1038 struct ipu_image_convert_priv
*priv
= chan
->priv
;
1039 const struct ipu_image_pixfmt
*fmt
= image
->fmt
;
1040 unsigned int row
, col
, tile
= 0;
1041 u32 bpp
, stride
, offset
;
1042 u32 row_off
, col_off
;
1044 /* setup some convenience vars */
1045 stride
= image
->stride
;
1048 for (row
= 0; row
< image
->num_rows
; row
++) {
1049 row_off
= image
->tile
[tile
].top
* stride
;
1051 for (col
= 0; col
< image
->num_cols
; col
++) {
1052 col_off
= (image
->tile
[tile
].left
* bpp
) >> 3;
1054 offset
= row_off
+ col_off
;
1056 image
->tile
[tile
].offset
= offset
;
1057 image
->tile
[tile
].u_off
= 0;
1058 image
->tile
[tile
++].v_off
= 0;
1061 dev_err(priv
->ipu
->dev
,
1062 "task %u: ctx %p: %s@[%d,%d]: "
1065 image
->type
== IMAGE_CONVERT_IN
?
1066 "Input" : "Output", row
, col
,
1076 static int calc_tile_offsets(struct ipu_image_convert_ctx
*ctx
,
1077 struct ipu_image_convert_image
*image
)
1079 if (image
->fmt
->planar
)
1080 return calc_tile_offsets_planar(ctx
, image
);
1082 return calc_tile_offsets_packed(ctx
, image
);
1086 * Calculate the resizing ratio for the IC main processing section given input
1087 * size, fixed downsizing coefficient, and output size.
1088 * Either round to closest for the next tile's first pixel to minimize seams
1089 * and distortion (for all but right column / bottom row), or round down to
1090 * avoid sampling beyond the edges of the input image for this tile's last
1092 * Returns the resizing coefficient, resizing ratio is 8192.0 / resize_coeff.
1094 static u32
calc_resize_coeff(u32 input_size
, u32 downsize_coeff
,
1095 u32 output_size
, bool allow_overshoot
)
1097 u32 downsized
= input_size
>> downsize_coeff
;
1099 if (allow_overshoot
)
1100 return DIV_ROUND_CLOSEST(8192 * downsized
, output_size
);
1102 return 8192 * (downsized
- 1) / (output_size
- 1);
1106 * Slightly modify resize coefficients per tile to hide the bilinear
1107 * interpolator reset at tile borders, shifting the right / bottom edge
1108 * by up to a half input pixel. This removes noticeable seams between
1109 * tiles at higher upscaling factors.
1111 static void calc_tile_resize_coefficients(struct ipu_image_convert_ctx
*ctx
)
1113 struct ipu_image_convert_chan
*chan
= ctx
->chan
;
1114 struct ipu_image_convert_priv
*priv
= chan
->priv
;
1115 struct ipu_image_tile
*in_tile
, *out_tile
;
1116 unsigned int col
, row
, tile_idx
;
1117 unsigned int last_output
;
1119 for (col
= 0; col
< ctx
->in
.num_cols
; col
++) {
1120 bool closest
= (col
< ctx
->in
.num_cols
- 1) &&
1121 !(ctx
->rot_mode
& IPU_ROT_BIT_HFLIP
);
1127 in_tile
= &ctx
->in
.tile
[tile_idx
];
1128 out_tile
= &ctx
->out
.tile
[ctx
->out_tile_map
[tile_idx
]];
1130 if (ipu_rot_mode_is_irt(ctx
->rot_mode
))
1131 resized_width
= out_tile
->height
;
1133 resized_width
= out_tile
->width
;
1135 resize_coeff_h
= calc_resize_coeff(in_tile
->width
,
1136 ctx
->downsize_coeff_h
,
1137 resized_width
, closest
);
1139 dev_dbg(priv
->ipu
->dev
, "%s: column %u hscale: *8192/%u\n",
1140 __func__
, col
, resize_coeff_h
);
1143 * With the horizontal scaling factor known, round up resized
1144 * width (output width or height) to burst size.
1146 resized_width
= round_up(resized_width
, 8);
1149 * Calculate input width from the last accessed input pixel
1150 * given resized width and scaling coefficients. Round up to
1153 last_output
= resized_width
- 1;
1154 if (closest
&& ((last_output
* resize_coeff_h
) % 8192))
1156 in_width
= round_up(
1157 (DIV_ROUND_UP(last_output
* resize_coeff_h
, 8192) + 1)
1158 << ctx
->downsize_coeff_h
, 8);
1160 for (row
= 0; row
< ctx
->in
.num_rows
; row
++) {
1161 tile_idx
= row
* ctx
->in
.num_cols
+ col
;
1162 in_tile
= &ctx
->in
.tile
[tile_idx
];
1163 out_tile
= &ctx
->out
.tile
[ctx
->out_tile_map
[tile_idx
]];
1165 if (ipu_rot_mode_is_irt(ctx
->rot_mode
))
1166 out_tile
->height
= resized_width
;
1168 out_tile
->width
= resized_width
;
1170 in_tile
->width
= in_width
;
1173 ctx
->resize_coeffs_h
[col
] = resize_coeff_h
;
1176 for (row
= 0; row
< ctx
->in
.num_rows
; row
++) {
1177 bool closest
= (row
< ctx
->in
.num_rows
- 1) &&
1178 !(ctx
->rot_mode
& IPU_ROT_BIT_VFLIP
);
1183 tile_idx
= row
* ctx
->in
.num_cols
;
1184 in_tile
= &ctx
->in
.tile
[tile_idx
];
1185 out_tile
= &ctx
->out
.tile
[ctx
->out_tile_map
[tile_idx
]];
1187 if (ipu_rot_mode_is_irt(ctx
->rot_mode
))
1188 resized_height
= out_tile
->width
;
1190 resized_height
= out_tile
->height
;
1192 resize_coeff_v
= calc_resize_coeff(in_tile
->height
,
1193 ctx
->downsize_coeff_v
,
1194 resized_height
, closest
);
1196 dev_dbg(priv
->ipu
->dev
, "%s: row %u vscale: *8192/%u\n",
1197 __func__
, row
, resize_coeff_v
);
1200 * With the vertical scaling factor known, round up resized
1201 * height (output width or height) to IDMAC limitations.
1203 resized_height
= round_up(resized_height
, 2);
1206 * Calculate input width from the last accessed input pixel
1207 * given resized height and scaling coefficients. Align to
1208 * IDMAC restrictions.
1210 last_output
= resized_height
- 1;
1211 if (closest
&& ((last_output
* resize_coeff_v
) % 8192))
1213 in_height
= round_up(
1214 (DIV_ROUND_UP(last_output
* resize_coeff_v
, 8192) + 1)
1215 << ctx
->downsize_coeff_v
, 2);
1217 for (col
= 0; col
< ctx
->in
.num_cols
; col
++) {
1218 tile_idx
= row
* ctx
->in
.num_cols
+ col
;
1219 in_tile
= &ctx
->in
.tile
[tile_idx
];
1220 out_tile
= &ctx
->out
.tile
[ctx
->out_tile_map
[tile_idx
]];
1222 if (ipu_rot_mode_is_irt(ctx
->rot_mode
))
1223 out_tile
->width
= resized_height
;
1225 out_tile
->height
= resized_height
;
1227 in_tile
->height
= in_height
;
1230 ctx
->resize_coeffs_v
[row
] = resize_coeff_v
;
1235 * return the number of runs in given queue (pending_q or done_q)
1236 * for this context. hold irqlock when calling.
1238 static int get_run_count(struct ipu_image_convert_ctx
*ctx
,
1239 struct list_head
*q
)
1241 struct ipu_image_convert_run
*run
;
1244 lockdep_assert_held(&ctx
->chan
->irqlock
);
1246 list_for_each_entry(run
, q
, list
) {
1247 if (run
->ctx
== ctx
)
1254 static void convert_stop(struct ipu_image_convert_run
*run
)
1256 struct ipu_image_convert_ctx
*ctx
= run
->ctx
;
1257 struct ipu_image_convert_chan
*chan
= ctx
->chan
;
1258 struct ipu_image_convert_priv
*priv
= chan
->priv
;
1260 dev_dbg(priv
->ipu
->dev
, "%s: task %u: stopping ctx %p run %p\n",
1261 __func__
, chan
->ic_task
, ctx
, run
);
1263 /* disable IC tasks and the channels */
1264 ipu_ic_task_disable(chan
->ic
);
1265 ipu_idmac_disable_channel(chan
->in_chan
);
1266 ipu_idmac_disable_channel(chan
->out_chan
);
1268 if (ipu_rot_mode_is_irt(ctx
->rot_mode
)) {
1269 ipu_idmac_disable_channel(chan
->rotation_in_chan
);
1270 ipu_idmac_disable_channel(chan
->rotation_out_chan
);
1271 ipu_idmac_unlink(chan
->out_chan
, chan
->rotation_in_chan
);
1274 ipu_ic_disable(chan
->ic
);
1277 static void init_idmac_channel(struct ipu_image_convert_ctx
*ctx
,
1278 struct ipuv3_channel
*channel
,
1279 struct ipu_image_convert_image
*image
,
1280 enum ipu_rotate_mode rot_mode
,
1281 bool rot_swap_width_height
,
1284 struct ipu_image_convert_chan
*chan
= ctx
->chan
;
1285 unsigned int burst_size
;
1286 u32 width
, height
, stride
;
1287 dma_addr_t addr0
, addr1
= 0;
1288 struct ipu_image tile_image
;
1289 unsigned int tile_idx
[2];
1291 if (image
->type
== IMAGE_CONVERT_OUT
) {
1292 tile_idx
[0] = ctx
->out_tile_map
[tile
];
1293 tile_idx
[1] = ctx
->out_tile_map
[1];
1299 if (rot_swap_width_height
) {
1300 width
= image
->tile
[tile_idx
[0]].height
;
1301 height
= image
->tile
[tile_idx
[0]].width
;
1302 stride
= image
->tile
[tile_idx
[0]].rot_stride
;
1303 addr0
= ctx
->rot_intermediate
[0].phys
;
1304 if (ctx
->double_buffering
)
1305 addr1
= ctx
->rot_intermediate
[1].phys
;
1307 width
= image
->tile
[tile_idx
[0]].width
;
1308 height
= image
->tile
[tile_idx
[0]].height
;
1309 stride
= image
->stride
;
1310 addr0
= image
->base
.phys0
+
1311 image
->tile
[tile_idx
[0]].offset
;
1312 if (ctx
->double_buffering
)
1313 addr1
= image
->base
.phys0
+
1314 image
->tile
[tile_idx
[1]].offset
;
1317 ipu_cpmem_zero(channel
);
1319 memset(&tile_image
, 0, sizeof(tile_image
));
1320 tile_image
.pix
.width
= tile_image
.rect
.width
= width
;
1321 tile_image
.pix
.height
= tile_image
.rect
.height
= height
;
1322 tile_image
.pix
.bytesperline
= stride
;
1323 tile_image
.pix
.pixelformat
= image
->fmt
->fourcc
;
1324 tile_image
.phys0
= addr0
;
1325 tile_image
.phys1
= addr1
;
1326 if (image
->fmt
->planar
&& !rot_swap_width_height
) {
1327 tile_image
.u_offset
= image
->tile
[tile_idx
[0]].u_off
;
1328 tile_image
.v_offset
= image
->tile
[tile_idx
[0]].v_off
;
1331 ipu_cpmem_set_image(channel
, &tile_image
);
1334 ipu_cpmem_set_rotation(channel
, rot_mode
);
1337 * Skip writing U and V components to odd rows in the output
1338 * channels for planar 4:2:0.
1340 if ((channel
== chan
->out_chan
||
1341 channel
== chan
->rotation_out_chan
) &&
1342 image
->fmt
->planar
&& image
->fmt
->uv_height_dec
== 2)
1343 ipu_cpmem_skip_odd_chroma_rows(channel
);
1345 if (channel
== chan
->rotation_in_chan
||
1346 channel
== chan
->rotation_out_chan
) {
1348 ipu_cpmem_set_block_mode(channel
);
1350 burst_size
= (width
% 16) ? 8 : 16;
1352 ipu_cpmem_set_burstsize(channel
, burst_size
);
1354 ipu_ic_task_idma_init(chan
->ic
, channel
, width
, height
,
1355 burst_size
, rot_mode
);
1358 * Setting a non-zero AXI ID collides with the PRG AXI snooping, so
1359 * only do this when there is no PRG present.
1361 if (!channel
->ipu
->prg_priv
)
1362 ipu_cpmem_set_axi_id(channel
, 1);
1364 ipu_idmac_set_double_buffer(channel
, ctx
->double_buffering
);
1367 static int convert_start(struct ipu_image_convert_run
*run
, unsigned int tile
)
1369 struct ipu_image_convert_ctx
*ctx
= run
->ctx
;
1370 struct ipu_image_convert_chan
*chan
= ctx
->chan
;
1371 struct ipu_image_convert_priv
*priv
= chan
->priv
;
1372 struct ipu_image_convert_image
*s_image
= &ctx
->in
;
1373 struct ipu_image_convert_image
*d_image
= &ctx
->out
;
1374 unsigned int dst_tile
= ctx
->out_tile_map
[tile
];
1375 unsigned int dest_width
, dest_height
;
1376 unsigned int col
, row
;
1380 dev_dbg(priv
->ipu
->dev
, "%s: task %u: starting ctx %p run %p tile %u -> %u\n",
1381 __func__
, chan
->ic_task
, ctx
, run
, tile
, dst_tile
);
1383 if (ipu_rot_mode_is_irt(ctx
->rot_mode
)) {
1384 /* swap width/height for resizer */
1385 dest_width
= d_image
->tile
[dst_tile
].height
;
1386 dest_height
= d_image
->tile
[dst_tile
].width
;
1388 dest_width
= d_image
->tile
[dst_tile
].width
;
1389 dest_height
= d_image
->tile
[dst_tile
].height
;
1392 row
= tile
/ s_image
->num_cols
;
1393 col
= tile
% s_image
->num_cols
;
1395 rsc
= (ctx
->downsize_coeff_v
<< 30) |
1396 (ctx
->resize_coeffs_v
[row
] << 16) |
1397 (ctx
->downsize_coeff_h
<< 14) |
1398 (ctx
->resize_coeffs_h
[col
]);
1400 dev_dbg(priv
->ipu
->dev
, "%s: %ux%u -> %ux%u (rsc = 0x%x)\n",
1401 __func__
, s_image
->tile
[tile
].width
,
1402 s_image
->tile
[tile
].height
, dest_width
, dest_height
, rsc
);
1404 /* setup the IC resizer and CSC */
1405 ret
= ipu_ic_task_init_rsc(chan
->ic
, &ctx
->csc
,
1406 s_image
->tile
[tile
].width
,
1407 s_image
->tile
[tile
].height
,
1412 dev_err(priv
->ipu
->dev
, "ipu_ic_task_init failed, %d\n", ret
);
1416 /* init the source MEM-->IC PP IDMAC channel */
1417 init_idmac_channel(ctx
, chan
->in_chan
, s_image
,
1418 IPU_ROTATE_NONE
, false, tile
);
1420 if (ipu_rot_mode_is_irt(ctx
->rot_mode
)) {
1421 /* init the IC PP-->MEM IDMAC channel */
1422 init_idmac_channel(ctx
, chan
->out_chan
, d_image
,
1423 IPU_ROTATE_NONE
, true, tile
);
1425 /* init the MEM-->IC PP ROT IDMAC channel */
1426 init_idmac_channel(ctx
, chan
->rotation_in_chan
, d_image
,
1427 ctx
->rot_mode
, true, tile
);
1429 /* init the destination IC PP ROT-->MEM IDMAC channel */
1430 init_idmac_channel(ctx
, chan
->rotation_out_chan
, d_image
,
1431 IPU_ROTATE_NONE
, false, tile
);
1433 /* now link IC PP-->MEM to MEM-->IC PP ROT */
1434 ipu_idmac_link(chan
->out_chan
, chan
->rotation_in_chan
);
1436 /* init the destination IC PP-->MEM IDMAC channel */
1437 init_idmac_channel(ctx
, chan
->out_chan
, d_image
,
1438 ctx
->rot_mode
, false, tile
);
1442 ipu_ic_enable(chan
->ic
);
1444 /* set buffers ready */
1445 ipu_idmac_select_buffer(chan
->in_chan
, 0);
1446 ipu_idmac_select_buffer(chan
->out_chan
, 0);
1447 if (ipu_rot_mode_is_irt(ctx
->rot_mode
))
1448 ipu_idmac_select_buffer(chan
->rotation_out_chan
, 0);
1449 if (ctx
->double_buffering
) {
1450 ipu_idmac_select_buffer(chan
->in_chan
, 1);
1451 ipu_idmac_select_buffer(chan
->out_chan
, 1);
1452 if (ipu_rot_mode_is_irt(ctx
->rot_mode
))
1453 ipu_idmac_select_buffer(chan
->rotation_out_chan
, 1);
1456 /* enable the channels! */
1457 ipu_idmac_enable_channel(chan
->in_chan
);
1458 ipu_idmac_enable_channel(chan
->out_chan
);
1459 if (ipu_rot_mode_is_irt(ctx
->rot_mode
)) {
1460 ipu_idmac_enable_channel(chan
->rotation_in_chan
);
1461 ipu_idmac_enable_channel(chan
->rotation_out_chan
);
1464 ipu_ic_task_enable(chan
->ic
);
1466 ipu_cpmem_dump(chan
->in_chan
);
1467 ipu_cpmem_dump(chan
->out_chan
);
1468 if (ipu_rot_mode_is_irt(ctx
->rot_mode
)) {
1469 ipu_cpmem_dump(chan
->rotation_in_chan
);
1470 ipu_cpmem_dump(chan
->rotation_out_chan
);
1473 ipu_dump(priv
->ipu
);
1478 /* hold irqlock when calling */
1479 static int do_run(struct ipu_image_convert_run
*run
)
1481 struct ipu_image_convert_ctx
*ctx
= run
->ctx
;
1482 struct ipu_image_convert_chan
*chan
= ctx
->chan
;
1484 lockdep_assert_held(&chan
->irqlock
);
1486 ctx
->in
.base
.phys0
= run
->in_phys
;
1487 ctx
->out
.base
.phys0
= run
->out_phys
;
1489 ctx
->cur_buf_num
= 0;
1492 /* remove run from pending_q and set as current */
1493 list_del(&run
->list
);
1494 chan
->current_run
= run
;
1496 return convert_start(run
, 0);
1499 /* hold irqlock when calling */
1500 static void run_next(struct ipu_image_convert_chan
*chan
)
1502 struct ipu_image_convert_priv
*priv
= chan
->priv
;
1503 struct ipu_image_convert_run
*run
, *tmp
;
1506 lockdep_assert_held(&chan
->irqlock
);
1508 list_for_each_entry_safe(run
, tmp
, &chan
->pending_q
, list
) {
1509 /* skip contexts that are aborting */
1510 if (run
->ctx
->aborting
) {
1511 dev_dbg(priv
->ipu
->dev
,
1512 "%s: task %u: skipping aborting ctx %p run %p\n",
1513 __func__
, chan
->ic_task
, run
->ctx
, run
);
1522 * something went wrong with start, add the run
1523 * to done q and continue to the next run in the
1527 list_add_tail(&run
->list
, &chan
->done_q
);
1528 chan
->current_run
= NULL
;
1532 static void empty_done_q(struct ipu_image_convert_chan
*chan
)
1534 struct ipu_image_convert_priv
*priv
= chan
->priv
;
1535 struct ipu_image_convert_run
*run
;
1536 unsigned long flags
;
1538 spin_lock_irqsave(&chan
->irqlock
, flags
);
1540 while (!list_empty(&chan
->done_q
)) {
1541 run
= list_entry(chan
->done_q
.next
,
1542 struct ipu_image_convert_run
,
1545 list_del(&run
->list
);
1547 dev_dbg(priv
->ipu
->dev
,
1548 "%s: task %u: completing ctx %p run %p with %d\n",
1549 __func__
, chan
->ic_task
, run
->ctx
, run
, run
->status
);
1551 /* call the completion callback and free the run */
1552 spin_unlock_irqrestore(&chan
->irqlock
, flags
);
1553 run
->ctx
->complete(run
, run
->ctx
->complete_context
);
1554 spin_lock_irqsave(&chan
->irqlock
, flags
);
1557 spin_unlock_irqrestore(&chan
->irqlock
, flags
);
1561 * the bottom half thread clears out the done_q, calling the
1562 * completion handler for each.
1564 static irqreturn_t
do_bh(int irq
, void *dev_id
)
1566 struct ipu_image_convert_chan
*chan
= dev_id
;
1567 struct ipu_image_convert_priv
*priv
= chan
->priv
;
1568 struct ipu_image_convert_ctx
*ctx
;
1569 unsigned long flags
;
1571 dev_dbg(priv
->ipu
->dev
, "%s: task %u: enter\n", __func__
,
1576 spin_lock_irqsave(&chan
->irqlock
, flags
);
1579 * the done_q is cleared out, signal any contexts
1580 * that are aborting that abort can complete.
1582 list_for_each_entry(ctx
, &chan
->ctx_list
, list
) {
1583 if (ctx
->aborting
) {
1584 dev_dbg(priv
->ipu
->dev
,
1585 "%s: task %u: signaling abort for ctx %p\n",
1586 __func__
, chan
->ic_task
, ctx
);
1587 complete_all(&ctx
->aborted
);
1591 spin_unlock_irqrestore(&chan
->irqlock
, flags
);
1593 dev_dbg(priv
->ipu
->dev
, "%s: task %u: exit\n", __func__
,
1599 static bool ic_settings_changed(struct ipu_image_convert_ctx
*ctx
)
1601 unsigned int cur_tile
= ctx
->next_tile
- 1;
1602 unsigned int next_tile
= ctx
->next_tile
;
1604 if (ctx
->resize_coeffs_h
[cur_tile
% ctx
->in
.num_cols
] !=
1605 ctx
->resize_coeffs_h
[next_tile
% ctx
->in
.num_cols
] ||
1606 ctx
->resize_coeffs_v
[cur_tile
/ ctx
->in
.num_cols
] !=
1607 ctx
->resize_coeffs_v
[next_tile
/ ctx
->in
.num_cols
] ||
1608 ctx
->in
.tile
[cur_tile
].width
!= ctx
->in
.tile
[next_tile
].width
||
1609 ctx
->in
.tile
[cur_tile
].height
!= ctx
->in
.tile
[next_tile
].height
||
1610 ctx
->out
.tile
[cur_tile
].width
!= ctx
->out
.tile
[next_tile
].width
||
1611 ctx
->out
.tile
[cur_tile
].height
!= ctx
->out
.tile
[next_tile
].height
)
1617 /* hold irqlock when calling */
1618 static irqreturn_t
do_irq(struct ipu_image_convert_run
*run
)
1620 struct ipu_image_convert_ctx
*ctx
= run
->ctx
;
1621 struct ipu_image_convert_chan
*chan
= ctx
->chan
;
1622 struct ipu_image_tile
*src_tile
, *dst_tile
;
1623 struct ipu_image_convert_image
*s_image
= &ctx
->in
;
1624 struct ipu_image_convert_image
*d_image
= &ctx
->out
;
1625 struct ipuv3_channel
*outch
;
1626 unsigned int dst_idx
;
1628 lockdep_assert_held(&chan
->irqlock
);
1630 outch
= ipu_rot_mode_is_irt(ctx
->rot_mode
) ?
1631 chan
->rotation_out_chan
: chan
->out_chan
;
1634 * It is difficult to stop the channel DMA before the channels
1635 * enter the paused state. Without double-buffering the channels
1636 * are always in a paused state when the EOF irq occurs, so it
1637 * is safe to stop the channels now. For double-buffering we
1638 * just ignore the abort until the operation completes, when it
1639 * is safe to shut down.
1641 if (ctx
->aborting
&& !ctx
->double_buffering
) {
1647 if (ctx
->next_tile
== ctx
->num_tiles
) {
1649 * the conversion is complete
1657 * not done, place the next tile buffers.
1659 if (!ctx
->double_buffering
) {
1660 if (ic_settings_changed(ctx
)) {
1662 convert_start(run
, ctx
->next_tile
);
1664 src_tile
= &s_image
->tile
[ctx
->next_tile
];
1665 dst_idx
= ctx
->out_tile_map
[ctx
->next_tile
];
1666 dst_tile
= &d_image
->tile
[dst_idx
];
1668 ipu_cpmem_set_buffer(chan
->in_chan
, 0,
1669 s_image
->base
.phys0
+
1671 ipu_cpmem_set_buffer(outch
, 0,
1672 d_image
->base
.phys0
+
1674 if (s_image
->fmt
->planar
)
1675 ipu_cpmem_set_uv_offset(chan
->in_chan
,
1678 if (d_image
->fmt
->planar
)
1679 ipu_cpmem_set_uv_offset(outch
,
1683 ipu_idmac_select_buffer(chan
->in_chan
, 0);
1684 ipu_idmac_select_buffer(outch
, 0);
1686 } else if (ctx
->next_tile
< ctx
->num_tiles
- 1) {
1688 src_tile
= &s_image
->tile
[ctx
->next_tile
+ 1];
1689 dst_idx
= ctx
->out_tile_map
[ctx
->next_tile
+ 1];
1690 dst_tile
= &d_image
->tile
[dst_idx
];
1692 ipu_cpmem_set_buffer(chan
->in_chan
, ctx
->cur_buf_num
,
1693 s_image
->base
.phys0
+ src_tile
->offset
);
1694 ipu_cpmem_set_buffer(outch
, ctx
->cur_buf_num
,
1695 d_image
->base
.phys0
+ dst_tile
->offset
);
1697 ipu_idmac_select_buffer(chan
->in_chan
, ctx
->cur_buf_num
);
1698 ipu_idmac_select_buffer(outch
, ctx
->cur_buf_num
);
1700 ctx
->cur_buf_num
^= 1;
1706 list_add_tail(&run
->list
, &chan
->done_q
);
1707 chan
->current_run
= NULL
;
1709 return IRQ_WAKE_THREAD
;
1712 static irqreturn_t
norotate_irq(int irq
, void *data
)
1714 struct ipu_image_convert_chan
*chan
= data
;
1715 struct ipu_image_convert_ctx
*ctx
;
1716 struct ipu_image_convert_run
*run
;
1717 unsigned long flags
;
1720 spin_lock_irqsave(&chan
->irqlock
, flags
);
1722 /* get current run and its context */
1723 run
= chan
->current_run
;
1731 if (ipu_rot_mode_is_irt(ctx
->rot_mode
)) {
1732 /* this is a rotation operation, just ignore */
1733 spin_unlock_irqrestore(&chan
->irqlock
, flags
);
1739 spin_unlock_irqrestore(&chan
->irqlock
, flags
);
1743 static irqreturn_t
rotate_irq(int irq
, void *data
)
1745 struct ipu_image_convert_chan
*chan
= data
;
1746 struct ipu_image_convert_priv
*priv
= chan
->priv
;
1747 struct ipu_image_convert_ctx
*ctx
;
1748 struct ipu_image_convert_run
*run
;
1749 unsigned long flags
;
1752 spin_lock_irqsave(&chan
->irqlock
, flags
);
1754 /* get current run and its context */
1755 run
= chan
->current_run
;
1763 if (!ipu_rot_mode_is_irt(ctx
->rot_mode
)) {
1764 /* this was NOT a rotation operation, shouldn't happen */
1765 dev_err(priv
->ipu
->dev
, "Unexpected rotation interrupt\n");
1766 spin_unlock_irqrestore(&chan
->irqlock
, flags
);
1772 spin_unlock_irqrestore(&chan
->irqlock
, flags
);
1777 * try to force the completion of runs for this ctx. Called when
1778 * abort wait times out in ipu_image_convert_abort().
1780 static void force_abort(struct ipu_image_convert_ctx
*ctx
)
1782 struct ipu_image_convert_chan
*chan
= ctx
->chan
;
1783 struct ipu_image_convert_run
*run
;
1784 unsigned long flags
;
1786 spin_lock_irqsave(&chan
->irqlock
, flags
);
1788 run
= chan
->current_run
;
1789 if (run
&& run
->ctx
== ctx
) {
1792 list_add_tail(&run
->list
, &chan
->done_q
);
1793 chan
->current_run
= NULL
;
1797 spin_unlock_irqrestore(&chan
->irqlock
, flags
);
1802 static void release_ipu_resources(struct ipu_image_convert_chan
*chan
)
1804 if (chan
->out_eof_irq
>= 0)
1805 free_irq(chan
->out_eof_irq
, chan
);
1806 if (chan
->rot_out_eof_irq
>= 0)
1807 free_irq(chan
->rot_out_eof_irq
, chan
);
1809 if (!IS_ERR_OR_NULL(chan
->in_chan
))
1810 ipu_idmac_put(chan
->in_chan
);
1811 if (!IS_ERR_OR_NULL(chan
->out_chan
))
1812 ipu_idmac_put(chan
->out_chan
);
1813 if (!IS_ERR_OR_NULL(chan
->rotation_in_chan
))
1814 ipu_idmac_put(chan
->rotation_in_chan
);
1815 if (!IS_ERR_OR_NULL(chan
->rotation_out_chan
))
1816 ipu_idmac_put(chan
->rotation_out_chan
);
1817 if (!IS_ERR_OR_NULL(chan
->ic
))
1818 ipu_ic_put(chan
->ic
);
1820 chan
->in_chan
= chan
->out_chan
= chan
->rotation_in_chan
=
1821 chan
->rotation_out_chan
= NULL
;
1822 chan
->out_eof_irq
= chan
->rot_out_eof_irq
= -1;
1825 static int get_ipu_resources(struct ipu_image_convert_chan
*chan
)
1827 const struct ipu_image_convert_dma_chan
*dma
= chan
->dma_ch
;
1828 struct ipu_image_convert_priv
*priv
= chan
->priv
;
1832 chan
->ic
= ipu_ic_get(priv
->ipu
, chan
->ic_task
);
1833 if (IS_ERR(chan
->ic
)) {
1834 dev_err(priv
->ipu
->dev
, "could not acquire IC\n");
1835 ret
= PTR_ERR(chan
->ic
);
1839 /* get IDMAC channels */
1840 chan
->in_chan
= ipu_idmac_get(priv
->ipu
, dma
->in
);
1841 chan
->out_chan
= ipu_idmac_get(priv
->ipu
, dma
->out
);
1842 if (IS_ERR(chan
->in_chan
) || IS_ERR(chan
->out_chan
)) {
1843 dev_err(priv
->ipu
->dev
, "could not acquire idmac channels\n");
1848 chan
->rotation_in_chan
= ipu_idmac_get(priv
->ipu
, dma
->rot_in
);
1849 chan
->rotation_out_chan
= ipu_idmac_get(priv
->ipu
, dma
->rot_out
);
1850 if (IS_ERR(chan
->rotation_in_chan
) || IS_ERR(chan
->rotation_out_chan
)) {
1851 dev_err(priv
->ipu
->dev
,
1852 "could not acquire idmac rotation channels\n");
1857 /* acquire the EOF interrupts */
1858 chan
->out_eof_irq
= ipu_idmac_channel_irq(priv
->ipu
,
1862 ret
= request_threaded_irq(chan
->out_eof_irq
, norotate_irq
, do_bh
,
1865 dev_err(priv
->ipu
->dev
, "could not acquire irq %d\n",
1867 chan
->out_eof_irq
= -1;
1871 chan
->rot_out_eof_irq
= ipu_idmac_channel_irq(priv
->ipu
,
1872 chan
->rotation_out_chan
,
1875 ret
= request_threaded_irq(chan
->rot_out_eof_irq
, rotate_irq
, do_bh
,
1878 dev_err(priv
->ipu
->dev
, "could not acquire irq %d\n",
1879 chan
->rot_out_eof_irq
);
1880 chan
->rot_out_eof_irq
= -1;
1886 release_ipu_resources(chan
);
1890 static int fill_image(struct ipu_image_convert_ctx
*ctx
,
1891 struct ipu_image_convert_image
*ic_image
,
1892 struct ipu_image
*image
,
1893 enum ipu_image_convert_type type
)
1895 struct ipu_image_convert_priv
*priv
= ctx
->chan
->priv
;
1897 ic_image
->base
= *image
;
1898 ic_image
->type
= type
;
1900 ic_image
->fmt
= get_format(image
->pix
.pixelformat
);
1901 if (!ic_image
->fmt
) {
1902 dev_err(priv
->ipu
->dev
, "pixelformat not supported for %s\n",
1903 type
== IMAGE_CONVERT_OUT
? "Output" : "Input");
1907 if (ic_image
->fmt
->planar
)
1908 ic_image
->stride
= ic_image
->base
.pix
.width
;
1910 ic_image
->stride
= ic_image
->base
.pix
.bytesperline
;
1915 /* borrowed from drivers/media/v4l2-core/v4l2-common.c */
1916 static unsigned int clamp_align(unsigned int x
, unsigned int min
,
1917 unsigned int max
, unsigned int align
)
1919 /* Bits that must be zero to be aligned */
1920 unsigned int mask
= ~((1 << align
) - 1);
1922 /* Clamp to aligned min and max */
1923 x
= clamp(x
, (min
+ ~mask
) & mask
, max
& mask
);
1925 /* Round to nearest aligned value */
1927 x
= (x
+ (1 << (align
- 1))) & mask
;
1932 /* Adjusts input/output images to IPU restrictions */
1933 void ipu_image_convert_adjust(struct ipu_image
*in
, struct ipu_image
*out
,
1934 enum ipu_rotate_mode rot_mode
)
1936 const struct ipu_image_pixfmt
*infmt
, *outfmt
;
1937 u32 w_align_out
, h_align_out
;
1938 u32 w_align_in
, h_align_in
;
1940 infmt
= get_format(in
->pix
.pixelformat
);
1941 outfmt
= get_format(out
->pix
.pixelformat
);
1943 /* set some default pixel formats if needed */
1945 in
->pix
.pixelformat
= V4L2_PIX_FMT_RGB24
;
1946 infmt
= get_format(V4L2_PIX_FMT_RGB24
);
1949 out
->pix
.pixelformat
= V4L2_PIX_FMT_RGB24
;
1950 outfmt
= get_format(V4L2_PIX_FMT_RGB24
);
1953 /* image converter does not handle fields */
1954 in
->pix
.field
= out
->pix
.field
= V4L2_FIELD_NONE
;
1956 /* resizer cannot downsize more than 4:1 */
1957 if (ipu_rot_mode_is_irt(rot_mode
)) {
1958 out
->pix
.height
= max_t(__u32
, out
->pix
.height
,
1960 out
->pix
.width
= max_t(__u32
, out
->pix
.width
,
1961 in
->pix
.height
/ 4);
1963 out
->pix
.width
= max_t(__u32
, out
->pix
.width
,
1965 out
->pix
.height
= max_t(__u32
, out
->pix
.height
,
1966 in
->pix
.height
/ 4);
1969 /* align input width/height */
1970 w_align_in
= ilog2(tile_width_align(IMAGE_CONVERT_IN
, infmt
,
1972 h_align_in
= ilog2(tile_height_align(IMAGE_CONVERT_IN
, infmt
,
1974 in
->pix
.width
= clamp_align(in
->pix
.width
, MIN_W
, MAX_W
,
1976 in
->pix
.height
= clamp_align(in
->pix
.height
, MIN_H
, MAX_H
,
1979 /* align output width/height */
1980 w_align_out
= ilog2(tile_width_align(IMAGE_CONVERT_OUT
, outfmt
,
1982 h_align_out
= ilog2(tile_height_align(IMAGE_CONVERT_OUT
, outfmt
,
1984 out
->pix
.width
= clamp_align(out
->pix
.width
, MIN_W
, MAX_W
,
1986 out
->pix
.height
= clamp_align(out
->pix
.height
, MIN_H
, MAX_H
,
1989 /* set input/output strides and image sizes */
1990 in
->pix
.bytesperline
= infmt
->planar
?
1991 clamp_align(in
->pix
.width
, 2 << w_align_in
, MAX_W
,
1993 clamp_align((in
->pix
.width
* infmt
->bpp
) >> 3,
1994 ((2 << w_align_in
) * infmt
->bpp
) >> 3,
1995 (MAX_W
* infmt
->bpp
) >> 3,
1997 in
->pix
.sizeimage
= infmt
->planar
?
1998 (in
->pix
.height
* in
->pix
.bytesperline
* infmt
->bpp
) >> 3 :
1999 in
->pix
.height
* in
->pix
.bytesperline
;
2000 out
->pix
.bytesperline
= outfmt
->planar
? out
->pix
.width
:
2001 (out
->pix
.width
* outfmt
->bpp
) >> 3;
2002 out
->pix
.sizeimage
= outfmt
->planar
?
2003 (out
->pix
.height
* out
->pix
.bytesperline
* outfmt
->bpp
) >> 3 :
2004 out
->pix
.height
* out
->pix
.bytesperline
;
2006 EXPORT_SYMBOL_GPL(ipu_image_convert_adjust
);
2009 * this is used by ipu_image_convert_prepare() to verify set input and
2010 * output images are valid before starting the conversion. Clients can
2011 * also call it before calling ipu_image_convert_prepare().
2013 int ipu_image_convert_verify(struct ipu_image
*in
, struct ipu_image
*out
,
2014 enum ipu_rotate_mode rot_mode
)
2016 struct ipu_image testin
, testout
;
2021 ipu_image_convert_adjust(&testin
, &testout
, rot_mode
);
2023 if (testin
.pix
.width
!= in
->pix
.width
||
2024 testin
.pix
.height
!= in
->pix
.height
||
2025 testout
.pix
.width
!= out
->pix
.width
||
2026 testout
.pix
.height
!= out
->pix
.height
)
2031 EXPORT_SYMBOL_GPL(ipu_image_convert_verify
);
2034 * Call ipu_image_convert_prepare() to prepare for the conversion of
2035 * given images and rotation mode. Returns a new conversion context.
2037 struct ipu_image_convert_ctx
*
2038 ipu_image_convert_prepare(struct ipu_soc
*ipu
, enum ipu_ic_task ic_task
,
2039 struct ipu_image
*in
, struct ipu_image
*out
,
2040 enum ipu_rotate_mode rot_mode
,
2041 ipu_image_convert_cb_t complete
,
2042 void *complete_context
)
2044 struct ipu_image_convert_priv
*priv
= ipu
->image_convert_priv
;
2045 struct ipu_image_convert_image
*s_image
, *d_image
;
2046 struct ipu_image_convert_chan
*chan
;
2047 struct ipu_image_convert_ctx
*ctx
;
2048 unsigned long flags
;
2053 if (!in
|| !out
|| !complete
||
2054 (ic_task
!= IC_TASK_VIEWFINDER
&&
2055 ic_task
!= IC_TASK_POST_PROCESSOR
))
2056 return ERR_PTR(-EINVAL
);
2058 /* verify the in/out images before continuing */
2059 ret
= ipu_image_convert_verify(in
, out
, rot_mode
);
2061 dev_err(priv
->ipu
->dev
, "%s: in/out formats invalid\n",
2063 return ERR_PTR(ret
);
2066 chan
= &priv
->chan
[ic_task
];
2068 ctx
= kzalloc(sizeof(*ctx
), GFP_KERNEL
);
2070 return ERR_PTR(-ENOMEM
);
2072 dev_dbg(priv
->ipu
->dev
, "%s: task %u: ctx %p\n", __func__
,
2073 chan
->ic_task
, ctx
);
2076 init_completion(&ctx
->aborted
);
2078 ctx
->rot_mode
= rot_mode
;
2080 /* Sets ctx->in.num_rows/cols as well */
2081 ret
= calc_image_resize_coefficients(ctx
, in
, out
);
2086 d_image
= &ctx
->out
;
2088 /* set tiling and rotation */
2089 if (ipu_rot_mode_is_irt(rot_mode
)) {
2090 d_image
->num_rows
= s_image
->num_cols
;
2091 d_image
->num_cols
= s_image
->num_rows
;
2093 d_image
->num_rows
= s_image
->num_rows
;
2094 d_image
->num_cols
= s_image
->num_cols
;
2097 ctx
->num_tiles
= d_image
->num_cols
* d_image
->num_rows
;
2099 ret
= fill_image(ctx
, s_image
, in
, IMAGE_CONVERT_IN
);
2102 ret
= fill_image(ctx
, d_image
, out
, IMAGE_CONVERT_OUT
);
2106 calc_out_tile_map(ctx
);
2108 find_seams(ctx
, s_image
, d_image
);
2110 ret
= calc_tile_dimensions(ctx
, s_image
);
2114 ret
= calc_tile_offsets(ctx
, s_image
);
2118 calc_tile_dimensions(ctx
, d_image
);
2119 ret
= calc_tile_offsets(ctx
, d_image
);
2123 calc_tile_resize_coefficients(ctx
);
2125 ret
= ipu_ic_calc_csc(&ctx
->csc
,
2126 s_image
->base
.pix
.ycbcr_enc
,
2127 s_image
->base
.pix
.quantization
,
2128 ipu_pixelformat_to_colorspace(s_image
->fmt
->fourcc
),
2129 d_image
->base
.pix
.ycbcr_enc
,
2130 d_image
->base
.pix
.quantization
,
2131 ipu_pixelformat_to_colorspace(d_image
->fmt
->fourcc
));
2135 dump_format(ctx
, s_image
);
2136 dump_format(ctx
, d_image
);
2138 ctx
->complete
= complete
;
2139 ctx
->complete_context
= complete_context
;
2142 * Can we use double-buffering for this operation? If there is
2143 * only one tile (the whole image can be converted in a single
2144 * operation) there's no point in using double-buffering. Also,
2145 * the IPU's IDMAC channels allow only a single U and V plane
2146 * offset shared between both buffers, but these offsets change
2147 * for every tile, and therefore would have to be updated for
2148 * each buffer which is not possible. So double-buffering is
2149 * impossible when either the source or destination images are
2150 * a planar format (YUV420, YUV422P, etc.). Further, differently
2151 * sized tiles or different resizing coefficients per tile
2152 * prevent double-buffering as well.
2154 ctx
->double_buffering
= (ctx
->num_tiles
> 1 &&
2155 !s_image
->fmt
->planar
&&
2156 !d_image
->fmt
->planar
);
2157 for (i
= 1; i
< ctx
->num_tiles
; i
++) {
2158 if (ctx
->in
.tile
[i
].width
!= ctx
->in
.tile
[0].width
||
2159 ctx
->in
.tile
[i
].height
!= ctx
->in
.tile
[0].height
||
2160 ctx
->out
.tile
[i
].width
!= ctx
->out
.tile
[0].width
||
2161 ctx
->out
.tile
[i
].height
!= ctx
->out
.tile
[0].height
) {
2162 ctx
->double_buffering
= false;
2166 for (i
= 1; i
< ctx
->in
.num_cols
; i
++) {
2167 if (ctx
->resize_coeffs_h
[i
] != ctx
->resize_coeffs_h
[0]) {
2168 ctx
->double_buffering
= false;
2172 for (i
= 1; i
< ctx
->in
.num_rows
; i
++) {
2173 if (ctx
->resize_coeffs_v
[i
] != ctx
->resize_coeffs_v
[0]) {
2174 ctx
->double_buffering
= false;
2179 if (ipu_rot_mode_is_irt(ctx
->rot_mode
)) {
2180 unsigned long intermediate_size
= d_image
->tile
[0].size
;
2182 for (i
= 1; i
< ctx
->num_tiles
; i
++) {
2183 if (d_image
->tile
[i
].size
> intermediate_size
)
2184 intermediate_size
= d_image
->tile
[i
].size
;
2187 ret
= alloc_dma_buf(priv
, &ctx
->rot_intermediate
[0],
2191 if (ctx
->double_buffering
) {
2192 ret
= alloc_dma_buf(priv
,
2193 &ctx
->rot_intermediate
[1],
2196 goto out_free_dmabuf0
;
2200 spin_lock_irqsave(&chan
->irqlock
, flags
);
2202 get_res
= list_empty(&chan
->ctx_list
);
2204 list_add_tail(&ctx
->list
, &chan
->ctx_list
);
2206 spin_unlock_irqrestore(&chan
->irqlock
, flags
);
2209 ret
= get_ipu_resources(chan
);
2211 goto out_free_dmabuf1
;
2217 free_dma_buf(priv
, &ctx
->rot_intermediate
[1]);
2218 spin_lock_irqsave(&chan
->irqlock
, flags
);
2219 list_del(&ctx
->list
);
2220 spin_unlock_irqrestore(&chan
->irqlock
, flags
);
2222 free_dma_buf(priv
, &ctx
->rot_intermediate
[0]);
2225 return ERR_PTR(ret
);
2227 EXPORT_SYMBOL_GPL(ipu_image_convert_prepare
);
2230 * Carry out a single image conversion run. Only the physaddr's of the input
2231 * and output image buffers are needed. The conversion context must have
2232 * been created previously with ipu_image_convert_prepare().
2234 int ipu_image_convert_queue(struct ipu_image_convert_run
*run
)
2236 struct ipu_image_convert_chan
*chan
;
2237 struct ipu_image_convert_priv
*priv
;
2238 struct ipu_image_convert_ctx
*ctx
;
2239 unsigned long flags
;
2242 if (!run
|| !run
->ctx
|| !run
->in_phys
|| !run
->out_phys
)
2249 dev_dbg(priv
->ipu
->dev
, "%s: task %u: ctx %p run %p\n", __func__
,
2250 chan
->ic_task
, ctx
, run
);
2252 INIT_LIST_HEAD(&run
->list
);
2254 spin_lock_irqsave(&chan
->irqlock
, flags
);
2256 if (ctx
->aborting
) {
2261 list_add_tail(&run
->list
, &chan
->pending_q
);
2263 if (!chan
->current_run
) {
2266 chan
->current_run
= NULL
;
2269 spin_unlock_irqrestore(&chan
->irqlock
, flags
);
2272 EXPORT_SYMBOL_GPL(ipu_image_convert_queue
);
2274 /* Abort any active or pending conversions for this context */
2275 static void __ipu_image_convert_abort(struct ipu_image_convert_ctx
*ctx
)
2277 struct ipu_image_convert_chan
*chan
= ctx
->chan
;
2278 struct ipu_image_convert_priv
*priv
= chan
->priv
;
2279 struct ipu_image_convert_run
*run
, *active_run
, *tmp
;
2280 unsigned long flags
;
2283 spin_lock_irqsave(&chan
->irqlock
, flags
);
2285 /* move all remaining pending runs in this context to done_q */
2286 list_for_each_entry_safe(run
, tmp
, &chan
->pending_q
, list
) {
2287 if (run
->ctx
!= ctx
)
2290 list_move_tail(&run
->list
, &chan
->done_q
);
2293 run_count
= get_run_count(ctx
, &chan
->done_q
);
2294 active_run
= (chan
->current_run
&& chan
->current_run
->ctx
== ctx
) ?
2295 chan
->current_run
: NULL
;
2298 reinit_completion(&ctx
->aborted
);
2300 ctx
->aborting
= true;
2302 spin_unlock_irqrestore(&chan
->irqlock
, flags
);
2304 if (!run_count
&& !active_run
) {
2305 dev_dbg(priv
->ipu
->dev
,
2306 "%s: task %u: no abort needed for ctx %p\n",
2307 __func__
, chan
->ic_task
, ctx
);
2316 dev_dbg(priv
->ipu
->dev
,
2317 "%s: task %u: wait for completion: %d runs\n",
2318 __func__
, chan
->ic_task
, run_count
);
2320 ret
= wait_for_completion_timeout(&ctx
->aborted
,
2321 msecs_to_jiffies(10000));
2323 dev_warn(priv
->ipu
->dev
, "%s: timeout\n", __func__
);
2328 void ipu_image_convert_abort(struct ipu_image_convert_ctx
*ctx
)
2330 __ipu_image_convert_abort(ctx
);
2331 ctx
->aborting
= false;
2333 EXPORT_SYMBOL_GPL(ipu_image_convert_abort
);
2335 /* Unprepare image conversion context */
2336 void ipu_image_convert_unprepare(struct ipu_image_convert_ctx
*ctx
)
2338 struct ipu_image_convert_chan
*chan
= ctx
->chan
;
2339 struct ipu_image_convert_priv
*priv
= chan
->priv
;
2340 unsigned long flags
;
2343 /* make sure no runs are hanging around */
2344 __ipu_image_convert_abort(ctx
);
2346 dev_dbg(priv
->ipu
->dev
, "%s: task %u: removing ctx %p\n", __func__
,
2347 chan
->ic_task
, ctx
);
2349 spin_lock_irqsave(&chan
->irqlock
, flags
);
2351 list_del(&ctx
->list
);
2353 put_res
= list_empty(&chan
->ctx_list
);
2355 spin_unlock_irqrestore(&chan
->irqlock
, flags
);
2358 release_ipu_resources(chan
);
2360 free_dma_buf(priv
, &ctx
->rot_intermediate
[1]);
2361 free_dma_buf(priv
, &ctx
->rot_intermediate
[0]);
2365 EXPORT_SYMBOL_GPL(ipu_image_convert_unprepare
);
2368 * "Canned" asynchronous single image conversion. Allocates and returns
2369 * a new conversion run. On successful return the caller must free the
2370 * run and call ipu_image_convert_unprepare() after conversion completes.
2372 struct ipu_image_convert_run
*
2373 ipu_image_convert(struct ipu_soc
*ipu
, enum ipu_ic_task ic_task
,
2374 struct ipu_image
*in
, struct ipu_image
*out
,
2375 enum ipu_rotate_mode rot_mode
,
2376 ipu_image_convert_cb_t complete
,
2377 void *complete_context
)
2379 struct ipu_image_convert_ctx
*ctx
;
2380 struct ipu_image_convert_run
*run
;
2383 ctx
= ipu_image_convert_prepare(ipu
, ic_task
, in
, out
, rot_mode
,
2384 complete
, complete_context
);
2386 return ERR_CAST(ctx
);
2388 run
= kzalloc(sizeof(*run
), GFP_KERNEL
);
2390 ipu_image_convert_unprepare(ctx
);
2391 return ERR_PTR(-ENOMEM
);
2395 run
->in_phys
= in
->phys0
;
2396 run
->out_phys
= out
->phys0
;
2398 ret
= ipu_image_convert_queue(run
);
2400 ipu_image_convert_unprepare(ctx
);
2402 return ERR_PTR(ret
);
2407 EXPORT_SYMBOL_GPL(ipu_image_convert
);
2409 /* "Canned" synchronous single image conversion */
2410 static void image_convert_sync_complete(struct ipu_image_convert_run
*run
,
2413 struct completion
*comp
= data
;
2418 int ipu_image_convert_sync(struct ipu_soc
*ipu
, enum ipu_ic_task ic_task
,
2419 struct ipu_image
*in
, struct ipu_image
*out
,
2420 enum ipu_rotate_mode rot_mode
)
2422 struct ipu_image_convert_run
*run
;
2423 struct completion comp
;
2426 init_completion(&comp
);
2428 run
= ipu_image_convert(ipu
, ic_task
, in
, out
, rot_mode
,
2429 image_convert_sync_complete
, &comp
);
2431 return PTR_ERR(run
);
2433 ret
= wait_for_completion_timeout(&comp
, msecs_to_jiffies(10000));
2434 ret
= (ret
== 0) ? -ETIMEDOUT
: 0;
2436 ipu_image_convert_unprepare(run
->ctx
);
2441 EXPORT_SYMBOL_GPL(ipu_image_convert_sync
);
2443 int ipu_image_convert_init(struct ipu_soc
*ipu
, struct device
*dev
)
2445 struct ipu_image_convert_priv
*priv
;
2448 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
2452 ipu
->image_convert_priv
= priv
;
2455 for (i
= 0; i
< IC_NUM_TASKS
; i
++) {
2456 struct ipu_image_convert_chan
*chan
= &priv
->chan
[i
];
2460 chan
->dma_ch
= &image_convert_dma_chan
[i
];
2461 chan
->out_eof_irq
= -1;
2462 chan
->rot_out_eof_irq
= -1;
2464 spin_lock_init(&chan
->irqlock
);
2465 INIT_LIST_HEAD(&chan
->ctx_list
);
2466 INIT_LIST_HEAD(&chan
->pending_q
);
2467 INIT_LIST_HEAD(&chan
->done_q
);
2473 void ipu_image_convert_exit(struct ipu_soc
*ipu
)