@@ -324,14 +324,10 @@ static enum pixel_fmt fourcc_to_ipu_pix(__u32 fourcc)
{
/* Add more formats as need arises and test possibilities appear... */
switch (fourcc) {
- case V4L2_PIX_FMT_RGB565:
- return IPU_PIX_FMT_RGB565;
case V4L2_PIX_FMT_RGB24:
return IPU_PIX_FMT_RGB24;
- case V4L2_PIX_FMT_RGB332:
- return IPU_PIX_FMT_RGB332;
- case V4L2_PIX_FMT_YUV422P:
- return IPU_PIX_FMT_YVU422P;
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_RGB565:
default:
return IPU_PIX_FMT_GENERIC;
}
@@ -359,9 +355,31 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq,
/* This is the configuration of one sg-element */
video->out_pixel_fmt = fourcc_to_ipu_pix(fourcc);
- video->out_width = icd->user_width;
- video->out_height = icd->user_height;
- video->out_stride = icd->user_width;
+
+ if (video->out_pixel_fmt == IPU_PIX_FMT_GENERIC) {
+ /*
+ * If the IPU DMA channel is configured to transport
+ * generic 8-bit data, we have to set up correctly the
+ * geometry parameters upon the current pixel format.
+ * So, since the DMA horizontal parameters are expressed
+ * in bytes not pixels, convert these in the right unit.
+ */
+ int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+ icd->current_fmt->host_fmt);
+ BUG_ON(bytes_per_line <= 0);
+
+ video->out_width = bytes_per_line;
+ video->out_height = icd->user_height;
+ video->out_stride = bytes_per_line;
+ } else {
+ /*
+ * For IPU known formats the pixel unit will be managed
+ * successfully by the IPU code
+ */
+ video->out_width = icd->user_width;
+ video->out_height = icd->user_height;
+ video->out_stride = icd->user_width;
+ }
#ifdef DEBUG
/* helps to see what DMA actually has written */
@@ -734,18 +752,36 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int id
if (xlate) {
xlate->host_fmt = fmt;
xlate->code = code;
+ dev_dbg(dev, "Providing format %c%c%c%c in pass-through mode\n",
+ (fmt->fourcc >> (0*8)) & 0xFF,
+ (fmt->fourcc >> (1*8)) & 0xFF,
+ (fmt->fourcc >> (2*8)) & 0xFF,
+ (fmt->fourcc >> (3*8)) & 0xFF);
xlate++;
- dev_dbg(dev, "Providing format %x in pass-through mode\n",
- xlate->host_fmt->fourcc);
}
return formats;
}
static void configure_geometry(struct mx3_camera_dev *mx3_cam,
- unsigned int width, unsigned int height)
+ unsigned int width, unsigned int height,
+ enum v4l2_mbus_pixelcode code)
{
u32 ctrl, width_field, height_field;
+ const struct soc_mbus_pixelfmt *fmt;
+
+ fmt = soc_mbus_get_fmtdesc(code);
+ BUG_ON(!fmt);
+
+ if (fourcc_to_ipu_pix(fmt->fourcc) == IPU_PIX_FMT_GENERIC) {
+ /*
+ * As the CSI will be configured to output BAYER, here
+ * the width parameter count the number of samples to
+ * capture to complete the whole image width.
+ */
+ width *= soc_mbus_samples_per_pixel(fmt);
+ BUG_ON(!width);
+ }
/* Setup frame size - this cannot be changed on-the-fly... */
width_field = width - 1;
@@ -854,7 +890,7 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd,
return ret;
}
- configure_geometry(mx3_cam, mf.width, mf.height);
+ configure_geometry(mx3_cam, mf.width, mf.height, mf.code);
}
dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n",
@@ -897,7 +933,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd,
* mxc_v4l2_s_fmt()
*/
- configure_geometry(mx3_cam, pix->width, pix->height);
+ configure_geometry(mx3_cam, pix->width, pix->height, xlate->code);
mf.width = pix->width;
mf.height = pix->height;