Hi Xavier, On 30/07/2022 12:24, Xavier Roumegue wrote: > Add a V4L2 mem-to-mem driver for the Vivante DW100 Dewarp Processor IP > core found on i.MX8MP SoC. > > The processor core applies a programmable geometrical transformation on > input images to correct distorsion introduced by lenses. > The transformation function is exposed as a grid map with 16x16 pixel > macroblocks indexed using X, Y vertex coordinates. > > The dewarping map can be set from application through a dedicated v4l2 > control. If not set or invalid, the driver computes an identity map > prior to starting the processing engine. > > The driver supports scaling, cropping and pixel format conversion. > > Signed-off-by: Xavier Roumegue <xavier.roumegue@xxxxxxxxxxx> > Reviewed-by: Ezequiel Garcia <ezequiel@xxxxxxxxxxxxxxxxxxxx> > Reviewed-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> > --- > drivers/media/platform/nxp/Kconfig | 1 + > drivers/media/platform/nxp/Makefile | 1 + > drivers/media/platform/nxp/dw100/Kconfig | 17 + > drivers/media/platform/nxp/dw100/Makefile | 3 + > drivers/media/platform/nxp/dw100/dw100.c | 1712 +++++++++++++++++ > drivers/media/platform/nxp/dw100/dw100_regs.h | 117 ++ > 6 files changed, 1851 insertions(+) > create mode 100644 drivers/media/platform/nxp/dw100/Kconfig > create mode 100644 drivers/media/platform/nxp/dw100/Makefile > create mode 100644 drivers/media/platform/nxp/dw100/dw100.c > create mode 100644 drivers/media/platform/nxp/dw100/dw100_regs.h > <snip> > +/* > + * Initialize the dewarping map with an identity mapping. > + * > + * A 16 pixels cell size grid is mapped on the destination image. > + * The last cells width/height might be lesser than 16 if the destination image > + * width/height is not divisible by 16. This dewarping grid map specifies the > + * source image pixel location (x, y) on each grid intersection point. > + * Bilinear interpolation is used to compute inner cell points locations. > + * > + * The coordinates are saved in UQ12.4 fixed point format. > + */ > +static void dw100_ctrl_dewarping_map_init(const struct v4l2_ctrl *ctrl, > + u32 from_idx, u32 elems, > + union v4l2_ctrl_ptr ptr) > +{ > + struct dw100_ctx *ctx = > + container_of(ctrl->handler, struct dw100_ctx, hdl); > + > + u32 sw, sh, dw, dh, mw, mh, i, j; > + u16 qx, qy, qdx, qdy, qsh, qsw; > + u32 *map = ctrl->p_cur.p_u32; > + > + sw = ctx->q_data[DW100_QUEUE_SRC].pix_fmt.width; > + dw = ctx->q_data[DW100_QUEUE_DST].pix_fmt.width; > + sh = ctx->q_data[DW100_QUEUE_SRC].pix_fmt.height; > + dh = ctx->q_data[DW100_QUEUE_DST].pix_fmt.height; > + > + mw = dw100_get_n_vertices_from_length(dw); > + mh = dw100_get_n_vertices_from_length(dh); Note that ctrl->dims[] contains the array dimensions: use that rather than calculating from dw/dh since using dims[] is more robust. > + > + qsw = dw100_map_convert_to_uq12_4(sw); > + qsh = dw100_map_convert_to_uq12_4(sh); > + qdx = qsw / (mw - 1); > + qdy = qsh / (mh - 1); > + > + ctx->map_width = mw; > + ctx->map_height = mh; > + ctx->map_size = mh * mw * sizeof(u32); > + > + for (i = 0, qy = 0; i < mh; i++, qy += qdy) { This isn't correct: you actually start from 'from_idx', which is almost always 0, except if userspace only sets the first N elements of an array, in that case those N elements are copied to the control array and the remainder is initialized. I admit that it doesn't make much sense in this particular case, but you still need to take it into account. I also would rename i and j to y and x, that makes more sense here. > + if (qy > qsh) > + qy = qsh; > + for (j = 0, qx = 0; j < mw; j++, qx += qdx) { > + if (qx > qsw) > + qx = qsw; > + *map++ = dw100_map_format_coordinates(qx, qy); > + } > + } > + > + ctx->user_map_is_set = false; > +} Regards, Hans > + > +static const struct v4l2_ctrl_type_ops dw100_ctrl_type_ops = { > + .init = dw100_ctrl_dewarping_map_init, > + .validate = v4l2_ctrl_type_op_validate, > + .log = v4l2_ctrl_type_op_log, > + .equal = v4l2_ctrl_type_op_equal, > +}; > + > +static const struct v4l2_ctrl_config controls[] = { > + [DW100_CTRL_DEWARPING_MAP] = { > + .ops = &dw100_ctrl_ops, > + .type_ops = &dw100_ctrl_type_ops, > + .id = V4L2_CID_DW100_DEWARPING_16x16_VERTEX_MAP, > + .name = "Dewarping Vertex Map", > + .type = V4L2_CTRL_TYPE_U32, > + .min = 0x00000000, > + .max = 0xffffffff, > + .step = 1, > + .def = 0, > + .dims = { DW100_DEF_LUT_W, DW100_DEF_LUT_H }, > + }, > +}; Regards, Hans