From 6310474d2fdc91dc2aac87e25ef17fc682a3c94d Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 16 Apr 2012 22:42:06 +0200 Subject: omap3isp: Support the CCDC lane shifter Signed-off-by: Laurent Pinchart --- isp/omap3isp.c | 149 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 103 insertions(+), 46 deletions(-) (limited to 'isp/omap3isp.c') diff --git a/isp/omap3isp.c b/isp/omap3isp.c index 3d687a6..341b5e1 100644 --- a/isp/omap3isp.c +++ b/isp/omap3isp.c @@ -67,60 +67,109 @@ static int setup_link(struct omap3_isp_device *isp, struct media_entity *source, return ret; } +/* + * struct isp_format_info - ISP media bus format information + * @code: V4L2 media bus format code + * @flavor: V4L2 media bus format code for the same pixel layout but + * shifted to be 8 bits per pixel. =0 if format is not shiftable. + * @pixelformat: V4L2 pixel format FCC identifier + */ +struct isp_format_info { + enum v4l2_mbus_pixelcode code; + enum v4l2_mbus_pixelcode flavor; + __u32 pixelformat; +}; + +static const struct isp_format_info formats[] = { + { V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8, + V4L2_PIX_FMT_SBGGR8, }, + { V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8, + V4L2_PIX_FMT_SGBRG8, }, + { V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8, + V4L2_PIX_FMT_SGRBG8, }, + { V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8, + V4L2_PIX_FMT_SRGGB8, }, + { V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR8_1X8, + V4L2_PIX_FMT_SBGGR10, }, + { V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG8_1X8, + V4L2_PIX_FMT_SGBRG10, }, + { V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG8_1X8, + V4L2_PIX_FMT_SGRBG10, }, + { V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB8_1X8, + V4L2_PIX_FMT_SRGGB10, }, + { V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR8_1X8, + V4L2_PIX_FMT_SBGGR12, }, + { V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG8_1X8, + V4L2_PIX_FMT_SGBRG12, }, + { V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG8_1X8, + V4L2_PIX_FMT_SGRBG12, }, + { V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB8_1X8, + V4L2_PIX_FMT_SRGGB12, }, + { V4L2_MBUS_FMT_UYVY8_1X16, 0, V4L2_PIX_FMT_UYVY, }, + { V4L2_MBUS_FMT_YUYV8_1X16, 0, V4L2_PIX_FMT_YUYV, }, +}; + +const struct isp_format_info * +omap3_isp_format_info(enum v4l2_mbus_pixelcode code) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(formats); ++i) { + if (formats[i].code == code) + return &formats[i]; + } + + return NULL; +} + +/* + * Decide whether desired output pixel code can be obtained with + * the lane shifter by shifting the input pixel code. + * @in: input pixelcode to shifter + * @out: output pixelcode from shifter + * + * return true if the combination is possible + * return false otherwise + */ +static bool format_is_shiftable(enum v4l2_mbus_pixelcode in, + enum v4l2_mbus_pixelcode out) +{ + const struct isp_format_info *in_info, *out_info; + + if (in == out) + return true; + + in_info = omap3_isp_format_info(in); + out_info = omap3_isp_format_info(out); + + if ((in_info->flavor == 0) || (out_info->flavor == 0)) + return false; + + return in_info->flavor == out_info->flavor; +} + static __u32 mbus_to_pix(enum v4l2_mbus_pixelcode code) { - switch (code) { - case V4L2_MBUS_FMT_SBGGR10_1X10: - return V4L2_PIX_FMT_SBGGR10; - case V4L2_MBUS_FMT_SGBRG10_1X10: - return V4L2_PIX_FMT_SGBRG10; - case V4L2_MBUS_FMT_SGRBG10_1X10: - return V4L2_PIX_FMT_SGRBG10; - case V4L2_MBUS_FMT_SRGGB10_1X10: - return V4L2_PIX_FMT_SRGGB10; - case V4L2_MBUS_FMT_SBGGR12_1X12: - return V4L2_PIX_FMT_SBGGR12; - case V4L2_MBUS_FMT_SGBRG12_1X12: - return V4L2_PIX_FMT_SGBRG12; - case V4L2_MBUS_FMT_SGRBG12_1X12: - return V4L2_PIX_FMT_SGRBG12; - case V4L2_MBUS_FMT_SRGGB12_1X12: - return V4L2_PIX_FMT_SRGGB12; - case V4L2_MBUS_FMT_UYVY8_1X16: - return V4L2_PIX_FMT_UYVY; - case V4L2_MBUS_FMT_YUYV8_1X16: - return V4L2_PIX_FMT_YUYV; - default: - return 0; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(formats); ++i) { + if (formats[i].code == code) + return formats[i].pixelformat; } + + return 0; } static enum v4l2_mbus_pixelcode pix_to_mbus(__u32 pixelformat) { - switch (pixelformat) { - case V4L2_PIX_FMT_SBGGR10: - return V4L2_MBUS_FMT_SBGGR10_1X10; - case V4L2_PIX_FMT_SGBRG10: - return V4L2_MBUS_FMT_SGBRG10_1X10; - case V4L2_PIX_FMT_SGRBG10: - return V4L2_MBUS_FMT_SGRBG10_1X10; - case V4L2_PIX_FMT_SRGGB10: - return V4L2_MBUS_FMT_SRGGB10_1X10; - case V4L2_PIX_FMT_SBGGR12: - return V4L2_MBUS_FMT_SBGGR12_1X12; - case V4L2_PIX_FMT_SGBRG12: - return V4L2_MBUS_FMT_SGBRG12_1X12; - case V4L2_PIX_FMT_SGRBG12: - return V4L2_MBUS_FMT_SGRBG12_1X12; - case V4L2_PIX_FMT_SRGGB12: - return V4L2_MBUS_FMT_SRGGB12_1X12; - case V4L2_PIX_FMT_UYVY: - return V4L2_MBUS_FMT_UYVY8_1X16; - case V4L2_PIX_FMT_YUYV: - return V4L2_MBUS_FMT_YUYV8_1X16; - default: - return 0; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(formats); ++i) { + if (formats[i].pixelformat == pixelformat) + return formats[i].code; } + + return 0; } static const char *entity_name(struct omap3_isp_entity *entity) @@ -627,6 +676,11 @@ static int omap3_isp_pipeline_try_format(struct omap3_isp_device *isp, } if (sink->type == OMAP3_ISP_ENTITY_ENTITY) { + if (sink->entity == isp->ccdc) { + if (format_is_shiftable(format.code, ofmt->code)) + format.code = ofmt->code; + } + /* Propagate the format to the link target. */ pad = sink->sink.link->sink; @@ -739,6 +793,9 @@ static int omap3_isp_pipeline_activate(struct omap3_isp_device *isp, } if (sink->type == OMAP3_ISP_ENTITY_ENTITY) { + if (sink->entity == isp->ccdc) + format.code = sink->sink.format.code; + /* Propagate the format to the link target. */ pad = sink->sink.link->sink; -- cgit v1.2.3