summaryrefslogtreecommitdiff
path: root/isp
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-04-16 22:42:06 +0200
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-04-16 23:40:29 +0200
commit6310474d2fdc91dc2aac87e25ef17fc682a3c94d (patch)
treedc4abee2e9d5267a38ea87d96406f063caa73e4e /isp
parent53f5c69a3c6a88cb706fa56e44b3e2f8f55aa3b4 (diff)
omap3isp: Support the CCDC lane shifter
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'isp')
-rw-r--r--isp/omap3isp.c149
1 files changed, 103 insertions, 46 deletions
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;