[media] marvell-ccic: add new formats support for marvell-ccic driver
This patch adds some planar formats support for marvell-ccic. Signed-off-by: Albert Wang <twang13@marvell.com> Signed-off-by: Libin Yang <lbyang@marvell.com> Acked-by: Jonathan Corbet <corbet@lwn.net> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
This commit is contained in:
committed by
Mauro Carvalho Chehab
parent
1d3953fb16
commit
ad6ac45222
@@ -102,6 +102,7 @@ static struct mcam_format_struct {
|
|||||||
__u8 *desc;
|
__u8 *desc;
|
||||||
__u32 pixelformat;
|
__u32 pixelformat;
|
||||||
int bpp; /* Bytes per pixel */
|
int bpp; /* Bytes per pixel */
|
||||||
|
bool planar;
|
||||||
enum v4l2_mbus_pixelcode mbus_code;
|
enum v4l2_mbus_pixelcode mbus_code;
|
||||||
} mcam_formats[] = {
|
} mcam_formats[] = {
|
||||||
{
|
{
|
||||||
@@ -109,24 +110,56 @@ static struct mcam_format_struct {
|
|||||||
.pixelformat = V4L2_PIX_FMT_YUYV,
|
.pixelformat = V4L2_PIX_FMT_YUYV,
|
||||||
.mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
|
.mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
|
||||||
.bpp = 2,
|
.bpp = 2,
|
||||||
|
.planar = false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.desc = "UYVY 4:2:2",
|
||||||
|
.pixelformat = V4L2_PIX_FMT_UYVY,
|
||||||
|
.mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
|
||||||
|
.bpp = 2,
|
||||||
|
.planar = false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.desc = "YUV 4:2:2 PLANAR",
|
||||||
|
.pixelformat = V4L2_PIX_FMT_YUV422P,
|
||||||
|
.mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
|
||||||
|
.bpp = 2,
|
||||||
|
.planar = true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.desc = "YUV 4:2:0 PLANAR",
|
||||||
|
.pixelformat = V4L2_PIX_FMT_YUV420,
|
||||||
|
.mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
|
||||||
|
.bpp = 2,
|
||||||
|
.planar = true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.desc = "YVU 4:2:0 PLANAR",
|
||||||
|
.pixelformat = V4L2_PIX_FMT_YVU420,
|
||||||
|
.mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
|
||||||
|
.bpp = 2,
|
||||||
|
.planar = true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.desc = "RGB 444",
|
.desc = "RGB 444",
|
||||||
.pixelformat = V4L2_PIX_FMT_RGB444,
|
.pixelformat = V4L2_PIX_FMT_RGB444,
|
||||||
.mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
|
.mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
|
||||||
.bpp = 2,
|
.bpp = 2,
|
||||||
|
.planar = false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.desc = "RGB 565",
|
.desc = "RGB 565",
|
||||||
.pixelformat = V4L2_PIX_FMT_RGB565,
|
.pixelformat = V4L2_PIX_FMT_RGB565,
|
||||||
.mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE,
|
.mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE,
|
||||||
.bpp = 2,
|
.bpp = 2,
|
||||||
|
.planar = false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.desc = "Raw RGB Bayer",
|
.desc = "Raw RGB Bayer",
|
||||||
.pixelformat = V4L2_PIX_FMT_SBGGR8,
|
.pixelformat = V4L2_PIX_FMT_SBGGR8,
|
||||||
.mbus_code = V4L2_MBUS_FMT_SBGGR8_1X8,
|
.mbus_code = V4L2_MBUS_FMT_SBGGR8_1X8,
|
||||||
.bpp = 1
|
.bpp = 1,
|
||||||
|
.planar = false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
#define N_MCAM_FMTS ARRAY_SIZE(mcam_formats)
|
#define N_MCAM_FMTS ARRAY_SIZE(mcam_formats)
|
||||||
@@ -169,6 +202,12 @@ struct mcam_dma_desc {
|
|||||||
u32 segment_len;
|
u32 segment_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct yuv_pointer_t {
|
||||||
|
dma_addr_t y;
|
||||||
|
dma_addr_t u;
|
||||||
|
dma_addr_t v;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Our buffer type for working with videobuf2. Note that the vb2
|
* Our buffer type for working with videobuf2. Note that the vb2
|
||||||
* developers have decreed that struct vb2_buffer must be at the
|
* developers have decreed that struct vb2_buffer must be at the
|
||||||
@@ -180,6 +219,7 @@ struct mcam_vb_buffer {
|
|||||||
struct mcam_dma_desc *dma_desc; /* Descriptor virtual address */
|
struct mcam_dma_desc *dma_desc; /* Descriptor virtual address */
|
||||||
dma_addr_t dma_desc_pa; /* Descriptor physical address */
|
dma_addr_t dma_desc_pa; /* Descriptor physical address */
|
||||||
int dma_desc_nent; /* Number of mapped descriptors */
|
int dma_desc_nent; /* Number of mapped descriptors */
|
||||||
|
struct yuv_pointer_t yuv_p;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb)
|
static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb)
|
||||||
@@ -465,6 +505,15 @@ static inline int mcam_check_dma_buffers(struct mcam_camera *cam)
|
|||||||
/*
|
/*
|
||||||
* DMA-contiguous code.
|
* DMA-contiguous code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static bool mcam_fmt_is_planar(__u32 pfmt)
|
||||||
|
{
|
||||||
|
struct mcam_format_struct *f;
|
||||||
|
|
||||||
|
f = mcam_find_format(pfmt);
|
||||||
|
return f->planar;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up a contiguous buffer for the given frame. Here also is where
|
* Set up a contiguous buffer for the given frame. Here also is where
|
||||||
* the underrun strategy is set: if there is no buffer available, reuse
|
* the underrun strategy is set: if there is no buffer available, reuse
|
||||||
@@ -476,6 +525,11 @@ static inline int mcam_check_dma_buffers(struct mcam_camera *cam)
|
|||||||
static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
|
static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
|
||||||
{
|
{
|
||||||
struct mcam_vb_buffer *buf;
|
struct mcam_vb_buffer *buf;
|
||||||
|
struct v4l2_pix_format *fmt = &cam->pix_format;
|
||||||
|
dma_addr_t dma_handle;
|
||||||
|
u32 pixel_count = fmt->width * fmt->height;
|
||||||
|
struct vb2_buffer *vb;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there are no available buffers, go into single mode
|
* If there are no available buffers, go into single mode
|
||||||
*/
|
*/
|
||||||
@@ -494,8 +548,35 @@ static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cam->vb_bufs[frame] = buf;
|
cam->vb_bufs[frame] = buf;
|
||||||
mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
|
vb = &buf->vb_buf;
|
||||||
vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0));
|
|
||||||
|
dma_handle = vb2_dma_contig_plane_dma_addr(vb, 0);
|
||||||
|
buf->yuv_p.y = dma_handle;
|
||||||
|
|
||||||
|
switch (cam->pix_format.pixelformat) {
|
||||||
|
case V4L2_PIX_FMT_YUV422P:
|
||||||
|
buf->yuv_p.u = buf->yuv_p.y + pixel_count;
|
||||||
|
buf->yuv_p.v = buf->yuv_p.u + pixel_count / 2;
|
||||||
|
break;
|
||||||
|
case V4L2_PIX_FMT_YUV420:
|
||||||
|
buf->yuv_p.u = buf->yuv_p.y + pixel_count;
|
||||||
|
buf->yuv_p.v = buf->yuv_p.u + pixel_count / 4;
|
||||||
|
break;
|
||||||
|
case V4L2_PIX_FMT_YVU420:
|
||||||
|
buf->yuv_p.v = buf->yuv_p.y + pixel_count;
|
||||||
|
buf->yuv_p.u = buf->yuv_p.v + pixel_count / 4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR, buf->yuv_p.y);
|
||||||
|
if (mcam_fmt_is_planar(fmt->pixelformat)) {
|
||||||
|
mcam_reg_write(cam, frame == 0 ?
|
||||||
|
REG_U0BAR : REG_U1BAR, buf->yuv_p.u);
|
||||||
|
mcam_reg_write(cam, frame == 0 ?
|
||||||
|
REG_V0BAR : REG_V1BAR, buf->yuv_p.v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -653,49 +734,84 @@ static inline void mcam_sg_restart(struct mcam_camera *cam)
|
|||||||
*/
|
*/
|
||||||
static void mcam_ctlr_image(struct mcam_camera *cam)
|
static void mcam_ctlr_image(struct mcam_camera *cam)
|
||||||
{
|
{
|
||||||
int imgsz;
|
|
||||||
struct v4l2_pix_format *fmt = &cam->pix_format;
|
struct v4l2_pix_format *fmt = &cam->pix_format;
|
||||||
|
u32 widthy = 0, widthuv = 0, imgsz_h, imgsz_w;
|
||||||
|
|
||||||
|
cam_dbg(cam, "camera: bytesperline = %d; height = %d\n",
|
||||||
|
fmt->bytesperline, fmt->sizeimage / fmt->bytesperline);
|
||||||
|
imgsz_h = (fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK;
|
||||||
|
imgsz_w = (fmt->width * 2) & IMGSZ_H_MASK;
|
||||||
|
|
||||||
|
switch (fmt->pixelformat) {
|
||||||
|
case V4L2_PIX_FMT_YUYV:
|
||||||
|
case V4L2_PIX_FMT_UYVY:
|
||||||
|
widthy = fmt->width * 2;
|
||||||
|
widthuv = 0;
|
||||||
|
break;
|
||||||
|
case V4L2_PIX_FMT_JPEG:
|
||||||
|
imgsz_h = (fmt->sizeimage / fmt->bytesperline) << IMGSZ_V_SHIFT;
|
||||||
|
widthy = fmt->bytesperline;
|
||||||
|
widthuv = 0;
|
||||||
|
break;
|
||||||
|
case V4L2_PIX_FMT_YUV422P:
|
||||||
|
case V4L2_PIX_FMT_YUV420:
|
||||||
|
case V4L2_PIX_FMT_YVU420:
|
||||||
|
widthy = fmt->width;
|
||||||
|
widthuv = fmt->width / 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
widthy = fmt->bytesperline;
|
||||||
|
widthuv = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mcam_reg_write_mask(cam, REG_IMGPITCH, widthuv << 16 | widthy,
|
||||||
|
IMGP_YP_MASK | IMGP_UVP_MASK);
|
||||||
|
mcam_reg_write(cam, REG_IMGSIZE, imgsz_h | imgsz_w);
|
||||||
|
mcam_reg_write(cam, REG_IMGOFFSET, 0x0);
|
||||||
|
|
||||||
imgsz = ((fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK) |
|
|
||||||
(fmt->bytesperline & IMGSZ_H_MASK);
|
|
||||||
mcam_reg_write(cam, REG_IMGSIZE, imgsz);
|
|
||||||
mcam_reg_write(cam, REG_IMGOFFSET, 0);
|
|
||||||
/* YPITCH just drops the last two bits */
|
|
||||||
mcam_reg_write_mask(cam, REG_IMGPITCH, fmt->bytesperline,
|
|
||||||
IMGP_YP_MASK);
|
|
||||||
/*
|
/*
|
||||||
* Tell the controller about the image format we are using.
|
* Tell the controller about the image format we are using.
|
||||||
*/
|
*/
|
||||||
switch (cam->pix_format.pixelformat) {
|
switch (fmt->pixelformat) {
|
||||||
|
case V4L2_PIX_FMT_YUV422P:
|
||||||
|
mcam_reg_write_mask(cam, REG_CTRL0,
|
||||||
|
C0_DF_YUV | C0_YUV_PLANAR | C0_YUVE_YVYU, C0_DF_MASK);
|
||||||
|
break;
|
||||||
|
case V4L2_PIX_FMT_YUV420:
|
||||||
|
case V4L2_PIX_FMT_YVU420:
|
||||||
|
mcam_reg_write_mask(cam, REG_CTRL0,
|
||||||
|
C0_DF_YUV | C0_YUV_420PL | C0_YUVE_YVYU, C0_DF_MASK);
|
||||||
|
break;
|
||||||
case V4L2_PIX_FMT_YUYV:
|
case V4L2_PIX_FMT_YUYV:
|
||||||
mcam_reg_write_mask(cam, REG_CTRL0,
|
mcam_reg_write_mask(cam, REG_CTRL0,
|
||||||
C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV,
|
C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_UYVY, C0_DF_MASK);
|
||||||
C0_DF_MASK);
|
break;
|
||||||
break;
|
case V4L2_PIX_FMT_UYVY:
|
||||||
|
mcam_reg_write_mask(cam, REG_CTRL0,
|
||||||
|
C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK);
|
||||||
|
break;
|
||||||
|
case V4L2_PIX_FMT_JPEG:
|
||||||
|
mcam_reg_write_mask(cam, REG_CTRL0,
|
||||||
|
C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK);
|
||||||
|
break;
|
||||||
case V4L2_PIX_FMT_RGB444:
|
case V4L2_PIX_FMT_RGB444:
|
||||||
mcam_reg_write_mask(cam, REG_CTRL0,
|
mcam_reg_write_mask(cam, REG_CTRL0,
|
||||||
C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB,
|
C0_DF_RGB | C0_RGBF_444 | C0_RGB4_XRGB, C0_DF_MASK);
|
||||||
C0_DF_MASK);
|
|
||||||
/* Alpha value? */
|
/* Alpha value? */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case V4L2_PIX_FMT_RGB565:
|
case V4L2_PIX_FMT_RGB565:
|
||||||
mcam_reg_write_mask(cam, REG_CTRL0,
|
mcam_reg_write_mask(cam, REG_CTRL0,
|
||||||
C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR,
|
C0_DF_RGB | C0_RGBF_565 | C0_RGB5_BGGR, C0_DF_MASK);
|
||||||
C0_DF_MASK);
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat);
|
cam_err(cam, "camera: unknown format: %#x\n", fmt->pixelformat);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure it knows we want to use hsync/vsync.
|
* Make sure it knows we want to use hsync/vsync.
|
||||||
*/
|
*/
|
||||||
mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC,
|
mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC, C0_SIFM_MASK);
|
||||||
C0_SIFM_MASK);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This field controls the generation of EOF(DVP only)
|
* This field controls the generation of EOF(DVP only)
|
||||||
*/
|
*/
|
||||||
@@ -1156,6 +1272,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
|
|||||||
#ifdef MCAM_MODE_DMA_CONTIG
|
#ifdef MCAM_MODE_DMA_CONTIG
|
||||||
vq->ops = &mcam_vb2_ops;
|
vq->ops = &mcam_vb2_ops;
|
||||||
vq->mem_ops = &vb2_dma_contig_memops;
|
vq->mem_ops = &vb2_dma_contig_memops;
|
||||||
|
vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
|
||||||
cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev);
|
cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev);
|
||||||
vq->io_modes = VB2_MMAP | VB2_USERPTR;
|
vq->io_modes = VB2_MMAP | VB2_USERPTR;
|
||||||
cam->dma_setup = mcam_ctlr_dma_contig;
|
cam->dma_setup = mcam_ctlr_dma_contig;
|
||||||
@@ -1166,6 +1283,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
|
|||||||
#ifdef MCAM_MODE_DMA_SG
|
#ifdef MCAM_MODE_DMA_SG
|
||||||
vq->ops = &mcam_vb2_sg_ops;
|
vq->ops = &mcam_vb2_sg_ops;
|
||||||
vq->mem_ops = &vb2_dma_sg_memops;
|
vq->mem_ops = &vb2_dma_sg_memops;
|
||||||
|
vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
|
||||||
vq->io_modes = VB2_MMAP | VB2_USERPTR;
|
vq->io_modes = VB2_MMAP | VB2_USERPTR;
|
||||||
cam->dma_setup = mcam_ctlr_dma_sg;
|
cam->dma_setup = mcam_ctlr_dma_sg;
|
||||||
cam->frame_complete = mcam_dma_sg_done;
|
cam->frame_complete = mcam_dma_sg_done;
|
||||||
@@ -1316,7 +1434,15 @@ static int mcam_vidioc_try_fmt_vid_cap(struct file *filp, void *priv,
|
|||||||
ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt);
|
ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt);
|
||||||
mutex_unlock(&cam->s_mutex);
|
mutex_unlock(&cam->s_mutex);
|
||||||
v4l2_fill_pix_format(pix, &mbus_fmt);
|
v4l2_fill_pix_format(pix, &mbus_fmt);
|
||||||
pix->bytesperline = pix->width * f->bpp;
|
switch (f->pixelformat) {
|
||||||
|
case V4L2_PIX_FMT_YUV420:
|
||||||
|
case V4L2_PIX_FMT_YVU420:
|
||||||
|
pix->bytesperline = pix->width * 3 / 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pix->bytesperline = pix->width * f->bpp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
pix->sizeimage = pix->height * pix->bytesperline;
|
pix->sizeimage = pix->height * pix->bytesperline;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@@ -249,6 +249,12 @@ int mccic_resume(struct mcam_camera *cam);
|
|||||||
#define REG_Y0BAR 0x00
|
#define REG_Y0BAR 0x00
|
||||||
#define REG_Y1BAR 0x04
|
#define REG_Y1BAR 0x04
|
||||||
#define REG_Y2BAR 0x08
|
#define REG_Y2BAR 0x08
|
||||||
|
#define REG_U0BAR 0x0c
|
||||||
|
#define REG_U1BAR 0x10
|
||||||
|
#define REG_U2BAR 0x14
|
||||||
|
#define REG_V0BAR 0x18
|
||||||
|
#define REG_V1BAR 0x1C
|
||||||
|
#define REG_V2BAR 0x20
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* register definitions for MIPI support
|
* register definitions for MIPI support
|
||||||
|
Reference in New Issue
Block a user