On Fri, 23 Nov 2012, Albert Wang wrote:

> From: Libin Yang <lby...@marvell.com>
> 
> This patch adds the new formats support for marvell-ccic.
> 
> Signed-off-by: Albert Wang <twan...@marvell.com>
> Signed-off-by: Libin Yang <lby...@marvell.com>
> ---
>  drivers/media/platform/marvell-ccic/mcam-core.c |  178 
> ++++++++++++++++++-----
>  drivers/media/platform/marvell-ccic/mcam-core.h |    6 +
>  2 files changed, 151 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c 
> b/drivers/media/platform/marvell-ccic/mcam-core.c
> index 67d4f2f..c9f7250 100755
> --- a/drivers/media/platform/marvell-ccic/mcam-core.c
> +++ b/drivers/media/platform/marvell-ccic/mcam-core.c
> @@ -110,6 +110,30 @@ static struct mcam_format_struct {
>               .bpp            = 2,
>       },
>       {
> +             .desc           = "UYVY 4:2:2",
> +             .pixelformat    = V4L2_PIX_FMT_UYVY,
> +             .mbus_code      = V4L2_MBUS_FMT_UYVY8_2X8,
> +             .bpp            = 2,
> +     },
> +     {
> +             .desc           = "YUV 4:2:2 PLANAR",
> +             .pixelformat    = V4L2_PIX_FMT_YUV422P,
> +             .mbus_code      = V4L2_MBUS_FMT_UYVY8_2X8,
> +             .bpp            = 2,
> +     },
> +     {
> +             .desc           = "YUV 4:2:0 PLANAR",
> +             .pixelformat    = V4L2_PIX_FMT_YUV420,
> +             .mbus_code      = V4L2_MBUS_FMT_YUYV8_1_5X8,
> +             .bpp            = 2,
> +     },
> +     {
> +             .desc           = "YVU 4:2:0 PLANAR",
> +             .pixelformat    = V4L2_PIX_FMT_YVU420,
> +             .mbus_code      = V4L2_MBUS_FMT_YVYU8_1_5X8,
> +             .bpp            = 2,
> +     },
> +     {
>               .desc           = "RGB 444",
>               .pixelformat    = V4L2_PIX_FMT_RGB444,
>               .mbus_code      = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
> @@ -168,6 +192,12 @@ struct mcam_dma_desc {
>       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
>   * developers have decreed that struct vb2_buffer must be at the
> @@ -179,6 +209,7 @@ struct mcam_vb_buffer {
>       struct mcam_dma_desc *dma_desc; /* Descriptor virtual address */
>       dma_addr_t dma_desc_pa;         /* Descriptor physical address */
>       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)
> @@ -465,6 +496,18 @@ static inline int mcam_check_dma_buffers(struct 
> mcam_camera *cam)
>  /*
>   * DMA-contiguous code.
>   */
> +
> +static bool mcam_fmt_is_planar(__u32 pfmt)
> +{
> +     switch (pfmt) {
> +     case V4L2_PIX_FMT_YUV422P:
> +     case V4L2_PIX_FMT_YUV420:
> +     case V4L2_PIX_FMT_YVU420:
> +             return true;
> +     }
> +     return false;
> +}
> +
>  /*
>   * 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
> @@ -476,6 +519,8 @@ static inline int mcam_check_dma_buffers(struct 
> mcam_camera *cam)
>  static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
>  {
>       struct mcam_vb_buffer *buf;
> +     struct v4l2_pix_format *fmt = &cam->pix_format;
> +
>       /*
>        * If there are no available buffers, go into single mode
>        */
> @@ -494,8 +539,13 @@ static void mcam_set_contig_buffer(struct mcam_camera 
> *cam, int frame)
>       }
>  
>       cam->vb_bufs[frame] = buf;
> -     mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
> -                     vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0));
> +     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 +703,91 @@ static inline void mcam_sg_restart(struct mcam_camera 
> *cam)
>   */
>  static void mcam_ctlr_image(struct mcam_camera *cam)
>  {
> -     int imgsz;
>       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->bytesperline & IMGSZ_H_MASK;
> +
> +     if (fmt->pixelformat == V4L2_PIX_FMT_YUV420
> +             || fmt->pixelformat == V4L2_PIX_FMT_YVU420)
> +             imgsz_w = (fmt->bytesperline * 4 / 3) & IMGSZ_H_MASK;
> +     else if (fmt->pixelformat == V4L2_PIX_FMT_JPEG)
> +             imgsz_h = (fmt->sizeimage / fmt->bytesperline) << IMGSZ_V_SHIFT;
> +
> +     switch (fmt->pixelformat) {
> +     case V4L2_PIX_FMT_YUYV:
> +     case V4L2_PIX_FMT_UYVY:
> +             widthy = fmt->width * 2;
> +             widthuv = fmt->width * 2;
> +             break;

I think, you can move imgsz_h and imgsz_w calculations from above to this 
switch too?

> +     case V4L2_PIX_FMT_RGB565:
> +             widthy = fmt->width * 2;
> +             widthuv = 0;
> +             break;
> +     case V4L2_PIX_FMT_JPEG:
> +             widthy = fmt->bytesperline;
> +             widthuv = fmt->bytesperline;
> +             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:
> +             break;
> +     }
> +
> +     mcam_reg_write_mask(cam, REG_IMGPITCH, widthuv << 16 | widthy,
> +                     IMGP_YP_MASK | IMGP_UVP_MASK);

Hm, are you sure you're not breaking other currently supported pixel 
formats, like V4L2_PIX_FMT_RGB444, V4L2_PIX_FMT_SBGGR8?

> +     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);

