Lines Matching +full:double +full:- +full:channel

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2012-2016 Mentor Graphics Inc.
9 #include <linux/dma-mapping.h>
10 #include <video/imx-ipu-image-convert.h>
11 #include "ipu-prv.h"
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
33 * +---------+-----+
34 * +-----+---+ | A | B |
36 * +-----+---+ --> +---------+-----+
38 * +-----+---+ | | |
39 * +---------+-----+
45 * +-----+-----+
47 * +-----+---+ +---------+ | C | A |
49 * +-----+---+ --> | C,D | | --> | | |
50 * | C | D | +---------+ +-----+-----+
51 * +-----+---+ | D | B |
53 * +-----+-----+
172 /* current buffer number for double buffering */
178 /* can we use double-buffering for this conversion operation? */
205 /* the IPU end-of-frame irqs */
340 struct ipu_image_convert_chan *chan = ctx->chan; in dump_format()
341 struct ipu_image_convert_priv *priv = chan->priv; in dump_format()
343 dev_dbg(priv->ipu->dev, in dump_format()
345 chan->ic_task, ctx, in dump_format()
346 ic_image->type == IMAGE_CONVERT_OUT ? "Output" : "Input", in dump_format()
347 ic_image->base.pix.width, ic_image->base.pix.height, in dump_format()
348 ic_image->num_cols, ic_image->num_rows, in dump_format()
349 ic_image->fmt->fourcc & 0xff, in dump_format()
350 (ic_image->fmt->fourcc >> 8) & 0xff, in dump_format()
351 (ic_image->fmt->fourcc >> 16) & 0xff, in dump_format()
352 (ic_image->fmt->fourcc >> 24) & 0xff); in dump_format()
360 return -EINVAL; in ipu_image_convert_enum_format()
364 *fourcc = fmt->fourcc; in ipu_image_convert_enum_format()
372 if (buf->virt) in free_dma_buf()
373 dma_free_coherent(priv->ipu->dev, in free_dma_buf()
374 buf->len, buf->virt, buf->phys); in free_dma_buf()
375 buf->virt = NULL; in free_dma_buf()
376 buf->phys = 0; in free_dma_buf()
383 buf->len = PAGE_ALIGN(size); in alloc_dma_buf()
384 buf->virt = dma_alloc_coherent(priv->ipu->dev, buf->len, &buf->phys, in alloc_dma_buf()
386 if (!buf->virt) { in alloc_dma_buf()
387 dev_err(priv->ipu->dev, "failed to alloc dma buffer\n"); in alloc_dma_buf()
388 return -ENOMEM; in alloc_dma_buf()
396 return (dim - 1) / 1024 + 1; in num_stripes()
411 u32 downsized_width = in->rect.width; in calc_image_resize_coefficients()
412 u32 downsized_height = in->rect.height; in calc_image_resize_coefficients()
415 u32 resized_width = out->rect.width; in calc_image_resize_coefficients()
416 u32 resized_height = out->rect.height; in calc_image_resize_coefficients()
422 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in calc_image_resize_coefficients()
423 resized_width = out->rect.height; in calc_image_resize_coefficients()
424 resized_height = out->rect.width; in calc_image_resize_coefficients()
429 return -EINVAL; in calc_image_resize_coefficients()
447 resize_coeff_h = 8192 * (downsized_width - 1) / (resized_width - 1); in calc_image_resize_coefficients()
448 resize_coeff_v = 8192 * (downsized_height - 1) / (resized_height - 1); in calc_image_resize_coefficients()
458 dev_dbg(ctx->chan->priv->ipu->dev, in calc_image_resize_coefficients()
465 return -EINVAL; in calc_image_resize_coefficients()
467 ctx->downsize_coeff_h = downsize_coeff_h; in calc_image_resize_coefficients()
468 ctx->downsize_coeff_v = downsize_coeff_v; in calc_image_resize_coefficients()
469 ctx->image_resize_coeff_h = resize_coeff_h; in calc_image_resize_coefficients()
470 ctx->image_resize_coeff_v = resize_coeff_v; in calc_image_resize_coefficients()
471 ctx->in.num_cols = cols; in calc_image_resize_coefficients()
472 ctx->in.num_rows = rows; in calc_image_resize_coefficients()
486 * @in_align: input alignment, either horizontal 8-byte line start address
488 * @out_align: output alignment, either horizontal 8-byte line start address
511 struct device *dev = ctx->chan->priv->ipu->dev; in find_best_seam()
523 out_start = max_t(int, index * out_align, out_edge - 1024); in find_best_seam()
532 in_edge - (1024 << downsize_coeff)); in find_best_seam()
553 if ((out_burst > 1) && (out_edge - out_pos) % out_burst) in find_best_seam()
575 (in_edge - in_pos_rounded) % in_burst) in find_best_seam()
579 abs_diff = in_pos_aligned - in_pos; in find_best_seam()
581 abs_diff = in_pos - in_pos_aligned; in find_best_seam()
605 if (fmt->planar) in tile_left_align()
606 return fmt->uv_packed ? 8 : 8 * fmt->uv_width_dec; in tile_left_align()
608 return fmt->bpp == 32 ? 2 : fmt->bpp == 16 ? 4 : 8; in tile_left_align()
616 return fmt->uv_height_dec > 1 ? 2 : 1; in tile_top_align()
636 * formats to guarantee 8-byte aligned line start addresses in the in tile_width_align()
641 fmt->planar && !fmt->uv_packed) ? in tile_width_align()
642 8 * fmt->uv_width_dec : 8; in tile_width_align()
654 * formats to guarantee 8-byte aligned line start addresses in the in tile_height_align()
658 return (fmt->planar && !fmt->uv_packed) ? 8 * fmt->uv_width_dec : 8; in tile_height_align()
676 for (row = 0; row < in->num_rows; row++) { in fill_tile_column()
677 tile_idx = in->num_cols * row + col; in fill_tile_column()
678 in_tile = &in->tile[tile_idx]; in fill_tile_column()
679 out_tile = &out->tile[ctx->out_tile_map[tile_idx]]; in fill_tile_column()
681 in_tile->left = in_left; in fill_tile_column()
682 in_tile->width = in_width; in fill_tile_column()
684 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in fill_tile_column()
685 out_tile->top = out_left; in fill_tile_column()
686 out_tile->height = out_width; in fill_tile_column()
688 out_tile->left = out_left; in fill_tile_column()
689 out_tile->width = out_width; in fill_tile_column()
708 for (col = 0; col < in->num_cols; col++) { in fill_tile_row()
709 tile_idx = in->num_cols * row + col; in fill_tile_row()
710 in_tile = &in->tile[tile_idx]; in fill_tile_row()
711 out_tile = &out->tile[ctx->out_tile_map[tile_idx]]; in fill_tile_row()
713 in_tile->top = in_top; in fill_tile_row()
714 in_tile->height = in_height; in fill_tile_row()
716 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in fill_tile_row()
717 out_tile->left = out_top; in fill_tile_row()
718 out_tile->width = out_height; in fill_tile_row()
720 out_tile->top = out_top; in fill_tile_row()
721 out_tile->height = out_height; in fill_tile_row()
735 struct device *dev = ctx->chan->priv->ipu->dev; in find_seams()
736 unsigned int resized_width = out->base.rect.width; in find_seams()
737 unsigned int resized_height = out->base.rect.height; in find_seams()
740 unsigned int in_left_align = tile_left_align(in->fmt); in find_seams()
741 unsigned int in_top_align = tile_top_align(in->fmt); in find_seams()
742 unsigned int out_left_align = tile_left_align(out->fmt); in find_seams()
743 unsigned int out_top_align = tile_top_align(out->fmt); in find_seams()
744 unsigned int out_width_align = tile_width_align(out->type, out->fmt, in find_seams()
745 ctx->rot_mode); in find_seams()
746 unsigned int out_height_align = tile_height_align(out->type, out->fmt, in find_seams()
747 ctx->rot_mode); in find_seams()
748 unsigned int in_right = in->base.rect.width; in find_seams()
749 unsigned int in_bottom = in->base.rect.height; in find_seams()
750 unsigned int out_right = out->base.rect.width; in find_seams()
751 unsigned int out_bottom = out->base.rect.height; in find_seams()
755 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in find_seams()
757 resized_width = out->base.rect.height; in find_seams()
758 resized_height = out->base.rect.width; in find_seams()
763 out_right = out->base.rect.height; in find_seams()
764 out_bottom = out->base.rect.width; in find_seams()
767 for (col = in->num_cols - 1; col > 0; col--) { in find_seams()
768 bool allow_in_overshoot = ipu_rot_mode_is_irt(ctx->rot_mode) || in find_seams()
769 !(ctx->rot_mode & IPU_ROT_BIT_HFLIP); in find_seams()
770 bool allow_out_overshoot = (col < in->num_cols - 1) && in find_seams()
771 !(ctx->rot_mode & IPU_ROT_BIT_HFLIP); in find_seams()
785 ctx->downsize_coeff_h, ctx->image_resize_coeff_h, in find_seams()
788 if (ctx->rot_mode & IPU_ROT_BIT_HFLIP) in find_seams()
789 flipped_out_left = resized_width - out_right; in find_seams()
793 fill_tile_column(ctx, col, in, in_left, in_right - in_left, in find_seams()
794 out, flipped_out_left, out_right - out_left); in find_seams()
796 dev_dbg(dev, "%s: col %u: %u, %u -> %u, %u\n", __func__, col, in find_seams()
797 in_left, in_right - in_left, in find_seams()
798 flipped_out_left, out_right - out_left); in find_seams()
804 flipped_out_left = (ctx->rot_mode & IPU_ROT_BIT_HFLIP) ? in find_seams()
805 resized_width - out_right : 0; in find_seams()
810 dev_dbg(dev, "%s: col 0: 0, %u -> %u, %u\n", __func__, in find_seams()
813 for (row = in->num_rows - 1; row > 0; row--) { in find_seams()
814 bool allow_overshoot = row < in->num_rows - 1; in find_seams()
822 ctx->downsize_coeff_v, ctx->image_resize_coeff_v, in find_seams()
825 if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^ in find_seams()
826 ipu_rot_mode_is_irt(ctx->rot_mode)) in find_seams()
827 flipped_out_top = resized_height - out_bottom; in find_seams()
831 fill_tile_row(ctx, row, in, in_top, in_bottom - in_top, in find_seams()
832 out, flipped_out_top, out_bottom - out_top); in find_seams()
834 dev_dbg(dev, "%s: row %u: %u, %u -> %u, %u\n", __func__, row, in find_seams()
835 in_top, in_bottom - in_top, in find_seams()
836 flipped_out_top, out_bottom - out_top); in find_seams()
842 if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^ in find_seams()
843 ipu_rot_mode_is_irt(ctx->rot_mode)) in find_seams()
844 flipped_out_top = resized_height - out_bottom; in find_seams()
851 dev_dbg(dev, "%s: row 0: 0, %u -> %u, %u\n", __func__, in find_seams()
858 struct ipu_image_convert_chan *chan = ctx->chan; in calc_tile_dimensions()
859 struct ipu_image_convert_priv *priv = chan->priv; in calc_tile_dimensions()
864 if (image->type == IMAGE_CONVERT_IN) { in calc_tile_dimensions()
866 max_width <<= ctx->downsize_coeff_h; in calc_tile_dimensions()
867 max_height <<= ctx->downsize_coeff_v; in calc_tile_dimensions()
870 for (i = 0; i < ctx->num_tiles; i++) { in calc_tile_dimensions()
872 const unsigned int row = i / image->num_cols; in calc_tile_dimensions()
873 const unsigned int col = i % image->num_cols; in calc_tile_dimensions()
875 if (image->type == IMAGE_CONVERT_OUT) in calc_tile_dimensions()
876 tile = &image->tile[ctx->out_tile_map[i]]; in calc_tile_dimensions()
878 tile = &image->tile[i]; in calc_tile_dimensions()
880 tile->size = ((tile->height * image->fmt->bpp) >> 3) * in calc_tile_dimensions()
881 tile->width; in calc_tile_dimensions()
883 if (image->fmt->planar) { in calc_tile_dimensions()
884 tile->stride = tile->width; in calc_tile_dimensions()
885 tile->rot_stride = tile->height; in calc_tile_dimensions()
887 tile->stride = in calc_tile_dimensions()
888 (image->fmt->bpp * tile->width) >> 3; in calc_tile_dimensions()
889 tile->rot_stride = in calc_tile_dimensions()
890 (image->fmt->bpp * tile->height) >> 3; in calc_tile_dimensions()
893 dev_dbg(priv->ipu->dev, in calc_tile_dimensions()
895 chan->ic_task, ctx, in calc_tile_dimensions()
896 image->type == IMAGE_CONVERT_IN ? "Input" : "Output", in calc_tile_dimensions()
898 tile->width, tile->height, tile->left, tile->top); in calc_tile_dimensions()
900 if (!tile->width || tile->width > max_width || in calc_tile_dimensions()
901 !tile->height || tile->height > max_height) { in calc_tile_dimensions()
902 dev_err(priv->ipu->dev, "invalid %s tile size: %ux%u\n", in calc_tile_dimensions()
903 image->type == IMAGE_CONVERT_IN ? "input" : in calc_tile_dimensions()
904 "output", tile->width, tile->height); in calc_tile_dimensions()
905 return -EINVAL; in calc_tile_dimensions()
921 struct ipu_image_convert_chan *chan = ctx->chan; in transform_tile_index()
922 struct ipu_image_convert_priv *priv = chan->priv; in transform_tile_index()
923 struct ipu_image_convert_image *s_image = &ctx->in; in transform_tile_index()
924 struct ipu_image_convert_image *d_image = &ctx->out; in transform_tile_index()
928 if (ctx->rot_mode == IPU_ROTATE_NONE) in transform_tile_index()
929 return src_row * s_image->num_cols + src_col; in transform_tile_index()
935 src_row = src_row * 2 - (s_image->num_rows - 1); in transform_tile_index()
936 src_col = src_col * 2 - (s_image->num_cols - 1); in transform_tile_index()
939 if (ctx->rot_mode & IPU_ROT_BIT_90) { in transform_tile_index()
940 dst_col = -src_row; in transform_tile_index()
948 if (ctx->rot_mode & IPU_ROT_BIT_HFLIP) in transform_tile_index()
949 dst_col = -dst_col; in transform_tile_index()
950 if (ctx->rot_mode & IPU_ROT_BIT_VFLIP) in transform_tile_index()
951 dst_row = -dst_row; in transform_tile_index()
953 dev_dbg(priv->ipu->dev, "task %u: ctx %p: [%d,%d] --> [%d,%d]\n", in transform_tile_index()
954 chan->ic_task, ctx, src_col, src_row, dst_col, dst_row); in transform_tile_index()
960 dst_row += d_image->num_rows - 1; in transform_tile_index()
961 dst_col += d_image->num_cols - 1; in transform_tile_index()
965 return dst_row * d_image->num_cols + dst_col; in transform_tile_index()
973 struct ipu_image_convert_image *s_image = &ctx->in; in calc_out_tile_map()
976 for (row = 0; row < s_image->num_rows; row++) { in calc_out_tile_map()
977 for (col = 0; col < s_image->num_cols; col++) { in calc_out_tile_map()
978 ctx->out_tile_map[tile] = in calc_out_tile_map()
988 struct ipu_image_convert_chan *chan = ctx->chan; in calc_tile_offsets_planar()
989 struct ipu_image_convert_priv *priv = chan->priv; in calc_tile_offsets_planar()
990 const struct ipu_image_pixfmt *fmt = image->fmt; in calc_tile_offsets_planar()
998 H = image->base.pix.height; in calc_tile_offsets_planar()
1000 y_stride = image->stride; in calc_tile_offsets_planar()
1001 uv_stride = y_stride / fmt->uv_width_dec; in calc_tile_offsets_planar()
1002 if (fmt->uv_packed) in calc_tile_offsets_planar()
1006 uv_size = y_size / (fmt->uv_width_dec * fmt->uv_height_dec); in calc_tile_offsets_planar()
1008 for (row = 0; row < image->num_rows; row++) { in calc_tile_offsets_planar()
1009 top = image->tile[tile].top; in calc_tile_offsets_planar()
1011 uv_row_off = (top * uv_stride) / fmt->uv_height_dec; in calc_tile_offsets_planar()
1013 for (col = 0; col < image->num_cols; col++) { in calc_tile_offsets_planar()
1014 y_col_off = image->tile[tile].left; in calc_tile_offsets_planar()
1015 uv_col_off = y_col_off / fmt->uv_width_dec; in calc_tile_offsets_planar()
1016 if (fmt->uv_packed) in calc_tile_offsets_planar()
1022 u_off = y_size - y_off + uv_off; in calc_tile_offsets_planar()
1023 v_off = (fmt->uv_packed) ? 0 : u_off + uv_size; in calc_tile_offsets_planar()
1024 if (fmt->uv_swapped) in calc_tile_offsets_planar()
1027 image->tile[tile].offset = y_off; in calc_tile_offsets_planar()
1028 image->tile[tile].u_off = u_off; in calc_tile_offsets_planar()
1029 image->tile[tile++].v_off = v_off; in calc_tile_offsets_planar()
1032 dev_err(priv->ipu->dev, in calc_tile_offsets_planar()
1035 chan->ic_task, ctx, in calc_tile_offsets_planar()
1036 image->type == IMAGE_CONVERT_IN ? in calc_tile_offsets_planar()
1039 return -EINVAL; in calc_tile_offsets_planar()
1050 struct ipu_image_convert_chan *chan = ctx->chan; in calc_tile_offsets_packed()
1051 struct ipu_image_convert_priv *priv = chan->priv; in calc_tile_offsets_packed()
1052 const struct ipu_image_pixfmt *fmt = image->fmt; in calc_tile_offsets_packed()
1058 stride = image->stride; in calc_tile_offsets_packed()
1059 bpp = fmt->bpp; in calc_tile_offsets_packed()
1061 for (row = 0; row < image->num_rows; row++) { in calc_tile_offsets_packed()
1062 row_off = image->tile[tile].top * stride; in calc_tile_offsets_packed()
1064 for (col = 0; col < image->num_cols; col++) { in calc_tile_offsets_packed()
1065 col_off = (image->tile[tile].left * bpp) >> 3; in calc_tile_offsets_packed()
1069 image->tile[tile].offset = offset; in calc_tile_offsets_packed()
1070 image->tile[tile].u_off = 0; in calc_tile_offsets_packed()
1071 image->tile[tile++].v_off = 0; in calc_tile_offsets_packed()
1074 dev_err(priv->ipu->dev, in calc_tile_offsets_packed()
1077 chan->ic_task, ctx, in calc_tile_offsets_packed()
1078 image->type == IMAGE_CONVERT_IN ? in calc_tile_offsets_packed()
1081 return -EINVAL; in calc_tile_offsets_packed()
1092 if (image->fmt->planar) in calc_tile_offsets()
1115 return 8192 * (downsized - 1) / (output_size - 1); in calc_resize_coeff()
1126 struct ipu_image_convert_chan *chan = ctx->chan; in calc_tile_resize_coefficients()
1127 struct ipu_image_convert_priv *priv = chan->priv; in calc_tile_resize_coefficients()
1132 for (col = 0; col < ctx->in.num_cols; col++) { in calc_tile_resize_coefficients()
1133 bool closest = (col < ctx->in.num_cols - 1) && in calc_tile_resize_coefficients()
1134 !(ctx->rot_mode & IPU_ROT_BIT_HFLIP); in calc_tile_resize_coefficients()
1140 in_tile = &ctx->in.tile[tile_idx]; in calc_tile_resize_coefficients()
1141 out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]]; in calc_tile_resize_coefficients()
1143 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in calc_tile_resize_coefficients()
1144 resized_width = out_tile->height; in calc_tile_resize_coefficients()
1146 resized_width = out_tile->width; in calc_tile_resize_coefficients()
1148 resize_coeff_h = calc_resize_coeff(in_tile->width, in calc_tile_resize_coefficients()
1149 ctx->downsize_coeff_h, in calc_tile_resize_coefficients()
1152 dev_dbg(priv->ipu->dev, "%s: column %u hscale: *8192/%u\n", in calc_tile_resize_coefficients()
1166 last_output = resized_width - 1; in calc_tile_resize_coefficients()
1171 << ctx->downsize_coeff_h, 8); in calc_tile_resize_coefficients()
1173 for (row = 0; row < ctx->in.num_rows; row++) { in calc_tile_resize_coefficients()
1174 tile_idx = row * ctx->in.num_cols + col; in calc_tile_resize_coefficients()
1175 in_tile = &ctx->in.tile[tile_idx]; in calc_tile_resize_coefficients()
1176 out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]]; in calc_tile_resize_coefficients()
1178 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in calc_tile_resize_coefficients()
1179 out_tile->height = resized_width; in calc_tile_resize_coefficients()
1181 out_tile->width = resized_width; in calc_tile_resize_coefficients()
1183 in_tile->width = in_width; in calc_tile_resize_coefficients()
1186 ctx->resize_coeffs_h[col] = resize_coeff_h; in calc_tile_resize_coefficients()
1189 for (row = 0; row < ctx->in.num_rows; row++) { in calc_tile_resize_coefficients()
1190 bool closest = (row < ctx->in.num_rows - 1) && in calc_tile_resize_coefficients()
1191 !(ctx->rot_mode & IPU_ROT_BIT_VFLIP); in calc_tile_resize_coefficients()
1196 tile_idx = row * ctx->in.num_cols; in calc_tile_resize_coefficients()
1197 in_tile = &ctx->in.tile[tile_idx]; in calc_tile_resize_coefficients()
1198 out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]]; in calc_tile_resize_coefficients()
1200 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in calc_tile_resize_coefficients()
1201 resized_height = out_tile->width; in calc_tile_resize_coefficients()
1203 resized_height = out_tile->height; in calc_tile_resize_coefficients()
1205 resize_coeff_v = calc_resize_coeff(in_tile->height, in calc_tile_resize_coefficients()
1206 ctx->downsize_coeff_v, in calc_tile_resize_coefficients()
1209 dev_dbg(priv->ipu->dev, "%s: row %u vscale: *8192/%u\n", in calc_tile_resize_coefficients()
1223 last_output = resized_height - 1; in calc_tile_resize_coefficients()
1228 << ctx->downsize_coeff_v, 2); in calc_tile_resize_coefficients()
1230 for (col = 0; col < ctx->in.num_cols; col++) { in calc_tile_resize_coefficients()
1231 tile_idx = row * ctx->in.num_cols + col; in calc_tile_resize_coefficients()
1232 in_tile = &ctx->in.tile[tile_idx]; in calc_tile_resize_coefficients()
1233 out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]]; in calc_tile_resize_coefficients()
1235 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in calc_tile_resize_coefficients()
1236 out_tile->width = resized_height; in calc_tile_resize_coefficients()
1238 out_tile->height = resized_height; in calc_tile_resize_coefficients()
1240 in_tile->height = in_height; in calc_tile_resize_coefficients()
1243 ctx->resize_coeffs_v[row] = resize_coeff_v; in calc_tile_resize_coefficients()
1257 lockdep_assert_held(&ctx->chan->irqlock); in get_run_count()
1260 if (run->ctx == ctx) in get_run_count()
1269 struct ipu_image_convert_ctx *ctx = run->ctx; in convert_stop()
1270 struct ipu_image_convert_chan *chan = ctx->chan; in convert_stop()
1271 struct ipu_image_convert_priv *priv = chan->priv; in convert_stop()
1273 dev_dbg(priv->ipu->dev, "%s: task %u: stopping ctx %p run %p\n", in convert_stop()
1274 __func__, chan->ic_task, ctx, run); in convert_stop()
1277 ipu_ic_task_disable(chan->ic); in convert_stop()
1278 ipu_idmac_disable_channel(chan->in_chan); in convert_stop()
1279 ipu_idmac_disable_channel(chan->out_chan); in convert_stop()
1281 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in convert_stop()
1282 ipu_idmac_disable_channel(chan->rotation_in_chan); in convert_stop()
1283 ipu_idmac_disable_channel(chan->rotation_out_chan); in convert_stop()
1284 ipu_idmac_unlink(chan->out_chan, chan->rotation_in_chan); in convert_stop()
1287 ipu_ic_disable(chan->ic); in convert_stop()
1291 struct ipuv3_channel *channel, in init_idmac_channel() argument
1297 struct ipu_image_convert_chan *chan = ctx->chan; in init_idmac_channel()
1304 if (image->type == IMAGE_CONVERT_OUT) { in init_idmac_channel()
1305 tile_idx[0] = ctx->out_tile_map[tile]; in init_idmac_channel()
1306 tile_idx[1] = ctx->out_tile_map[1]; in init_idmac_channel()
1313 width = image->tile[tile_idx[0]].height; in init_idmac_channel()
1314 height = image->tile[tile_idx[0]].width; in init_idmac_channel()
1315 stride = image->tile[tile_idx[0]].rot_stride; in init_idmac_channel()
1316 addr0 = ctx->rot_intermediate[0].phys; in init_idmac_channel()
1317 if (ctx->double_buffering) in init_idmac_channel()
1318 addr1 = ctx->rot_intermediate[1].phys; in init_idmac_channel()
1320 width = image->tile[tile_idx[0]].width; in init_idmac_channel()
1321 height = image->tile[tile_idx[0]].height; in init_idmac_channel()
1322 stride = image->stride; in init_idmac_channel()
1323 addr0 = image->base.phys0 + in init_idmac_channel()
1324 image->tile[tile_idx[0]].offset; in init_idmac_channel()
1325 if (ctx->double_buffering) in init_idmac_channel()
1326 addr1 = image->base.phys0 + in init_idmac_channel()
1327 image->tile[tile_idx[1]].offset; in init_idmac_channel()
1330 ipu_cpmem_zero(channel); in init_idmac_channel()
1336 tile_image.pix.pixelformat = image->fmt->fourcc; in init_idmac_channel()
1339 if (image->fmt->planar && !rot_swap_width_height) { in init_idmac_channel()
1340 tile_image.u_offset = image->tile[tile_idx[0]].u_off; in init_idmac_channel()
1341 tile_image.v_offset = image->tile[tile_idx[0]].v_off; in init_idmac_channel()
1344 ipu_cpmem_set_image(channel, &tile_image); in init_idmac_channel()
1347 ipu_cpmem_set_rotation(channel, rot_mode); in init_idmac_channel()
1353 if ((channel == chan->out_chan || in init_idmac_channel()
1354 channel == chan->rotation_out_chan) && in init_idmac_channel()
1355 image->fmt->planar && image->fmt->uv_height_dec == 2) in init_idmac_channel()
1356 ipu_cpmem_skip_odd_chroma_rows(channel); in init_idmac_channel()
1358 if (channel == chan->rotation_in_chan || in init_idmac_channel()
1359 channel == chan->rotation_out_chan) { in init_idmac_channel()
1361 ipu_cpmem_set_block_mode(channel); in init_idmac_channel()
1365 ipu_cpmem_set_burstsize(channel, burst_size); in init_idmac_channel()
1367 ipu_ic_task_idma_init(chan->ic, channel, width, height, in init_idmac_channel()
1371 * Setting a non-zero AXI ID collides with the PRG AXI snooping, so in init_idmac_channel()
1374 if (!channel->ipu->prg_priv) in init_idmac_channel()
1375 ipu_cpmem_set_axi_id(channel, 1); in init_idmac_channel()
1377 ipu_idmac_set_double_buffer(channel, ctx->double_buffering); in init_idmac_channel()
1382 struct ipu_image_convert_ctx *ctx = run->ctx; in convert_start()
1383 struct ipu_image_convert_chan *chan = ctx->chan; in convert_start()
1384 struct ipu_image_convert_priv *priv = chan->priv; in convert_start()
1385 struct ipu_image_convert_image *s_image = &ctx->in; in convert_start()
1386 struct ipu_image_convert_image *d_image = &ctx->out; in convert_start()
1387 unsigned int dst_tile = ctx->out_tile_map[tile]; in convert_start()
1393 dev_dbg(priv->ipu->dev, "%s: task %u: starting ctx %p run %p tile %u -> %u\n", in convert_start()
1394 __func__, chan->ic_task, ctx, run, tile, dst_tile); in convert_start()
1397 ctx->eof_mask = 0; in convert_start()
1399 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in convert_start()
1401 dest_width = d_image->tile[dst_tile].height; in convert_start()
1402 dest_height = d_image->tile[dst_tile].width; in convert_start()
1404 dest_width = d_image->tile[dst_tile].width; in convert_start()
1405 dest_height = d_image->tile[dst_tile].height; in convert_start()
1408 row = tile / s_image->num_cols; in convert_start()
1409 col = tile % s_image->num_cols; in convert_start()
1411 rsc = (ctx->downsize_coeff_v << 30) | in convert_start()
1412 (ctx->resize_coeffs_v[row] << 16) | in convert_start()
1413 (ctx->downsize_coeff_h << 14) | in convert_start()
1414 (ctx->resize_coeffs_h[col]); in convert_start()
1416 dev_dbg(priv->ipu->dev, "%s: %ux%u -> %ux%u (rsc = 0x%x)\n", in convert_start()
1417 __func__, s_image->tile[tile].width, in convert_start()
1418 s_image->tile[tile].height, dest_width, dest_height, rsc); in convert_start()
1421 ret = ipu_ic_task_init_rsc(chan->ic, &ctx->csc, in convert_start()
1422 s_image->tile[tile].width, in convert_start()
1423 s_image->tile[tile].height, in convert_start()
1428 dev_err(priv->ipu->dev, "ipu_ic_task_init failed, %d\n", ret); in convert_start()
1432 /* init the source MEM-->IC PP IDMAC channel */ in convert_start()
1433 init_idmac_channel(ctx, chan->in_chan, s_image, in convert_start()
1436 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in convert_start()
1437 /* init the IC PP-->MEM IDMAC channel */ in convert_start()
1438 init_idmac_channel(ctx, chan->out_chan, d_image, in convert_start()
1441 /* init the MEM-->IC PP ROT IDMAC channel */ in convert_start()
1442 init_idmac_channel(ctx, chan->rotation_in_chan, d_image, in convert_start()
1443 ctx->rot_mode, true, tile); in convert_start()
1445 /* init the destination IC PP ROT-->MEM IDMAC channel */ in convert_start()
1446 init_idmac_channel(ctx, chan->rotation_out_chan, d_image, in convert_start()
1449 /* now link IC PP-->MEM to MEM-->IC PP ROT */ in convert_start()
1450 ipu_idmac_link(chan->out_chan, chan->rotation_in_chan); in convert_start()
1452 /* init the destination IC PP-->MEM IDMAC channel */ in convert_start()
1453 init_idmac_channel(ctx, chan->out_chan, d_image, in convert_start()
1454 ctx->rot_mode, false, tile); in convert_start()
1458 ipu_ic_enable(chan->ic); in convert_start()
1461 ipu_idmac_select_buffer(chan->in_chan, 0); in convert_start()
1462 ipu_idmac_select_buffer(chan->out_chan, 0); in convert_start()
1463 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in convert_start()
1464 ipu_idmac_select_buffer(chan->rotation_out_chan, 0); in convert_start()
1465 if (ctx->double_buffering) { in convert_start()
1466 ipu_idmac_select_buffer(chan->in_chan, 1); in convert_start()
1467 ipu_idmac_select_buffer(chan->out_chan, 1); in convert_start()
1468 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in convert_start()
1469 ipu_idmac_select_buffer(chan->rotation_out_chan, 1); in convert_start()
1473 ipu_idmac_enable_channel(chan->in_chan); in convert_start()
1474 ipu_idmac_enable_channel(chan->out_chan); in convert_start()
1475 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in convert_start()
1476 ipu_idmac_enable_channel(chan->rotation_in_chan); in convert_start()
1477 ipu_idmac_enable_channel(chan->rotation_out_chan); in convert_start()
1480 ipu_ic_task_enable(chan->ic); in convert_start()
1482 ipu_cpmem_dump(chan->in_chan); in convert_start()
1483 ipu_cpmem_dump(chan->out_chan); in convert_start()
1484 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in convert_start()
1485 ipu_cpmem_dump(chan->rotation_in_chan); in convert_start()
1486 ipu_cpmem_dump(chan->rotation_out_chan); in convert_start()
1489 ipu_dump(priv->ipu); in convert_start()
1497 struct ipu_image_convert_ctx *ctx = run->ctx; in do_run()
1498 struct ipu_image_convert_chan *chan = ctx->chan; in do_run()
1500 lockdep_assert_held(&chan->irqlock); in do_run()
1502 ctx->in.base.phys0 = run->in_phys; in do_run()
1503 ctx->out.base.phys0 = run->out_phys; in do_run()
1505 ctx->cur_buf_num = 0; in do_run()
1506 ctx->next_tile = 1; in do_run()
1509 list_del(&run->list); in do_run()
1510 chan->current_run = run; in do_run()
1518 struct ipu_image_convert_priv *priv = chan->priv; in run_next()
1522 lockdep_assert_held(&chan->irqlock); in run_next()
1524 list_for_each_entry_safe(run, tmp, &chan->pending_q, list) { in run_next()
1526 if (run->ctx->aborting) { in run_next()
1527 dev_dbg(priv->ipu->dev, in run_next()
1529 __func__, chan->ic_task, run->ctx, run); in run_next()
1542 run->status = ret; in run_next()
1543 list_add_tail(&run->list, &chan->done_q); in run_next()
1544 chan->current_run = NULL; in run_next()
1550 struct ipu_image_convert_priv *priv = chan->priv; in empty_done_q()
1554 spin_lock_irqsave(&chan->irqlock, flags); in empty_done_q()
1556 while (!list_empty(&chan->done_q)) { in empty_done_q()
1557 run = list_entry(chan->done_q.next, in empty_done_q()
1561 list_del(&run->list); in empty_done_q()
1563 dev_dbg(priv->ipu->dev, in empty_done_q()
1565 __func__, chan->ic_task, run->ctx, run, run->status); in empty_done_q()
1568 spin_unlock_irqrestore(&chan->irqlock, flags); in empty_done_q()
1569 run->ctx->complete(run, run->ctx->complete_context); in empty_done_q()
1570 spin_lock_irqsave(&chan->irqlock, flags); in empty_done_q()
1573 spin_unlock_irqrestore(&chan->irqlock, flags); in empty_done_q()
1583 struct ipu_image_convert_priv *priv = chan->priv; in do_bh()
1587 dev_dbg(priv->ipu->dev, "%s: task %u: enter\n", __func__, in do_bh()
1588 chan->ic_task); in do_bh()
1592 spin_lock_irqsave(&chan->irqlock, flags); in do_bh()
1598 list_for_each_entry(ctx, &chan->ctx_list, list) { in do_bh()
1599 if (ctx->aborting) { in do_bh()
1600 dev_dbg(priv->ipu->dev, in do_bh()
1602 __func__, chan->ic_task, ctx); in do_bh()
1603 complete_all(&ctx->aborted); in do_bh()
1607 spin_unlock_irqrestore(&chan->irqlock, flags); in do_bh()
1609 dev_dbg(priv->ipu->dev, "%s: task %u: exit\n", __func__, in do_bh()
1610 chan->ic_task); in do_bh()
1617 unsigned int cur_tile = ctx->next_tile - 1; in ic_settings_changed()
1618 unsigned int next_tile = ctx->next_tile; in ic_settings_changed()
1620 if (ctx->resize_coeffs_h[cur_tile % ctx->in.num_cols] != in ic_settings_changed()
1621 ctx->resize_coeffs_h[next_tile % ctx->in.num_cols] || in ic_settings_changed()
1622 ctx->resize_coeffs_v[cur_tile / ctx->in.num_cols] != in ic_settings_changed()
1623 ctx->resize_coeffs_v[next_tile / ctx->in.num_cols] || in ic_settings_changed()
1624 ctx->in.tile[cur_tile].width != ctx->in.tile[next_tile].width || in ic_settings_changed()
1625 ctx->in.tile[cur_tile].height != ctx->in.tile[next_tile].height || in ic_settings_changed()
1626 ctx->out.tile[cur_tile].width != ctx->out.tile[next_tile].width || in ic_settings_changed()
1627 ctx->out.tile[cur_tile].height != ctx->out.tile[next_tile].height) in ic_settings_changed()
1636 struct ipu_image_convert_ctx *ctx = run->ctx; in do_tile_complete()
1637 struct ipu_image_convert_chan *chan = ctx->chan; in do_tile_complete()
1639 struct ipu_image_convert_image *s_image = &ctx->in; in do_tile_complete()
1640 struct ipu_image_convert_image *d_image = &ctx->out; in do_tile_complete()
1644 lockdep_assert_held(&chan->irqlock); in do_tile_complete()
1646 outch = ipu_rot_mode_is_irt(ctx->rot_mode) ? in do_tile_complete()
1647 chan->rotation_out_chan : chan->out_chan; in do_tile_complete()
1650 * It is difficult to stop the channel DMA before the channels in do_tile_complete()
1651 * enter the paused state. Without double-buffering the channels in do_tile_complete()
1653 * is safe to stop the channels now. For double-buffering we in do_tile_complete()
1657 if (ctx->aborting && !ctx->double_buffering) { in do_tile_complete()
1659 run->status = -EIO; in do_tile_complete()
1663 if (ctx->next_tile == ctx->num_tiles) { in do_tile_complete()
1668 run->status = 0; in do_tile_complete()
1675 if (!ctx->double_buffering) { in do_tile_complete()
1678 convert_start(run, ctx->next_tile); in do_tile_complete()
1680 src_tile = &s_image->tile[ctx->next_tile]; in do_tile_complete()
1681 dst_idx = ctx->out_tile_map[ctx->next_tile]; in do_tile_complete()
1682 dst_tile = &d_image->tile[dst_idx]; in do_tile_complete()
1684 ipu_cpmem_set_buffer(chan->in_chan, 0, in do_tile_complete()
1685 s_image->base.phys0 + in do_tile_complete()
1686 src_tile->offset); in do_tile_complete()
1688 d_image->base.phys0 + in do_tile_complete()
1689 dst_tile->offset); in do_tile_complete()
1690 if (s_image->fmt->planar) in do_tile_complete()
1691 ipu_cpmem_set_uv_offset(chan->in_chan, in do_tile_complete()
1692 src_tile->u_off, in do_tile_complete()
1693 src_tile->v_off); in do_tile_complete()
1694 if (d_image->fmt->planar) in do_tile_complete()
1696 dst_tile->u_off, in do_tile_complete()
1697 dst_tile->v_off); in do_tile_complete()
1699 ipu_idmac_select_buffer(chan->in_chan, 0); in do_tile_complete()
1702 } else if (ctx->next_tile < ctx->num_tiles - 1) { in do_tile_complete()
1704 src_tile = &s_image->tile[ctx->next_tile + 1]; in do_tile_complete()
1705 dst_idx = ctx->out_tile_map[ctx->next_tile + 1]; in do_tile_complete()
1706 dst_tile = &d_image->tile[dst_idx]; in do_tile_complete()
1708 ipu_cpmem_set_buffer(chan->in_chan, ctx->cur_buf_num, in do_tile_complete()
1709 s_image->base.phys0 + src_tile->offset); in do_tile_complete()
1710 ipu_cpmem_set_buffer(outch, ctx->cur_buf_num, in do_tile_complete()
1711 d_image->base.phys0 + dst_tile->offset); in do_tile_complete()
1713 ipu_idmac_select_buffer(chan->in_chan, ctx->cur_buf_num); in do_tile_complete()
1714 ipu_idmac_select_buffer(outch, ctx->cur_buf_num); in do_tile_complete()
1716 ctx->cur_buf_num ^= 1; in do_tile_complete()
1719 ctx->eof_mask = 0; /* clear EOF irq mask for next tile */ in do_tile_complete()
1720 ctx->next_tile++; in do_tile_complete()
1723 list_add_tail(&run->list, &chan->done_q); in do_tile_complete()
1724 chan->current_run = NULL; in do_tile_complete()
1732 struct ipu_image_convert_priv *priv = chan->priv; in eof_irq()
1739 spin_lock_irqsave(&chan->irqlock, flags); in eof_irq()
1742 run = chan->current_run; in eof_irq()
1748 ctx = run->ctx; in eof_irq()
1750 if (irq == chan->in_eof_irq) { in eof_irq()
1751 ctx->eof_mask |= EOF_IRQ_IN; in eof_irq()
1752 } else if (irq == chan->out_eof_irq) { in eof_irq()
1753 ctx->eof_mask |= EOF_IRQ_OUT; in eof_irq()
1754 } else if (irq == chan->rot_in_eof_irq || in eof_irq()
1755 irq == chan->rot_out_eof_irq) { in eof_irq()
1756 if (!ipu_rot_mode_is_irt(ctx->rot_mode)) { in eof_irq()
1758 dev_err(priv->ipu->dev, in eof_irq()
1762 ctx->eof_mask |= (irq == chan->rot_in_eof_irq) ? in eof_irq()
1765 dev_err(priv->ipu->dev, "Received unknown irq %d\n", irq); in eof_irq()
1770 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in eof_irq()
1771 tile_complete = (ctx->eof_mask == EOF_IRQ_ROT_COMPLETE); in eof_irq()
1773 tile_complete = (ctx->eof_mask == EOF_IRQ_COMPLETE); in eof_irq()
1778 spin_unlock_irqrestore(&chan->irqlock, flags); in eof_irq()
1788 struct ipu_image_convert_chan *chan = ctx->chan; in force_abort()
1792 spin_lock_irqsave(&chan->irqlock, flags); in force_abort()
1794 run = chan->current_run; in force_abort()
1795 if (run && run->ctx == ctx) { in force_abort()
1797 run->status = -EIO; in force_abort()
1798 list_add_tail(&run->list, &chan->done_q); in force_abort()
1799 chan->current_run = NULL; in force_abort()
1803 spin_unlock_irqrestore(&chan->irqlock, flags); in force_abort()
1810 if (chan->in_eof_irq >= 0) in release_ipu_resources()
1811 free_irq(chan->in_eof_irq, chan); in release_ipu_resources()
1812 if (chan->rot_in_eof_irq >= 0) in release_ipu_resources()
1813 free_irq(chan->rot_in_eof_irq, chan); in release_ipu_resources()
1814 if (chan->out_eof_irq >= 0) in release_ipu_resources()
1815 free_irq(chan->out_eof_irq, chan); in release_ipu_resources()
1816 if (chan->rot_out_eof_irq >= 0) in release_ipu_resources()
1817 free_irq(chan->rot_out_eof_irq, chan); in release_ipu_resources()
1819 if (!IS_ERR_OR_NULL(chan->in_chan)) in release_ipu_resources()
1820 ipu_idmac_put(chan->in_chan); in release_ipu_resources()
1821 if (!IS_ERR_OR_NULL(chan->out_chan)) in release_ipu_resources()
1822 ipu_idmac_put(chan->out_chan); in release_ipu_resources()
1823 if (!IS_ERR_OR_NULL(chan->rotation_in_chan)) in release_ipu_resources()
1824 ipu_idmac_put(chan->rotation_in_chan); in release_ipu_resources()
1825 if (!IS_ERR_OR_NULL(chan->rotation_out_chan)) in release_ipu_resources()
1826 ipu_idmac_put(chan->rotation_out_chan); in release_ipu_resources()
1827 if (!IS_ERR_OR_NULL(chan->ic)) in release_ipu_resources()
1828 ipu_ic_put(chan->ic); in release_ipu_resources()
1830 chan->in_chan = chan->out_chan = chan->rotation_in_chan = in release_ipu_resources()
1831 chan->rotation_out_chan = NULL; in release_ipu_resources()
1832 chan->in_eof_irq = -1; in release_ipu_resources()
1833 chan->rot_in_eof_irq = -1; in release_ipu_resources()
1834 chan->out_eof_irq = -1; in release_ipu_resources()
1835 chan->rot_out_eof_irq = -1; in release_ipu_resources()
1839 struct ipuv3_channel *channel) in get_eof_irq() argument
1841 struct ipu_image_convert_priv *priv = chan->priv; in get_eof_irq()
1844 irq = ipu_idmac_channel_irq(priv->ipu, channel, IPU_IRQ_EOF); in get_eof_irq()
1846 ret = request_threaded_irq(irq, eof_irq, do_bh, 0, "ipu-ic", chan); in get_eof_irq()
1848 dev_err(priv->ipu->dev, "could not acquire irq %d\n", irq); in get_eof_irq()
1857 const struct ipu_image_convert_dma_chan *dma = chan->dma_ch; in get_ipu_resources()
1858 struct ipu_image_convert_priv *priv = chan->priv; in get_ipu_resources()
1862 chan->ic = ipu_ic_get(priv->ipu, chan->ic_task); in get_ipu_resources()
1863 if (IS_ERR(chan->ic)) { in get_ipu_resources()
1864 dev_err(priv->ipu->dev, "could not acquire IC\n"); in get_ipu_resources()
1865 ret = PTR_ERR(chan->ic); in get_ipu_resources()
1870 chan->in_chan = ipu_idmac_get(priv->ipu, dma->in); in get_ipu_resources()
1871 chan->out_chan = ipu_idmac_get(priv->ipu, dma->out); in get_ipu_resources()
1872 if (IS_ERR(chan->in_chan) || IS_ERR(chan->out_chan)) { in get_ipu_resources()
1873 dev_err(priv->ipu->dev, "could not acquire idmac channels\n"); in get_ipu_resources()
1874 ret = -EBUSY; in get_ipu_resources()
1878 chan->rotation_in_chan = ipu_idmac_get(priv->ipu, dma->rot_in); in get_ipu_resources()
1879 chan->rotation_out_chan = ipu_idmac_get(priv->ipu, dma->rot_out); in get_ipu_resources()
1880 if (IS_ERR(chan->rotation_in_chan) || IS_ERR(chan->rotation_out_chan)) { in get_ipu_resources()
1881 dev_err(priv->ipu->dev, in get_ipu_resources()
1883 ret = -EBUSY; in get_ipu_resources()
1888 ret = get_eof_irq(chan, chan->in_chan); in get_ipu_resources()
1890 chan->in_eof_irq = -1; in get_ipu_resources()
1893 chan->in_eof_irq = ret; in get_ipu_resources()
1895 ret = get_eof_irq(chan, chan->rotation_in_chan); in get_ipu_resources()
1897 chan->rot_in_eof_irq = -1; in get_ipu_resources()
1900 chan->rot_in_eof_irq = ret; in get_ipu_resources()
1902 ret = get_eof_irq(chan, chan->out_chan); in get_ipu_resources()
1904 chan->out_eof_irq = -1; in get_ipu_resources()
1907 chan->out_eof_irq = ret; in get_ipu_resources()
1909 ret = get_eof_irq(chan, chan->rotation_out_chan); in get_ipu_resources()
1911 chan->rot_out_eof_irq = -1; in get_ipu_resources()
1914 chan->rot_out_eof_irq = ret; in get_ipu_resources()
1927 struct ipu_image_convert_priv *priv = ctx->chan->priv; in fill_image()
1929 ic_image->base = *image; in fill_image()
1930 ic_image->type = type; in fill_image()
1932 ic_image->fmt = get_format(image->pix.pixelformat); in fill_image()
1933 if (!ic_image->fmt) { in fill_image()
1934 dev_err(priv->ipu->dev, "pixelformat not supported for %s\n", in fill_image()
1936 return -EINVAL; in fill_image()
1939 if (ic_image->fmt->planar) in fill_image()
1940 ic_image->stride = ic_image->base.pix.width; in fill_image()
1942 ic_image->stride = ic_image->base.pix.bytesperline; in fill_image()
1947 /* borrowed from drivers/media/v4l2-core/v4l2-common.c */
1952 unsigned int mask = ~((1 << align) - 1); in clamp_align()
1959 x = (x + (1 << (align - 1))) & mask; in clamp_align()
1972 infmt = get_format(in->pix.pixelformat); in ipu_image_convert_adjust()
1973 outfmt = get_format(out->pix.pixelformat); in ipu_image_convert_adjust()
1977 in->pix.pixelformat = V4L2_PIX_FMT_RGB24; in ipu_image_convert_adjust()
1981 out->pix.pixelformat = V4L2_PIX_FMT_RGB24; in ipu_image_convert_adjust()
1986 in->pix.field = out->pix.field = V4L2_FIELD_NONE; in ipu_image_convert_adjust()
1990 out->pix.height = max_t(__u32, out->pix.height, in ipu_image_convert_adjust()
1991 in->pix.width / 4); in ipu_image_convert_adjust()
1992 out->pix.width = max_t(__u32, out->pix.width, in ipu_image_convert_adjust()
1993 in->pix.height / 4); in ipu_image_convert_adjust()
1995 out->pix.width = max_t(__u32, out->pix.width, in ipu_image_convert_adjust()
1996 in->pix.width / 4); in ipu_image_convert_adjust()
1997 out->pix.height = max_t(__u32, out->pix.height, in ipu_image_convert_adjust()
1998 in->pix.height / 4); in ipu_image_convert_adjust()
2006 in->pix.width = clamp_align(in->pix.width, MIN_W, MAX_W, in ipu_image_convert_adjust()
2008 in->pix.height = clamp_align(in->pix.height, MIN_H, MAX_H, in ipu_image_convert_adjust()
2016 out->pix.width = clamp_align(out->pix.width, MIN_W, MAX_W, in ipu_image_convert_adjust()
2018 out->pix.height = clamp_align(out->pix.height, MIN_H, MAX_H, in ipu_image_convert_adjust()
2022 in->pix.bytesperline = infmt->planar ? in ipu_image_convert_adjust()
2023 clamp_align(in->pix.width, 2 << w_align_in, MAX_W, in ipu_image_convert_adjust()
2025 clamp_align((in->pix.width * infmt->bpp) >> 3, in ipu_image_convert_adjust()
2026 ((2 << w_align_in) * infmt->bpp) >> 3, in ipu_image_convert_adjust()
2027 (MAX_W * infmt->bpp) >> 3, in ipu_image_convert_adjust()
2029 in->pix.sizeimage = infmt->planar ? in ipu_image_convert_adjust()
2030 (in->pix.height * in->pix.bytesperline * infmt->bpp) >> 3 : in ipu_image_convert_adjust()
2031 in->pix.height * in->pix.bytesperline; in ipu_image_convert_adjust()
2032 out->pix.bytesperline = outfmt->planar ? out->pix.width : in ipu_image_convert_adjust()
2033 (out->pix.width * outfmt->bpp) >> 3; in ipu_image_convert_adjust()
2034 out->pix.sizeimage = outfmt->planar ? in ipu_image_convert_adjust()
2035 (out->pix.height * out->pix.bytesperline * outfmt->bpp) >> 3 : in ipu_image_convert_adjust()
2036 out->pix.height * out->pix.bytesperline; in ipu_image_convert_adjust()
2055 if (testin.pix.width != in->pix.width || in ipu_image_convert_verify()
2056 testin.pix.height != in->pix.height || in ipu_image_convert_verify()
2057 testout.pix.width != out->pix.width || in ipu_image_convert_verify()
2058 testout.pix.height != out->pix.height) in ipu_image_convert_verify()
2059 return -EINVAL; in ipu_image_convert_verify()
2076 struct ipu_image_convert_priv *priv = ipu->image_convert_priv; in ipu_image_convert_prepare()
2088 return ERR_PTR(-EINVAL); in ipu_image_convert_prepare()
2093 dev_err(priv->ipu->dev, "%s: in/out formats invalid\n", in ipu_image_convert_prepare()
2098 chan = &priv->chan[ic_task]; in ipu_image_convert_prepare()
2102 return ERR_PTR(-ENOMEM); in ipu_image_convert_prepare()
2104 dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p\n", __func__, in ipu_image_convert_prepare()
2105 chan->ic_task, ctx); in ipu_image_convert_prepare()
2107 ctx->chan = chan; in ipu_image_convert_prepare()
2108 init_completion(&ctx->aborted); in ipu_image_convert_prepare()
2110 ctx->rot_mode = rot_mode; in ipu_image_convert_prepare()
2112 /* Sets ctx->in.num_rows/cols as well */ in ipu_image_convert_prepare()
2117 s_image = &ctx->in; in ipu_image_convert_prepare()
2118 d_image = &ctx->out; in ipu_image_convert_prepare()
2122 d_image->num_rows = s_image->num_cols; in ipu_image_convert_prepare()
2123 d_image->num_cols = s_image->num_rows; in ipu_image_convert_prepare()
2125 d_image->num_rows = s_image->num_rows; in ipu_image_convert_prepare()
2126 d_image->num_cols = s_image->num_cols; in ipu_image_convert_prepare()
2129 ctx->num_tiles = d_image->num_cols * d_image->num_rows; in ipu_image_convert_prepare()
2157 ret = ipu_ic_calc_csc(&ctx->csc, in ipu_image_convert_prepare()
2158 s_image->base.pix.ycbcr_enc, in ipu_image_convert_prepare()
2159 s_image->base.pix.quantization, in ipu_image_convert_prepare()
2160 ipu_pixelformat_to_colorspace(s_image->fmt->fourcc), in ipu_image_convert_prepare()
2161 d_image->base.pix.ycbcr_enc, in ipu_image_convert_prepare()
2162 d_image->base.pix.quantization, in ipu_image_convert_prepare()
2163 ipu_pixelformat_to_colorspace(d_image->fmt->fourcc)); in ipu_image_convert_prepare()
2170 ctx->complete = complete; in ipu_image_convert_prepare()
2171 ctx->complete_context = complete_context; in ipu_image_convert_prepare()
2174 * Can we use double-buffering for this operation? If there is in ipu_image_convert_prepare()
2176 * operation) there's no point in using double-buffering. Also, in ipu_image_convert_prepare()
2180 * each buffer which is not possible. So double-buffering is in ipu_image_convert_prepare()
2184 * prevent double-buffering as well. in ipu_image_convert_prepare()
2186 ctx->double_buffering = (ctx->num_tiles > 1 && in ipu_image_convert_prepare()
2187 !s_image->fmt->planar && in ipu_image_convert_prepare()
2188 !d_image->fmt->planar); in ipu_image_convert_prepare()
2189 for (i = 1; i < ctx->num_tiles; i++) { in ipu_image_convert_prepare()
2190 if (ctx->in.tile[i].width != ctx->in.tile[0].width || in ipu_image_convert_prepare()
2191 ctx->in.tile[i].height != ctx->in.tile[0].height || in ipu_image_convert_prepare()
2192 ctx->out.tile[i].width != ctx->out.tile[0].width || in ipu_image_convert_prepare()
2193 ctx->out.tile[i].height != ctx->out.tile[0].height) { in ipu_image_convert_prepare()
2194 ctx->double_buffering = false; in ipu_image_convert_prepare()
2198 for (i = 1; i < ctx->in.num_cols; i++) { in ipu_image_convert_prepare()
2199 if (ctx->resize_coeffs_h[i] != ctx->resize_coeffs_h[0]) { in ipu_image_convert_prepare()
2200 ctx->double_buffering = false; in ipu_image_convert_prepare()
2204 for (i = 1; i < ctx->in.num_rows; i++) { in ipu_image_convert_prepare()
2205 if (ctx->resize_coeffs_v[i] != ctx->resize_coeffs_v[0]) { in ipu_image_convert_prepare()
2206 ctx->double_buffering = false; in ipu_image_convert_prepare()
2211 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in ipu_image_convert_prepare()
2212 unsigned long intermediate_size = d_image->tile[0].size; in ipu_image_convert_prepare()
2214 for (i = 1; i < ctx->num_tiles; i++) { in ipu_image_convert_prepare()
2215 if (d_image->tile[i].size > intermediate_size) in ipu_image_convert_prepare()
2216 intermediate_size = d_image->tile[i].size; in ipu_image_convert_prepare()
2219 ret = alloc_dma_buf(priv, &ctx->rot_intermediate[0], in ipu_image_convert_prepare()
2223 if (ctx->double_buffering) { in ipu_image_convert_prepare()
2225 &ctx->rot_intermediate[1], in ipu_image_convert_prepare()
2232 spin_lock_irqsave(&chan->irqlock, flags); in ipu_image_convert_prepare()
2234 get_res = list_empty(&chan->ctx_list); in ipu_image_convert_prepare()
2236 list_add_tail(&ctx->list, &chan->ctx_list); in ipu_image_convert_prepare()
2238 spin_unlock_irqrestore(&chan->irqlock, flags); in ipu_image_convert_prepare()
2249 free_dma_buf(priv, &ctx->rot_intermediate[1]); in ipu_image_convert_prepare()
2250 spin_lock_irqsave(&chan->irqlock, flags); in ipu_image_convert_prepare()
2251 list_del(&ctx->list); in ipu_image_convert_prepare()
2252 spin_unlock_irqrestore(&chan->irqlock, flags); in ipu_image_convert_prepare()
2254 free_dma_buf(priv, &ctx->rot_intermediate[0]); in ipu_image_convert_prepare()
2274 if (!run || !run->ctx || !run->in_phys || !run->out_phys) in ipu_image_convert_queue()
2275 return -EINVAL; in ipu_image_convert_queue()
2277 ctx = run->ctx; in ipu_image_convert_queue()
2278 chan = ctx->chan; in ipu_image_convert_queue()
2279 priv = chan->priv; in ipu_image_convert_queue()
2281 dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p run %p\n", __func__, in ipu_image_convert_queue()
2282 chan->ic_task, ctx, run); in ipu_image_convert_queue()
2284 INIT_LIST_HEAD(&run->list); in ipu_image_convert_queue()
2286 spin_lock_irqsave(&chan->irqlock, flags); in ipu_image_convert_queue()
2288 if (ctx->aborting) { in ipu_image_convert_queue()
2289 ret = -EIO; in ipu_image_convert_queue()
2293 list_add_tail(&run->list, &chan->pending_q); in ipu_image_convert_queue()
2295 if (!chan->current_run) { in ipu_image_convert_queue()
2298 chan->current_run = NULL; in ipu_image_convert_queue()
2301 spin_unlock_irqrestore(&chan->irqlock, flags); in ipu_image_convert_queue()
2309 struct ipu_image_convert_chan *chan = ctx->chan; in __ipu_image_convert_abort()
2310 struct ipu_image_convert_priv *priv = chan->priv; in __ipu_image_convert_abort()
2315 spin_lock_irqsave(&chan->irqlock, flags); in __ipu_image_convert_abort()
2318 list_for_each_entry_safe(run, tmp, &chan->pending_q, list) { in __ipu_image_convert_abort()
2319 if (run->ctx != ctx) in __ipu_image_convert_abort()
2321 run->status = -EIO; in __ipu_image_convert_abort()
2322 list_move_tail(&run->list, &chan->done_q); in __ipu_image_convert_abort()
2325 run_count = get_run_count(ctx, &chan->done_q); in __ipu_image_convert_abort()
2326 active_run = (chan->current_run && chan->current_run->ctx == ctx) ? in __ipu_image_convert_abort()
2327 chan->current_run : NULL; in __ipu_image_convert_abort()
2330 reinit_completion(&ctx->aborted); in __ipu_image_convert_abort()
2332 ctx->aborting = true; in __ipu_image_convert_abort()
2334 spin_unlock_irqrestore(&chan->irqlock, flags); in __ipu_image_convert_abort()
2337 dev_dbg(priv->ipu->dev, in __ipu_image_convert_abort()
2339 __func__, chan->ic_task, ctx); in __ipu_image_convert_abort()
2348 dev_dbg(priv->ipu->dev, in __ipu_image_convert_abort()
2350 __func__, chan->ic_task, run_count); in __ipu_image_convert_abort()
2352 ret = wait_for_completion_timeout(&ctx->aborted, in __ipu_image_convert_abort()
2355 dev_warn(priv->ipu->dev, "%s: timeout\n", __func__); in __ipu_image_convert_abort()
2363 ctx->aborting = false; in ipu_image_convert_abort()
2370 struct ipu_image_convert_chan *chan = ctx->chan; in ipu_image_convert_unprepare()
2371 struct ipu_image_convert_priv *priv = chan->priv; in ipu_image_convert_unprepare()
2378 dev_dbg(priv->ipu->dev, "%s: task %u: removing ctx %p\n", __func__, in ipu_image_convert_unprepare()
2379 chan->ic_task, ctx); in ipu_image_convert_unprepare()
2381 spin_lock_irqsave(&chan->irqlock, flags); in ipu_image_convert_unprepare()
2383 list_del(&ctx->list); in ipu_image_convert_unprepare()
2385 put_res = list_empty(&chan->ctx_list); in ipu_image_convert_unprepare()
2387 spin_unlock_irqrestore(&chan->irqlock, flags); in ipu_image_convert_unprepare()
2392 free_dma_buf(priv, &ctx->rot_intermediate[1]); in ipu_image_convert_unprepare()
2393 free_dma_buf(priv, &ctx->rot_intermediate[0]); in ipu_image_convert_unprepare()
2423 return ERR_PTR(-ENOMEM); in ipu_image_convert()
2426 run->ctx = ctx; in ipu_image_convert()
2427 run->in_phys = in->phys0; in ipu_image_convert()
2428 run->out_phys = out->phys0; in ipu_image_convert()
2466 ret = (ret == 0) ? -ETIMEDOUT : 0; in ipu_image_convert_sync()
2468 ipu_image_convert_unprepare(run->ctx); in ipu_image_convert_sync()
2482 return -ENOMEM; in ipu_image_convert_init()
2484 ipu->image_convert_priv = priv; in ipu_image_convert_init()
2485 priv->ipu = ipu; in ipu_image_convert_init()
2488 struct ipu_image_convert_chan *chan = &priv->chan[i]; in ipu_image_convert_init()
2490 chan->ic_task = i; in ipu_image_convert_init()
2491 chan->priv = priv; in ipu_image_convert_init()
2492 chan->dma_ch = &image_convert_dma_chan[i]; in ipu_image_convert_init()
2493 chan->in_eof_irq = -1; in ipu_image_convert_init()
2494 chan->rot_in_eof_irq = -1; in ipu_image_convert_init()
2495 chan->out_eof_irq = -1; in ipu_image_convert_init()
2496 chan->rot_out_eof_irq = -1; in ipu_image_convert_init()
2498 spin_lock_init(&chan->irqlock); in ipu_image_convert_init()
2499 INIT_LIST_HEAD(&chan->ctx_list); in ipu_image_convert_init()
2500 INIT_LIST_HEAD(&chan->pending_q); in ipu_image_convert_init()
2501 INIT_LIST_HEAD(&chan->done_q); in ipu_image_convert_init()