static void csi2_try_format(struct iss_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; const struct iss_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 = V4L2_MBUS_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, fh, CSI2_PAD_SINK, which); memcpy(fmt, format, sizeof(*fmt)); /* * Only Allow DPCM decompression, and check that the * pattern is preserved */ info = omap4iss_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; }
int omap4iss_get_external_info(struct iss_pipeline *pipe, struct media_link *link) { struct iss_device *iss = container_of(pipe, struct iss_video, pipe)->iss; struct v4l2_subdev_format fmt; struct v4l2_ctrl *ctrl; int ret; if (!pipe->external) return 0; if (pipe->external_rate) return 0; memset(&fmt, 0, sizeof(fmt)); fmt.pad = link->source->index; fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; ret = v4l2_subdev_call(media_entity_to_v4l2_subdev(link->sink->entity), pad, get_fmt, NULL, &fmt); if (ret < 0) return -EPIPE; pipe->external_bpp = omap4iss_video_format_info(fmt.format.code)->bpp; ctrl = v4l2_ctrl_find(pipe->external->ctrl_handler, V4L2_CID_PIXEL_RATE); if (!ctrl) { dev_warn(iss->dev, "no pixel rate control in subdev %s\n", pipe->external->name); return -EPIPE; } pipe->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl); return 0; }
/* * csi2_enum_mbus_code - Handle pixel format enumeration * @sd : pointer to v4l2 subdev structure * @fh : V4L2 subdev file handle * @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_fh *fh, struct v4l2_subdev_mbus_code_enum *code) { struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *format; const struct iss_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, 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 */ info = omap4iss_video_format_info(format->code); if (info->uncompressed == format->code) return -EINVAL; code->code = info->uncompressed; break; default: return -EINVAL; } } return 0; }
static void ipipeif_configure(struct iss_ipipeif_device *ipipeif) { struct iss_device *iss = to_iss_device(ipipeif); const struct iss_format_info *info; struct v4l2_mbus_framefmt *format; u32 isif_ccolp = 0; omap4iss_configure_bridge(iss, ipipeif->input); /* IPIPEIF_PAD_SINK */ format = &ipipeif->formats[IPIPEIF_PAD_SINK]; /* IPIPEIF with YUV422 input from ISIF */ iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_IPIPEIF, IPIPEIF_CFG1, IPIPEIF_CFG1_INPSRC1_MASK | IPIPEIF_CFG1_INPSRC2_MASK); /* Select ISIF/IPIPEIF input format */ switch (format->code) { case V4L2_MBUS_FMT_UYVY8_1X16: case V4L2_MBUS_FMT_YUYV8_1X16: iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_MODESET, ISIF_MODESET_CCDMD | ISIF_MODESET_INPMOD_MASK | ISIF_MODESET_CCDW_MASK, ISIF_MODESET_INPMOD_YCBCR16); iss_reg_update(iss, OMAP4_ISS_MEM_ISP_IPIPEIF, IPIPEIF_CFG2, IPIPEIF_CFG2_YUV8, IPIPEIF_CFG2_YUV16); break; case V4L2_MBUS_FMT_SGRBG10_1X10: isif_ccolp = ISIF_CCOLP_CP0_F0_GR | ISIF_CCOLP_CP1_F0_R | ISIF_CCOLP_CP2_F0_B | ISIF_CCOLP_CP3_F0_GB; goto cont_raw; case V4L2_MBUS_FMT_SRGGB10_1X10: isif_ccolp = ISIF_CCOLP_CP0_F0_R | ISIF_CCOLP_CP1_F0_GR | ISIF_CCOLP_CP2_F0_GB | ISIF_CCOLP_CP3_F0_B; goto cont_raw; case V4L2_MBUS_FMT_SBGGR10_1X10: isif_ccolp = ISIF_CCOLP_CP0_F0_B | ISIF_CCOLP_CP1_F0_GB | ISIF_CCOLP_CP2_F0_GR | ISIF_CCOLP_CP3_F0_R; goto cont_raw; case V4L2_MBUS_FMT_SGBRG10_1X10: isif_ccolp = ISIF_CCOLP_CP0_F0_GB | ISIF_CCOLP_CP1_F0_B | ISIF_CCOLP_CP2_F0_R | ISIF_CCOLP_CP3_F0_GR; cont_raw: iss_reg_clr(iss, OMAP4_ISS_MEM_ISP_IPIPEIF, IPIPEIF_CFG2, IPIPEIF_CFG2_YUV16); iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_MODESET, ISIF_MODESET_CCDMD | ISIF_MODESET_INPMOD_MASK | ISIF_MODESET_CCDW_MASK, ISIF_MODESET_INPMOD_RAW | ISIF_MODESET_CCDW_2BIT); info = omap4iss_video_format_info(format->code); iss_reg_update(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_CGAMMAWD, ISIF_CGAMMAWD_GWDI_MASK, ISIF_CGAMMAWD_GWDI(info->bpp)); /* Set RAW Bayer pattern */ iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_CCOLP, isif_ccolp); break; } iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_SPH, 0 & ISIF_SPH_MASK); iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_LNH, (format->width - 1) & ISIF_LNH_MASK); iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_LNV, (format->height - 1) & ISIF_LNV_MASK); /* Generate ISIF0 on the last line of the image */ iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_VDINT(0), format->height - 1); /* IPIPEIF_PAD_SOURCE_ISIF_SF */ format = &ipipeif->formats[IPIPEIF_PAD_SOURCE_ISIF_SF]; iss_reg_write(iss, OMAP4_ISS_MEM_ISP_ISIF, ISIF_HSIZE, (ipipeif->video_out.bpl_value >> 5) & ISIF_HSIZE_HSIZE_MASK); /* IPIPEIF_PAD_SOURCE_VP */ /* Do nothing? */ }