|
@@ -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 < 0);
|
|
|
+ }
|
|
|
|
|
|
/* 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;
|