Lines Matching +full:double +full:- +full:buffering
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 * +-----+-----+
175 /* current buffer number for double buffering */
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()
361 if (buf->virt) in free_dma_buf()
362 dma_free_coherent(priv->ipu->dev, in free_dma_buf()
363 buf->len, buf->virt, buf->phys); in free_dma_buf()
364 buf->virt = NULL; in free_dma_buf()
365 buf->phys = 0; in free_dma_buf()
372 buf->len = PAGE_ALIGN(size); in alloc_dma_buf()
373 buf->virt = dma_alloc_coherent(priv->ipu->dev, buf->len, &buf->phys, in alloc_dma_buf()
375 if (!buf->virt) { in alloc_dma_buf()
376 dev_err(priv->ipu->dev, "failed to alloc dma buffer\n"); in alloc_dma_buf()
377 return -ENOMEM; in alloc_dma_buf()
385 return (dim - 1) / 1024 + 1; in num_stripes()
400 u32 downsized_width = in->rect.width; in calc_image_resize_coefficients()
401 u32 downsized_height = in->rect.height; in calc_image_resize_coefficients()
404 u32 resized_width = out->rect.width; in calc_image_resize_coefficients()
405 u32 resized_height = out->rect.height; in calc_image_resize_coefficients()
411 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in calc_image_resize_coefficients()
412 resized_width = out->rect.height; in calc_image_resize_coefficients()
413 resized_height = out->rect.width; in calc_image_resize_coefficients()
418 return -EINVAL; in calc_image_resize_coefficients()
436 resize_coeff_h = 8192 * (downsized_width - 1) / (resized_width - 1); in calc_image_resize_coefficients()
437 resize_coeff_v = 8192 * (downsized_height - 1) / (resized_height - 1); in calc_image_resize_coefficients()
447 dev_dbg(ctx->chan->priv->ipu->dev, in calc_image_resize_coefficients()
454 return -EINVAL; in calc_image_resize_coefficients()
456 ctx->downsize_coeff_h = downsize_coeff_h; in calc_image_resize_coefficients()
457 ctx->downsize_coeff_v = downsize_coeff_v; in calc_image_resize_coefficients()
458 ctx->image_resize_coeff_h = resize_coeff_h; in calc_image_resize_coefficients()
459 ctx->image_resize_coeff_v = resize_coeff_v; in calc_image_resize_coefficients()
460 ctx->in.num_cols = cols; in calc_image_resize_coefficients()
461 ctx->in.num_rows = rows; in calc_image_resize_coefficients()
475 * @in_align: input alignment, either horizontal 8-byte line start address
477 * @out_align: output alignment, either horizontal 8-byte line start address
500 struct device *dev = ctx->chan->priv->ipu->dev; in find_best_seam()
512 out_start = max_t(int, index * out_align, out_edge - 1024); in find_best_seam()
521 in_edge - (1024 << downsize_coeff)); in find_best_seam()
542 if ((out_burst > 1) && (out_edge - out_pos) % out_burst) in find_best_seam()
564 (in_edge - in_pos_rounded) % in_burst) in find_best_seam()
590 if (fmt->planar) in tile_left_align()
591 return fmt->uv_packed ? 8 : 8 * fmt->uv_width_dec; in tile_left_align()
593 return fmt->bpp == 32 ? 2 : fmt->bpp == 16 ? 4 : 8; in tile_left_align()
601 return fmt->uv_height_dec > 1 ? 2 : 1; in tile_top_align()
621 * formats to guarantee 8-byte aligned line start addresses in the in tile_width_align()
626 fmt->planar && !fmt->uv_packed) ? in tile_width_align()
627 8 * fmt->uv_width_dec : 8; in tile_width_align()
639 * formats to guarantee 8-byte aligned line start addresses in the in tile_height_align()
643 return (fmt->planar && !fmt->uv_packed) ? 8 * fmt->uv_width_dec : 8; in tile_height_align()
661 for (row = 0; row < in->num_rows; row++) { in fill_tile_column()
662 tile_idx = in->num_cols * row + col; in fill_tile_column()
663 in_tile = &in->tile[tile_idx]; in fill_tile_column()
664 out_tile = &out->tile[ctx->out_tile_map[tile_idx]]; in fill_tile_column()
666 in_tile->left = in_left; in fill_tile_column()
667 in_tile->width = in_width; in fill_tile_column()
669 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in fill_tile_column()
670 out_tile->top = out_left; in fill_tile_column()
671 out_tile->height = out_width; in fill_tile_column()
673 out_tile->left = out_left; in fill_tile_column()
674 out_tile->width = out_width; in fill_tile_column()
693 for (col = 0; col < in->num_cols; col++) { in fill_tile_row()
694 tile_idx = in->num_cols * row + col; in fill_tile_row()
695 in_tile = &in->tile[tile_idx]; in fill_tile_row()
696 out_tile = &out->tile[ctx->out_tile_map[tile_idx]]; in fill_tile_row()
698 in_tile->top = in_top; in fill_tile_row()
699 in_tile->height = in_height; in fill_tile_row()
701 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in fill_tile_row()
702 out_tile->left = out_top; in fill_tile_row()
703 out_tile->width = out_height; in fill_tile_row()
705 out_tile->top = out_top; in fill_tile_row()
706 out_tile->height = out_height; in fill_tile_row()
720 struct device *dev = ctx->chan->priv->ipu->dev; in find_seams()
721 unsigned int resized_width = out->base.rect.width; in find_seams()
722 unsigned int resized_height = out->base.rect.height; in find_seams()
725 unsigned int in_left_align = tile_left_align(in->fmt); in find_seams()
726 unsigned int in_top_align = tile_top_align(in->fmt); in find_seams()
727 unsigned int out_left_align = tile_left_align(out->fmt); in find_seams()
728 unsigned int out_top_align = tile_top_align(out->fmt); in find_seams()
729 unsigned int out_width_align = tile_width_align(out->type, out->fmt, in find_seams()
730 ctx->rot_mode); in find_seams()
731 unsigned int out_height_align = tile_height_align(out->type, out->fmt, in find_seams()
732 ctx->rot_mode); in find_seams()
733 unsigned int in_right = in->base.rect.width; in find_seams()
734 unsigned int in_bottom = in->base.rect.height; in find_seams()
735 unsigned int out_right = out->base.rect.width; in find_seams()
736 unsigned int out_bottom = out->base.rect.height; in find_seams()
740 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in find_seams()
742 resized_width = out->base.rect.height; in find_seams()
743 resized_height = out->base.rect.width; in find_seams()
748 out_right = out->base.rect.height; in find_seams()
749 out_bottom = out->base.rect.width; in find_seams()
752 for (col = in->num_cols - 1; col > 0; col--) { in find_seams()
753 bool allow_in_overshoot = ipu_rot_mode_is_irt(ctx->rot_mode) || in find_seams()
754 !(ctx->rot_mode & IPU_ROT_BIT_HFLIP); in find_seams()
755 bool allow_out_overshoot = (col < in->num_cols - 1) && in find_seams()
756 !(ctx->rot_mode & IPU_ROT_BIT_HFLIP); in find_seams()
770 ctx->downsize_coeff_h, ctx->image_resize_coeff_h, in find_seams()
773 if (ctx->rot_mode & IPU_ROT_BIT_HFLIP) in find_seams()
774 flipped_out_left = resized_width - out_right; in find_seams()
778 fill_tile_column(ctx, col, in, in_left, in_right - in_left, in find_seams()
779 out, flipped_out_left, out_right - out_left); in find_seams()
781 dev_dbg(dev, "%s: col %u: %u, %u -> %u, %u\n", __func__, col, in find_seams()
782 in_left, in_right - in_left, in find_seams()
783 flipped_out_left, out_right - out_left); in find_seams()
789 flipped_out_left = (ctx->rot_mode & IPU_ROT_BIT_HFLIP) ? in find_seams()
790 resized_width - out_right : 0; in find_seams()
795 dev_dbg(dev, "%s: col 0: 0, %u -> %u, %u\n", __func__, in find_seams()
798 for (row = in->num_rows - 1; row > 0; row--) { in find_seams()
799 bool allow_overshoot = row < in->num_rows - 1; in find_seams()
807 ctx->downsize_coeff_v, ctx->image_resize_coeff_v, in find_seams()
810 if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^ in find_seams()
811 ipu_rot_mode_is_irt(ctx->rot_mode)) in find_seams()
812 flipped_out_top = resized_height - out_bottom; in find_seams()
816 fill_tile_row(ctx, row, in, in_top, in_bottom - in_top, in find_seams()
817 out, flipped_out_top, out_bottom - out_top); in find_seams()
819 dev_dbg(dev, "%s: row %u: %u, %u -> %u, %u\n", __func__, row, in find_seams()
820 in_top, in_bottom - in_top, in find_seams()
821 flipped_out_top, out_bottom - out_top); in find_seams()
827 if ((ctx->rot_mode & IPU_ROT_BIT_VFLIP) ^ in find_seams()
828 ipu_rot_mode_is_irt(ctx->rot_mode)) in find_seams()
829 flipped_out_top = resized_height - out_bottom; in find_seams()
836 dev_dbg(dev, "%s: row 0: 0, %u -> %u, %u\n", __func__, in find_seams()
843 struct ipu_image_convert_chan *chan = ctx->chan; in calc_tile_dimensions()
844 struct ipu_image_convert_priv *priv = chan->priv; in calc_tile_dimensions()
849 if (image->type == IMAGE_CONVERT_IN) { in calc_tile_dimensions()
851 max_width <<= ctx->downsize_coeff_h; in calc_tile_dimensions()
852 max_height <<= ctx->downsize_coeff_v; in calc_tile_dimensions()
855 for (i = 0; i < ctx->num_tiles; i++) { in calc_tile_dimensions()
857 const unsigned int row = i / image->num_cols; in calc_tile_dimensions()
858 const unsigned int col = i % image->num_cols; in calc_tile_dimensions()
860 if (image->type == IMAGE_CONVERT_OUT) in calc_tile_dimensions()
861 tile = &image->tile[ctx->out_tile_map[i]]; in calc_tile_dimensions()
863 tile = &image->tile[i]; in calc_tile_dimensions()
865 tile->size = ((tile->height * image->fmt->bpp) >> 3) * in calc_tile_dimensions()
866 tile->width; in calc_tile_dimensions()
868 if (image->fmt->planar) { in calc_tile_dimensions()
869 tile->stride = tile->width; in calc_tile_dimensions()
870 tile->rot_stride = tile->height; in calc_tile_dimensions()
872 tile->stride = in calc_tile_dimensions()
873 (image->fmt->bpp * tile->width) >> 3; in calc_tile_dimensions()
874 tile->rot_stride = in calc_tile_dimensions()
875 (image->fmt->bpp * tile->height) >> 3; in calc_tile_dimensions()
878 dev_dbg(priv->ipu->dev, in calc_tile_dimensions()
880 chan->ic_task, ctx, in calc_tile_dimensions()
881 image->type == IMAGE_CONVERT_IN ? "Input" : "Output", in calc_tile_dimensions()
883 tile->width, tile->height, tile->left, tile->top); in calc_tile_dimensions()
885 if (!tile->width || tile->width > max_width || in calc_tile_dimensions()
886 !tile->height || tile->height > max_height) { in calc_tile_dimensions()
887 dev_err(priv->ipu->dev, "invalid %s tile size: %ux%u\n", in calc_tile_dimensions()
888 image->type == IMAGE_CONVERT_IN ? "input" : in calc_tile_dimensions()
889 "output", tile->width, tile->height); in calc_tile_dimensions()
890 return -EINVAL; in calc_tile_dimensions()
906 struct ipu_image_convert_chan *chan = ctx->chan; in transform_tile_index()
907 struct ipu_image_convert_priv *priv = chan->priv; in transform_tile_index()
908 struct ipu_image_convert_image *s_image = &ctx->in; in transform_tile_index()
909 struct ipu_image_convert_image *d_image = &ctx->out; in transform_tile_index()
913 if (ctx->rot_mode == IPU_ROTATE_NONE) in transform_tile_index()
914 return src_row * s_image->num_cols + src_col; in transform_tile_index()
920 src_row = src_row * 2 - (s_image->num_rows - 1); in transform_tile_index()
921 src_col = src_col * 2 - (s_image->num_cols - 1); in transform_tile_index()
924 if (ctx->rot_mode & IPU_ROT_BIT_90) { in transform_tile_index()
925 dst_col = -src_row; in transform_tile_index()
933 if (ctx->rot_mode & IPU_ROT_BIT_HFLIP) in transform_tile_index()
934 dst_col = -dst_col; in transform_tile_index()
935 if (ctx->rot_mode & IPU_ROT_BIT_VFLIP) in transform_tile_index()
936 dst_row = -dst_row; in transform_tile_index()
938 dev_dbg(priv->ipu->dev, "task %u: ctx %p: [%d,%d] --> [%d,%d]\n", in transform_tile_index()
939 chan->ic_task, ctx, src_col, src_row, dst_col, dst_row); in transform_tile_index()
945 dst_row += d_image->num_rows - 1; in transform_tile_index()
946 dst_col += d_image->num_cols - 1; in transform_tile_index()
950 return dst_row * d_image->num_cols + dst_col; in transform_tile_index()
958 struct ipu_image_convert_image *s_image = &ctx->in; in calc_out_tile_map()
961 for (row = 0; row < s_image->num_rows; row++) { in calc_out_tile_map()
962 for (col = 0; col < s_image->num_cols; col++) { in calc_out_tile_map()
963 ctx->out_tile_map[tile] = in calc_out_tile_map()
973 struct ipu_image_convert_chan *chan = ctx->chan; in calc_tile_offsets_planar()
974 struct ipu_image_convert_priv *priv = chan->priv; in calc_tile_offsets_planar()
975 const struct ipu_image_pixfmt *fmt = image->fmt; in calc_tile_offsets_planar()
983 H = image->base.pix.height; in calc_tile_offsets_planar()
985 y_stride = image->stride; in calc_tile_offsets_planar()
986 uv_stride = y_stride / fmt->uv_width_dec; in calc_tile_offsets_planar()
987 if (fmt->uv_packed) in calc_tile_offsets_planar()
991 uv_size = y_size / (fmt->uv_width_dec * fmt->uv_height_dec); in calc_tile_offsets_planar()
993 for (row = 0; row < image->num_rows; row++) { in calc_tile_offsets_planar()
994 top = image->tile[tile].top; in calc_tile_offsets_planar()
996 uv_row_off = (top * uv_stride) / fmt->uv_height_dec; in calc_tile_offsets_planar()
998 for (col = 0; col < image->num_cols; col++) { in calc_tile_offsets_planar()
999 y_col_off = image->tile[tile].left; in calc_tile_offsets_planar()
1000 uv_col_off = y_col_off / fmt->uv_width_dec; in calc_tile_offsets_planar()
1001 if (fmt->uv_packed) in calc_tile_offsets_planar()
1007 u_off = y_size - y_off + uv_off; in calc_tile_offsets_planar()
1008 v_off = (fmt->uv_packed) ? 0 : u_off + uv_size; in calc_tile_offsets_planar()
1009 if (fmt->uv_swapped) in calc_tile_offsets_planar()
1012 image->tile[tile].offset = y_off; in calc_tile_offsets_planar()
1013 image->tile[tile].u_off = u_off; in calc_tile_offsets_planar()
1014 image->tile[tile++].v_off = v_off; in calc_tile_offsets_planar()
1017 dev_err(priv->ipu->dev, in calc_tile_offsets_planar()
1020 chan->ic_task, ctx, in calc_tile_offsets_planar()
1021 image->type == IMAGE_CONVERT_IN ? in calc_tile_offsets_planar()
1024 return -EINVAL; in calc_tile_offsets_planar()
1035 struct ipu_image_convert_chan *chan = ctx->chan; in calc_tile_offsets_packed()
1036 struct ipu_image_convert_priv *priv = chan->priv; in calc_tile_offsets_packed()
1037 const struct ipu_image_pixfmt *fmt = image->fmt; in calc_tile_offsets_packed()
1043 stride = image->stride; in calc_tile_offsets_packed()
1044 bpp = fmt->bpp; in calc_tile_offsets_packed()
1046 for (row = 0; row < image->num_rows; row++) { in calc_tile_offsets_packed()
1047 row_off = image->tile[tile].top * stride; in calc_tile_offsets_packed()
1049 for (col = 0; col < image->num_cols; col++) { in calc_tile_offsets_packed()
1050 col_off = (image->tile[tile].left * bpp) >> 3; in calc_tile_offsets_packed()
1054 image->tile[tile].offset = offset; in calc_tile_offsets_packed()
1055 image->tile[tile].u_off = 0; in calc_tile_offsets_packed()
1056 image->tile[tile++].v_off = 0; in calc_tile_offsets_packed()
1059 dev_err(priv->ipu->dev, in calc_tile_offsets_packed()
1062 chan->ic_task, ctx, in calc_tile_offsets_packed()
1063 image->type == IMAGE_CONVERT_IN ? in calc_tile_offsets_packed()
1066 return -EINVAL; in calc_tile_offsets_packed()
1077 if (image->fmt->planar) in calc_tile_offsets()
1100 return 8192 * (downsized - 1) / (output_size - 1); in calc_resize_coeff()
1111 struct ipu_image_convert_chan *chan = ctx->chan; in calc_tile_resize_coefficients()
1112 struct ipu_image_convert_priv *priv = chan->priv; in calc_tile_resize_coefficients()
1117 for (col = 0; col < ctx->in.num_cols; col++) { in calc_tile_resize_coefficients()
1118 bool closest = (col < ctx->in.num_cols - 1) && in calc_tile_resize_coefficients()
1119 !(ctx->rot_mode & IPU_ROT_BIT_HFLIP); in calc_tile_resize_coefficients()
1125 in_tile = &ctx->in.tile[tile_idx]; in calc_tile_resize_coefficients()
1126 out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]]; in calc_tile_resize_coefficients()
1128 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in calc_tile_resize_coefficients()
1129 resized_width = out_tile->height; in calc_tile_resize_coefficients()
1131 resized_width = out_tile->width; in calc_tile_resize_coefficients()
1133 resize_coeff_h = calc_resize_coeff(in_tile->width, in calc_tile_resize_coefficients()
1134 ctx->downsize_coeff_h, in calc_tile_resize_coefficients()
1137 dev_dbg(priv->ipu->dev, "%s: column %u hscale: *8192/%u\n", in calc_tile_resize_coefficients()
1151 last_output = resized_width - 1; in calc_tile_resize_coefficients()
1156 << ctx->downsize_coeff_h, 8); in calc_tile_resize_coefficients()
1158 for (row = 0; row < ctx->in.num_rows; row++) { in calc_tile_resize_coefficients()
1159 tile_idx = row * ctx->in.num_cols + col; in calc_tile_resize_coefficients()
1160 in_tile = &ctx->in.tile[tile_idx]; in calc_tile_resize_coefficients()
1161 out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]]; in calc_tile_resize_coefficients()
1163 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in calc_tile_resize_coefficients()
1164 out_tile->height = resized_width; in calc_tile_resize_coefficients()
1166 out_tile->width = resized_width; in calc_tile_resize_coefficients()
1168 in_tile->width = in_width; in calc_tile_resize_coefficients()
1171 ctx->resize_coeffs_h[col] = resize_coeff_h; in calc_tile_resize_coefficients()
1174 for (row = 0; row < ctx->in.num_rows; row++) { in calc_tile_resize_coefficients()
1175 bool closest = (row < ctx->in.num_rows - 1) && in calc_tile_resize_coefficients()
1176 !(ctx->rot_mode & IPU_ROT_BIT_VFLIP); in calc_tile_resize_coefficients()
1181 tile_idx = row * ctx->in.num_cols; in calc_tile_resize_coefficients()
1182 in_tile = &ctx->in.tile[tile_idx]; in calc_tile_resize_coefficients()
1183 out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]]; in calc_tile_resize_coefficients()
1185 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in calc_tile_resize_coefficients()
1186 resized_height = out_tile->width; in calc_tile_resize_coefficients()
1188 resized_height = out_tile->height; in calc_tile_resize_coefficients()
1190 resize_coeff_v = calc_resize_coeff(in_tile->height, in calc_tile_resize_coefficients()
1191 ctx->downsize_coeff_v, in calc_tile_resize_coefficients()
1194 dev_dbg(priv->ipu->dev, "%s: row %u vscale: *8192/%u\n", in calc_tile_resize_coefficients()
1208 last_output = resized_height - 1; in calc_tile_resize_coefficients()
1213 << ctx->downsize_coeff_v, 2); in calc_tile_resize_coefficients()
1215 for (col = 0; col < ctx->in.num_cols; col++) { in calc_tile_resize_coefficients()
1216 tile_idx = row * ctx->in.num_cols + col; in calc_tile_resize_coefficients()
1217 in_tile = &ctx->in.tile[tile_idx]; in calc_tile_resize_coefficients()
1218 out_tile = &ctx->out.tile[ctx->out_tile_map[tile_idx]]; in calc_tile_resize_coefficients()
1220 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in calc_tile_resize_coefficients()
1221 out_tile->width = resized_height; in calc_tile_resize_coefficients()
1223 out_tile->height = resized_height; in calc_tile_resize_coefficients()
1225 in_tile->height = in_height; in calc_tile_resize_coefficients()
1228 ctx->resize_coeffs_v[row] = resize_coeff_v; in calc_tile_resize_coefficients()
1242 lockdep_assert_held(&ctx->chan->irqlock); in get_run_count()
1245 if (run->ctx == ctx) in get_run_count()
1254 struct ipu_image_convert_ctx *ctx = run->ctx; in convert_stop()
1255 struct ipu_image_convert_chan *chan = ctx->chan; in convert_stop()
1256 struct ipu_image_convert_priv *priv = chan->priv; in convert_stop()
1258 dev_dbg(priv->ipu->dev, "%s: task %u: stopping ctx %p run %p\n", in convert_stop()
1259 __func__, chan->ic_task, ctx, run); in convert_stop()
1262 ipu_ic_task_disable(chan->ic); in convert_stop()
1263 ipu_idmac_disable_channel(chan->in_chan); in convert_stop()
1264 ipu_idmac_disable_channel(chan->out_chan); in convert_stop()
1266 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in convert_stop()
1267 ipu_idmac_disable_channel(chan->rotation_in_chan); in convert_stop()
1268 ipu_idmac_disable_channel(chan->rotation_out_chan); in convert_stop()
1269 ipu_idmac_unlink(chan->out_chan, chan->rotation_in_chan); in convert_stop()
1272 ipu_ic_disable(chan->ic); in convert_stop()
1282 struct ipu_image_convert_chan *chan = ctx->chan; in init_idmac_channel()
1289 if (image->type == IMAGE_CONVERT_OUT) { in init_idmac_channel()
1290 tile_idx[0] = ctx->out_tile_map[tile]; in init_idmac_channel()
1291 tile_idx[1] = ctx->out_tile_map[1]; in init_idmac_channel()
1298 width = image->tile[tile_idx[0]].height; in init_idmac_channel()
1299 height = image->tile[tile_idx[0]].width; in init_idmac_channel()
1300 stride = image->tile[tile_idx[0]].rot_stride; in init_idmac_channel()
1301 addr0 = ctx->rot_intermediate[0].phys; in init_idmac_channel()
1302 if (ctx->double_buffering) in init_idmac_channel()
1303 addr1 = ctx->rot_intermediate[1].phys; in init_idmac_channel()
1305 width = image->tile[tile_idx[0]].width; in init_idmac_channel()
1306 height = image->tile[tile_idx[0]].height; in init_idmac_channel()
1307 stride = image->stride; in init_idmac_channel()
1308 addr0 = image->base.phys0 + in init_idmac_channel()
1309 image->tile[tile_idx[0]].offset; in init_idmac_channel()
1310 if (ctx->double_buffering) in init_idmac_channel()
1311 addr1 = image->base.phys0 + in init_idmac_channel()
1312 image->tile[tile_idx[1]].offset; in init_idmac_channel()
1321 tile_image.pix.pixelformat = image->fmt->fourcc; in init_idmac_channel()
1324 if (image->fmt->planar && !rot_swap_width_height) { in init_idmac_channel()
1325 tile_image.u_offset = image->tile[tile_idx[0]].u_off; in init_idmac_channel()
1326 tile_image.v_offset = image->tile[tile_idx[0]].v_off; in init_idmac_channel()
1338 if ((channel == chan->out_chan || in init_idmac_channel()
1339 channel == chan->rotation_out_chan) && in init_idmac_channel()
1340 image->fmt->planar && image->fmt->uv_height_dec == 2) in init_idmac_channel()
1343 if (channel == chan->rotation_in_chan || in init_idmac_channel()
1344 channel == chan->rotation_out_chan) { in init_idmac_channel()
1352 ipu_ic_task_idma_init(chan->ic, channel, width, height, in init_idmac_channel()
1356 * Setting a non-zero AXI ID collides with the PRG AXI snooping, so in init_idmac_channel()
1359 if (!channel->ipu->prg_priv) in init_idmac_channel()
1362 ipu_idmac_set_double_buffer(channel, ctx->double_buffering); in init_idmac_channel()
1367 struct ipu_image_convert_ctx *ctx = run->ctx; in convert_start()
1368 struct ipu_image_convert_chan *chan = ctx->chan; in convert_start()
1369 struct ipu_image_convert_priv *priv = chan->priv; in convert_start()
1370 struct ipu_image_convert_image *s_image = &ctx->in; in convert_start()
1371 struct ipu_image_convert_image *d_image = &ctx->out; in convert_start()
1372 unsigned int dst_tile = ctx->out_tile_map[tile]; in convert_start()
1378 dev_dbg(priv->ipu->dev, "%s: task %u: starting ctx %p run %p tile %u -> %u\n", in convert_start()
1379 __func__, chan->ic_task, ctx, run, tile, dst_tile); in convert_start()
1382 ctx->eof_mask = 0; in convert_start()
1384 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in convert_start()
1386 dest_width = d_image->tile[dst_tile].height; in convert_start()
1387 dest_height = d_image->tile[dst_tile].width; in convert_start()
1389 dest_width = d_image->tile[dst_tile].width; in convert_start()
1390 dest_height = d_image->tile[dst_tile].height; in convert_start()
1393 row = tile / s_image->num_cols; in convert_start()
1394 col = tile % s_image->num_cols; in convert_start()
1396 rsc = (ctx->downsize_coeff_v << 30) | in convert_start()
1397 (ctx->resize_coeffs_v[row] << 16) | in convert_start()
1398 (ctx->downsize_coeff_h << 14) | in convert_start()
1399 (ctx->resize_coeffs_h[col]); in convert_start()
1401 dev_dbg(priv->ipu->dev, "%s: %ux%u -> %ux%u (rsc = 0x%x)\n", in convert_start()
1402 __func__, s_image->tile[tile].width, in convert_start()
1403 s_image->tile[tile].height, dest_width, dest_height, rsc); in convert_start()
1406 ret = ipu_ic_task_init_rsc(chan->ic, &ctx->csc, in convert_start()
1407 s_image->tile[tile].width, in convert_start()
1408 s_image->tile[tile].height, in convert_start()
1413 dev_err(priv->ipu->dev, "ipu_ic_task_init failed, %d\n", ret); in convert_start()
1417 /* init the source MEM-->IC PP IDMAC channel */ in convert_start()
1418 init_idmac_channel(ctx, chan->in_chan, s_image, in convert_start()
1421 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in convert_start()
1422 /* init the IC PP-->MEM IDMAC channel */ in convert_start()
1423 init_idmac_channel(ctx, chan->out_chan, d_image, in convert_start()
1426 /* init the MEM-->IC PP ROT IDMAC channel */ in convert_start()
1427 init_idmac_channel(ctx, chan->rotation_in_chan, d_image, in convert_start()
1428 ctx->rot_mode, true, tile); in convert_start()
1430 /* init the destination IC PP ROT-->MEM IDMAC channel */ in convert_start()
1431 init_idmac_channel(ctx, chan->rotation_out_chan, d_image, in convert_start()
1434 /* now link IC PP-->MEM to MEM-->IC PP ROT */ in convert_start()
1435 ipu_idmac_link(chan->out_chan, chan->rotation_in_chan); in convert_start()
1437 /* init the destination IC PP-->MEM IDMAC channel */ in convert_start()
1438 init_idmac_channel(ctx, chan->out_chan, d_image, in convert_start()
1439 ctx->rot_mode, false, tile); in convert_start()
1443 ipu_ic_enable(chan->ic); in convert_start()
1446 ipu_idmac_select_buffer(chan->in_chan, 0); in convert_start()
1447 ipu_idmac_select_buffer(chan->out_chan, 0); in convert_start()
1448 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in convert_start()
1449 ipu_idmac_select_buffer(chan->rotation_out_chan, 0); in convert_start()
1450 if (ctx->double_buffering) { in convert_start()
1451 ipu_idmac_select_buffer(chan->in_chan, 1); in convert_start()
1452 ipu_idmac_select_buffer(chan->out_chan, 1); in convert_start()
1453 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in convert_start()
1454 ipu_idmac_select_buffer(chan->rotation_out_chan, 1); in convert_start()
1458 ipu_idmac_enable_channel(chan->in_chan); in convert_start()
1459 ipu_idmac_enable_channel(chan->out_chan); in convert_start()
1460 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in convert_start()
1461 ipu_idmac_enable_channel(chan->rotation_in_chan); in convert_start()
1462 ipu_idmac_enable_channel(chan->rotation_out_chan); in convert_start()
1465 ipu_ic_task_enable(chan->ic); in convert_start()
1467 ipu_cpmem_dump(chan->in_chan); in convert_start()
1468 ipu_cpmem_dump(chan->out_chan); in convert_start()
1469 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in convert_start()
1470 ipu_cpmem_dump(chan->rotation_in_chan); in convert_start()
1471 ipu_cpmem_dump(chan->rotation_out_chan); in convert_start()
1474 ipu_dump(priv->ipu); in convert_start()
1482 struct ipu_image_convert_ctx *ctx = run->ctx; in do_run()
1483 struct ipu_image_convert_chan *chan = ctx->chan; in do_run()
1485 lockdep_assert_held(&chan->irqlock); in do_run()
1487 ctx->in.base.phys0 = run->in_phys; in do_run()
1488 ctx->out.base.phys0 = run->out_phys; in do_run()
1490 ctx->cur_buf_num = 0; in do_run()
1491 ctx->next_tile = 1; in do_run()
1494 list_del(&run->list); in do_run()
1495 chan->current_run = run; in do_run()
1503 struct ipu_image_convert_priv *priv = chan->priv; in run_next()
1507 lockdep_assert_held(&chan->irqlock); in run_next()
1509 list_for_each_entry_safe(run, tmp, &chan->pending_q, list) { in run_next()
1511 if (run->ctx->aborting) { in run_next()
1512 dev_dbg(priv->ipu->dev, in run_next()
1514 __func__, chan->ic_task, run->ctx, run); in run_next()
1527 run->status = ret; in run_next()
1528 list_add_tail(&run->list, &chan->done_q); in run_next()
1529 chan->current_run = NULL; in run_next()
1535 struct ipu_image_convert_priv *priv = chan->priv; in empty_done_q()
1539 spin_lock_irqsave(&chan->irqlock, flags); in empty_done_q()
1541 while (!list_empty(&chan->done_q)) { in empty_done_q()
1542 run = list_entry(chan->done_q.next, in empty_done_q()
1546 list_del(&run->list); in empty_done_q()
1548 dev_dbg(priv->ipu->dev, in empty_done_q()
1550 __func__, chan->ic_task, run->ctx, run, run->status); in empty_done_q()
1553 spin_unlock_irqrestore(&chan->irqlock, flags); in empty_done_q()
1554 run->ctx->complete(run, run->ctx->complete_context); in empty_done_q()
1555 spin_lock_irqsave(&chan->irqlock, flags); in empty_done_q()
1558 spin_unlock_irqrestore(&chan->irqlock, flags); in empty_done_q()
1568 struct ipu_image_convert_priv *priv = chan->priv; in do_bh()
1572 dev_dbg(priv->ipu->dev, "%s: task %u: enter\n", __func__, in do_bh()
1573 chan->ic_task); in do_bh()
1577 spin_lock_irqsave(&chan->irqlock, flags); in do_bh()
1583 list_for_each_entry(ctx, &chan->ctx_list, list) { in do_bh()
1584 if (ctx->aborting) { in do_bh()
1585 dev_dbg(priv->ipu->dev, in do_bh()
1587 __func__, chan->ic_task, ctx); in do_bh()
1588 complete_all(&ctx->aborted); in do_bh()
1592 spin_unlock_irqrestore(&chan->irqlock, flags); in do_bh()
1594 dev_dbg(priv->ipu->dev, "%s: task %u: exit\n", __func__, in do_bh()
1595 chan->ic_task); in do_bh()
1602 unsigned int cur_tile = ctx->next_tile - 1; in ic_settings_changed()
1603 unsigned int next_tile = ctx->next_tile; in ic_settings_changed()
1605 if (ctx->resize_coeffs_h[cur_tile % ctx->in.num_cols] != in ic_settings_changed()
1606 ctx->resize_coeffs_h[next_tile % ctx->in.num_cols] || in ic_settings_changed()
1607 ctx->resize_coeffs_v[cur_tile / ctx->in.num_cols] != in ic_settings_changed()
1608 ctx->resize_coeffs_v[next_tile / ctx->in.num_cols] || in ic_settings_changed()
1609 ctx->in.tile[cur_tile].width != ctx->in.tile[next_tile].width || in ic_settings_changed()
1610 ctx->in.tile[cur_tile].height != ctx->in.tile[next_tile].height || in ic_settings_changed()
1611 ctx->out.tile[cur_tile].width != ctx->out.tile[next_tile].width || in ic_settings_changed()
1612 ctx->out.tile[cur_tile].height != ctx->out.tile[next_tile].height) in ic_settings_changed()
1621 struct ipu_image_convert_ctx *ctx = run->ctx; in do_tile_complete()
1622 struct ipu_image_convert_chan *chan = ctx->chan; in do_tile_complete()
1624 struct ipu_image_convert_image *s_image = &ctx->in; in do_tile_complete()
1625 struct ipu_image_convert_image *d_image = &ctx->out; in do_tile_complete()
1629 lockdep_assert_held(&chan->irqlock); in do_tile_complete()
1631 outch = ipu_rot_mode_is_irt(ctx->rot_mode) ? in do_tile_complete()
1632 chan->rotation_out_chan : chan->out_chan; in do_tile_complete()
1636 * enter the paused state. Without double-buffering the channels in do_tile_complete()
1638 * is safe to stop the channels now. For double-buffering we in do_tile_complete()
1642 if (ctx->aborting && !ctx->double_buffering) { in do_tile_complete()
1644 run->status = -EIO; in do_tile_complete()
1648 if (ctx->next_tile == ctx->num_tiles) { in do_tile_complete()
1653 run->status = 0; in do_tile_complete()
1660 if (!ctx->double_buffering) { in do_tile_complete()
1663 convert_start(run, ctx->next_tile); in do_tile_complete()
1665 src_tile = &s_image->tile[ctx->next_tile]; in do_tile_complete()
1666 dst_idx = ctx->out_tile_map[ctx->next_tile]; in do_tile_complete()
1667 dst_tile = &d_image->tile[dst_idx]; in do_tile_complete()
1669 ipu_cpmem_set_buffer(chan->in_chan, 0, in do_tile_complete()
1670 s_image->base.phys0 + in do_tile_complete()
1671 src_tile->offset); in do_tile_complete()
1673 d_image->base.phys0 + in do_tile_complete()
1674 dst_tile->offset); in do_tile_complete()
1675 if (s_image->fmt->planar) in do_tile_complete()
1676 ipu_cpmem_set_uv_offset(chan->in_chan, in do_tile_complete()
1677 src_tile->u_off, in do_tile_complete()
1678 src_tile->v_off); in do_tile_complete()
1679 if (d_image->fmt->planar) in do_tile_complete()
1681 dst_tile->u_off, in do_tile_complete()
1682 dst_tile->v_off); in do_tile_complete()
1684 ipu_idmac_select_buffer(chan->in_chan, 0); in do_tile_complete()
1687 } else if (ctx->next_tile < ctx->num_tiles - 1) { in do_tile_complete()
1689 src_tile = &s_image->tile[ctx->next_tile + 1]; in do_tile_complete()
1690 dst_idx = ctx->out_tile_map[ctx->next_tile + 1]; in do_tile_complete()
1691 dst_tile = &d_image->tile[dst_idx]; in do_tile_complete()
1693 ipu_cpmem_set_buffer(chan->in_chan, ctx->cur_buf_num, in do_tile_complete()
1694 s_image->base.phys0 + src_tile->offset); in do_tile_complete()
1695 ipu_cpmem_set_buffer(outch, ctx->cur_buf_num, in do_tile_complete()
1696 d_image->base.phys0 + dst_tile->offset); in do_tile_complete()
1698 ipu_idmac_select_buffer(chan->in_chan, ctx->cur_buf_num); in do_tile_complete()
1699 ipu_idmac_select_buffer(outch, ctx->cur_buf_num); in do_tile_complete()
1701 ctx->cur_buf_num ^= 1; in do_tile_complete()
1704 ctx->eof_mask = 0; /* clear EOF irq mask for next tile */ in do_tile_complete()
1705 ctx->next_tile++; in do_tile_complete()
1708 list_add_tail(&run->list, &chan->done_q); in do_tile_complete()
1709 chan->current_run = NULL; in do_tile_complete()
1717 struct ipu_image_convert_priv *priv = chan->priv; in eof_irq()
1724 spin_lock_irqsave(&chan->irqlock, flags); in eof_irq()
1727 run = chan->current_run; in eof_irq()
1733 ctx = run->ctx; in eof_irq()
1735 if (irq == chan->in_eof_irq) { in eof_irq()
1736 ctx->eof_mask |= EOF_IRQ_IN; in eof_irq()
1737 } else if (irq == chan->out_eof_irq) { in eof_irq()
1738 ctx->eof_mask |= EOF_IRQ_OUT; in eof_irq()
1739 } else if (irq == chan->rot_in_eof_irq || in eof_irq()
1740 irq == chan->rot_out_eof_irq) { in eof_irq()
1741 if (!ipu_rot_mode_is_irt(ctx->rot_mode)) { in eof_irq()
1743 dev_err(priv->ipu->dev, in eof_irq()
1747 ctx->eof_mask |= (irq == chan->rot_in_eof_irq) ? in eof_irq()
1750 dev_err(priv->ipu->dev, "Received unknown irq %d\n", irq); in eof_irq()
1755 if (ipu_rot_mode_is_irt(ctx->rot_mode)) in eof_irq()
1756 tile_complete = (ctx->eof_mask == EOF_IRQ_ROT_COMPLETE); in eof_irq()
1758 tile_complete = (ctx->eof_mask == EOF_IRQ_COMPLETE); in eof_irq()
1763 spin_unlock_irqrestore(&chan->irqlock, flags); in eof_irq()
1773 struct ipu_image_convert_chan *chan = ctx->chan; in force_abort()
1777 spin_lock_irqsave(&chan->irqlock, flags); in force_abort()
1779 run = chan->current_run; in force_abort()
1780 if (run && run->ctx == ctx) { in force_abort()
1782 run->status = -EIO; in force_abort()
1783 list_add_tail(&run->list, &chan->done_q); in force_abort()
1784 chan->current_run = NULL; in force_abort()
1788 spin_unlock_irqrestore(&chan->irqlock, flags); in force_abort()
1795 if (chan->in_eof_irq >= 0) in release_ipu_resources()
1796 free_irq(chan->in_eof_irq, chan); in release_ipu_resources()
1797 if (chan->rot_in_eof_irq >= 0) in release_ipu_resources()
1798 free_irq(chan->rot_in_eof_irq, chan); in release_ipu_resources()
1799 if (chan->out_eof_irq >= 0) in release_ipu_resources()
1800 free_irq(chan->out_eof_irq, chan); in release_ipu_resources()
1801 if (chan->rot_out_eof_irq >= 0) in release_ipu_resources()
1802 free_irq(chan->rot_out_eof_irq, chan); in release_ipu_resources()
1804 if (!IS_ERR_OR_NULL(chan->in_chan)) in release_ipu_resources()
1805 ipu_idmac_put(chan->in_chan); in release_ipu_resources()
1806 if (!IS_ERR_OR_NULL(chan->out_chan)) in release_ipu_resources()
1807 ipu_idmac_put(chan->out_chan); in release_ipu_resources()
1808 if (!IS_ERR_OR_NULL(chan->rotation_in_chan)) in release_ipu_resources()
1809 ipu_idmac_put(chan->rotation_in_chan); in release_ipu_resources()
1810 if (!IS_ERR_OR_NULL(chan->rotation_out_chan)) in release_ipu_resources()
1811 ipu_idmac_put(chan->rotation_out_chan); in release_ipu_resources()
1812 if (!IS_ERR_OR_NULL(chan->ic)) in release_ipu_resources()
1813 ipu_ic_put(chan->ic); in release_ipu_resources()
1815 chan->in_chan = chan->out_chan = chan->rotation_in_chan = in release_ipu_resources()
1816 chan->rotation_out_chan = NULL; in release_ipu_resources()
1817 chan->in_eof_irq = -1; in release_ipu_resources()
1818 chan->rot_in_eof_irq = -1; in release_ipu_resources()
1819 chan->out_eof_irq = -1; in release_ipu_resources()
1820 chan->rot_out_eof_irq = -1; in release_ipu_resources()
1826 struct ipu_image_convert_priv *priv = chan->priv; in get_eof_irq()
1829 irq = ipu_idmac_channel_irq(priv->ipu, channel, IPU_IRQ_EOF); in get_eof_irq()
1831 ret = request_threaded_irq(irq, eof_irq, do_bh, 0, "ipu-ic", chan); in get_eof_irq()
1833 dev_err(priv->ipu->dev, "could not acquire irq %d\n", irq); in get_eof_irq()
1842 const struct ipu_image_convert_dma_chan *dma = chan->dma_ch; in get_ipu_resources()
1843 struct ipu_image_convert_priv *priv = chan->priv; in get_ipu_resources()
1847 chan->ic = ipu_ic_get(priv->ipu, chan->ic_task); in get_ipu_resources()
1848 if (IS_ERR(chan->ic)) { in get_ipu_resources()
1849 dev_err(priv->ipu->dev, "could not acquire IC\n"); in get_ipu_resources()
1850 ret = PTR_ERR(chan->ic); in get_ipu_resources()
1855 chan->in_chan = ipu_idmac_get(priv->ipu, dma->in); in get_ipu_resources()
1856 chan->out_chan = ipu_idmac_get(priv->ipu, dma->out); in get_ipu_resources()
1857 if (IS_ERR(chan->in_chan) || IS_ERR(chan->out_chan)) { in get_ipu_resources()
1858 dev_err(priv->ipu->dev, "could not acquire idmac channels\n"); in get_ipu_resources()
1859 ret = -EBUSY; in get_ipu_resources()
1863 chan->rotation_in_chan = ipu_idmac_get(priv->ipu, dma->rot_in); in get_ipu_resources()
1864 chan->rotation_out_chan = ipu_idmac_get(priv->ipu, dma->rot_out); in get_ipu_resources()
1865 if (IS_ERR(chan->rotation_in_chan) || IS_ERR(chan->rotation_out_chan)) { in get_ipu_resources()
1866 dev_err(priv->ipu->dev, in get_ipu_resources()
1868 ret = -EBUSY; in get_ipu_resources()
1873 ret = get_eof_irq(chan, chan->in_chan); in get_ipu_resources()
1875 chan->in_eof_irq = -1; in get_ipu_resources()
1878 chan->in_eof_irq = ret; in get_ipu_resources()
1880 ret = get_eof_irq(chan, chan->rotation_in_chan); in get_ipu_resources()
1882 chan->rot_in_eof_irq = -1; in get_ipu_resources()
1885 chan->rot_in_eof_irq = ret; in get_ipu_resources()
1887 ret = get_eof_irq(chan, chan->out_chan); in get_ipu_resources()
1889 chan->out_eof_irq = -1; in get_ipu_resources()
1892 chan->out_eof_irq = ret; in get_ipu_resources()
1894 ret = get_eof_irq(chan, chan->rotation_out_chan); in get_ipu_resources()
1896 chan->rot_out_eof_irq = -1; in get_ipu_resources()
1899 chan->rot_out_eof_irq = ret; in get_ipu_resources()
1912 struct ipu_image_convert_priv *priv = ctx->chan->priv; in fill_image()
1914 ic_image->base = *image; in fill_image()
1915 ic_image->type = type; in fill_image()
1917 ic_image->fmt = get_format(image->pix.pixelformat); in fill_image()
1918 if (!ic_image->fmt) { in fill_image()
1919 dev_err(priv->ipu->dev, "pixelformat not supported for %s\n", in fill_image()
1921 return -EINVAL; in fill_image()
1924 if (ic_image->fmt->planar) in fill_image()
1925 ic_image->stride = ic_image->base.pix.width; in fill_image()
1927 ic_image->stride = ic_image->base.pix.bytesperline; in fill_image()
1932 /* borrowed from drivers/media/v4l2-core/v4l2-common.c */
1937 unsigned int mask = ~((1 << align) - 1); in clamp_align()
1944 x = (x + (1 << (align - 1))) & mask; in clamp_align()
1957 infmt = get_format(in->pix.pixelformat); in ipu_image_convert_adjust()
1958 outfmt = get_format(out->pix.pixelformat); in ipu_image_convert_adjust()
1962 in->pix.pixelformat = V4L2_PIX_FMT_RGB24; in ipu_image_convert_adjust()
1966 out->pix.pixelformat = V4L2_PIX_FMT_RGB24; in ipu_image_convert_adjust()
1971 in->pix.field = out->pix.field = V4L2_FIELD_NONE; in ipu_image_convert_adjust()
1975 out->pix.height = max_t(__u32, out->pix.height, in ipu_image_convert_adjust()
1976 in->pix.width / 4); in ipu_image_convert_adjust()
1977 out->pix.width = max_t(__u32, out->pix.width, in ipu_image_convert_adjust()
1978 in->pix.height / 4); in ipu_image_convert_adjust()
1980 out->pix.width = max_t(__u32, out->pix.width, in ipu_image_convert_adjust()
1981 in->pix.width / 4); in ipu_image_convert_adjust()
1982 out->pix.height = max_t(__u32, out->pix.height, in ipu_image_convert_adjust()
1983 in->pix.height / 4); in ipu_image_convert_adjust()
1991 in->pix.width = clamp_align(in->pix.width, MIN_W, MAX_W, in ipu_image_convert_adjust()
1993 in->pix.height = clamp_align(in->pix.height, MIN_H, MAX_H, in ipu_image_convert_adjust()
2001 out->pix.width = clamp_align(out->pix.width, MIN_W, MAX_W, in ipu_image_convert_adjust()
2003 out->pix.height = clamp_align(out->pix.height, MIN_H, MAX_H, in ipu_image_convert_adjust()
2007 in->pix.bytesperline = infmt->planar ? in ipu_image_convert_adjust()
2008 clamp_align(in->pix.width, 2 << w_align_in, MAX_W, in ipu_image_convert_adjust()
2010 clamp_align((in->pix.width * infmt->bpp) >> 3, in ipu_image_convert_adjust()
2011 ((2 << w_align_in) * infmt->bpp) >> 3, in ipu_image_convert_adjust()
2012 (MAX_W * infmt->bpp) >> 3, in ipu_image_convert_adjust()
2014 in->pix.sizeimage = infmt->planar ? in ipu_image_convert_adjust()
2015 (in->pix.height * in->pix.bytesperline * infmt->bpp) >> 3 : in ipu_image_convert_adjust()
2016 in->pix.height * in->pix.bytesperline; in ipu_image_convert_adjust()
2017 out->pix.bytesperline = outfmt->planar ? out->pix.width : in ipu_image_convert_adjust()
2018 (out->pix.width * outfmt->bpp) >> 3; in ipu_image_convert_adjust()
2019 out->pix.sizeimage = outfmt->planar ? in ipu_image_convert_adjust()
2020 (out->pix.height * out->pix.bytesperline * outfmt->bpp) >> 3 : in ipu_image_convert_adjust()
2021 out->pix.height * out->pix.bytesperline; in ipu_image_convert_adjust()
2040 if (testin.pix.width != in->pix.width || in ipu_image_convert_verify()
2041 testin.pix.height != in->pix.height || in ipu_image_convert_verify()
2042 testout.pix.width != out->pix.width || in ipu_image_convert_verify()
2043 testout.pix.height != out->pix.height) in ipu_image_convert_verify()
2044 return -EINVAL; in ipu_image_convert_verify()
2061 struct ipu_image_convert_priv *priv = ipu->image_convert_priv; in ipu_image_convert_prepare()
2073 return ERR_PTR(-EINVAL); in ipu_image_convert_prepare()
2078 dev_err(priv->ipu->dev, "%s: in/out formats invalid\n", in ipu_image_convert_prepare()
2083 chan = &priv->chan[ic_task]; in ipu_image_convert_prepare()
2087 return ERR_PTR(-ENOMEM); in ipu_image_convert_prepare()
2089 dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p\n", __func__, in ipu_image_convert_prepare()
2090 chan->ic_task, ctx); in ipu_image_convert_prepare()
2092 ctx->chan = chan; in ipu_image_convert_prepare()
2093 init_completion(&ctx->aborted); in ipu_image_convert_prepare()
2095 ctx->rot_mode = rot_mode; in ipu_image_convert_prepare()
2097 /* Sets ctx->in.num_rows/cols as well */ in ipu_image_convert_prepare()
2102 s_image = &ctx->in; in ipu_image_convert_prepare()
2103 d_image = &ctx->out; in ipu_image_convert_prepare()
2107 d_image->num_rows = s_image->num_cols; in ipu_image_convert_prepare()
2108 d_image->num_cols = s_image->num_rows; in ipu_image_convert_prepare()
2110 d_image->num_rows = s_image->num_rows; in ipu_image_convert_prepare()
2111 d_image->num_cols = s_image->num_cols; in ipu_image_convert_prepare()
2114 ctx->num_tiles = d_image->num_cols * d_image->num_rows; in ipu_image_convert_prepare()
2142 ret = ipu_ic_calc_csc(&ctx->csc, in ipu_image_convert_prepare()
2143 s_image->base.pix.ycbcr_enc, in ipu_image_convert_prepare()
2144 s_image->base.pix.quantization, in ipu_image_convert_prepare()
2145 ipu_pixelformat_to_colorspace(s_image->fmt->fourcc), in ipu_image_convert_prepare()
2146 d_image->base.pix.ycbcr_enc, in ipu_image_convert_prepare()
2147 d_image->base.pix.quantization, in ipu_image_convert_prepare()
2148 ipu_pixelformat_to_colorspace(d_image->fmt->fourcc)); in ipu_image_convert_prepare()
2155 ctx->complete = complete; in ipu_image_convert_prepare()
2156 ctx->complete_context = complete_context; in ipu_image_convert_prepare()
2159 * Can we use double-buffering for this operation? If there is in ipu_image_convert_prepare()
2161 * operation) there's no point in using double-buffering. Also, in ipu_image_convert_prepare()
2165 * each buffer which is not possible. So double-buffering is in ipu_image_convert_prepare()
2169 * prevent double-buffering as well. in ipu_image_convert_prepare()
2171 ctx->double_buffering = (ctx->num_tiles > 1 && in ipu_image_convert_prepare()
2172 !s_image->fmt->planar && in ipu_image_convert_prepare()
2173 !d_image->fmt->planar); in ipu_image_convert_prepare()
2174 for (i = 1; i < ctx->num_tiles; i++) { in ipu_image_convert_prepare()
2175 if (ctx->in.tile[i].width != ctx->in.tile[0].width || in ipu_image_convert_prepare()
2176 ctx->in.tile[i].height != ctx->in.tile[0].height || in ipu_image_convert_prepare()
2177 ctx->out.tile[i].width != ctx->out.tile[0].width || in ipu_image_convert_prepare()
2178 ctx->out.tile[i].height != ctx->out.tile[0].height) { in ipu_image_convert_prepare()
2179 ctx->double_buffering = false; in ipu_image_convert_prepare()
2183 for (i = 1; i < ctx->in.num_cols; i++) { in ipu_image_convert_prepare()
2184 if (ctx->resize_coeffs_h[i] != ctx->resize_coeffs_h[0]) { in ipu_image_convert_prepare()
2185 ctx->double_buffering = false; in ipu_image_convert_prepare()
2189 for (i = 1; i < ctx->in.num_rows; i++) { in ipu_image_convert_prepare()
2190 if (ctx->resize_coeffs_v[i] != ctx->resize_coeffs_v[0]) { in ipu_image_convert_prepare()
2191 ctx->double_buffering = false; in ipu_image_convert_prepare()
2196 if (ipu_rot_mode_is_irt(ctx->rot_mode)) { in ipu_image_convert_prepare()
2197 unsigned long intermediate_size = d_image->tile[0].size; in ipu_image_convert_prepare()
2199 for (i = 1; i < ctx->num_tiles; i++) { in ipu_image_convert_prepare()
2200 if (d_image->tile[i].size > intermediate_size) in ipu_image_convert_prepare()
2201 intermediate_size = d_image->tile[i].size; in ipu_image_convert_prepare()
2204 ret = alloc_dma_buf(priv, &ctx->rot_intermediate[0], in ipu_image_convert_prepare()
2208 if (ctx->double_buffering) { in ipu_image_convert_prepare()
2210 &ctx->rot_intermediate[1], in ipu_image_convert_prepare()
2217 spin_lock_irqsave(&chan->irqlock, flags); in ipu_image_convert_prepare()
2219 get_res = list_empty(&chan->ctx_list); in ipu_image_convert_prepare()
2221 list_add_tail(&ctx->list, &chan->ctx_list); in ipu_image_convert_prepare()
2223 spin_unlock_irqrestore(&chan->irqlock, flags); in ipu_image_convert_prepare()
2234 free_dma_buf(priv, &ctx->rot_intermediate[1]); in ipu_image_convert_prepare()
2235 spin_lock_irqsave(&chan->irqlock, flags); in ipu_image_convert_prepare()
2236 list_del(&ctx->list); in ipu_image_convert_prepare()
2237 spin_unlock_irqrestore(&chan->irqlock, flags); in ipu_image_convert_prepare()
2239 free_dma_buf(priv, &ctx->rot_intermediate[0]); in ipu_image_convert_prepare()
2259 if (!run || !run->ctx || !run->in_phys || !run->out_phys) in ipu_image_convert_queue()
2260 return -EINVAL; in ipu_image_convert_queue()
2262 ctx = run->ctx; in ipu_image_convert_queue()
2263 chan = ctx->chan; in ipu_image_convert_queue()
2264 priv = chan->priv; in ipu_image_convert_queue()
2266 dev_dbg(priv->ipu->dev, "%s: task %u: ctx %p run %p\n", __func__, in ipu_image_convert_queue()
2267 chan->ic_task, ctx, run); in ipu_image_convert_queue()
2269 INIT_LIST_HEAD(&run->list); in ipu_image_convert_queue()
2271 spin_lock_irqsave(&chan->irqlock, flags); in ipu_image_convert_queue()
2273 if (ctx->aborting) { in ipu_image_convert_queue()
2274 ret = -EIO; in ipu_image_convert_queue()
2278 list_add_tail(&run->list, &chan->pending_q); in ipu_image_convert_queue()
2280 if (!chan->current_run) { in ipu_image_convert_queue()
2283 chan->current_run = NULL; in ipu_image_convert_queue()
2286 spin_unlock_irqrestore(&chan->irqlock, flags); in ipu_image_convert_queue()
2294 struct ipu_image_convert_chan *chan = ctx->chan; in __ipu_image_convert_abort()
2295 struct ipu_image_convert_priv *priv = chan->priv; in __ipu_image_convert_abort()
2300 spin_lock_irqsave(&chan->irqlock, flags); in __ipu_image_convert_abort()
2303 list_for_each_entry_safe(run, tmp, &chan->pending_q, list) { in __ipu_image_convert_abort()
2304 if (run->ctx != ctx) in __ipu_image_convert_abort()
2306 run->status = -EIO; in __ipu_image_convert_abort()
2307 list_move_tail(&run->list, &chan->done_q); in __ipu_image_convert_abort()
2310 run_count = get_run_count(ctx, &chan->done_q); in __ipu_image_convert_abort()
2311 active_run = (chan->current_run && chan->current_run->ctx == ctx) ? in __ipu_image_convert_abort()
2312 chan->current_run : NULL; in __ipu_image_convert_abort()
2315 reinit_completion(&ctx->aborted); in __ipu_image_convert_abort()
2317 ctx->aborting = true; in __ipu_image_convert_abort()
2319 spin_unlock_irqrestore(&chan->irqlock, flags); in __ipu_image_convert_abort()
2322 dev_dbg(priv->ipu->dev, in __ipu_image_convert_abort()
2324 __func__, chan->ic_task, ctx); in __ipu_image_convert_abort()
2333 dev_dbg(priv->ipu->dev, in __ipu_image_convert_abort()
2335 __func__, chan->ic_task, run_count); in __ipu_image_convert_abort()
2337 ret = wait_for_completion_timeout(&ctx->aborted, in __ipu_image_convert_abort()
2340 dev_warn(priv->ipu->dev, "%s: timeout\n", __func__); in __ipu_image_convert_abort()
2348 ctx->aborting = false; in ipu_image_convert_abort()
2355 struct ipu_image_convert_chan *chan = ctx->chan; in ipu_image_convert_unprepare()
2356 struct ipu_image_convert_priv *priv = chan->priv; in ipu_image_convert_unprepare()
2363 dev_dbg(priv->ipu->dev, "%s: task %u: removing ctx %p\n", __func__, in ipu_image_convert_unprepare()
2364 chan->ic_task, ctx); in ipu_image_convert_unprepare()
2366 spin_lock_irqsave(&chan->irqlock, flags); in ipu_image_convert_unprepare()
2368 list_del(&ctx->list); in ipu_image_convert_unprepare()
2370 put_res = list_empty(&chan->ctx_list); in ipu_image_convert_unprepare()
2372 spin_unlock_irqrestore(&chan->irqlock, flags); in ipu_image_convert_unprepare()
2377 free_dma_buf(priv, &ctx->rot_intermediate[1]); in ipu_image_convert_unprepare()
2378 free_dma_buf(priv, &ctx->rot_intermediate[0]); in ipu_image_convert_unprepare()
2408 return ERR_PTR(-ENOMEM); in ipu_image_convert()
2411 run->ctx = ctx; in ipu_image_convert()
2412 run->in_phys = in->phys0; in ipu_image_convert()
2413 run->out_phys = out->phys0; in ipu_image_convert()
2433 return -ENOMEM; in ipu_image_convert_init()
2435 ipu->image_convert_priv = priv; in ipu_image_convert_init()
2436 priv->ipu = ipu; in ipu_image_convert_init()
2439 struct ipu_image_convert_chan *chan = &priv->chan[i]; in ipu_image_convert_init()
2441 chan->ic_task = i; in ipu_image_convert_init()
2442 chan->priv = priv; in ipu_image_convert_init()
2443 chan->dma_ch = &image_convert_dma_chan[i]; in ipu_image_convert_init()
2444 chan->in_eof_irq = -1; in ipu_image_convert_init()
2445 chan->rot_in_eof_irq = -1; in ipu_image_convert_init()
2446 chan->out_eof_irq = -1; in ipu_image_convert_init()
2447 chan->rot_out_eof_irq = -1; in ipu_image_convert_init()
2449 spin_lock_init(&chan->irqlock); in ipu_image_convert_init()
2450 INIT_LIST_HEAD(&chan->ctx_list); in ipu_image_convert_init()
2451 INIT_LIST_HEAD(&chan->pending_q); in ipu_image_convert_init()
2452 INIT_LIST_HEAD(&chan->done_q); in ipu_image_convert_init()