Lines Matching +full:min +full:- +full:pix +full:- +full:alignment

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2012-2016 Mentor Graphics Inc.
9 #include <linux/dma-mapping.h>
12 #include <video/imx-ipu-image-convert.h>
14 #include "ipu-prv.h"
29 * the DMA channel's parameter memory!). IDMA double-buffering is used
30 * to convert each tile back-to-back when possible (see note below
36 * +---------+-----+
37 * +-----+---+ | A | B |
39 * +-----+---+ --> +---------+-----+
41 * +-----+---+ | | |
42 * +---------+-----+
48 * +-----+-----+
50 * +-----+---+ +---------+ | C | A |
52 * +-----+---+ --> | C,D | | --> | | |
53 * | C | D | +---------+ +-----+-----+
54 * +-----+---+ | D | B |
56 * +-----+-----+
181 /* can we use double-buffering for this conversion operation? */
208 /* the IPU end-of-frame irqs */
343 struct ipu_image_convert_chan *chan = ctx->chan; in dump_format()
344 struct ipu_image_convert_priv *priv = chan->priv; in dump_format()
346 dev_dbg(priv->ipu->dev, in dump_format()
348 chan->ic_task, ctx, in dump_format()
349 ic_image->type == IMAGE_CONVERT_OUT ? "Output" : "Input", in dump_format()
350 ic_image->base.pix.width, ic_image->base.pix.height, in dump_format()
351 ic_image->num_cols, ic_image->num_rows, in dump_format()
352 ic_image->fmt->fourcc & 0xff, in dump_format()
353 (ic_image->fmt->fourcc >> 8) & 0xff, in dump_format()
354 (ic_image->fmt->fourcc >> 16) & 0xff, in dump_format()
355 (ic_image->fmt->fourcc >> 24) & 0xff); in dump_format()
363 return -EINVAL; in ipu_image_convert_enum_format()
367 *fourcc = fmt->fourcc; in ipu_image_convert_enum_format()
375 if (buf->virt) in free_dma_buf()
376 dma_free_coherent(priv->ipu->dev, in free_dma_buf()
377 buf->len, buf->virt, buf->phys); in free_dma_buf()
378 buf->virt = NULL; in free_dma_buf()
379 buf->phys = 0; in free_dma_buf()
386 buf->len = PAGE_ALIGN(size); in alloc_dma_buf()
387 buf->virt = dma_alloc_coherent(priv->ipu->dev, buf->len, &buf->phys, in alloc_dma_buf()
389 if (!buf->virt) { in alloc_dma_buf()
390 dev_err(priv->ipu->dev, "failed to alloc dma buffer\n"); in alloc_dma_buf()
391 return -ENOMEM; in alloc_dma_buf()
399 return (dim - 1) / 1024 + 1; in num_stripes()
414 u32 downsized_width = in->rect.width; in calc_image_resize_coefficients()
415 u32 downsized_height = in->rect.height; in calc_image_resize_coefficients()
418 u32 resized_width = out->rect.width; in calc_image_resize_coefficients()
419 u32 resized_height = out->rect.height; in calc_image_resize_coefficients()
425 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in calc_image_resize_coefficients()
426 resized_width = out->rect.height; in calc_image_resize_coefficients()
427 resized_height = out->rect.width; in calc_image_resize_coefficients()
432 return -EINVAL; in calc_image_resize_coefficients()
450 resize_coeff_h = 8192 * (downsized_width - 1) / (resized_width - 1); in calc_image_resize_coefficients()
451 resize_coeff_v = 8192 * (downsized_height - 1) / (resized_height - 1); in calc_image_resize_coefficients()
461 dev_dbg(ctx->chan->priv->ipu->dev, in calc_image_resize_coefficients()
468 return -EINVAL; in calc_image_resize_coefficients()
470 ctx->downsize_coeff_h = downsize_coeff_h; in calc_image_resize_coefficients()
471 ctx->downsize_coeff_v = downsize_coeff_v; in calc_image_resize_coefficients()
472 ctx->image_resize_coeff_h = resize_coeff_h; in calc_image_resize_coefficients()
473 ctx->image_resize_coeff_v = resize_coeff_v; in calc_image_resize_coefficients()
474 ctx->in.num_cols = cols; in calc_image_resize_coefficients()
475 ctx->in.num_rows = rows; in calc_image_resize_coefficients()
489 * @in_align: input alignment, either horizontal 8-byte line start address
490 * alignment, or pixel alignment due to image format
491 * @out_align: output alignment, either horizontal 8-byte line start address
492 * alignment, or pixel alignment due to image format or rotator
514 struct device *dev = ctx->chan->priv->ipu->dev; in find_best_seam()
526 out_start = max_t(int, index * out_align, out_edge - 1024); in find_best_seam()
535 in_edge - (1024 << downsize_coeff)); in find_best_seam()
556 if ((out_burst > 1) && (out_edge - out_pos) % out_burst) in find_best_seam()
578 (in_edge - in_pos_rounded) % in_burst) in find_best_seam()
604 if (fmt->planar) in tile_left_align()
605 return fmt->uv_packed ? 8 : 8 * fmt->uv_width_dec; in tile_left_align()
607 return fmt->bpp == 32 ? 2 : fmt->bpp == 16 ? 4 : 8; in tile_left_align()
611 * Tile top edge alignment is only limited by chroma subsampling.
615 return fmt->uv_height_dec > 1 ? 2 : 1; in tile_top_align()
635 * formats to guarantee 8-byte aligned line start addresses in the in tile_width_align()
640 fmt->planar && !fmt->uv_packed) ? in tile_width_align()
641 8 * fmt->uv_width_dec : 8; in tile_width_align()
653 * formats to guarantee 8-byte aligned line start addresses in the in tile_height_align()
657 return (fmt->planar && !fmt->uv_packed) ? 8 * fmt->uv_width_dec : 8; in tile_height_align()
675 for (row = 0; row < in->num_rows; row++) { in fill_tile_column()
676 tile_idx = in->num_cols * row + col; in fill_tile_column()
677 in_tile = &in->tile[tile_idx]; in fill_tile_column()
678 out_tile = &out->tile[ctx->out_tile_map[tile_idx]]; in fill_tile_column()
680 in_tile->left = in_left; in fill_tile_column()
681 in_tile->width = in_width; in fill_tile_column()
683 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in fill_tile_column()
684 out_tile->top = out_left; in fill_tile_column()
685 out_tile->height = out_width; in fill_tile_column()
687 out_tile->left = out_left; in fill_tile_column()
688 out_tile->width = out_width; in fill_tile_column()
707 for (col = 0; col < in->num_cols; col++) { in fill_tile_row()
708 tile_idx = in->num_cols * row + col; in fill_tile_row()
709 in_tile = &in->tile[tile_idx]; in fill_tile_row()
710 out_tile = &out->tile[ctx->out_tile_map[tile_idx]]; in fill_tile_row()
712 in_tile->top = in_top; in fill_tile_row()
713 in_tile->height = in_height; in fill_tile_row()
715 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in fill_tile_row()
716 out_tile->left = out_top; in fill_tile_row()
717 out_tile->width = out_height; in fill_tile_row()
719 out_tile->top = out_top; in fill_tile_row()
720 out_tile->height = out_height; in fill_tile_row()
734 struct device *dev = ctx->chan->priv->ipu->dev; in find_seams()
735 unsigned int resized_width = out->base.rect.width; in find_seams()
736 unsigned int resized_height = out->base.rect.height; in find_seams()
739 unsigned int in_left_align = tile_left_align(in->fmt); in find_seams()
740 unsigned int in_top_align = tile_top_align(in->fmt); in find_seams()
741 unsigned int out_left_align = tile_left_align(out->fmt); in find_seams()
742 unsigned int out_top_align = tile_top_align(out->fmt); in find_seams()
743 unsigned int out_width_align = tile_width_align(out->type, out->fmt, in find_seams()
744 ctx->rot_mode); in find_seams()
745 unsigned int out_height_align = tile_height_align(out->type, out->fmt, in find_seams()
746 ctx->rot_mode); in find_seams()
747 unsigned int in_right = in->base.rect.width; in find_seams()
748 unsigned int in_bottom = in->base.rect.height; in find_seams()
749 unsigned int out_right = out->base.rect.width; in find_seams()
750 unsigned int out_bottom = out->base.rect.height; in find_seams()
754 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in find_seams()
756 resized_width = out->base.rect.height; in find_seams()
757 resized_height = out->base.rect.width; in find_seams()
762 out_right = out->base.rect.height; in find_seams()
763 out_bottom = out->base.rect.width; in find_seams()
766 for (col = in->num_cols - 1; col > 0; col--) { in find_seams()
767 bool allow_in_overshoot = ipu_rot_mode_is_irt(ctx->rot_mode) || in find_seams()
768 !(ctx->rot_mode & IPU_ROT_BIT_HFLIP); in find_seams()
769 bool allow_out_overshoot = (col < in->num_cols - 1) && in find_seams()
770 !(ctx->rot_mode & IPU_ROT_BIT_HFLIP); in find_seams()
784 ctx->downsize_coeff_h, ctx->image_resize_coeff_h, in find_seams()
787 if (ctx->rot_mode & IPU_ROT_BIT_HFLIP) in find_seams()
788 flipped_out_left = resized_width - out_right; in find_seams()
792 fill_tile_column(ctx, col, in, in_left, in_right - in_left, in find_seams()
793 out, flipped_out_left, out_right - out_left); in find_seams()
795 dev_dbg(dev, "%s: col %u: %u, %u -> %u, %u\n", __func__, col, in find_seams()
796 in_left, in_right - in_left, in find_seams()
797 flipped_out_left, out_right - out_left); in find_seams()
803 flipped_out_left = (ctx->rot_mode & IPU_ROT_BIT_HFLIP) ? in find_seams()
804 resized_width - out_right : 0; in find_seams()
809 dev_dbg(dev, "%s: col 0: 0, %u -> %u, %u\n", __func__, in find_seams()
812 for (row = in->num_rows - 1; row > 0; row--) { in find_seams()
813 bool allow_overshoot = row < in->num_rows - 1; in find_seams()
821 ctx->downsize_coeff_v, ctx->image_resize_coeff_v, in find_seams()
824 if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^ in find_seams()
825 ipu_rot_mode_is_irt(ctx->rot_mode)) in find_seams()
826 flipped_out_top = resized_height - out_bottom; in find_seams()
830 fill_tile_row(ctx, row, in, in_top, in_bottom - in_top, in find_seams()
831 out, flipped_out_top, out_bottom - out_top); in find_seams()
833 dev_dbg(dev, "%s: row %u: %u, %u -> %u, %u\n", __func__, row, in find_seams()
834 in_top, in_bottom - in_top, in find_seams()
835 flipped_out_top, out_bottom - out_top); in find_seams()
841 if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^ in find_seams()
842 ipu_rot_mode_is_irt(ctx->rot_mode)) in find_seams()
843 flipped_out_top = resized_height - out_bottom; in find_seams()
850 dev_dbg(dev, "%s: row 0: 0, %u -> %u, %u\n", __func__, in find_seams()
857 struct ipu_image_convert_chan *chan = ctx->chan; in calc_tile_dimensions()
858 struct ipu_image_convert_priv *priv = chan->priv; in calc_tile_dimensions()
863 if (image->type == IMAGE_CONVERT_IN) { in calc_tile_dimensions()
865 max_width <<= ctx->downsize_coeff_h; in calc_tile_dimensions()
866 max_height <<= ctx->downsize_coeff_v; in calc_tile_dimensions()
869 for (i = 0; i < ctx->num_tiles; i++) { in calc_tile_dimensions()
871 const unsigned int row = i / image->num_cols; in calc_tile_dimensions()
872 const unsigned int col = i % image->num_cols; in calc_tile_dimensions()
874 if (image->type == IMAGE_CONVERT_OUT) in calc_tile_dimensions()
875 tile = &image->tile[ctx->out_tile_map[i]]; in calc_tile_dimensions()
877 tile = &image->tile[i]; in calc_tile_dimensions()
879 tile->size = ((tile->height * image->fmt->bpp) >> 3) * in calc_tile_dimensions()
880 tile->width; in calc_tile_dimensions()
882 if (image->fmt->planar) { in calc_tile_dimensions()
883 tile->stride = tile->width; in calc_tile_dimensions()
884 tile->rot_stride = tile->height; in calc_tile_dimensions()
886 tile->stride = in calc_tile_dimensions()
887 (image->fmt->bpp * tile->width) >> 3; in calc_tile_dimensions()
888 tile->rot_stride = in calc_tile_dimensions()
889 (image->fmt->bpp * tile->height) >> 3; in calc_tile_dimensions()
892 dev_dbg(priv->ipu->dev, in calc_tile_dimensions()
894 chan->ic_task, ctx, in calc_tile_dimensions()
895 image->type == IMAGE_CONVERT_IN ? "Input" : "Output", in calc_tile_dimensions()
897 tile->width, tile->height, tile->left, tile->top); in calc_tile_dimensions()
899 if (!tile->width || tile->width > max_width || in calc_tile_dimensions()
900 !tile->height || tile->height > max_height) { in calc_tile_dimensions()
901 dev_err(priv->ipu->dev, "invalid %s tile size: %ux%u\n", in calc_tile_dimensions()
902 image->type == IMAGE_CONVERT_IN ? "input" : in calc_tile_dimensions()
903 "output", tile->width, tile->height); in calc_tile_dimensions()
904 return -EINVAL; in calc_tile_dimensions()
920 struct ipu_image_convert_chan *chan = ctx->chan; in transform_tile_index()
921 struct ipu_image_convert_priv *priv = chan->priv; in transform_tile_index()
922 struct ipu_image_convert_image *s_image = &ctx->in; in transform_tile_index()
923 struct ipu_image_convert_image *d_image = &ctx->out; in transform_tile_index()
927 if (ctx->rot_mode == IPU_ROTATE_NONE) in transform_tile_index()
928 return src_row * s_image->num_cols + src_col; in transform_tile_index()
934 src_row = src_row * 2 - (s_image->num_rows - 1); in transform_tile_index()
935 src_col = src_col * 2 - (s_image->num_cols - 1); in transform_tile_index()
938 if (ctx->rot_mode & IPU_ROT_BIT_90) { in transform_tile_index()
939 dst_col = -src_row; in transform_tile_index()
947 if (ctx->rot_mode & IPU_ROT_BIT_HFLIP) in transform_tile_index()
948 dst_col = -dst_col; in transform_tile_index()
949 if (ctx->rot_mode & IPU_ROT_BIT_VFLIP) in transform_tile_index()
950 dst_row = -dst_row; in transform_tile_index()
952 dev_dbg(priv->ipu->dev, "task %u: ctx %p: [%d,%d] --> [%d,%d]\n", in transform_tile_index()
953 chan->ic_task, ctx, src_col, src_row, dst_col, dst_row); in transform_tile_index()
959 dst_row += d_image->num_rows - 1; in transform_tile_index()
960 dst_col += d_image->num_cols - 1; in transform_tile_index()
964 return dst_row * d_image->num_cols + dst_col; in transform_tile_index()
972 struct ipu_image_convert_image *s_image = &ctx->in; in calc_out_tile_map()
975 for (row = 0; row < s_image->num_rows; row++) { in calc_out_tile_map()
976 for (col = 0; col < s_image->num_cols; col++) { in calc_out_tile_map()
977 ctx->out_tile_map[tile] = in calc_out_tile_map()
987 struct ipu_image_convert_chan *chan = ctx->chan; in calc_tile_offsets_planar()
988 struct ipu_image_convert_priv *priv = chan->priv; in calc_tile_offsets_planar()
989 const struct ipu_image_pixfmt *fmt = image->fmt; in calc_tile_offsets_planar()
997 H = image->base.pix.height; in calc_tile_offsets_planar()
999 y_stride = image->stride; in calc_tile_offsets_planar()
1000 uv_stride = y_stride / fmt->uv_width_dec; in calc_tile_offsets_planar()
1001 if (fmt->uv_packed) in calc_tile_offsets_planar()
1005 uv_size = y_size / (fmt->uv_width_dec * fmt->uv_height_dec); in calc_tile_offsets_planar()
1007 for (row = 0; row < image->num_rows; row++) { in calc_tile_offsets_planar()
1008 top = image->tile[tile].top; in calc_tile_offsets_planar()
1010 uv_row_off = (top * uv_stride) / fmt->uv_height_dec; in calc_tile_offsets_planar()
1012 for (col = 0; col < image->num_cols; col++) { in calc_tile_offsets_planar()
1013 y_col_off = image->tile[tile].left; in calc_tile_offsets_planar()
1014 uv_col_off = y_col_off / fmt->uv_width_dec; in calc_tile_offsets_planar()
1015 if (fmt->uv_packed) in calc_tile_offsets_planar()
1021 u_off = y_size - y_off + uv_off; in calc_tile_offsets_planar()
1022 v_off = (fmt->uv_packed) ? 0 : u_off + uv_size; in calc_tile_offsets_planar()
1023 if (fmt->uv_swapped) in calc_tile_offsets_planar()
1026 image->tile[tile].offset = y_off; in calc_tile_offsets_planar()
1027 image->tile[tile].u_off = u_off; in calc_tile_offsets_planar()
1028 image->tile[tile++].v_off = v_off; in calc_tile_offsets_planar()
1031 dev_err(priv->ipu->dev, in calc_tile_offsets_planar()
1034 chan->ic_task, ctx, in calc_tile_offsets_planar()
1035 image->type == IMAGE_CONVERT_IN ? in calc_tile_offsets_planar()
1038 return -EINVAL; in calc_tile_offsets_planar()
1049 struct ipu_image_convert_chan *chan = ctx->chan; in calc_tile_offsets_packed()
1050 struct ipu_image_convert_priv *priv = chan->priv; in calc_tile_offsets_packed()
1051 const struct ipu_image_pixfmt *fmt = image->fmt; in calc_tile_offsets_packed()
1057 stride = image->stride; in calc_tile_offsets_packed()
1058 bpp = fmt->bpp; in calc_tile_offsets_packed()
1060 for (row = 0; row < image->num_rows; row++) { in calc_tile_offsets_packed()
1061 row_off = image->tile[tile].top * stride; in calc_tile_offsets_packed()
1063 for (col = 0; col < image->num_cols; col++) { in calc_tile_offsets_packed()
1064 col_off = (image->tile[tile].left * bpp) >> 3; in calc_tile_offsets_packed()
1068 image->tile[tile].offset = offset; in calc_tile_offsets_packed()
1069 image->tile[tile].u_off = 0; in calc_tile_offsets_packed()
1070 image->tile[tile++].v_off = 0; in calc_tile_offsets_packed()
1073 dev_err(priv->ipu->dev, in calc_tile_offsets_packed()
1076 chan->ic_task, ctx, in calc_tile_offsets_packed()
1077 image->type == IMAGE_CONVERT_IN ? in calc_tile_offsets_packed()
1080 return -EINVAL; in calc_tile_offsets_packed()
1091 if (image->fmt->planar) in calc_tile_offsets()
1114 return 8192 * (downsized - 1) / (output_size - 1); in calc_resize_coeff()
1125 struct ipu_image_convert_chan *chan = ctx->chan; in calc_tile_resize_coefficients()
1126 struct ipu_image_convert_priv *priv = chan->priv; in calc_tile_resize_coefficients()
1131 for (col = 0; col < ctx->in.num_cols; col++) { in calc_tile_resize_coefficients()
1132 bool closest = (col < ctx->in.num_cols - 1) && in calc_tile_resize_coefficients()
1133 !(ctx->rot_mode & IPU_ROT_BIT_HFLIP); in calc_tile_resize_coefficients()
1139 in_tile = &ctx->in.tile[tile_idx]; in calc_tile_resize_coefficients()
1140 out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]]; in calc_tile_resize_coefficients()
1142 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in calc_tile_resize_coefficients()
1143 resized_width = out_tile->height; in calc_tile_resize_coefficients()
1145 resized_width = out_tile->width; in calc_tile_resize_coefficients()
1147 resize_coeff_h = calc_resize_coeff(in_tile->width, in calc_tile_resize_coefficients()
1148 ctx->downsize_coeff_h, in calc_tile_resize_coefficients()
1151 dev_dbg(priv->ipu->dev, "%s: column %u hscale: *8192/%u\n", in calc_tile_resize_coefficients()
1165 last_output = resized_width - 1; in calc_tile_resize_coefficients()
1170 << ctx->downsize_coeff_h, 8); in calc_tile_resize_coefficients()
1172 for (row = 0; row < ctx->in.num_rows; row++) { in calc_tile_resize_coefficients()
1173 tile_idx = row * ctx->in.num_cols + col; in calc_tile_resize_coefficients()
1174 in_tile = &ctx->in.tile[tile_idx]; in calc_tile_resize_coefficients()
1175 out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]]; in calc_tile_resize_coefficients()
1177 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in calc_tile_resize_coefficients()
1178 out_tile->height = resized_width; in calc_tile_resize_coefficients()
1180 out_tile->width = resized_width; in calc_tile_resize_coefficients()
1182 in_tile->width = in_width; in calc_tile_resize_coefficients()
1185 ctx->resize_coeffs_h[col] = resize_coeff_h; in calc_tile_resize_coefficients()
1188 for (row = 0; row < ctx->in.num_rows; row++) { in calc_tile_resize_coefficients()
1189 bool closest = (row < ctx->in.num_rows - 1) && in calc_tile_resize_coefficients()
1190 !(ctx->rot_mode & IPU_ROT_BIT_VFLIP); in calc_tile_resize_coefficients()
1195 tile_idx = row * ctx->in.num_cols; in calc_tile_resize_coefficients()
1196 in_tile = &ctx->in.tile[tile_idx]; in calc_tile_resize_coefficients()
1197 out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]]; in calc_tile_resize_coefficients()
1199 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in calc_tile_resize_coefficients()
1200 resized_height = out_tile->width; in calc_tile_resize_coefficients()
1202 resized_height = out_tile->height; in calc_tile_resize_coefficients()
1204 resize_coeff_v = calc_resize_coeff(in_tile->height, in calc_tile_resize_coefficients()
1205 ctx->downsize_coeff_v, in calc_tile_resize_coefficients()
1208 dev_dbg(priv->ipu->dev, "%s: row %u vscale: *8192/%u\n", in calc_tile_resize_coefficients()
1222 last_output = resized_height - 1; in calc_tile_resize_coefficients()
1227 << ctx->downsize_coeff_v, 2); in calc_tile_resize_coefficients()
1229 for (col = 0; col < ctx->in.num_cols; col++) { in calc_tile_resize_coefficients()
1230 tile_idx = row * ctx->in.num_cols + col; in calc_tile_resize_coefficients()
1231 in_tile = &ctx->in.tile[tile_idx]; in calc_tile_resize_coefficients()
1232 out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]]; in calc_tile_resize_coefficients()
1234 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in calc_tile_resize_coefficients()
1235 out_tile->width = resized_height; in calc_tile_resize_coefficients()
1237 out_tile->height = resized_height; in calc_tile_resize_coefficients()
1239 in_tile->height = in_height; in calc_tile_resize_coefficients()
1242 ctx->resize_coeffs_v[row] = resize_coeff_v; in calc_tile_resize_coefficients()
1256 lockdep_assert_held(&ctx->chan->irqlock); in get_run_count()
1259 if (run->ctx == ctx) in get_run_count()
1268 struct ipu_image_convert_ctx *ctx = run->ctx; in convert_stop()
1269 struct ipu_image_convert_chan *chan = ctx->chan; in convert_stop()
1270 struct ipu_image_convert_priv *priv = chan->priv; in convert_stop()
1272 dev_dbg(priv->ipu->dev, "%s: task %u: stopping ctx %p run %p\n", in convert_stop()
1273 __func__, chan->ic_task, ctx, run); in convert_stop()
1276 ipu_ic_task_disable(chan->ic); in convert_stop()
1277 ipu_idmac_disable_channel(chan->in_chan); in convert_stop()
1278 ipu_idmac_disable_channel(chan->out_chan); in convert_stop()
1280 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in convert_stop()
1281 ipu_idmac_disable_channel(chan->rotation_in_chan); in convert_stop()
1282 ipu_idmac_disable_channel(chan->rotation_out_chan); in convert_stop()
1283 ipu_idmac_unlink(chan->out_chan, chan->rotation_in_chan); in convert_stop()
1286 ipu_ic_disable(chan->ic); in convert_stop()
1296 struct ipu_image_convert_chan *chan = ctx->chan; in init_idmac_channel()
1303 if (image->type == IMAGE_CONVERT_OUT) { in init_idmac_channel()
1304 tile_idx[0] = ctx->out_tile_map[tile]; in init_idmac_channel()
1305 tile_idx[1] = ctx->out_tile_map[1]; in init_idmac_channel()
1312 width = image->tile[tile_idx[0]].height; in init_idmac_channel()
1313 height = image->tile[tile_idx[0]].width; in init_idmac_channel()
1314 stride = image->tile[tile_idx[0]].rot_stride; in init_idmac_channel()
1315 addr0 = ctx->rot_intermediate[0].phys; in init_idmac_channel()
1316 if (ctx->double_buffering) in init_idmac_channel()
1317 addr1 = ctx->rot_intermediate[1].phys; in init_idmac_channel()
1319 width = image->tile[tile_idx[0]].width; in init_idmac_channel()
1320 height = image->tile[tile_idx[0]].height; in init_idmac_channel()
1321 stride = image->stride; in init_idmac_channel()
1322 addr0 = image->base.phys0 + in init_idmac_channel()
1323 image->tile[tile_idx[0]].offset; in init_idmac_channel()
1324 if (ctx->double_buffering) in init_idmac_channel()
1325 addr1 = image->base.phys0 + in init_idmac_channel()
1326 image->tile[tile_idx[1]].offset; in init_idmac_channel()
1332 tile_image.pix.width = tile_image.rect.width = width; in init_idmac_channel()
1333 tile_image.pix.height = tile_image.rect.height = height; in init_idmac_channel()
1334 tile_image.pix.bytesperline = stride; in init_idmac_channel()
1335 tile_image.pix.pixelformat = image->fmt->fourcc; in init_idmac_channel()
1338 if (image->fmt->planar && !rot_swap_width_height) { in init_idmac_channel()
1339 tile_image.u_offset = image->tile[tile_idx[0]].u_off; in init_idmac_channel()
1340 tile_image.v_offset = image->tile[tile_idx[0]].v_off; in init_idmac_channel()
1352 if ((channel == chan->out_chan || in init_idmac_channel()
1353 channel == chan->rotation_out_chan) && in init_idmac_channel()
1354 image->fmt->planar && image->fmt->uv_height_dec == 2) in init_idmac_channel()
1357 if (channel == chan->rotation_in_chan || in init_idmac_channel()
1358 channel == chan->rotation_out_chan) { in init_idmac_channel()
1366 ipu_ic_task_idma_init(chan->ic, channel, width, height, in init_idmac_channel()
1370 * Setting a non-zero AXI ID collides with the PRG AXI snooping, so in init_idmac_channel()
1373 if (!channel->ipu->prg_priv) in init_idmac_channel()
1376 ipu_idmac_set_double_buffer(channel, ctx->double_buffering); in init_idmac_channel()
1381 struct ipu_image_convert_ctx *ctx = run->ctx; in convert_start()
1382 struct ipu_image_convert_chan *chan = ctx->chan; in convert_start()
1383 struct ipu_image_convert_priv *priv = chan->priv; in convert_start()
1384 struct ipu_image_convert_image *s_image = &ctx->in; in convert_start()
1385 struct ipu_image_convert_image *d_image = &ctx->out; in convert_start()
1386 unsigned int dst_tile = ctx->out_tile_map[tile]; in convert_start()
1392 dev_dbg(priv->ipu->dev, "%s: task %u: starting ctx %p run %p tile %u -> %u\n", in convert_start()
1393 __func__, chan->ic_task, ctx, run, tile, dst_tile); in convert_start()
1396 ctx->eof_mask = 0; in convert_start()
1398 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in convert_start()
1400 dest_width = d_image->tile[dst_tile].height; in convert_start()
1401 dest_height = d_image->tile[dst_tile].width; in convert_start()
1403 dest_width = d_image->tile[dst_tile].width; in convert_start()
1404 dest_height = d_image->tile[dst_tile].height; in convert_start()
1407 row = tile / s_image->num_cols; in convert_start()
1408 col = tile % s_image->num_cols; in convert_start()
1410 rsc = (ctx->downsize_coeff_v << 30) | in convert_start()
1411 (ctx->resize_coeffs_v[row] << 16) | in convert_start()
1412 (ctx->downsize_coeff_h << 14) | in convert_start()
1413 (ctx->resize_coeffs_h[col]); in convert_start()
1415 dev_dbg(priv->ipu->dev, "%s: %ux%u -> %ux%u (rsc = 0x%x)\n", in convert_start()
1416 __func__, s_image->tile[tile].width, in convert_start()
1417 s_image->tile[tile].height, dest_width, dest_height, rsc); in convert_start()
1420 ret = ipu_ic_task_init_rsc(chan->ic, &ctx->csc, in convert_start()
1421 s_image->tile[tile].width, in convert_start()
1422 s_image->tile[tile].height, in convert_start()
1427 dev_err(priv->ipu->dev, "ipu_ic_task_init failed, %d\n", ret); in convert_start()
1431 /* init the source MEM-->IC PP IDMAC channel */ in convert_start()
1432 init_idmac_channel(ctx, chan->in_chan, s_image, in convert_start()
1435 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in convert_start()
1436 /* init the IC PP-->MEM IDMAC channel */ in convert_start()
1437 init_idmac_channel(ctx, chan->out_chan, d_image, in convert_start()
1440 /* init the MEM-->IC PP ROT IDMAC channel */ in convert_start()
1441 init_idmac_channel(ctx, chan->rotation_in_chan, d_image, in convert_start()
1442 ctx->rot_mode, true, tile); in convert_start()
1444 /* init the destination IC PP ROT-->MEM IDMAC channel */ in convert_start()
1445 init_idmac_channel(ctx, chan->rotation_out_chan, d_image, in convert_start()
1448 /* now link IC PP-->MEM to MEM-->IC PP ROT */ in convert_start()
1449 ipu_idmac_link(chan->out_chan, chan->rotation_in_chan); in convert_start()
1451 /* init the destination IC PP-->MEM IDMAC channel */ in convert_start()
1452 init_idmac_channel(ctx, chan->out_chan, d_image, in convert_start()
1453 ctx->rot_mode, false, tile); in convert_start()
1457 ipu_ic_enable(chan->ic); in convert_start()
1460 ipu_idmac_select_buffer(chan->in_chan, 0); in convert_start()
1461 ipu_idmac_select_buffer(chan->out_chan, 0); in convert_start()
1462 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in convert_start()
1463 ipu_idmac_select_buffer(chan->rotation_out_chan, 0); in convert_start()
1464 if (ctx->double_buffering) { in convert_start()
1465 ipu_idmac_select_buffer(chan->in_chan, 1); in convert_start()
1466 ipu_idmac_select_buffer(chan->out_chan, 1); in convert_start()
1467 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in convert_start()
1468 ipu_idmac_select_buffer(chan->rotation_out_chan, 1); in convert_start()
1472 ipu_idmac_enable_channel(chan->in_chan); in convert_start()
1473 ipu_idmac_enable_channel(chan->out_chan); in convert_start()
1474 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in convert_start()
1475 ipu_idmac_enable_channel(chan->rotation_in_chan); in convert_start()
1476 ipu_idmac_enable_channel(chan->rotation_out_chan); in convert_start()
1479 ipu_ic_task_enable(chan->ic); in convert_start()
1481 ipu_cpmem_dump(chan->in_chan); in convert_start()
1482 ipu_cpmem_dump(chan->out_chan); in convert_start()
1483 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in convert_start()
1484 ipu_cpmem_dump(chan->rotation_in_chan); in convert_start()
1485 ipu_cpmem_dump(chan->rotation_out_chan); in convert_start()
1488 ipu_dump(priv->ipu); in convert_start()
1496 struct ipu_image_convert_ctx *ctx = run->ctx; in do_run()
1497 struct ipu_image_convert_chan *chan = ctx->chan; in do_run()
1499 lockdep_assert_held(&chan->irqlock); in do_run()
1501 ctx->in.base.phys0 = run->in_phys; in do_run()
1502 ctx->out.base.phys0 = run->out_phys; in do_run()
1504 ctx->cur_buf_num = 0; in do_run()
1505 ctx->next_tile = 1; in do_run()
1508 list_del(&run->list); in do_run()
1509 chan->current_run = run; in do_run()
1517 struct ipu_image_convert_priv *priv = chan->priv; in run_next()
1521 lockdep_assert_held(&chan->irqlock); in run_next()
1523 list_for_each_entry_safe(run, tmp, &chan->pending_q, list) { in run_next()
1525 if (run->ctx->aborting) { in run_next()
1526 dev_dbg(priv->ipu->dev, in run_next()
1528 __func__, chan->ic_task, run->ctx, run); in run_next()
1541 run->status = ret; in run_next()
1542 list_add_tail(&run->list, &chan->done_q); in run_next()
1543 chan->current_run = NULL; in run_next()
1549 struct ipu_image_convert_priv *priv = chan->priv; in empty_done_q()
1553 spin_lock_irqsave(&chan->irqlock, flags); in empty_done_q()
1555 while (!list_empty(&chan->done_q)) { in empty_done_q()
1556 run = list_entry(chan->done_q.next, in empty_done_q()
1560 list_del(&run->list); in empty_done_q()
1562 dev_dbg(priv->ipu->dev, in empty_done_q()
1564 __func__, chan->ic_task, run->ctx, run, run->status); in empty_done_q()
1567 spin_unlock_irqrestore(&chan->irqlock, flags); in empty_done_q()
1568 run->ctx->complete(run, run->ctx->complete_context); in empty_done_q()
1569 spin_lock_irqsave(&chan->irqlock, flags); in empty_done_q()
1572 spin_unlock_irqrestore(&chan->irqlock, flags); in empty_done_q()
1582 struct ipu_image_convert_priv *priv = chan->priv; in do_bh()
1586 dev_dbg(priv->ipu->dev, "%s: task %u: enter\n", __func__, in do_bh()
1587 chan->ic_task); in do_bh()
1591 spin_lock_irqsave(&chan->irqlock, flags); in do_bh()
1597 list_for_each_entry(ctx, &chan->ctx_list, list) { in do_bh()
1598 if (ctx->aborting) { in do_bh()
1599 dev_dbg(priv->ipu->dev, in do_bh()
1601 __func__, chan->ic_task, ctx); in do_bh()
1602 complete_all(&ctx->aborted); in do_bh()
1606 spin_unlock_irqrestore(&chan->irqlock, flags); in do_bh()
1608 dev_dbg(priv->ipu->dev, "%s: task %u: exit\n", __func__, in do_bh()
1609 chan->ic_task); in do_bh()
1616 unsigned int cur_tile = ctx->next_tile - 1; in ic_settings_changed()
1617 unsigned int next_tile = ctx->next_tile; in ic_settings_changed()
1619 if (ctx->resize_coeffs_h[cur_tile % ctx->in.num_cols] != in ic_settings_changed()
1620 ctx->resize_coeffs_h[next_tile % ctx->in.num_cols] || in ic_settings_changed()
1621 ctx->resize_coeffs_v[cur_tile / ctx->in.num_cols] != in ic_settings_changed()
1622 ctx->resize_coeffs_v[next_tile / ctx->in.num_cols] || in ic_settings_changed()
1623 ctx->in.tile[cur_tile].width != ctx->in.tile[next_tile].width || in ic_settings_changed()
1624 ctx->in.tile[cur_tile].height != ctx->in.tile[next_tile].height || in ic_settings_changed()
1625 ctx->out.tile[cur_tile].width != ctx->out.tile[next_tile].width || in ic_settings_changed()
1626 ctx->out.tile[cur_tile].height != ctx->out.tile[next_tile].height) in ic_settings_changed()
1635 struct ipu_image_convert_ctx *ctx = run->ctx; in do_tile_complete()
1636 struct ipu_image_convert_chan *chan = ctx->chan; in do_tile_complete()
1638 struct ipu_image_convert_image *s_image = &ctx->in; in do_tile_complete()
1639 struct ipu_image_convert_image *d_image = &ctx->out; in do_tile_complete()
1643 lockdep_assert_held(&chan->irqlock); in do_tile_complete()
1645 outch = ipu_rot_mode_is_irt(ctx->rot_mode) ? in do_tile_complete()
1646 chan->rotation_out_chan : chan->out_chan; in do_tile_complete()
1650 * enter the paused state. Without double-buffering the channels in do_tile_complete()
1652 * is safe to stop the channels now. For double-buffering we in do_tile_complete()
1656 if (ctx->aborting && !ctx->double_buffering) { in do_tile_complete()
1658 run->status = -EIO; in do_tile_complete()
1662 if (ctx->next_tile == ctx->num_tiles) { in do_tile_complete()
1667 run->status = 0; in do_tile_complete()
1674 if (!ctx->double_buffering) { in do_tile_complete()
1677 convert_start(run, ctx->next_tile); in do_tile_complete()
1679 src_tile = &s_image->tile[ctx->next_tile]; in do_tile_complete()
1680 dst_idx = ctx->out_tile_map[ctx->next_tile]; in do_tile_complete()
1681 dst_tile = &d_image->tile[dst_idx]; in do_tile_complete()
1683 ipu_cpmem_set_buffer(chan->in_chan, 0, in do_tile_complete()
1684 s_image->base.phys0 + in do_tile_complete()
1685 src_tile->offset); in do_tile_complete()
1687 d_image->base.phys0 + in do_tile_complete()
1688 dst_tile->offset); in do_tile_complete()
1689 if (s_image->fmt->planar) in do_tile_complete()
1690 ipu_cpmem_set_uv_offset(chan->in_chan, in do_tile_complete()
1691 src_tile->u_off, in do_tile_complete()
1692 src_tile->v_off); in do_tile_complete()
1693 if (d_image->fmt->planar) in do_tile_complete()
1695 dst_tile->u_off, in do_tile_complete()
1696 dst_tile->v_off); in do_tile_complete()
1698 ipu_idmac_select_buffer(chan->in_chan, 0); in do_tile_complete()
1701 } else if (ctx->next_tile < ctx->num_tiles - 1) { in do_tile_complete()
1703 src_tile = &s_image->tile[ctx->next_tile + 1]; in do_tile_complete()
1704 dst_idx = ctx->out_tile_map[ctx->next_tile + 1]; in do_tile_complete()
1705 dst_tile = &d_image->tile[dst_idx]; in do_tile_complete()
1707 ipu_cpmem_set_buffer(chan->in_chan, ctx->cur_buf_num, in do_tile_complete()
1708 s_image->base.phys0 + src_tile->offset); in do_tile_complete()
1709 ipu_cpmem_set_buffer(outch, ctx->cur_buf_num, in do_tile_complete()
1710 d_image->base.phys0 + dst_tile->offset); in do_tile_complete()
1712 ipu_idmac_select_buffer(chan->in_chan, ctx->cur_buf_num); in do_tile_complete()
1713 ipu_idmac_select_buffer(outch, ctx->cur_buf_num); in do_tile_complete()
1715 ctx->cur_buf_num ^= 1; in do_tile_complete()
1718 ctx->eof_mask = 0; /* clear EOF irq mask for next tile */ in do_tile_complete()
1719 ctx->next_tile++; in do_tile_complete()
1722 list_add_tail(&run->list, &chan->done_q); in do_tile_complete()
1723 chan->current_run = NULL; in do_tile_complete()
1731 struct ipu_image_convert_priv *priv = chan->priv; in eof_irq()
1738 spin_lock_irqsave(&chan->irqlock, flags); in eof_irq()
1741 run = chan->current_run; in eof_irq()
1747 ctx = run->ctx; in eof_irq()
1749 if (irq == chan->in_eof_irq) { in eof_irq()
1750 ctx->eof_mask |= EOF_IRQ_IN; in eof_irq()
1751 } else if (irq == chan->out_eof_irq) { in eof_irq()
1752 ctx->eof_mask |= EOF_IRQ_OUT; in eof_irq()
1753 } else if (irq == chan->rot_in_eof_irq || in eof_irq()
1754 irq == chan->rot_out_eof_irq) { in eof_irq()
1755 if (!ipu_rot_mode_is_irt(ctx->rot_mode)) { in eof_irq()
1757 dev_err(priv->ipu->dev, in eof_irq()
1761 ctx->eof_mask |= (irq == chan->rot_in_eof_irq) ? in eof_irq()
1764 dev_err(priv->ipu->dev, "Received unknown irq %d\n", irq); in eof_irq()
1769 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in eof_irq()
1770 tile_complete = (ctx->eof_mask == EOF_IRQ_ROT_COMPLETE); in eof_irq()
1772 tile_complete = (ctx->eof_mask == EOF_IRQ_COMPLETE); in eof_irq()
1777 spin_unlock_irqrestore(&chan->irqlock, flags); in eof_irq()
1787 struct ipu_image_convert_chan *chan = ctx->chan; in force_abort()
1791 spin_lock_irqsave(&chan->irqlock, flags); in force_abort()
1793 run = chan->current_run; in force_abort()
1794 if (run && run->ctx == ctx) { in force_abort()
1796 run->status = -EIO; in force_abort()
1797 list_add_tail(&run->list, &chan->done_q); in force_abort()
1798 chan->current_run = NULL; in force_abort()
1802 spin_unlock_irqrestore(&chan->irqlock, flags); in force_abort()
1809 if (chan->in_eof_irq >= 0) in release_ipu_resources()
1810 free_irq(chan->in_eof_irq, chan); in release_ipu_resources()
1811 if (chan->rot_in_eof_irq >= 0) in release_ipu_resources()
1812 free_irq(chan->rot_in_eof_irq, chan); in release_ipu_resources()
1813 if (chan->out_eof_irq >= 0) in release_ipu_resources()
1814 free_irq(chan->out_eof_irq, chan); in release_ipu_resources()
1815 if (chan->rot_out_eof_irq >= 0) in release_ipu_resources()
1816 free_irq(chan->rot_out_eof_irq, chan); in release_ipu_resources()
1818 if (!IS_ERR_OR_NULL(chan->in_chan)) in release_ipu_resources()
1819 ipu_idmac_put(chan->in_chan); in release_ipu_resources()
1820 if (!IS_ERR_OR_NULL(chan->out_chan)) in release_ipu_resources()
1821 ipu_idmac_put(chan->out_chan); in release_ipu_resources()
1822 if (!IS_ERR_OR_NULL(chan->rotation_in_chan)) in release_ipu_resources()
1823 ipu_idmac_put(chan->rotation_in_chan); in release_ipu_resources()
1824 if (!IS_ERR_OR_NULL(chan->rotation_out_chan)) in release_ipu_resources()
1825 ipu_idmac_put(chan->rotation_out_chan); in release_ipu_resources()
1826 if (!IS_ERR_OR_NULL(chan->ic)) in release_ipu_resources()
1827 ipu_ic_put(chan->ic); in release_ipu_resources()
1829 chan->in_chan = chan->out_chan = chan->rotation_in_chan = in release_ipu_resources()
1830 chan->rotation_out_chan = NULL; in release_ipu_resources()
1831 chan->in_eof_irq = -1; in release_ipu_resources()
1832 chan->rot_in_eof_irq = -1; in release_ipu_resources()
1833 chan->out_eof_irq = -1; in release_ipu_resources()
1834 chan->rot_out_eof_irq = -1; in release_ipu_resources()
1840 struct ipu_image_convert_priv *priv = chan->priv; in get_eof_irq()
1843 irq = ipu_idmac_channel_irq(priv->ipu, channel, IPU_IRQ_EOF); in get_eof_irq()
1845 ret = request_threaded_irq(irq, eof_irq, do_bh, 0, "ipu-ic", chan); in get_eof_irq()
1847 dev_err(priv->ipu->dev, "could not acquire irq %d\n", irq); in get_eof_irq()
1856 const struct ipu_image_convert_dma_chan *dma = chan->dma_ch; in get_ipu_resources()
1857 struct ipu_image_convert_priv *priv = chan->priv; in get_ipu_resources()
1861 chan->ic = ipu_ic_get(priv->ipu, chan->ic_task); in get_ipu_resources()
1862 if (IS_ERR(chan->ic)) { in get_ipu_resources()
1863 dev_err(priv->ipu->dev, "could not acquire IC\n"); in get_ipu_resources()
1864 ret = PTR_ERR(chan->ic); in get_ipu_resources()
1869 chan->in_chan = ipu_idmac_get(priv->ipu, dma->in); in get_ipu_resources()
1870 chan->out_chan = ipu_idmac_get(priv->ipu, dma->out); in get_ipu_resources()
1871 if (IS_ERR(chan->in_chan) || IS_ERR(chan->out_chan)) { in get_ipu_resources()
1872 dev_err(priv->ipu->dev, "could not acquire idmac channels\n"); in get_ipu_resources()
1873 ret = -EBUSY; in get_ipu_resources()
1877 chan->rotation_in_chan = ipu_idmac_get(priv->ipu, dma->rot_in); in get_ipu_resources()
1878 chan->rotation_out_chan = ipu_idmac_get(priv->ipu, dma->rot_out); in get_ipu_resources()
1879 if (IS_ERR(chan->rotation_in_chan) || IS_ERR(chan->rotation_out_chan)) { in get_ipu_resources()
1880 dev_err(priv->ipu->dev, in get_ipu_resources()
1882 ret = -EBUSY; in get_ipu_resources()
1887 ret = get_eof_irq(chan, chan->in_chan); in get_ipu_resources()
1889 chan->in_eof_irq = -1; in get_ipu_resources()
1892 chan->in_eof_irq = ret; in get_ipu_resources()
1894 ret = get_eof_irq(chan, chan->rotation_in_chan); in get_ipu_resources()
1896 chan->rot_in_eof_irq = -1; in get_ipu_resources()
1899 chan->rot_in_eof_irq = ret; in get_ipu_resources()
1901 ret = get_eof_irq(chan, chan->out_chan); in get_ipu_resources()
1903 chan->out_eof_irq = -1; in get_ipu_resources()
1906 chan->out_eof_irq = ret; in get_ipu_resources()
1908 ret = get_eof_irq(chan, chan->rotation_out_chan); in get_ipu_resources()
1910 chan->rot_out_eof_irq = -1; in get_ipu_resources()
1913 chan->rot_out_eof_irq = ret; in get_ipu_resources()
1926 struct ipu_image_convert_priv *priv = ctx->chan->priv; in fill_image()
1928 ic_image->base = *image; in fill_image()
1929 ic_image->type = type; in fill_image()
1931 ic_image->fmt = get_format(image->pix.pixelformat); in fill_image()
1932 if (!ic_image->fmt) { in fill_image()
1933 dev_err(priv->ipu->dev, "pixelformat not supported for %s\n", in fill_image()
1935 return -EINVAL; in fill_image()
1938 if (ic_image->fmt->planar) in fill_image()
1939 ic_image->stride = ic_image->base.pix.width; in fill_image()
1941 ic_image->stride = ic_image->base.pix.bytesperline; in fill_image()
1946 /* borrowed from drivers/media/v4l2-core/v4l2-common.c */
1947 static unsigned int clamp_align(unsigned int x, unsigned int min, in clamp_align() argument
1951 unsigned int mask = ~((1 << align) - 1); in clamp_align()
1953 /* Clamp to aligned min and max */ in clamp_align()
1954 x = clamp(x, (min + ~mask) & mask, max & mask); in clamp_align()
1958 x = (x + (1 << (align - 1))) & mask; in clamp_align()
1971 infmt = get_format(in->pix.pixelformat); in ipu_image_convert_adjust()
1972 outfmt = get_format(out->pix.pixelformat); in ipu_image_convert_adjust()
1976 in->pix.pixelformat = V4L2_PIX_FMT_RGB24; in ipu_image_convert_adjust()
1980 out->pix.pixelformat = V4L2_PIX_FMT_RGB24; in ipu_image_convert_adjust()
1985 in->pix.field = out->pix.field = V4L2_FIELD_NONE; in ipu_image_convert_adjust()
1989 out->pix.height = max_t(__u32, out->pix.height, in ipu_image_convert_adjust()
1990 in->pix.width / 4); in ipu_image_convert_adjust()
1991 out->pix.width = max_t(__u32, out->pix.width, in ipu_image_convert_adjust()
1992 in->pix.height / 4); in ipu_image_convert_adjust()
1994 out->pix.width = max_t(__u32, out->pix.width, in ipu_image_convert_adjust()
1995 in->pix.width / 4); in ipu_image_convert_adjust()
1996 out->pix.height = max_t(__u32, out->pix.height, in ipu_image_convert_adjust()
1997 in->pix.height / 4); in ipu_image_convert_adjust()
2005 in->pix.width = clamp_align(in->pix.width, MIN_W, MAX_W, in ipu_image_convert_adjust()
2007 in->pix.height = clamp_align(in->pix.height, MIN_H, MAX_H, in ipu_image_convert_adjust()
2015 out->pix.width = clamp_align(out->pix.width, MIN_W, MAX_W, in ipu_image_convert_adjust()
2017 out->pix.height = clamp_align(out->pix.height, MIN_H, MAX_H, in ipu_image_convert_adjust()
2021 in->pix.bytesperline = infmt->planar ? in ipu_image_convert_adjust()
2022 clamp_align(in->pix.width, 2 << w_align_in, MAX_W, in ipu_image_convert_adjust()
2024 clamp_align((in->pix.width * infmt->bpp) >> 3, in ipu_image_convert_adjust()
2025 ((2 << w_align_in) * infmt->bpp) >> 3, in ipu_image_convert_adjust()
2026 (MAX_W * infmt->bpp) >> 3, in ipu_image_convert_adjust()
2028 in->pix.sizeimage = infmt->planar ? in ipu_image_convert_adjust()
2029 (in->pix.height * in->pix.bytesperline * infmt->bpp) >> 3 : in ipu_image_convert_adjust()
2030 in->pix.height * in->pix.bytesperline; in ipu_image_convert_adjust()
2031 out->pix.bytesperline = outfmt->planar ? out->pix.width : in ipu_image_convert_adjust()
2032 (out->pix.width * outfmt->bpp) >> 3; in ipu_image_convert_adjust()
2033 out->pix.sizeimage = outfmt->planar ? in ipu_image_convert_adjust()
2034 (out->pix.height * out->pix.bytesperline * outfmt->bpp) >> 3 : in ipu_image_convert_adjust()
2035 out->pix.height * out->pix.bytesperline; in ipu_image_convert_adjust()
2054 if (testin.pix.width != in->pix.width || in ipu_image_convert_verify()
2055 testin.pix.height != in->pix.height || in ipu_image_convert_verify()
2056 testout.pix.width != out->pix.width || in ipu_image_convert_verify()
2057 testout.pix.height != out->pix.height) in ipu_image_convert_verify()
2058 return -EINVAL; in ipu_image_convert_verify()
2075 struct ipu_image_convert_priv *priv = ipu->image_convert_priv; in ipu_image_convert_prepare()
2087 return ERR_PTR(-EINVAL); in ipu_image_convert_prepare()
2092 dev_err(priv->ipu->dev, "%s: in/out formats invalid\n", in ipu_image_convert_prepare()
2097 chan = &priv->chan[ic_task]; in ipu_image_convert_prepare()
2101 return ERR_PTR(-ENOMEM); in ipu_image_convert_prepare()
2103 dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p\n", __func__, in ipu_image_convert_prepare()
2104 chan->ic_task, ctx); in ipu_image_convert_prepare()
2106 ctx->chan = chan; in ipu_image_convert_prepare()
2107 init_completion(&ctx->aborted); in ipu_image_convert_prepare()
2109 ctx->rot_mode = rot_mode; in ipu_image_convert_prepare()
2111 /* Sets ctx->in.num_rows/cols as well */ in ipu_image_convert_prepare()
2116 s_image = &ctx->in; in ipu_image_convert_prepare()
2117 d_image = &ctx->out; in ipu_image_convert_prepare()
2121 d_image->num_rows = s_image->num_cols; in ipu_image_convert_prepare()
2122 d_image->num_cols = s_image->num_rows; in ipu_image_convert_prepare()
2124 d_image->num_rows = s_image->num_rows; in ipu_image_convert_prepare()
2125 d_image->num_cols = s_image->num_cols; in ipu_image_convert_prepare()
2128 ctx->num_tiles = d_image->num_cols * d_image->num_rows; in ipu_image_convert_prepare()
2156 ret = ipu_ic_calc_csc(&ctx->csc, in ipu_image_convert_prepare()
2157 s_image->base.pix.ycbcr_enc, in ipu_image_convert_prepare()
2158 s_image->base.pix.quantization, in ipu_image_convert_prepare()
2159 ipu_pixelformat_to_colorspace(s_image->fmt->fourcc), in ipu_image_convert_prepare()
2160 d_image->base.pix.ycbcr_enc, in ipu_image_convert_prepare()
2161 d_image->base.pix.quantization, in ipu_image_convert_prepare()
2162 ipu_pixelformat_to_colorspace(d_image->fmt->fourcc)); in ipu_image_convert_prepare()
2169 ctx->complete = complete; in ipu_image_convert_prepare()
2170 ctx->complete_context = complete_context; in ipu_image_convert_prepare()
2173 * Can we use double-buffering for this operation? If there is in ipu_image_convert_prepare()
2175 * operation) there's no point in using double-buffering. Also, in ipu_image_convert_prepare()
2179 * each buffer which is not possible. So double-buffering is in ipu_image_convert_prepare()
2183 * prevent double-buffering as well. in ipu_image_convert_prepare()
2185 ctx->double_buffering = (ctx->num_tiles > 1 && in ipu_image_convert_prepare()
2186 !s_image->fmt->planar && in ipu_image_convert_prepare()
2187 !d_image->fmt->planar); in ipu_image_convert_prepare()
2188 for (i = 1; i < ctx->num_tiles; i++) { in ipu_image_convert_prepare()
2189 if (ctx->in.tile[i].width != ctx->in.tile[0].width || in ipu_image_convert_prepare()
2190 ctx->in.tile[i].height != ctx->in.tile[0].height || in ipu_image_convert_prepare()
2191 ctx->out.tile[i].width != ctx->out.tile[0].width || in ipu_image_convert_prepare()
2192 ctx->out.tile[i].height != ctx->out.tile[0].height) { in ipu_image_convert_prepare()
2193 ctx->double_buffering = false; in ipu_image_convert_prepare()
2197 for (i = 1; i < ctx->in.num_cols; i++) { in ipu_image_convert_prepare()
2198 if (ctx->resize_coeffs_h[i] != ctx->resize_coeffs_h[0]) { in ipu_image_convert_prepare()
2199 ctx->double_buffering = false; in ipu_image_convert_prepare()
2203 for (i = 1; i < ctx->in.num_rows; i++) { in ipu_image_convert_prepare()
2204 if (ctx->resize_coeffs_v[i] != ctx->resize_coeffs_v[0]) { in ipu_image_convert_prepare()
2205 ctx->double_buffering = false; in ipu_image_convert_prepare()
2210 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in ipu_image_convert_prepare()
2211 unsigned long intermediate_size = d_image->tile[0].size; in ipu_image_convert_prepare()
2213 for (i = 1; i < ctx->num_tiles; i++) { in ipu_image_convert_prepare()
2214 if (d_image->tile[i].size > intermediate_size) in ipu_image_convert_prepare()
2215 intermediate_size = d_image->tile[i].size; in ipu_image_convert_prepare()
2218 ret = alloc_dma_buf(priv, &ctx->rot_intermediate[0], in ipu_image_convert_prepare()
2222 if (ctx->double_buffering) { in ipu_image_convert_prepare()
2224 &ctx->rot_intermediate[1], in ipu_image_convert_prepare()
2231 spin_lock_irqsave(&chan->irqlock, flags); in ipu_image_convert_prepare()
2233 get_res = list_empty(&chan->ctx_list); in ipu_image_convert_prepare()
2235 list_add_tail(&ctx->list, &chan->ctx_list); in ipu_image_convert_prepare()
2237 spin_unlock_irqrestore(&chan->irqlock, flags); in ipu_image_convert_prepare()
2248 free_dma_buf(priv, &ctx->rot_intermediate[1]); in ipu_image_convert_prepare()
2249 spin_lock_irqsave(&chan->irqlock, flags); in ipu_image_convert_prepare()
2250 list_del(&ctx->list); in ipu_image_convert_prepare()
2251 spin_unlock_irqrestore(&chan->irqlock, flags); in ipu_image_convert_prepare()
2253 free_dma_buf(priv, &ctx->rot_intermediate[0]); in ipu_image_convert_prepare()
2273 if (!run || !run->ctx || !run->in_phys || !run->out_phys) in ipu_image_convert_queue()
2274 return -EINVAL; in ipu_image_convert_queue()
2276 ctx = run->ctx; in ipu_image_convert_queue()
2277 chan = ctx->chan; in ipu_image_convert_queue()
2278 priv = chan->priv; in ipu_image_convert_queue()
2280 dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p run %p\n", __func__, in ipu_image_convert_queue()
2281 chan->ic_task, ctx, run); in ipu_image_convert_queue()
2283 INIT_LIST_HEAD(&run->list); in ipu_image_convert_queue()
2285 spin_lock_irqsave(&chan->irqlock, flags); in ipu_image_convert_queue()
2287 if (ctx->aborting) { in ipu_image_convert_queue()
2288 ret = -EIO; in ipu_image_convert_queue()
2292 list_add_tail(&run->list, &chan->pending_q); in ipu_image_convert_queue()
2294 if (!chan->current_run) { in ipu_image_convert_queue()
2297 chan->current_run = NULL; in ipu_image_convert_queue()
2300 spin_unlock_irqrestore(&chan->irqlock, flags); in ipu_image_convert_queue()
2308 struct ipu_image_convert_chan *chan = ctx->chan; in __ipu_image_convert_abort()
2309 struct ipu_image_convert_priv *priv = chan->priv; in __ipu_image_convert_abort()
2314 spin_lock_irqsave(&chan->irqlock, flags); in __ipu_image_convert_abort()
2317 list_for_each_entry_safe(run, tmp, &chan->pending_q, list) { in __ipu_image_convert_abort()
2318 if (run->ctx != ctx) in __ipu_image_convert_abort()
2320 run->status = -EIO; in __ipu_image_convert_abort()
2321 list_move_tail(&run->list, &chan->done_q); in __ipu_image_convert_abort()
2324 run_count = get_run_count(ctx, &chan->done_q); in __ipu_image_convert_abort()
2325 active_run = (chan->current_run && chan->current_run->ctx == ctx) ? in __ipu_image_convert_abort()
2326 chan->current_run : NULL; in __ipu_image_convert_abort()
2329 reinit_completion(&ctx->aborted); in __ipu_image_convert_abort()
2331 ctx->aborting = true; in __ipu_image_convert_abort()
2333 spin_unlock_irqrestore(&chan->irqlock, flags); in __ipu_image_convert_abort()
2336 dev_dbg(priv->ipu->dev, in __ipu_image_convert_abort()
2338 __func__, chan->ic_task, ctx); in __ipu_image_convert_abort()
2347 dev_dbg(priv->ipu->dev, in __ipu_image_convert_abort()
2349 __func__, chan->ic_task, run_count); in __ipu_image_convert_abort()
2351 ret = wait_for_completion_timeout(&ctx->aborted, in __ipu_image_convert_abort()
2354 dev_warn(priv->ipu->dev, "%s: timeout\n", __func__); in __ipu_image_convert_abort()
2362 ctx->aborting = false; in ipu_image_convert_abort()
2369 struct ipu_image_convert_chan *chan = ctx->chan; in ipu_image_convert_unprepare()
2370 struct ipu_image_convert_priv *priv = chan->priv; in ipu_image_convert_unprepare()
2377 dev_dbg(priv->ipu->dev, "%s: task %u: removing ctx %p\n", __func__, in ipu_image_convert_unprepare()
2378 chan->ic_task, ctx); in ipu_image_convert_unprepare()
2380 spin_lock_irqsave(&chan->irqlock, flags); in ipu_image_convert_unprepare()
2382 list_del(&ctx->list); in ipu_image_convert_unprepare()
2384 put_res = list_empty(&chan->ctx_list); in ipu_image_convert_unprepare()
2386 spin_unlock_irqrestore(&chan->irqlock, flags); in ipu_image_convert_unprepare()
2391 free_dma_buf(priv, &ctx->rot_intermediate[1]); in ipu_image_convert_unprepare()
2392 free_dma_buf(priv, &ctx->rot_intermediate[0]); in ipu_image_convert_unprepare()
2422 return ERR_PTR(-ENOMEM); in ipu_image_convert()
2425 run->ctx = ctx; in ipu_image_convert()
2426 run->in_phys = in->phys0; in ipu_image_convert()
2427 run->out_phys = out->phys0; in ipu_image_convert()
2465 ret = (ret == 0) ? -ETIMEDOUT : 0; in ipu_image_convert_sync()
2467 ipu_image_convert_unprepare(run->ctx); in ipu_image_convert_sync()
2481 return -ENOMEM; in ipu_image_convert_init()
2483 ipu->image_convert_priv = priv; in ipu_image_convert_init()
2484 priv->ipu = ipu; in ipu_image_convert_init()
2487 struct ipu_image_convert_chan *chan = &priv->chan[i]; in ipu_image_convert_init()
2489 chan->ic_task = i; in ipu_image_convert_init()
2490 chan->priv = priv; in ipu_image_convert_init()
2491 chan->dma_ch = &image_convert_dma_chan[i]; in ipu_image_convert_init()
2492 chan->in_eof_irq = -1; in ipu_image_convert_init()
2493 chan->rot_in_eof_irq = -1; in ipu_image_convert_init()
2494 chan->out_eof_irq = -1; in ipu_image_convert_init()
2495 chan->rot_out_eof_irq = -1; in ipu_image_convert_init()
2497 spin_lock_init(&chan->irqlock); in ipu_image_convert_init()
2498 INIT_LIST_HEAD(&chan->ctx_list); in ipu_image_convert_init()
2499 INIT_LIST_HEAD(&chan->pending_q); in ipu_image_convert_init()
2500 INIT_LIST_HEAD(&chan->done_q); in ipu_image_convert_init()