Let's see. Before we had

        REG_IMGPITCH = fmt->bytesperline & 0x3ffc;

after your change, say, for V4L2_PIX_FMT_YUYV (fmt->bytesperline = 
fmt->width * 2), you get

        REG_IMGPITCH = ((fmt->bytesperline << 16) | fmt->bytesperline) &
                0x3ffc3ffc;

Is this intentional? Doesn't widthuv have to be 0 for non-planar formats 
like V4L2_PIX_FMT_YUYV? Please, always when you change existing code make 
sure the original behaviour is preserved, unless there used to be a bug, 
in which case it should be fixed by a separate patch.

>       /*
>        * 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:
> -         mcam_reg_write_mask(cam, REG_CTRL0,
> -                         C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV,
> -                         C0_DF_MASK);
> -         break;
> -
> +             mcam_reg_write_mask(cam, REG_CTRL0,
> +                     C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_UYVY, C0_DF_MASK);
> +             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:
> -         mcam_reg_write_mask(cam, REG_CTRL0,
> -                         C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB,
> -                         C0_DF_MASK);
> -             /* Alpha value? */

Unless you have a specific reason, you could just as well preserve the 
comment.

> -         break;
> -
> +             mcam_reg_write_mask(cam, REG_CTRL0,
> +                     C0_DF_RGB | C0_RGBF_444 | C0_RGB4_XRGB, C0_DF_MASK);
> +             break;
>       case V4L2_PIX_FMT_RGB565:
> -         mcam_reg_write_mask(cam, REG_CTRL0,
> -                         C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR,
> -                         C0_DF_MASK);
> -         break;
> -
> +             mcam_reg_write_mask(cam, REG_CTRL0,
> +                     C0_DF_RGB | C0_RGBF_565 | C0_RGB5_BGGR, C0_DF_MASK);
> +             break;
>       default:
> -         cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat);
> -         break;
> +             cam_err(cam, "camera: unknown format: %c\n", fmt->pixelformat);

Don't think "%c" will produce a meaningful result here.

> +             break;
>       }
> +
>       /*
>        * Make sure it knows we want to use hsync/vsync.
>        */
> -     mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC,
> -                     C0_SIFM_MASK);
> -
> +     mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC, C0_SIFM_MASK);
>       /*
>        * This field controls the generation of EOF(DVP only)
>        */
> @@ -706,7 +798,6 @@ static void mcam_ctlr_image(struct mcam_camera *cam)
>       }
>  }
>  
> -
>  /*
>   * Configure the controller for operation; caller holds the
>   * device mutex.
> @@ -979,11 +1070,32 @@ static void mcam_vb_buf_queue(struct vb2_buffer *vb)
>  {
>       struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
>       struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
> +     struct v4l2_pix_format *fmt = &cam->pix_format;
>       unsigned long flags;
>       int start;
> +     dma_addr_t dma_handle;
> +     u32 base_size = fmt->width * fmt->height;

Shouldn't you be just using bytesperline? Is stride != width * height 
supported?

>  
>       spin_lock_irqsave(&cam->dev_lock, flags);
> +     dma_handle = vb2_dma_contig_plane_dma_addr(vb, 0);
> +     BUG_ON(!dma_handle);
>       start = (cam->state == S_BUFWAIT) && !list_empty(&cam->buffers);
> +
> +     if (cam->pix_format.pixelformat == V4L2_PIX_FMT_YUV422P) {

Better use a "switch."

> +             mvb->yuv_p.y = dma_handle;
> +             mvb->yuv_p.u = mvb->yuv_p.y + base_size;
> +             mvb->yuv_p.v = mvb->yuv_p.u + base_size / 2;
> +     } else if (cam->pix_format.pixelformat == V4L2_PIX_FMT_YUV420) {
> +             mvb->yuv_p.y = dma_handle;
> +             mvb->yuv_p.u = mvb->yuv_p.y + base_size;
> +             mvb->yuv_p.v = mvb->yuv_p.u + base_size / 4;
> +     } else if (cam->pix_format.pixelformat == V4L2_PIX_FMT_YVU420) {
> +             mvb->yuv_p.y = dma_handle;
> +             mvb->yuv_p.v = mvb->yuv_p.y + base_size;
> +             mvb->yuv_p.u = mvb->yuv_p.v + base_size / 4;
> +     } else
> +             mvb->yuv_p.y = dma_handle;
> +
>       list_add(&mvb->queue, &cam->buffers);
>       if (cam->state == S_STREAMING && test_bit(CF_SG_RESTART, &cam->flags))
>               mcam_sg_restart(cam);
> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h 
> b/drivers/media/platform/marvell-ccic/mcam-core.h
> index 40368f6..3f75d7d 100755
> --- a/drivers/media/platform/marvell-ccic/mcam-core.h
> +++ b/drivers/media/platform/marvell-ccic/mcam-core.h
> @@ -233,6 +233,12 @@ int mccic_resume(struct mcam_camera *cam);
>  #define REG_Y0BAR    0x00
>  #define REG_Y1BAR    0x04
>  #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
> -- 
> 1.7.9.5

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to