/* * csi2_enum_mbus_code - Handle pixel format enumeration * @sd : pointer to v4l2 subdev structure * @fh : V4L2 subdev file handle * @code : pointer to v4l2_subdev_pad_mbus_code_enum structure * return -EINVAL or zero on success */ static int csi2_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_mbus_code_enum *code) { struct atomisp_mipi_csi2_device *csi2 = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *format; if (code->pad == CSI2_PAD_SINK) { if (code->index >= ARRAY_SIZE(csi2_input_fmts)) return -EINVAL; code->code = csi2_input_fmts[code->index]; } else { format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK, V4L2_SUBDEV_FORMAT_TRY); switch (code->index) { case 0: /* Passthrough sink pad code */ code->code = format->code; break; case 1: /* Uncompressed code */ code->code = isp_video_uncompressed_code(format->code); break; default: /* Fallthrough if above is false */ return -EINVAL; } } return 0; }
/* * csi2_get_format - Handle get format by pads subdev method * @sd : pointer to v4l2 subdev structure * @cfg: V4L2 subdev pad configuration * @fmt: pointer to v4l2 subdev format structure * return -EINVAL or zero on success */ static int csi2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *format; format = __csi2_get_format(csi2, cfg, fmt->pad, fmt->which); if (format == NULL) return -EINVAL; fmt->format = *format; return 0; }
/* * csi2_get_format - Handle get format by pads subdev method * @sd : pointer to v4l2 subdev structure * @fh : V4L2 subdev file handle * @pad: pad num * @fmt: pointer to v4l2 format structure * return -EINVAL or zero on sucess */ static int csi2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *fmt) { struct atomisp_mipi_csi2_device *csi2 = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *format; format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which); if (format == NULL) return -EINVAL; fmt->format = *format; return 0; }
/* * csi2_set_format - Handle set format by pads subdev method * @sd : pointer to v4l2 subdev structure * @cfg: V4L2 subdev pad configuration * @fmt: pointer to v4l2 subdev format structure * return -EINVAL or zero on success */ static int csi2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *fmt) { struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *format; format = __csi2_get_format(csi2, cfg, fmt->pad, fmt->which); if (format == NULL) return -EINVAL; csi2_try_format(csi2, cfg, fmt->pad, &fmt->format, fmt->which); *format = fmt->format; /* Propagate the format from sink to source */ if (fmt->pad == CSI2_PAD_SINK) { format = __csi2_get_format(csi2, cfg, CSI2_PAD_SOURCE, fmt->which); *format = fmt->format; csi2_try_format(csi2, cfg, CSI2_PAD_SOURCE, format, fmt->which); } return 0; }
static void csi2_try_format(struct atomisp_mipi_csi2_device *csi2, struct v4l2_subdev_fh *fh, unsigned int pad, struct v4l2_mbus_framefmt *fmt, enum v4l2_subdev_format_whence which) { enum v4l2_mbus_pixelcode pixelcode; struct v4l2_mbus_framefmt *format; unsigned int i; switch (pad) { case CSI2_PAD_SINK: /* Clamp the width and height to valid range (1-8191). */ for (i = 0; i < ARRAY_SIZE(csi2_input_fmts); i++) { if (fmt->code == csi2_input_fmts[i]) break; } /* If not found, use SGRBG10 as default */ if (i >= ARRAY_SIZE(csi2_input_fmts)) fmt->code = V4L2_MBUS_FMT_SBGGR10_1X10; fmt->width = clamp_t(u32, fmt->width, 1, 4608); fmt->height = clamp_t(u32, fmt->height, 1, 8191); break; case CSI2_PAD_SOURCE: /* Source format same as sink format, except for DPCM * compression. */ pixelcode = fmt->code; format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK, which); memcpy(fmt, format, sizeof(*fmt)); /* allow dpcm decompression */ if (isp_video_uncompressed_code(fmt->code) == pixelcode) fmt->code = pixelcode; break; default: break; } /* RGB, non-interlaced */ fmt->colorspace = V4L2_COLORSPACE_SRGB; fmt->field = V4L2_FIELD_NONE; }
static void csi2_try_format(struct isp_csi2_device *csi2, struct v4l2_subdev_pad_config *cfg, unsigned int pad, struct v4l2_mbus_framefmt *fmt, enum v4l2_subdev_format_whence which) { u32 pixelcode; struct v4l2_mbus_framefmt *format; const struct isp_format_info *info; unsigned int i; switch (pad) { case CSI2_PAD_SINK: /* Clamp the width and height to valid range (1-8191). */ for (i = 0; i < ARRAY_SIZE(csi2_input_fmts); i++) { if (fmt->code == csi2_input_fmts[i]) break; } /* If not found, use SGRBG10 as default */ if (i >= ARRAY_SIZE(csi2_input_fmts)) fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; fmt->width = clamp_t(u32, fmt->width, 1, 8191); fmt->height = clamp_t(u32, fmt->height, 1, 8191); break; case CSI2_PAD_SOURCE: /* Source format same as sink format, except for DPCM * compression. */ pixelcode = fmt->code; format = __csi2_get_format(csi2, cfg, CSI2_PAD_SINK, which); memcpy(fmt, format, sizeof(*fmt)); /* * Only Allow DPCM decompression, and check that the * pattern is preserved */ info = omap3isp_video_format_info(fmt->code); if (info->uncompressed == pixelcode) fmt->code = pixelcode; break; } /* RGB, non-interlaced */ fmt->colorspace = V4L2_COLORSPACE_SRGB; fmt->field = V4L2_FIELD_NONE; }
/* * csi2_enum_mbus_code - Handle pixel format enumeration * @sd : pointer to v4l2 subdev structure * @cfg: V4L2 subdev pad configuration * @code : pointer to v4l2_subdev_mbus_code_enum structure * return -EINVAL or zero on success */ static int csi2_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code) { struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *format; const struct isp_format_info *info; if (code->pad == CSI2_PAD_SINK) { if (code->index >= ARRAY_SIZE(csi2_input_fmts)) return -EINVAL; code->code = csi2_input_fmts[code->index]; } else { format = __csi2_get_format(csi2, cfg, CSI2_PAD_SINK, V4L2_SUBDEV_FORMAT_TRY); switch (code->index) { case 0: /* Passthrough sink pad code */ code->code = format->code; break; case 1: /* Uncompressed code */ info = omap3isp_video_format_info(format->code); if (info->uncompressed == format->code) return -EINVAL; code->code = info->uncompressed; break; default: return -EINVAL; } } return 0; }