Upstream patches for Samsung Exynos s5p-mfc and gsc-m2m
Subsystems (2)
This patchset upstreams some changes carried in the ChromeOS kernel tree especially regarding the s5p-mfc video encoder and gsc-m2m color converter hardware functionality.
Patch 4 in particular affects the V4L2 interface by allowing VIDIOC_REQBUFS(0) to succeed when the queue is of type V4L2_MEMORY_MMAP, inline with the rest of the queue memory types.
PATCH 1/4 s5p-mfc: fix encoder crash after VIDIOC_STREAMOFF
VIDIOC_STREAMOFF clears the encoder's destination queue -- routines run from the interrupt handler cannot assume that the queue is non-empty.
--- drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-)
drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +11 -9
@@ -772,13 +772,16 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx)if (p->seq_hdr_mode ==V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE ) {spin_lock_irqsave (&dev->irqlock, flags); - dst_mb =list_entry (ctx->dst_queue.next, - struct s5p_mfc_buf, list); -list_del (&dst_mb->list); - ctx->dst_queue_cnt--; -vb2_set_plane_payload (dst_mb->b,0 , -s5p_mfc_hw_call (dev->mfc_ops, get_enc_strm_size, dev)); -vb2_buffer_done (dst_mb->b,VB2_BUF_STATE_DONE ); +if (!list_empty (&ctx->dst_queue)) { + dst_mb =list_entry (ctx->dst_queue.next, + struct s5p_mfc_buf, list); +list_del (&dst_mb->list); + ctx->dst_queue_cnt--; +vb2_set_plane_payload (dst_mb->b,0 , +s5p_mfc_hw_call (dev->mfc_ops, get_enc_strm_size, + dev)); +vb2_buffer_done (dst_mb->b,VB2_BUF_STATE_DONE ); + }spin_unlock_irqrestore (&dev->irqlock, flags); }
@@ -883,8 +886,7 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)mfc_debug (2 ,"enc src count: %d, enc ref count: %d\n" , ctx->src_queue_cnt, ctx->ref_queue_cnt); } -if (strm_size >0 ) { -/* at least one more dest. buffers exist always */ +if ((ctx->dst_queue_cnt >0 ) && (strm_size >0 )) { mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);list_del (&mb_entry->list);
Signature · 1 line
1.9.0.279.gdc9e3eb
PATCH 2/4 CHROMIUM: s5p-mfc: support dynamic encoding parameter changes
In reply to John SheuAdd support for dynamic encoding parameter changes in MFCv6. Parameters set are applied with the next OUTPUT buffer queued to the device with VIDIOC_QBUF.
Supported parameters are:
* GOP size (V4L2_CID_MPEG_VIDEO_GOP_SIZE)
* framerate (from VIDIOC_S_PARM)
* VBR target bitrate (V4L2_CID_MPEG_VIDEO_BITRATE)
* (h264) frame type (V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE)
--- drivers/media/platform/s5p-mfc/regs-mfc-v6.h | 4 ++ drivers/media/platform/s5p-mfc/s5p_mfc_common.h | 31 ++++++-- drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 53 +++++++++++--- drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c | 29 ++++---- drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c | 94 ++++++++++++++----------- 5 files changed, 140 insertions(+), 71 deletions(-)
drivers/media/platform/s5p-mfc/regs-mfc-v6.h +4 -0
@@ -331,6 +331,10 @@#define S5P_FIMV_E_MVC_RC_RPARA_VIEW1_V6 0xfd50#define S5P_FIMV_E_MVC_INTER_VIEW_PREDICTION_ON_V6 0xfd80 +#define S5P_FIMV_E_GOP_CONFIG_CHANGE_SHIFT_V6 0 +#define S5P_FIMV_E_FRAME_RATE_CHANGE_SHIFT_V6 1 +#define S5P_FIMV_E_BIT_RATE_CHANGE_SHIFT_V6 2 +/* Codec numbers */ #define S5P_FIMV_CODEC_NONE_V6 -1
drivers/media/platform/s5p-mfc/s5p_mfc_common.h +25 -6
@@ -164,12 +164,35 @@ enum s5p_mfc_decode_arg { MFC_DEC_RES_CHANGE, }; + +/** +* enum s5p_mfc_encoder_param_change - indicates runtime parameter change +*/ +enum s5p_mfc_encode_param_change { +MFC_ENC_GOP_CONFIG_CHANGE , +MFC_ENC_FRAME_RATE_CHANGE , +MFC_ENC_BIT_RATE_CHANGE , +MFC_ENC_FRAME_INSERTION , +}; +#define MFC_BUF_FLAG_USED (1 << 0)#define MFC_BUF_FLAG_EOS (1 << 1)struct s5p_mfc_ctx ;/** +* struct s5p_mfc_enc_params - runtime modifiable encoding parameters +*/ +struct s5p_mfc_runtime_enc_params { +u32 params_changed; +u16 gop_size; +u32 rc_framerate_num; +u32 rc_framerate_denom; +u32 rc_bitrate; +enum v4l2_mpeg_mfc51_video_force_frame_type force_frame_type; +}; + +/** * struct s5p_mfc_buf - MFC buffer */ struct s5p_mfc_buf {
@@ -183,6 +206,7 @@ struct s5p_mfc_buf {size_t stream; } cookie;int flags; +struct s5p_mfc_runtime_enc_params runtime_enc_params; };/**
@@ -429,7 +453,6 @@ struct s5p_mfc_enc_params {u32 mv_h_range;u32 mv_v_range; -u16 gop_size;enum v4l2_mpeg_video_multi_slice_mode slice_mode;u16 slice_mb;u32 slice_bit;
@@ -440,7 +463,6 @@ struct s5p_mfc_enc_params {u8 pad_cr;int rc_frame;int rc_mb; -u32 rc_bitrate;u16 rc_reaction_coeff;u16 vbv_size;u32 vbv_delay;
@@ -450,10 +472,9 @@ struct s5p_mfc_enc_params {int fixed_target_bit;u8 num_b_frame; -u32 rc_framerate_num; -u32 rc_framerate_denom;struct { +struct s5p_mfc_runtime_enc_params runtime;struct s5p_mfc_h264_enc_params h264;struct s5p_mfc_mpeg4_enc_params mpeg4;struct s5p_mfc_vp8_enc_params vp8;
@@ -634,8 +655,6 @@ struct s5p_mfc_ctx {size_t me_buffer_size;size_t tmv_buffer_size; -enum v4l2_mpeg_mfc51_video_force_frame_type force_frame_type; -struct list_head ref_queue;unsigned int ref_queue_cnt;
drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +44 -9
92 lines not on this page · raw message
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c +16 -13
@@ -688,7 +688,7 @@ static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx) reg =mfc_read (dev,S5P_FIMV_ENC_PIC_TYPE_CTRL ); reg |= (1 <<18 ); reg &= ~(0xFFFF ); - reg |= p->gop_size; + reg |= p->codec.runtime.gop_size;mfc_write (dev, reg,S5P_FIMV_ENC_PIC_TYPE_CTRL );mfc_write (dev,0 ,S5P_FIMV_ENC_B_RECON_WRITE_ON );/* multi-slice control */
@@ -736,7 +736,7 @@ static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)mfc_write (dev, reg,S5P_FIMV_ENC_RC_CONFIG );/* bit rate */ if (p->rc_frame) -mfc_write (dev, p->rc_bitrate, +mfc_write (dev, p->codec.runtime.rc_bitrate,S5P_FIMV_ENC_RC_BIT_RATE );else mfc_write (dev,0 ,S5P_FIMV_ENC_RC_BIT_RATE );
@@ -831,9 +831,10 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx) reg |= p_264->rc_frame_qp;mfc_write (dev, reg,S5P_FIMV_ENC_RC_CONFIG );/* frame rate */ -if (p->rc_frame && p->rc_framerate_denom) -mfc_write (dev, p->rc_framerate_num *1000 - / p->rc_framerate_denom,S5P_FIMV_ENC_RC_FRAME_RATE ); +if (p->rc_frame && p->codec.runtime.rc_framerate_denom) +mfc_write (dev, p->codec.runtime.rc_framerate_num *1000 + / p->codec.runtime.rc_framerate_denom, +S5P_FIMV_ENC_RC_FRAME_RATE );else mfc_write (dev,0 ,S5P_FIMV_ENC_RC_FRAME_RATE );/* max & min value of QP */
@@ -950,16 +951,17 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx) }/* frame rate */ if (p->rc_frame) { -if (p->rc_framerate_denom >0 ) { - framerate = p->rc_framerate_num *1000 / - p->rc_framerate_denom; +if (p->codec.runtime.rc_framerate_denom >0 ) { + framerate = p->codec.runtime.rc_framerate_num *1000 / + p->codec.runtime.rc_framerate_denom;mfc_write (dev, framerate,S5P_FIMV_ENC_RC_FRAME_RATE ); shm =s5p_mfc_read_info_v5 (ctx,RC_VOP_TIMING ); shm &= ~(0xFFFFFFFF ); shm |= (1 <<31 ); - shm |= ((p->rc_framerate_num &0x7FFF ) <<16 ); - shm |= (p->rc_framerate_denom &0xFFFF ); + shm |= ((p->codec.runtime.rc_framerate_num &0x7FFF ) + <<16 ); + shm |= (p->codec.runtime.rc_framerate_denom &0xFFFF );s5p_mfc_write_info_v5 (ctx, shm,RC_VOP_TIMING ); } }else {
@@ -1009,9 +1011,10 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)s5p_mfc_write_info_v5 (ctx, shm,P_B_FRAME_QP ); }/* frame rate */ -if (p->rc_frame && p->rc_framerate_denom) -mfc_write (dev, p->rc_framerate_num *1000 - / p->rc_framerate_denom,S5P_FIMV_ENC_RC_FRAME_RATE ); +if (p->rc_frame && p->codec.runtime.rc_framerate_denom) +mfc_write (dev, p->codec.runtime.rc_framerate_num *1000 + / p->codec.runtime.rc_framerate_denom, +S5P_FIMV_ENC_RC_FRAME_RATE );else mfc_write (dev,0 ,S5P_FIMV_ENC_RC_FRAME_RATE );/* rate control config. */
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c +51 -43
142 lines not on this page · raw message
Signature · 1 line
1.9.0.279.gdc9e3eb
PATCH 3/4 gsc-m2m: report correct format bytesperline and sizeimage
In reply to John SheuExplicitly specify sampling period for subsampled chroma formats, so stride and image size are properly reported through VIDIOC_{S,G}_FMT.
--- drivers/media/platform/exynos-gsc/gsc-core.c | 154 +++++++++++++++------------ drivers/media/platform/exynos-gsc/gsc-core.h | 16 +-- drivers/media/platform/exynos-gsc/gsc-regs.c | 40 +++---- drivers/media/platform/exynos-gsc/gsc-regs.h | 4 +- 4 files changed, 116 insertions(+), 98 deletions(-)
drivers/media/platform/exynos-gsc/gsc-core.c +84 -70
@@ -34,167 +34,185 @@ static const struct gsc_fmt gsc_formats[] = { { .name = "RGB565", .pixelformat = V4L2_PIX_FMT_RGB565X, - .depth = { 16 }, .color = GSC_RGB, .num_planes = 1, .num_comp = 1, + .depth = { 16 }, + .sampling = { { 1, 1 } }, }, { .name = "XRGB-8-8-8-8, 32 bpp", .pixelformat = V4L2_PIX_FMT_RGB32, - .depth = { 32 }, .color = GSC_RGB, .num_planes = 1, .num_comp = 1, + .depth = { 32 }, + .sampling = { { 1, 1 } }, }, { .name = "YUV 4:2:2 packed, YCbYCr", .pixelformat = V4L2_PIX_FMT_YUYV, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 1, + .depth = { 16 }, + .sampling = { { 1, 1 } }, .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, }, { .name = "YUV 4:2:2 packed, CbYCrY", .pixelformat = V4L2_PIX_FMT_UYVY, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_C, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 1, + .depth = { 16 }, + .sampling = { { 1, 1 } }, .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, }, { .name = "YUV 4:2:2 packed, CrYCbY", .pixelformat = V4L2_PIX_FMT_VYUY, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_C, .corder = GSC_CRCB, .num_planes = 1, .num_comp = 1, + .depth = { 16 }, + .sampling = { { 1, 1 } }, .mbus_code = V4L2_MBUS_FMT_VYUY8_2X8, }, { .name = "YUV 4:2:2 packed, YCrYCb", .pixelformat = V4L2_PIX_FMT_YVYU, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_Y, .corder = GSC_CRCB, .num_planes = 1, .num_comp = 1, + .depth = { 16 }, + .sampling = { { 1, 1 } }, .mbus_code = V4L2_MBUS_FMT_YVYU8_2X8, }, { .name = "YUV 4:4:4 planar, YCbYCr", .pixelformat = V4L2_PIX_FMT_YUV32, - .depth = { 32 }, .color = GSC_YUV444, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 1, + .depth = { 32 }, + .sampling = { { 1, 1 } }, }, { .name = "YUV 4:2:2 planar, Y/Cb/Cr", .pixelformat = V4L2_PIX_FMT_YUV422P, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 3, + .depth = { 8, 8, 8 }, + .sampling = { { 1, 1 }, { 2, 1 }, { 2, 1 } }, }, { .name ="YUV 4:2:2 planar, Y/CbCr" , .pixelformat = V4L2_PIX_FMT_NV16, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 2, + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 1 } }, }, { .name ="YUV 4:2:2 planar, Y/CrCb" , .pixelformat = V4L2_PIX_FMT_NV61, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_Y, .corder = GSC_CRCB, .num_planes = 1, .num_comp = 2, + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 1 } }, }, { .name ="YUV 4:2:0 planar, YCbCr" , .pixelformat = V4L2_PIX_FMT_YUV420, - .depth = { 12 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 3, + .depth = { 8, 8, 8 }, + .sampling = { { 1, 1 }, { 2, 2 }, { 2, 2 } }, }, { .name ="YUV 4:2:0 planar, YCrCb" , .pixelformat = V4L2_PIX_FMT_YVU420, - .depth = { 12 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CRCB, .num_planes = 1, .num_comp = 3, - + .depth = { 8, 8, 8 }, + .sampling = { { 1, 1 }, { 2, 2 }, { 2, 2 } }, }, { .name ="YUV 4:2:0 planar, Y/CbCr" , .pixelformat = V4L2_PIX_FMT_NV12, - .depth = { 12 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 2, + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 2 } }, }, { .name ="YUV 4:2:0 planar, Y/CrCb" , .pixelformat = V4L2_PIX_FMT_NV21, - .depth = { 12 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CRCB, .num_planes = 1, .num_comp = 2, + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 2 } }, }, { - .name = "YUV 4:2:0 non-contig. 2p, Y/CbCr", + .name ="YUV 4:2:0 non-contiguous 2-planar, Y/CbCr" , .pixelformat = V4L2_PIX_FMT_NV12M, - .depth = { 8, 4 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 2, .num_comp = 2, + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 2 } }, }, { - .name = "YUV 4:2:0 non-contig. 3p, Y/Cb/Cr", + .name ="YUV 4:2:0 non-contiguous 3-planar, Y/Cb/Cr" , .pixelformat = V4L2_PIX_FMT_YUV420M, - .depth = { 8, 2, 2 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 3, .num_comp = 3, + .depth = { 8, 8, 8 }, + .sampling = { { 1, 1 }, { 2, 2 }, { 2, 2 } }, }, { - .name = "YUV 4:2:0 non-contig. 3p, Y/Cr/Cb", + .name ="YUV 4:2:0 non-contiguous 3-planar, Y/Cr/Cb" , .pixelformat = V4L2_PIX_FMT_YVU420M, - .depth = { 8, 2, 2 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CRCB, .num_planes = 3, .num_comp = 3, + .depth = { 8, 8, 8 }, + .sampling = { { 1, 1 }, { 2, 2 }, { 2, 2 } }, }, { - .name = "YUV 4:2:0 n.c. 2p, Y/CbCr tiled", + .name = +"YUV 4:2:0 non-contiguous 2-planar, Y/CbCr, tiled" , .pixelformat = V4L2_PIX_FMT_NV12MT_16X16, - .depth = { 8, 4 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 2, .num_comp = 2, - } + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 2 } }, + }, };const struct gsc_fmt *get_format (int index)
@@ -384,6 +402,14 @@ void gsc_set_prefbuf(struct gsc_dev *gsc, struct gsc_frame *frm) f_chk_addr, f_chk_len, s_chk_addr, s_chk_len); } +static void get_format_size (__u32 width,__u32 height, +const struct gsc_fmt *fmt,int plane, +__u16 *bytesperline,__u32 *sizeimage) { +__u16 bpl = ((width * fmt->depth[plane]) / fmt->sampling[plane][0 ]) /8 ; + *bytesperline = bpl; + *sizeimage = (height * bpl) / fmt->sampling[plane][0 ]; +} +int gsc_try_fmt_mplane (struct gsc_ctx *ctx,struct v4l2_format *f) {struct gsc_dev *gsc = ctx->gsc_dev;
@@ -448,14 +474,16 @@ int gsc_try_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f)else /* SD */ pix_mp->colorspace =V4L2_COLORSPACE_SMPTE170M ; - +/* V4L2 specifies for contiguous planar formats that bytesperline and +sizeimage are set to values appropriate for the first plane. */ for (i =0 ; i < pix_mp->num_planes; ++i) { -int bpl = (pix_mp->width * fmt->depth[i]) >>3 ; - pix_mp->plane_fmt[i].bytesperline = bpl; - pix_mp->plane_fmt[i].sizeimage = bpl * pix_mp->height; +get_format_size (pix_mp->width, pix_mp->height, fmt, i, + &pix_mp->plane_fmt[i].bytesperline, + &pix_mp->plane_fmt[i].sizeimage);pr_debug ("[%d]: bpl: %d, sizeimage: %d" , - i, bpl, pix_mp->plane_fmt[i].sizeimage); + i, pix_mp->plane_fmt[i].bytesperline, + pix_mp->plane_fmt[i].sizeimage); }return 0 ;
@@ -465,26 +493,27 @@ int gsc_g_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f) {struct gsc_frame *frame;struct v4l2_pix_format_mplane *pix_mp; +const struct gsc_fmt *fmt;int i; frame =ctx_get_frame (ctx, f->type);if (IS_ERR (frame))return PTR_ERR (frame); + fmt = frame->fmt; pix_mp = &f->fmt.pix_mp; pix_mp->width = frame->f_width; pix_mp->height = frame->f_height; pix_mp->field =V4L2_FIELD_NONE ; - pix_mp->pixelformat = frame->fmt->pixelformat; + pix_mp->pixelformat = fmt->pixelformat; pix_mp->colorspace =V4L2_COLORSPACE_REC709 ; - pix_mp->num_planes = frame->fmt->num_planes; + pix_mp->num_planes = fmt->num_planes;for (i =0 ; i < pix_mp->num_planes; ++i) { - pix_mp->plane_fmt[i].bytesperline = (frame->f_width * - frame->fmt->depth[i]) /8 ; - pix_mp->plane_fmt[i].sizeimage = - pix_mp->plane_fmt[i].bytesperline * frame->f_height; +get_format_size (pix_mp->width, pix_mp->height, fmt, i, + &pix_mp->plane_fmt[i].bytesperline, + &pix_mp->plane_fmt[i].sizeimage); }return 0 ;
@@ -794,11 +823,12 @@ void gsc_ctrls_delete(struct gsc_ctx *ctx) } } -/* The color format (num_comp, num_planes) must be already configured. */ +/* The color format (num_planes, num_comp) must be already configured. */ int gsc_prepare_addr (struct gsc_ctx *ctx,struct vb2_buffer *vb,struct gsc_frame *frame,struct gsc_addr *addr) {int ret =0 ; +const struct gsc_fmt *fmt = frame->fmt;u32 pix_size;if ((vb ==NULL ) || (frame ==NULL ))
@@ -810,46 +840,30 @@ int gsc_prepare_addr(struct gsc_ctx *ctx, struct vb2_buffer *vb, frame->fmt->num_planes, frame->fmt->num_comp, pix_size); addr->y =vb2_dma_contig_plane_dma_addr (vb,0 ); - -if (frame->fmt->num_planes ==1 ) { -switch (frame->fmt->num_comp) { -case 1 : - addr->cb =0 ; - addr->cr =0 ; -break ; -case 2 : -/* decompose Y into Y/Cb */ - addr->cb = (dma_addr_t)(addr->y + pix_size); - addr->cr =0 ; -break ; -case 3 : -/* decompose Y into Y/Cb/Cr */ - addr->cb = (dma_addr_t)(addr->y + pix_size); -if (GSC_YUV420 == frame->fmt->color) - addr->cr = (dma_addr_t)(addr->cb - + (pix_size >>2 )); -else /* 422 */ - addr->cr = (dma_addr_t)(addr->cb - + (pix_size >>1 )); -break ; -default : -pr_err ("Invalid the number of color planes" ); -return -EINVAL ; + addr->cb =0 ; + addr->cr =0 ; + +if (fmt->num_planes ==1 ) { +if (fmt->num_comp >=2 ) { + addr->cb = (dma_addr_t)(addr->y + + ((pix_size * fmt->depth[0 ]) / + (fmt->sampling[0 ][0 ] * + fmt->sampling[0 ][1 ]) /8 )); + } +if (fmt->num_comp >=3 ) { + addr->cr = (dma_addr_t)(addr->cb + + ((pix_size * fmt->depth[1 ]) / + (fmt->sampling[1 ][0 ] * + fmt->sampling[1 ][1 ]) /8 )); } }else { -if (frame->fmt->num_planes >=2 ) +if (fmt->num_comp >=2 ) addr->cb =vb2_dma_contig_plane_dma_addr (vb,1 ); - -if (frame->fmt->num_planes ==3 ) +if (fmt->num_comp ==3 ) addr->cr =vb2_dma_contig_plane_dma_addr (vb,2 ); } -if ((frame->fmt->pixelformat ==V4L2_PIX_FMT_VYUY ) || - (frame->fmt->pixelformat ==V4L2_PIX_FMT_YVYU ) || - (frame->fmt->pixelformat ==V4L2_PIX_FMT_NV61 ) || - (frame->fmt->pixelformat ==V4L2_PIX_FMT_YVU420 ) || - (frame->fmt->pixelformat ==V4L2_PIX_FMT_NV21 ) || - (frame->fmt->pixelformat ==V4L2_PIX_FMT_YVU420M )) +if (fmt->corder ==GSC_CRCB )swap (addr->cb, addr->cr); pr_debug("ADDR: y= 0x%X cb= 0x%X cr= 0x%X ret= %d",
drivers/media/platform/exynos-gsc/gsc-core.h +8 -8
@@ -106,27 +106,27 @@ enum gsc_yuv_fmt { container_of((__ctrl)->handler, struct gsc_ctx, ctrl_handler)/** * struct gsc_fmt - the driver's internal color format data -* @mbus_code: Media Bus pixel code, -1 if not applicable * @name: format description * @pixelformat: the fourcc code for this format, 0 if not applicable * @yorder: Y/C order * @corder: Chrominance order control * @num_planes: number of physically non-contiguous data planes -* @nr_comp: number of physically contiguous data planes -* @depth: per plane driver's private 'number of bits per pixel' -* @flags: flags indicating which operation mode format applies to +* @num_comp: number of physically contiguous data planes +* @depth: bit depth of each component +* @sampling: sampling frequency of each components, X and Y +* @mbus_code: Media Bus pixel code, -1 if not applicable */struct gsc_fmt { -enum v4l2_mbus_pixelcode mbus_code;char *name;u32 pixelformat;u32 color;u32 yorder;u32 corder; -u16 num_planes; -u16 num_comp; +u8 num_planes; +u8 num_comp;u8 depth[VIDEO_MAX_PLANES ]; -u32 flags; +u8 sampling[VIDEO_MAX_PLANES ][2 ]; +enum v4l2_mbus_pixelcode mbus_code; };/**
drivers/media/platform/exynos-gsc/gsc-regs.c +22 -18
@@ -167,6 +167,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx) {struct gsc_dev *dev = ctx->gsc_dev;struct gsc_frame *frame = &ctx->s_frame; +const struct gsc_fmt *fmt = frame->fmt;u32 i, depth =0 ;u32 cfg;
@@ -176,21 +177,22 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx) GSC_IN_TILE_TYPE_MASK | GSC_IN_TILE_MODE);writel (cfg, dev->regs +GSC_IN_CON ); -if (is_rgb (frame->fmt->color)) { +if (is_rgb (fmt->color)) {gsc_hw_set_in_image_rgb (ctx);return ; } -for (i =0 ; i < frame->fmt->num_planes; i++) - depth += frame->fmt->depth[i]; +for (i =0 ; i < fmt->num_comp; i++) + depth += fmt->depth[i] / + (fmt->sampling[i][0 ] * fmt->sampling[i][1 ]); -switch (frame->fmt->num_comp) { +switch (fmt->num_comp) {case 1 : cfg |=GSC_IN_YUV422_1P ; -if (frame->fmt->yorder ==GSC_LSB_Y ) +if (fmt->yorder ==GSC_LSB_Y ) cfg |=GSC_IN_YUV422_1P_ORDER_LSB_Y ;else - cfg |=GSC_IN_YUV422_1P_OEDER_LSB_C ; -if (frame->fmt->corder ==GSC_CBCR ) + cfg |=GSC_IN_YUV422_1P_ORDER_LSB_C ; +if (fmt->corder ==GSC_CBCR ) cfg |=GSC_IN_CHROMA_ORDER_CBCR ;else cfg |=GSC_IN_CHROMA_ORDER_CRCB ;
@@ -200,7 +202,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx) cfg |=GSC_IN_YUV420_2P ; else cfg |= GSC_IN_YUV422_2P; -if (frame->fmt->corder ==GSC_CBCR ) +if (fmt->corder ==GSC_CBCR ) cfg |=GSC_IN_CHROMA_ORDER_CBCR ;else cfg |=GSC_IN_CHROMA_ORDER_CRCB ;
@@ -213,7 +215,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)break ; } -if (is_tiled (frame->fmt)) +if (is_tiled (fmt)) cfg |= GSC_IN_TILE_C_16x8 |GSC_IN_TILE_MODE ;writel (cfg, dev->regs +GSC_IN_CON );
@@ -287,6 +289,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx) {struct gsc_dev *dev = ctx->gsc_dev;struct gsc_frame *frame = &ctx->d_frame; +const struct gsc_fmt *fmt = frame->fmt;u32 i, depth =0 ;u32 cfg;
@@ -296,7 +299,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx) GSC_OUT_TILE_TYPE_MASK | GSC_OUT_TILE_MODE);writel (cfg, dev->regs +GSC_OUT_CON ); -if (is_rgb (frame->fmt->color)) { +if (is_rgb (fmt->color)) {gsc_hw_set_out_image_rgb (ctx);return ; }
@@ -306,17 +309,18 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx) goto end_set; } -for (i =0 ; i < frame->fmt->num_planes; i++) - depth += frame->fmt->depth[i]; +for (i =0 ; i < fmt->num_comp; i++) + depth += fmt->depth[i] / + (fmt->sampling[i][0 ] * fmt->sampling[i][1 ]); -switch (frame->fmt->num_comp) { +switch (fmt->num_comp) {case 1 : cfg |=GSC_OUT_YUV422_1P ; -if (frame->fmt->yorder ==GSC_LSB_Y ) +if (fmt->yorder ==GSC_LSB_Y ) cfg |=GSC_OUT_YUV422_1P_ORDER_LSB_Y ;else - cfg |=GSC_OUT_YUV422_1P_OEDER_LSB_C ; -if (frame->fmt->corder ==GSC_CBCR ) + cfg |=GSC_OUT_YUV422_1P_ORDER_LSB_C ; +if (fmt->corder ==GSC_CBCR ) cfg |=GSC_OUT_CHROMA_ORDER_CBCR ;else cfg |=GSC_OUT_CHROMA_ORDER_CRCB ;
@@ -326,7 +330,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx) cfg |=GSC_OUT_YUV420_2P ; else cfg |= GSC_OUT_YUV422_2P; -if (frame->fmt->corder ==GSC_CBCR ) +if (fmt->corder ==GSC_CBCR ) cfg |=GSC_OUT_CHROMA_ORDER_CBCR ;else cfg |=GSC_OUT_CHROMA_ORDER_CRCB ;
@@ -336,7 +340,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)break ; } -if (is_tiled (frame->fmt)) +if (is_tiled (fmt)) cfg |= GSC_OUT_TILE_C_16x8 |GSC_OUT_TILE_MODE ; end_set:
drivers/media/platform/exynos-gsc/gsc-regs.h +2 -2
@@ -46,7 +46,7 @@#define GSC_IN_RGB_SD_WIDE (0 << 14)#define GSC_IN_YUV422_1P_ORDER_MASK (1 << 13)#define GSC_IN_YUV422_1P_ORDER_LSB_Y (0 << 13) -#define GSC_IN_YUV422_1P_OEDER_LSB_C (1 << 13) +#define GSC_IN_YUV422_1P_ORDER_LSB_C (1 << 13)#define GSC_IN_CHROMA_ORDER_MASK (1 << 12)#define GSC_IN_CHROMA_ORDER_CBCR (0 << 12)#define GSC_IN_CHROMA_ORDER_CRCB (1 << 12)
@@ -91,7 +91,7 @@#define GSC_OUT_RGB_SD_NARROW (0 << 10)#define GSC_OUT_YUV422_1P_ORDER_MASK (1 << 9)#define GSC_OUT_YUV422_1P_ORDER_LSB_Y (0 << 9) -#define GSC_OUT_YUV422_1P_OEDER_LSB_C (1 << 9) +#define GSC_OUT_YUV422_1P_ORDER_LSB_C (1 << 9)#define GSC_OUT_CHROMA_ORDER_MASK (1 << 8)#define GSC_OUT_CHROMA_ORDER_CBCR (0 << 8)#define GSC_OUT_CHROMA_ORDER_CRCB (1 << 8)
Signature · 1 line
1.9.0.279.gdc9e3eb
RE: [PATCH 3/4] gsc-m2m: report correct format bytesperline and sizeimage
Hi Shaik, Sungchun,
Exynos-gsc has no maintainers mentioned in the MAINTAINERS file. I see your activity in the development of this driver. Do you have any comments on this patch?
Best wishes,
Signature · 2 lines
Kamil Debski Samsung R&D Institute Poland
Quoted 174 lines
-----Original Message-----
From: John Sheu [mailto:[email protected]]
Sent: Tuesday, March 11, 2014 11:52 PM
To: [email protected]
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; John Sheu
Subject: [PATCH 3/4] gsc-m2m: report correct format bytesperline and sizeimageExplicitly specify sampling period for subsampled chroma formats, so stride and image size are properly reported through VIDIOC_{S,G}_FMT.
Signed-off-by John Sheu <[email protected]>--- drivers/media/platform/exynos-gsc/gsc-core.c | 154 +++++++++++++++---- -------- drivers/media/platform/exynos-gsc/gsc-core.h | 16 +-- drivers/media/platform/exynos-gsc/gsc-regs.c | 40 +++---- drivers/media/platform/exynos-gsc/gsc-regs.h | 4 +- 4 files changed, 116 insertions(+), 98 deletions(-)drivers/media/platform/exynos-gsc/gsc-core.c +26
-15@@ -34,167 +34,185 @@ static const struct gsc_fmt gsc_formats[] = { { .name = "RGB565", .pixelformat = V4L2_PIX_FMT_RGB565X, - .depth = { 16 }, .color = GSC_RGB, .num_planes = 1, .num_comp = 1, + .depth = { 16 }, + .sampling = { { 1, 1 } }, }, { .name = "XRGB-8-8-8-8, 32 bpp", .pixelformat = V4L2_PIX_FMT_RGB32, - .depth = { 32 }, .color = GSC_RGB, .num_planes = 1, .num_comp = 1, + .depth = { 32 }, + .sampling = { { 1, 1 } }, }, { .name = "YUV 4:2:2 packed, YCbYCr", .pixelformat = V4L2_PIX_FMT_YUYV, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 1, + .depth = { 16 }, + .sampling = { { 1, 1 } }, .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, }, { .name = "YUV 4:2:2 packed, CbYCrY", .pixelformat = V4L2_PIX_FMT_UYVY, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_C, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 1, + .depth = { 16 }, + .sampling = { { 1, 1 } }, .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, }, { .name = "YUV 4:2:2 packed, CrYCbY", .pixelformat = V4L2_PIX_FMT_VYUY, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_C, .corder = GSC_CRCB, .num_planes = 1, .num_comp = 1, + .depth = { 16 }, + .sampling = { { 1, 1 } }, .mbus_code = V4L2_MBUS_FMT_VYUY8_2X8, }, { .name = "YUV 4:2:2 packed, YCrYCb", .pixelformat = V4L2_PIX_FMT_YVYU, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_Y, .corder = GSC_CRCB, .num_planes = 1, .num_comp = 1, + .depth = { 16 }, + .sampling = { { 1, 1 } }, .mbus_code = V4L2_MBUS_FMT_YVYU8_2X8, }, { .name = "YUV 4:4:4 planar, YCbYCr", .pixelformat = V4L2_PIX_FMT_YUV32, - .depth = { 32 }, .color = GSC_YUV444, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 1, + .depth = { 32 }, + .sampling = { { 1, 1 } }, }, { .name = "YUV 4:2:2 planar, Y/Cb/Cr", .pixelformat = V4L2_PIX_FMT_YUV422P, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 3, + .depth = { 8, 8, 8 }, + .sampling = { { 1, 1 }, { 2, 1 }, { 2, 1 } }, }, { .name ="YUV 4:2:2 planar, Y/CbCr" , .pixelformat = V4L2_PIX_FMT_NV16, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 2, + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 1 } }, }, { .name ="YUV 4:2:2 planar, Y/CrCb" , .pixelformat = V4L2_PIX_FMT_NV61, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_Y, .corder = GSC_CRCB, .num_planes = 1, .num_comp = 2, + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 1 } }, }, { .name ="YUV 4:2:0 planar, YCbCr" , .pixelformat = V4L2_PIX_FMT_YUV420, - .depth = { 12 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 3, + .depth = { 8, 8, 8 }, + .sampling = { { 1, 1 }, { 2, 2 }, { 2, 2 } }, }, { .name ="YUV 4:2:0 planar, YCrCb" , .pixelformat = V4L2_PIX_FMT_YVU420, - .depth = { 12 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CRCB, .num_planes = 1, .num_comp = 3, - + .depth = { 8, 8, 8 }, + .sampling = { { 1, 1 }, { 2, 2 }, { 2, 2 } }, }, { .name ="YUV 4:2:0 planar, Y/CbCr" , .pixelformat = V4L2_PIX_FMT_NV12, - .depth = { 12 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 2, + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 2 } }, }, { .name ="YUV 4:2:0 planar, Y/CrCb" , .pixelformat = V4L2_PIX_FMT_NV21, - .depth = { 12 },
drivers/media/platform/exynos-gsc/gsc-core.c static const struct gsc_fmt gsc_formats[] = { · line 175
Quoted 10 lines
drivers/media/platform/exynos-gsc/gsc-core.c +3
-1.color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CRCB, .num_planes = 1, .num_comp = 2, + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 2 } }, }, { - .name = "YUV 4:2:0 non-contig. 2p, Y/CbCr", + .name = "YUV 4:2:0 non-contiguous 2-planar,
Y/CbCr",
drivers/media/platform/exynos-gsc/gsc-core.c static const struct gsc_fmt gsc_formats[] = {
Quoted 12 lines
drivers/media/platform/exynos-gsc/gsc-core.c +3
-2.pixelformat = V4L2_PIX_FMT_NV12M, - .depth = { 8, 4 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 2, .num_comp = 2, + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 2 } }, }, { - .name = "YUV 4:2:0 non-contig. 3p, Y/Cb/Cr", + .name = "YUV 4:2:0 non-contiguous 3-planar,
Y/Cb/Cr",
drivers/media/platform/exynos-gsc/gsc-core.c static const struct gsc_fmt gsc_formats[] = {
Quoted 12 lines
drivers/media/platform/exynos-gsc/gsc-core.c +3
-2.pixelformat = V4L2_PIX_FMT_YUV420M, - .depth = { 8, 2, 2 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 3, .num_comp = 3, + .depth = { 8, 8, 8 }, + .sampling = { { 1, 1 }, { 2, 2 }, { 2, 2 } }, }, { - .name = "YUV 4:2:0 non-contig. 3p, Y/Cr/Cb", + .name = "YUV 4:2:0 non-contiguous 3-planar,
Y/Cr/Cb",
Quoted 375 lines
drivers/media/platform/exynos-gsc/gsc-core.c +7
-4.pixelformat = V4L2_PIX_FMT_YVU420M, - .depth = { 8, 2, 2 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CRCB, .num_planes = 3, .num_comp = 3, + .depth = { 8, 8, 8 }, + .sampling = { { 1, 1 }, { 2, 2 }, { 2, 2 } }, }, { - .name ="YUV 4:2:0 n.c. 2p, Y/CbCr tiled" , + .name = +"YUV 4:2:0 non-contiguous 2-planar, Y/CbCr, tiled" , .pixelformat = V4L2_PIX_FMT_NV12MT_16X16, - .depth = { 8, 4 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 2, .num_comp = 2, - } + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 2 } }, + }, }; const struct gsc_fmt *get_format(int index) @@ -384,6 +402,14 @@ void
gsc_set_prefbuf(struct gsc_dev *gsc, struct gsc_frame *frm)drivers/media/platform/exynos-gsc/gsc-core.c +4
-0f_chk_addr, f_chk_len, s_chk_addr, s_chk_len); } +static void get_format_size (__u32 width,__u32 height, +const struct gsc_fmt *fmt,int plane, +__u16 *bytesperline,__u32 *sizeimage) { + __u16 bpl = ((width * fmt->depth[plane]) / fmt-Quoted 1 line
sampling[plane][0]) / 8;
drivers/media/platform/exynos-gsc/gsc-core.c +4
-1+ *bytesperline = bpl; + *sizeimage = (height * bpl) / fmt->sampling[plane][0 ]; } +int gsc_try_fmt_mplane (struct gsc_ctx *ctx,struct v4l2_format *f) {struct gsc_dev *gsc = ctx->gsc_dev;@@ -448,14 +474,16 @@ int gsc_try_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f) else /* SD */ pix_mp->colorspace = V4L2_COLORSPACE_SMPTE170M; - +/* V4L2 specifies for contiguous planar formats that bytesperline and
drivers/media/platform/exynos-gsc/gsc-core.c +1
-0+ sizeimage are set to values appropriate for the first plane.*/
drivers/media/platform/exynos-gsc/gsc-core.c +12
-10for (i =0 ; i < pix_mp->num_planes; ++i) { -int bpl = (pix_mp->width * fmt->depth[i]) >>3 ; - pix_mp->plane_fmt[i].bytesperline = bpl; - pix_mp->plane_fmt[i].sizeimage = bpl * pix_mp->height; +get_format_size (pix_mp->width, pix_mp->height, fmt, i, + &pix_mp->plane_fmt[i].bytesperline, + &pix_mp->plane_fmt[i].sizeimage);pr_debug ("[%d]: bpl: %d, sizeimage: %d" , - i, bpl, pix_mp->plane_fmt[i].sizeimage); + i, pix_mp->plane_fmt[i].bytesperline, + pix_mp->plane_fmt[i].sizeimage); }return 0 ;@@ -465,26 +493,27 @@ int gsc_g_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f) {struct gsc_frame *frame;struct v4l2_pix_format_mplane *pix_mp; +const struct gsc_fmt *fmt;int i; frame =ctx_get_frame (ctx, f->type);if (IS_ERR (frame))return PTR_ERR (frame); + fmt = frame->fmt; pix_mp = &f->fmt.pix_mp; pix_mp->width = frame->f_width; pix_mp->height = frame->f_height; pix_mp->field =V4L2_FIELD_NONE ; - pix_mp->pixelformat = frame->fmt->pixelformat; + pix_mp->pixelformat = fmt->pixelformat; pix_mp->colorspace =V4L2_COLORSPACE_REC709 ; - pix_mp->num_planes = frame->fmt->num_planes; + pix_mp->num_planes = fmt->num_planes;for (i =0 ; i < pix_mp->num_planes; ++i) { - pix_mp->plane_fmt[i].bytesperline = (frame->f_width * - frame->fmt->depth[i]) /8 ; - pix_mp->plane_fmt[i].sizeimage = - pix_mp->plane_fmt[i].bytesperline * frame- f_height; +get_format_size (pix_mp->width, pix_mp->height, fmt, i, + &pix_mp->plane_fmt[i].bytesperline, + &pix_mp->plane_fmt[i].sizeimage); }drivers/media/platform/exynos-gsc/gsc-core.c +21
-35return 0 ;@@ -794,11 +823,12 @@ void gsc_ctrls_delete(struct gsc_ctx *ctx)} } -/* The color format (num_comp, num_planes) must be already configured. */ +/* The color format (num_planes, num_comp) must be already configured. +*/ int gsc_prepare_addr (struct gsc_ctx *ctx,struct vb2_buffer *vb,struct gsc_frame *frame,struct gsc_addr *addr) {int ret =0 ; +const struct gsc_fmt *fmt = frame->fmt;u32 pix_size;if ((vb ==NULL ) || (frame ==NULL ))@@ -810,46 +840,30 @@ int gsc_prepare_addr(struct gsc_ctx *ctx, struct vb2_buffer *vb, frame->fmt->num_planes, frame->fmt->num_comp, pix_size); addr->y =vb2_dma_contig_plane_dma_addr (vb,0 ); - -if (frame->fmt->num_planes ==1 ) { -switch (frame->fmt->num_comp) { -case 1 : - addr->cb =0 ; - addr->cr =0 ; -break ; -case 2 : -/* decompose Y into Y/Cb */ - addr->cb = (dma_addr_t)(addr->y + pix_size); - addr->cr =0 ; -break ; -case 3 : -/* decompose Y into Y/Cb/Cr */ - addr->cb = (dma_addr_t)(addr->y + pix_size); -if (GSC_YUV420 == frame->fmt->color) - addr->cr = (dma_addr_t)(addr->cb - + (pix_size >>2 )); -else /* 422 */ - addr->cr = (dma_addr_t)(addr->cb - + (pix_size >>1 )); -break ; -default : -pr_err ("Invalid the number of color planes" ); -return -EINVAL ; + addr->cb =0 ; + addr->cr =0 ; + +if (fmt->num_planes ==1 ) { +if (fmt->num_comp >=2 ) { + addr->cb = (dma_addr_t)(addr->y + + ((pix_size * fmt->depth[0 ]) / + (fmt->sampling[0 ][0 ] * + fmt->sampling[0 ][1 ]) /8 )); + } +if (fmt->num_comp >=3 ) { + addr->cr = (dma_addr_t)(addr->cb + + ((pix_size * fmt->depth[1 ]) / + (fmt->sampling[1 ][0 ] * + fmt->sampling[1 ][1 ]) /8 )); } }else { -if (frame->fmt->num_planes >=2 ) +if (fmt->num_comp >=2 ) addr->cb =vb2_dma_contig_plane_dma_addr (vb,1 ); - -if (frame->fmt->num_planes ==3 ) +if (fmt->num_comp ==3 ) addr->cr =vb2_dma_contig_plane_dma_addr (vb,2 ); } -if ((frame->fmt->pixelformat ==V4L2_PIX_FMT_VYUY ) || - (frame->fmt->pixelformat ==V4L2_PIX_FMT_YVYU ) || - (frame->fmt->pixelformat ==V4L2_PIX_FMT_NV61 ) || - (frame->fmt->pixelformat ==V4L2_PIX_FMT_YVU420 ) || - (frame->fmt->pixelformat ==V4L2_PIX_FMT_NV21 ) || - (frame->fmt->pixelformat ==V4L2_PIX_FMT_YVU420M )) +if (fmt->corder ==GSC_CRCB )swap (addr->cb, addr->cr);pr_debug("ADDR: y= 0x%X cb= 0x%X cr= 0x%X ret= %d", diff --git
a/drivers/media/platform/exynos-gsc/gsc-core.hb/drivers/media/platform/exynos-gsc/gsc-core.h
indexef0a6564..8fb07e0d100644drivers/media/platform/exynos-gsc/gsc-core.h +8
-8@@ -106,27 +106,27 @@ enum gsc_yuv_fmt { container_of((__ctrl)->handler, struct gsc_ctx, ctrl_handler)/** * struct gsc_fmt - the driver's internal color format data -* @mbus_code: Media Bus pixel code, -1 if not applicable * @name: format description * @pixelformat: the fourcc code for this format, 0 if not applicable * @yorder: Y/C order * @corder: Chrominance order control * @num_planes: number of physically non-contiguous data planes -* @nr_comp: number of physically contiguous data planes -* @depth: per plane driver's private 'number of bits per pixel' -* @flags: flags indicating which operation mode format applies to +* @num_comp: number of physically contiguous data planes +* @depth: bit depth of each component +* @sampling: sampling frequency of each components, X and Y +* @mbus_code: Media Bus pixel code, -1 if not applicable */struct gsc_fmt { -enum v4l2_mbus_pixelcode mbus_code;char *name;u32 pixelformat;u32 color;u32 yorder;u32 corder; -u16 num_planes; -u16 num_comp; +u8 num_planes; +u8 num_comp;u8 depth[VIDEO_MAX_PLANES ]; -u32 flags; +u8 sampling[VIDEO_MAX_PLANES ][2 ]; +enum v4l2_mbus_pixelcode mbus_code; };/** drivers/media/platform/exynos-gsc/gsc-regs.c +9
-7@@ -167,6 +167,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx) {struct gsc_dev *dev = ctx->gsc_dev;struct gsc_frame *frame = &ctx->s_frame; +const struct gsc_fmt *fmt = frame->fmt;u32 i, depth =0 ;u32 cfg;@@ -176,21 +177,22 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx) GSC_IN_TILE_TYPE_MASK | GSC_IN_TILE_MODE);writel (cfg, dev->regs +GSC_IN_CON ); -if (is_rgb (frame->fmt->color)) { +if (is_rgb (fmt->color)) {gsc_hw_set_in_image_rgb (ctx);return ; } -for (i =0 ; i < frame->fmt->num_planes; i++) - depth += frame->fmt->depth[i]; +for (i =0 ; i < fmt->num_comp; i++) + depth += fmt->depth[i] / + (fmt->sampling[i][0 ] * fmt->sampling[i][1 ]); -switch (frame->fmt->num_comp) { +switch (fmt->num_comp) {case 1 : cfg |=GSC_IN_YUV422_1P ; -if (frame->fmt->yorder ==GSC_LSB_Y ) +if (fmt->yorder ==GSC_LSB_Y ) cfg |=GSC_IN_YUV422_1P_ORDER_LSB_Y ;else - cfg |=GSC_IN_YUV422_1P_OEDER_LSB_C ; -if (frame->fmt->corder ==GSC_CBCR ) + cfg |=GSC_IN_YUV422_1P_ORDER_LSB_C ; +if (fmt->corder ==GSC_CBCR ) cfg |=GSC_IN_CHROMA_ORDER_CBCR ;else drivers/media/platform/exynos-gsc/gsc-regs.c +1
-1cfg |=GSC_IN_CHROMA_ORDER_CRCB ;@@ -200,7 +202,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx) cfg |=GSC_IN_YUV420_2P ; else cfg |= GSC_IN_YUV422_2P; -if (frame->fmt->corder ==GSC_CBCR ) +if (fmt->corder ==GSC_CBCR ) cfg |=GSC_IN_CHROMA_ORDER_CBCR ;else drivers/media/platform/exynos-gsc/gsc-regs.c +1
-1cfg |=GSC_IN_CHROMA_ORDER_CRCB ;@@ -213,7 +215,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)break ; } -if (is_tiled (frame->fmt)) +if (is_tiled (fmt)) cfg |= GSC_IN_TILE_C_16x8 |GSC_IN_TILE_MODE ;drivers/media/platform/exynos-gsc/gsc-regs.c +2
-1writel (cfg, dev->regs +GSC_IN_CON );@@ -287,6 +289,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx) {struct gsc_dev *dev = ctx->gsc_dev;struct gsc_frame *frame = &ctx->d_frame; +const struct gsc_fmt *fmt = frame->fmt;u32 i, depth =0 ;u32 cfg;@@ -296,7 +299,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx) GSC_OUT_TILE_TYPE_MASK | GSC_OUT_TILE_MODE);writel (cfg, dev->regs +GSC_OUT_CON ); -if (is_rgb (frame->fmt->color)) { +if (is_rgb (fmt->color)) {gsc_hw_set_out_image_rgb (ctx);return ;drivers/media/platform/exynos-gsc/gsc-regs.c +7
-6}@@ -306,17 +309,18 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx) goto end_set; } -for (i =0 ; i < frame->fmt->num_planes; i++) - depth += frame->fmt->depth[i]; +for (i =0 ; i < fmt->num_comp; i++) + depth += fmt->depth[i] / + (fmt->sampling[i][0 ] * fmt->sampling[i][1 ]); -switch (frame->fmt->num_comp) { +switch (fmt->num_comp) {case 1 : cfg |=GSC_OUT_YUV422_1P ; -if (frame->fmt->yorder ==GSC_LSB_Y ) +if (fmt->yorder ==GSC_LSB_Y ) cfg |=GSC_OUT_YUV422_1P_ORDER_LSB_Y ;else - cfg |=GSC_OUT_YUV422_1P_OEDER_LSB_C ; -if (frame->fmt->corder ==GSC_CBCR ) + cfg |=GSC_OUT_YUV422_1P_ORDER_LSB_C ; +if (fmt->corder ==GSC_CBCR ) cfg |=GSC_OUT_CHROMA_ORDER_CBCR ;else drivers/media/platform/exynos-gsc/gsc-regs.c +1
-1cfg |=GSC_OUT_CHROMA_ORDER_CRCB ;@@ -326,7 +330,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx) cfg |=GSC_OUT_YUV420_2P ; else cfg |= GSC_OUT_YUV422_2P; -if (frame->fmt->corder ==GSC_CBCR ) +if (fmt->corder ==GSC_CBCR ) cfg |=GSC_OUT_CHROMA_ORDER_CBCR ;else drivers/media/platform/exynos-gsc/gsc-regs.c +1
-1cfg |=GSC_OUT_CHROMA_ORDER_CRCB ;@@ -336,7 +340,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)break ; } -if (is_tiled (frame->fmt)) +if (is_tiled (fmt)) cfg |= GSC_OUT_TILE_C_16x8 |GSC_OUT_TILE_MODE ;
end_set:drivers/media/platform/exynos-gsc/gsc-regs.h +2
-3@@ -46,7 +46,7 @@#define GSC_IN_RGB_SD_WIDE (0 << 14)#define GSC_IN_YUV422_1P_ORDER_MASK (1 << 13)#define GSC_IN_YUV422_1P_ORDER_LSB_Y (0 << 13) -#define GSC_IN_YUV422_1P_OEDER_LSB_C (1 << 13) +#define GSC_IN_YUV422_1P_ORDER_LSB_C (1 << 13)#define GSC_IN_CHROMA_ORDER_MASK (1 << 12)#define GSC_IN_CHROMA_ORDER_CBCR (0 << 12)#define GSC_IN_CHROMA_ORDER_CRCB (1 << 12)@@ -91,7 +91,7 @@#define GSC_OUT_RGB_SD_NARROW (0 << 10)#define GSC_OUT_YUV422_1P_ORDER_MASK (1 << 9)#define GSC_OUT_YUV422_1P_ORDER_LSB_Y (0 << 9) -#define GSC_OUT_YUV422_1P_OEDER_LSB_C (1 << 9) +#define GSC_OUT_YUV422_1P_ORDER_LSB_C (1 << 9)#define GSC_OUT_CHROMA_ORDER_MASK (1 << 8)#define GSC_OUT_CHROMA_ORDER_CBCR (0 << 8)#define GSC_OUT_CHROMA_ORDER_CRCB (1 << 8) --1.9.0.279.gdc9e3eb
Re: [PATCH 3/4] gsc-m2m: report correct format bytesperline and sizeimage
In reply to John SheuHi John Sheu,
Thanks for the patch.
Please find the review comments inline.
Quoted 226 lines · John Sheu
Explicitly specify sampling period for subsampled chroma formats, so stride and image size are properly reported through VIDIOC_{S,G}_FMT.
Signed-off-by John Sheu <[email protected]>--- drivers/media/platform/exynos-gsc/gsc-core.c | 154 +++++++++++++++------------ drivers/media/platform/exynos-gsc/gsc-core.h | 16 +-- drivers/media/platform/exynos-gsc/gsc-regs.c | 40 +++---- drivers/media/platform/exynos-gsc/gsc-regs.h | 4 +- 4 files changed, 116 insertions(+), 98 deletions(-)drivers/media/platform/exynos-gsc/gsc-core.c +42
-24@@ -34,167 +34,185 @@ static const struct gsc_fmt gsc_formats[] = { { .name = "RGB565", .pixelformat = V4L2_PIX_FMT_RGB565X, - .depth = { 16 }, .color = GSC_RGB, .num_planes = 1, .num_comp = 1, + .depth = { 16 }, + .sampling = { { 1, 1 } }, }, { .name = "XRGB-8-8-8-8, 32 bpp", .pixelformat = V4L2_PIX_FMT_RGB32, - .depth = { 32 }, .color = GSC_RGB, .num_planes = 1, .num_comp = 1, + .depth = { 32 }, + .sampling = { { 1, 1 } }, }, { .name = "YUV 4:2:2 packed, YCbYCr", .pixelformat = V4L2_PIX_FMT_YUYV, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 1, + .depth = { 16 }, + .sampling = { { 1, 1 } }, .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, }, { .name ="YUV 4:2:2 packed, CbYCrY" , .pixelformat = V4L2_PIX_FMT_UYVY, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_C, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 1, + .depth = { 16 }, + .sampling = { { 1, 1 } }, .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, }, { .name ="YUV 4:2:2 packed, CrYCbY" , .pixelformat = V4L2_PIX_FMT_VYUY, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_C, .corder = GSC_CRCB, .num_planes = 1, .num_comp = 1, + .depth = { 16 }, + .sampling = { { 1, 1 } }, .mbus_code = V4L2_MBUS_FMT_VYUY8_2X8, }, { .name ="YUV 4:2:2 packed, YCrYCb" , .pixelformat = V4L2_PIX_FMT_YVYU, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_Y, .corder = GSC_CRCB, .num_planes = 1, .num_comp = 1, + .depth = { 16 }, + .sampling = { { 1, 1 } }, .mbus_code = V4L2_MBUS_FMT_YVYU8_2X8, }, { .name ="YUV 4:4:4 planar, YCbYCr" , .pixelformat = V4L2_PIX_FMT_YUV32, - .depth = { 32 }, .color = GSC_YUV444, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 1, + .depth = { 32 }, + .sampling = { { 1, 1 } }, }, { .name ="YUV 4:2:2 planar, Y/Cb/Cr" , .pixelformat = V4L2_PIX_FMT_YUV422P, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 3, + .depth = { 8, 8, 8 }, + .sampling = { { 1, 1 }, { 2, 1 }, { 2, 1 } }, }, { .name ="YUV 4:2:2 planar, Y/CbCr" , .pixelformat = V4L2_PIX_FMT_NV16, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 2, + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 1 } }, }, { .name ="YUV 4:2:2 planar, Y/CrCb" , .pixelformat = V4L2_PIX_FMT_NV61, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_Y, .corder = GSC_CRCB, .num_planes = 1, .num_comp = 2, + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 1 } }, }, { .name ="YUV 4:2:0 planar, YCbCr" , .pixelformat = V4L2_PIX_FMT_YUV420, - .depth = { 12 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 3, + .depth = { 8, 8, 8 }, + .sampling = { { 1, 1 }, { 2, 2 }, { 2, 2 } }, }, { .name ="YUV 4:2:0 planar, YCrCb" , .pixelformat = V4L2_PIX_FMT_YVU420, - .depth = { 12 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CRCB, .num_planes = 1, .num_comp = 3, - + .depth = { 8, 8, 8 }, + .sampling = { { 1, 1 }, { 2, 2 }, { 2, 2 } }, }, { .name ="YUV 4:2:0 planar, Y/CbCr" , .pixelformat = V4L2_PIX_FMT_NV12, - .depth = { 12 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 2, + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 2 } }, }, { .name ="YUV 4:2:0 planar, Y/CrCb" , .pixelformat = V4L2_PIX_FMT_NV21, - .depth = { 12 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CRCB, .num_planes = 1, .num_comp = 2, + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 2 } }, }, { - .name = "YUV 4:2:0 non-contig. 2p, Y/CbCr", + .name ="YUV 4:2:0 non-contiguous 2-planar, Y/CbCr" , .pixelformat = V4L2_PIX_FMT_NV12M, - .depth = { 8, 4 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 2, .num_comp = 2, + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 2 } }, }, { - .name = "YUV 4:2:0 non-contig. 3p, Y/Cb/Cr", + .name ="YUV 4:2:0 non-contiguous 3-planar, Y/Cb/Cr" , .pixelformat = V4L2_PIX_FMT_YUV420M, - .depth = { 8, 2, 2 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 3, .num_comp = 3, + .depth = { 8, 8, 8 }, + .sampling = { { 1, 1 }, { 2, 2 }, { 2, 2 } }, }, { - .name = "YUV 4:2:0 non-contig. 3p, Y/Cr/Cb", + .name ="YUV 4:2:0 non-contiguous 3-planar, Y/Cr/Cb" , .pixelformat = V4L2_PIX_FMT_YVU420M, - .depth = { 8, 2, 2 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CRCB, .num_planes = 3, .num_comp = 3, + .depth = { 8, 8, 8 }, + .sampling = { { 1, 1 }, { 2, 2 }, { 2, 2 } }, }, { - .name = "YUV 4:2:0 n.c. 2p, Y/CbCr tiled", + .name = +"YUV 4:2:0 non-contiguous 2-planar, Y/CbCr, tiled" , .pixelformat = V4L2_PIX_FMT_NV12MT_16X16, - .depth = { 8, 4 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 2, .num_comp = 2, - } + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 2 } }, + }, };const struct gsc_fmt *get_format (int index)
drivers/media/platform/exynos-gsc/gsc-core.c void gsc_set_prefbuf(struct gsc_dev *gsc, struct gsc_frame *frm) · line 410
Quoted 9 lines
drivers/media/platform/exynos-gsc/gsc-core.c +6
-0@@ -384,6 +402,14 @@ void gsc_set_prefbuf(struct gsc_dev *gsc, struct gsc_frame *frm) f_chk_addr, f_chk_len, s_chk_addr, s_chk_len); } +static void get_format_size (__u32 width,__u32 height, +const struct gsc_fmt *fmt,int plane, +__u16 *bytesperline,__u32 *sizeimage) { +__u16 bpl = ((width * fmt->depth[plane]) / fmt->sampling[plane][0 ]) /8 ; + *bytesperline = bpl; + *sizeimage = (height * bpl) / fmt->sampling[plane][0 ];
should use the height sampling instead ?? *sizeimage = (height * bpl) / fmt->sampling[plane][1];
Quoted 127 lines
drivers/media/platform/exynos-gsc/gsc-core.c +35
-40+} +int gsc_try_fmt_mplane (struct gsc_ctx *ctx,struct v4l2_format *f) {struct gsc_dev *gsc = ctx->gsc_dev;@@ -448,14 +474,16 @@ int gsc_try_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f)else /* SD */ pix_mp->colorspace =V4L2_COLORSPACE_SMPTE170M ; - +/* V4L2 specifies for contiguous planar formats that bytesperline and +sizeimage are set to values appropriate for the first plane. */ for (i =0 ; i < pix_mp->num_planes; ++i) { -int bpl = (pix_mp->width * fmt->depth[i]) >>3 ; - pix_mp->plane_fmt[i].bytesperline = bpl; - pix_mp->plane_fmt[i].sizeimage = bpl * pix_mp->height; +get_format_size (pix_mp->width, pix_mp->height, fmt, i, + &pix_mp->plane_fmt[i].bytesperline, + &pix_mp->plane_fmt[i].sizeimage);pr_debug ("[%d]: bpl: %d, sizeimage: %d" , - i, bpl, pix_mp->plane_fmt[i].sizeimage); + i, pix_mp->plane_fmt[i].bytesperline, + pix_mp->plane_fmt[i].sizeimage); }return 0 ;@@ -465,26 +493,27 @@ int gsc_g_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f) {struct gsc_frame *frame;struct v4l2_pix_format_mplane *pix_mp; +const struct gsc_fmt *fmt;int i; frame =ctx_get_frame (ctx, f->type);if (IS_ERR (frame))return PTR_ERR (frame); + fmt = frame->fmt; pix_mp = &f->fmt.pix_mp; pix_mp->width = frame->f_width; pix_mp->height = frame->f_height; pix_mp->field =V4L2_FIELD_NONE ; - pix_mp->pixelformat = frame->fmt->pixelformat; + pix_mp->pixelformat = fmt->pixelformat; pix_mp->colorspace =V4L2_COLORSPACE_REC709 ; - pix_mp->num_planes = frame->fmt->num_planes; + pix_mp->num_planes = fmt->num_planes;for (i =0 ; i < pix_mp->num_planes; ++i) { - pix_mp->plane_fmt[i].bytesperline = (frame->f_width * - frame->fmt->depth[i]) /8 ; - pix_mp->plane_fmt[i].sizeimage = - pix_mp->plane_fmt[i].bytesperline * frame->f_height; +get_format_size (pix_mp->width, pix_mp->height, fmt, i, + &pix_mp->plane_fmt[i].bytesperline, + &pix_mp->plane_fmt[i].sizeimage); }return 0 ;@@ -794,11 +823,12 @@ void gsc_ctrls_delete(struct gsc_ctx *ctx) } } -/* The color format (num_comp, num_planes) must be already configured. */ +/* The color format (num_planes, num_comp) must be already configured. */ int gsc_prepare_addr (struct gsc_ctx *ctx,struct vb2_buffer *vb,struct gsc_frame *frame,struct gsc_addr *addr) {int ret =0 ; +const struct gsc_fmt *fmt = frame->fmt;u32 pix_size;if ((vb ==NULL ) || (frame ==NULL ))@@ -810,46 +840,30 @@ int gsc_prepare_addr(struct gsc_ctx *ctx, struct vb2_buffer *vb, frame->fmt->num_planes, frame->fmt->num_comp, pix_size); addr->y =vb2_dma_contig_plane_dma_addr (vb,0 ); - -if (frame->fmt->num_planes ==1 ) { -switch (frame->fmt->num_comp) { -case 1 : - addr->cb =0 ; - addr->cr =0 ; -break ; -case 2 : -/* decompose Y into Y/Cb */ - addr->cb = (dma_addr_t)(addr->y + pix_size); - addr->cr =0 ; -break ; -case 3 : -/* decompose Y into Y/Cb/Cr */ - addr->cb = (dma_addr_t)(addr->y + pix_size); -if (GSC_YUV420 == frame->fmt->color) - addr->cr = (dma_addr_t)(addr->cb - + (pix_size >>2 )); -else /* 422 */ - addr->cr = (dma_addr_t)(addr->cb - + (pix_size >>1 )); -break ; -default : -pr_err ("Invalid the number of color planes" ); -return -EINVAL ; + addr->cb =0 ; + addr->cr =0 ; + +if (fmt->num_planes ==1 ) { +if (fmt->num_comp >=2 ) { + addr->cb = (dma_addr_t)(addr->y + + ((pix_size * fmt->depth[0 ]) / + (fmt->sampling[0 ][0 ] * + fmt->sampling[0 ][1 ]) /8 )); + } +if (fmt->num_comp >=3 ) { + addr->cr = (dma_addr_t)(addr->cb + + ((pix_size * fmt->depth[1 ]) / + (fmt->sampling[1 ][0 ] * + fmt->sampling[1 ][1 ]) /8 )); } }else { -if (frame->fmt->num_planes >=2 ) +if (fmt->num_comp >=2 ) addr->cb =vb2_dma_contig_plane_dma_addr (vb,1 ); - -if (frame->fmt->num_planes ==3 ) +if (fmt->num_comp ==3 )
drivers/media/platform/exynos-gsc/gsc-core.c int gsc_prepare_addr(struct gsc_ctx *ctx, struct vb2_buffer *vb, · line 866
Quoted 10 lines
drivers/media/platform/exynos-gsc/gsc-core.c +1
-6addr->cr =vb2_dma_contig_plane_dma_addr (vb,2 ); } -if ((frame->fmt->pixelformat ==V4L2_PIX_FMT_VYUY ) || - (frame->fmt->pixelformat ==V4L2_PIX_FMT_YVYU ) || - (frame->fmt->pixelformat ==V4L2_PIX_FMT_NV61 ) || - (frame->fmt->pixelformat ==V4L2_PIX_FMT_YVU420 ) || - (frame->fmt->pixelformat ==V4L2_PIX_FMT_NV21 ) || - (frame->fmt->pixelformat ==V4L2_PIX_FMT_YVU420M )) +if (fmt->corder ==GSC_CRCB )
if ((fmt->corder == GSC_CRCB) && (fmt->num_planes == 3))
I think it shoud only applicable to 3 component formats. for example, Incase of two component formats like V4L2_PIX_FMT_NV61, chroma base address becomes zero.
Regards,
Shaik Ameer Basha
Quoted 192 lines
drivers/media/platform/exynos-gsc/gsc-core.c +0
-0swap (addr->cb, addr->cr); pr_debug("ADDR: y= 0x%X cb= 0x%X cr= 0x%X ret= %d",drivers/media/platform/exynos-gsc/gsc-core.h +8
-8@@ -106,27 +106,27 @@ enum gsc_yuv_fmt { container_of((__ctrl)->handler, struct gsc_ctx, ctrl_handler)/** * struct gsc_fmt - the driver's internal color format data -* @mbus_code: Media Bus pixel code, -1 if not applicable * @name: format description * @pixelformat: the fourcc code for this format, 0 if not applicable * @yorder: Y/C order * @corder: Chrominance order control * @num_planes: number of physically non-contiguous data planes -* @nr_comp: number of physically contiguous data planes -* @depth: per plane driver's private 'number of bits per pixel' -* @flags: flags indicating which operation mode format applies to +* @num_comp: number of physically contiguous data planes +* @depth: bit depth of each component +* @sampling: sampling frequency of each components, X and Y +* @mbus_code: Media Bus pixel code, -1 if not applicable */struct gsc_fmt { -enum v4l2_mbus_pixelcode mbus_code;char *name;u32 pixelformat;u32 color;u32 yorder;u32 corder; -u16 num_planes; -u16 num_comp; +u8 num_planes; +u8 num_comp;u8 depth[VIDEO_MAX_PLANES ]; -u32 flags; +u8 sampling[VIDEO_MAX_PLANES ][2 ]; +enum v4l2_mbus_pixelcode mbus_code; };/** drivers/media/platform/exynos-gsc/gsc-regs.c +22
-18@@ -167,6 +167,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx) {struct gsc_dev *dev = ctx->gsc_dev;struct gsc_frame *frame = &ctx->s_frame; +const struct gsc_fmt *fmt = frame->fmt;u32 i, depth =0 ;u32 cfg;@@ -176,21 +177,22 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx) GSC_IN_TILE_TYPE_MASK | GSC_IN_TILE_MODE);writel (cfg, dev->regs +GSC_IN_CON ); -if (is_rgb (frame->fmt->color)) { +if (is_rgb (fmt->color)) {gsc_hw_set_in_image_rgb (ctx);return ; } -for (i =0 ; i < frame->fmt->num_planes; i++) - depth += frame->fmt->depth[i]; +for (i =0 ; i < fmt->num_comp; i++) + depth += fmt->depth[i] / + (fmt->sampling[i][0 ] * fmt->sampling[i][1 ]); -switch (frame->fmt->num_comp) { +switch (fmt->num_comp) {case 1 : cfg |=GSC_IN_YUV422_1P ; -if (frame->fmt->yorder ==GSC_LSB_Y ) +if (fmt->yorder ==GSC_LSB_Y ) cfg |=GSC_IN_YUV422_1P_ORDER_LSB_Y ;else - cfg |=GSC_IN_YUV422_1P_OEDER_LSB_C ; -if (frame->fmt->corder ==GSC_CBCR ) + cfg |=GSC_IN_YUV422_1P_ORDER_LSB_C ; +if (fmt->corder ==GSC_CBCR ) cfg |=GSC_IN_CHROMA_ORDER_CBCR ;else cfg |=GSC_IN_CHROMA_ORDER_CRCB ;@@ -200,7 +202,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx) cfg |=GSC_IN_YUV420_2P ; else cfg |= GSC_IN_YUV422_2P; -if (frame->fmt->corder ==GSC_CBCR ) +if (fmt->corder ==GSC_CBCR ) cfg |=GSC_IN_CHROMA_ORDER_CBCR ;else cfg |=GSC_IN_CHROMA_ORDER_CRCB ;@@ -213,7 +215,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)break ; } -if (is_tiled (frame->fmt)) +if (is_tiled (fmt)) cfg |= GSC_IN_TILE_C_16x8 |GSC_IN_TILE_MODE ;writel (cfg, dev->regs +GSC_IN_CON );@@ -287,6 +289,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx) {struct gsc_dev *dev = ctx->gsc_dev;struct gsc_frame *frame = &ctx->d_frame; +const struct gsc_fmt *fmt = frame->fmt;u32 i, depth =0 ;u32 cfg;@@ -296,7 +299,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx) GSC_OUT_TILE_TYPE_MASK | GSC_OUT_TILE_MODE);writel (cfg, dev->regs +GSC_OUT_CON ); -if (is_rgb (frame->fmt->color)) { +if (is_rgb (fmt->color)) {gsc_hw_set_out_image_rgb (ctx);return ; }@@ -306,17 +309,18 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx) goto end_set; } -for (i =0 ; i < frame->fmt->num_planes; i++) - depth += frame->fmt->depth[i]; +for (i =0 ; i < fmt->num_comp; i++) + depth += fmt->depth[i] / + (fmt->sampling[i][0 ] * fmt->sampling[i][1 ]); -switch (frame->fmt->num_comp) { +switch (fmt->num_comp) {case 1 : cfg |=GSC_OUT_YUV422_1P ; -if (frame->fmt->yorder ==GSC_LSB_Y ) +if (fmt->yorder ==GSC_LSB_Y ) cfg |=GSC_OUT_YUV422_1P_ORDER_LSB_Y ;else - cfg |=GSC_OUT_YUV422_1P_OEDER_LSB_C ; -if (frame->fmt->corder ==GSC_CBCR ) + cfg |=GSC_OUT_YUV422_1P_ORDER_LSB_C ; +if (fmt->corder ==GSC_CBCR ) cfg |=GSC_OUT_CHROMA_ORDER_CBCR ;else cfg |=GSC_OUT_CHROMA_ORDER_CRCB ;@@ -326,7 +330,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx) cfg |=GSC_OUT_YUV420_2P ; else cfg |= GSC_OUT_YUV422_2P; -if (frame->fmt->corder ==GSC_CBCR ) +if (fmt->corder ==GSC_CBCR ) cfg |=GSC_OUT_CHROMA_ORDER_CBCR ;else cfg |=GSC_OUT_CHROMA_ORDER_CRCB ;@@ -336,7 +340,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)break ; } -if (is_tiled (frame->fmt)) +if (is_tiled (fmt)) cfg |= GSC_OUT_TILE_C_16x8 |GSC_OUT_TILE_MODE ; end_set:drivers/media/platform/exynos-gsc/gsc-regs.h +2
-3@@ -46,7 +46,7 @@#define GSC_IN_RGB_SD_WIDE (0 << 14)#define GSC_IN_YUV422_1P_ORDER_MASK (1 << 13)#define GSC_IN_YUV422_1P_ORDER_LSB_Y (0 << 13) -#define GSC_IN_YUV422_1P_OEDER_LSB_C (1 << 13) +#define GSC_IN_YUV422_1P_ORDER_LSB_C (1 << 13)#define GSC_IN_CHROMA_ORDER_MASK (1 << 12)#define GSC_IN_CHROMA_ORDER_CBCR (0 << 12)#define GSC_IN_CHROMA_ORDER_CRCB (1 << 12)@@ -91,7 +91,7 @@#define GSC_OUT_RGB_SD_NARROW (0 << 10)#define GSC_OUT_YUV422_1P_ORDER_MASK (1 << 9)#define GSC_OUT_YUV422_1P_ORDER_LSB_Y (0 << 9) -#define GSC_OUT_YUV422_1P_OEDER_LSB_C (1 << 9) +#define GSC_OUT_YUV422_1P_ORDER_LSB_C (1 << 9)#define GSC_OUT_CHROMA_ORDER_MASK (1 << 8)#define GSC_OUT_CHROMA_ORDER_CBCR (0 << 8)#define GSC_OUT_CHROMA_ORDER_CRCB (1 << 8) --1.9.0.279.gdc9e3eb
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 3/4] gsc-m2m: report correct format bytesperline and sizeimage
Quoted 375 lines · Shaik Ameer Basha
Hi John Sheu,
Thanks for the patch.
Please find the review comments inline.Quoted 226 lines · John Sheu
Explicitly specify sampling period for subsampled chroma formats, so stride and image size are properly reported through VIDIOC_{S,G}_FMT.
Signed-off-by John Sheu <[email protected]>--- drivers/media/platform/exynos-gsc/gsc-core.c | 154 +++++++++++++++------------ drivers/media/platform/exynos-gsc/gsc-core.h | 16 +-- drivers/media/platform/exynos-gsc/gsc-regs.c | 40 +++---- drivers/media/platform/exynos-gsc/gsc-regs.h | 4 +- 4 files changed, 116 insertions(+), 98 deletions(-)drivers/media/platform/exynos-gsc/gsc-core.c +42
-24@@ -34,167 +34,185 @@ static const struct gsc_fmt gsc_formats[] = { { .name = "RGB565", .pixelformat = V4L2_PIX_FMT_RGB565X, - .depth = { 16 }, .color = GSC_RGB, .num_planes = 1, .num_comp = 1, + .depth = { 16 }, + .sampling = { { 1, 1 } }, }, { .name = "XRGB-8-8-8-8, 32 bpp", .pixelformat = V4L2_PIX_FMT_RGB32, - .depth = { 32 }, .color = GSC_RGB, .num_planes = 1, .num_comp = 1, + .depth = { 32 }, + .sampling = { { 1, 1 } }, }, { .name = "YUV 4:2:2 packed, YCbYCr", .pixelformat = V4L2_PIX_FMT_YUYV, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 1, + .depth = { 16 }, + .sampling = { { 1, 1 } }, .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, }, { .name ="YUV 4:2:2 packed, CbYCrY" , .pixelformat = V4L2_PIX_FMT_UYVY, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_C, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 1, + .depth = { 16 }, + .sampling = { { 1, 1 } }, .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8, }, { .name ="YUV 4:2:2 packed, CrYCbY" , .pixelformat = V4L2_PIX_FMT_VYUY, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_C, .corder = GSC_CRCB, .num_planes = 1, .num_comp = 1, + .depth = { 16 }, + .sampling = { { 1, 1 } }, .mbus_code = V4L2_MBUS_FMT_VYUY8_2X8, }, { .name ="YUV 4:2:2 packed, YCrYCb" , .pixelformat = V4L2_PIX_FMT_YVYU, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_Y, .corder = GSC_CRCB, .num_planes = 1, .num_comp = 1, + .depth = { 16 }, + .sampling = { { 1, 1 } }, .mbus_code = V4L2_MBUS_FMT_YVYU8_2X8, }, { .name ="YUV 4:4:4 planar, YCbYCr" , .pixelformat = V4L2_PIX_FMT_YUV32, - .depth = { 32 }, .color = GSC_YUV444, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 1, + .depth = { 32 }, + .sampling = { { 1, 1 } }, }, { .name ="YUV 4:2:2 planar, Y/Cb/Cr" , .pixelformat = V4L2_PIX_FMT_YUV422P, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 3, + .depth = { 8, 8, 8 }, + .sampling = { { 1, 1 }, { 2, 1 }, { 2, 1 } }, }, { .name ="YUV 4:2:2 planar, Y/CbCr" , .pixelformat = V4L2_PIX_FMT_NV16, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 2, + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 1 } }, }, { .name ="YUV 4:2:2 planar, Y/CrCb" , .pixelformat = V4L2_PIX_FMT_NV61, - .depth = { 16 }, .color = GSC_YUV422, .yorder = GSC_LSB_Y, .corder = GSC_CRCB, .num_planes = 1, .num_comp = 2, + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 1 } }, }, { .name ="YUV 4:2:0 planar, YCbCr" , .pixelformat = V4L2_PIX_FMT_YUV420, - .depth = { 12 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 3, + .depth = { 8, 8, 8 }, + .sampling = { { 1, 1 }, { 2, 2 }, { 2, 2 } }, }, { .name ="YUV 4:2:0 planar, YCrCb" , .pixelformat = V4L2_PIX_FMT_YVU420, - .depth = { 12 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CRCB, .num_planes = 1, .num_comp = 3, - + .depth = { 8, 8, 8 }, + .sampling = { { 1, 1 }, { 2, 2 }, { 2, 2 } }, }, { .name ="YUV 4:2:0 planar, Y/CbCr" , .pixelformat = V4L2_PIX_FMT_NV12, - .depth = { 12 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 1, .num_comp = 2, + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 2 } }, }, { .name ="YUV 4:2:0 planar, Y/CrCb" , .pixelformat = V4L2_PIX_FMT_NV21, - .depth = { 12 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CRCB, .num_planes = 1, .num_comp = 2, + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 2 } }, }, { - .name = "YUV 4:2:0 non-contig. 2p, Y/CbCr", + .name ="YUV 4:2:0 non-contiguous 2-planar, Y/CbCr" , .pixelformat = V4L2_PIX_FMT_NV12M, - .depth = { 8, 4 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 2, .num_comp = 2, + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 2 } }, }, { - .name = "YUV 4:2:0 non-contig. 3p, Y/Cb/Cr", + .name ="YUV 4:2:0 non-contiguous 3-planar, Y/Cb/Cr" , .pixelformat = V4L2_PIX_FMT_YUV420M, - .depth = { 8, 2, 2 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 3, .num_comp = 3, + .depth = { 8, 8, 8 }, + .sampling = { { 1, 1 }, { 2, 2 }, { 2, 2 } }, }, { - .name = "YUV 4:2:0 non-contig. 3p, Y/Cr/Cb", + .name ="YUV 4:2:0 non-contiguous 3-planar, Y/Cr/Cb" , .pixelformat = V4L2_PIX_FMT_YVU420M, - .depth = { 8, 2, 2 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CRCB, .num_planes = 3, .num_comp = 3, + .depth = { 8, 8, 8 }, + .sampling = { { 1, 1 }, { 2, 2 }, { 2, 2 } }, }, { - .name = "YUV 4:2:0 n.c. 2p, Y/CbCr tiled", + .name = +"YUV 4:2:0 non-contiguous 2-planar, Y/CbCr, tiled" , .pixelformat = V4L2_PIX_FMT_NV12MT_16X16, - .depth = { 8, 4 }, .color = GSC_YUV420, .yorder = GSC_LSB_Y, .corder = GSC_CBCR, .num_planes = 2, .num_comp = 2, - } + .depth = { 8, 16 }, + .sampling = { { 1, 1 }, { 2, 2 } }, + }, };const struct gsc_fmt *get_format (int index)drivers/media/platform/exynos-gsc/gsc-core.c void gsc_set_prefbuf(struct gsc_dev *gsc, struct gsc_frame *frm) · line 410
Quoted 9 lines
drivers/media/platform/exynos-gsc/gsc-core.c +6
-0@@ -384,6 +402,14 @@ void gsc_set_prefbuf(struct gsc_dev *gsc, struct gsc_frame *frm) f_chk_addr, f_chk_len, s_chk_addr, s_chk_len); } +static void get_format_size (__u32 width,__u32 height, +const struct gsc_fmt *fmt,int plane, +__u16 *bytesperline,__u32 *sizeimage) { +__u16 bpl = ((width * fmt->depth[plane]) / fmt->sampling[plane][0 ]) /8 ; + *bytesperline = bpl; + *sizeimage = (height * bpl) / fmt->sampling[plane][0 ];should use the height sampling instead ?? *sizeimage = (height * bpl) / fmt->sampling[plane][1];
Quoted 130 lines
drivers/media/platform/exynos-gsc/gsc-core.c +35
-40+} +int gsc_try_fmt_mplane (struct gsc_ctx *ctx,struct v4l2_format *f) {struct gsc_dev *gsc = ctx->gsc_dev;@@ -448,14 +474,16 @@ int gsc_try_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f)else /* SD */ pix_mp->colorspace =V4L2_COLORSPACE_SMPTE170M ; - +/* V4L2 specifies for contiguous planar formats that bytesperline and +sizeimage are set to values appropriate for the first plane. */ for (i =0 ; i < pix_mp->num_planes; ++i) { -int bpl = (pix_mp->width * fmt->depth[i]) >>3 ; - pix_mp->plane_fmt[i].bytesperline = bpl; - pix_mp->plane_fmt[i].sizeimage = bpl * pix_mp->height; +get_format_size (pix_mp->width, pix_mp->height, fmt, i, + &pix_mp->plane_fmt[i].bytesperline, + &pix_mp->plane_fmt[i].sizeimage);pr_debug ("[%d]: bpl: %d, sizeimage: %d" , - i, bpl, pix_mp->plane_fmt[i].sizeimage); + i, pix_mp->plane_fmt[i].bytesperline, + pix_mp->plane_fmt[i].sizeimage); }return 0 ;@@ -465,26 +493,27 @@ int gsc_g_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f) {struct gsc_frame *frame;struct v4l2_pix_format_mplane *pix_mp; +const struct gsc_fmt *fmt;int i; frame =ctx_get_frame (ctx, f->type);if (IS_ERR (frame))return PTR_ERR (frame); + fmt = frame->fmt; pix_mp = &f->fmt.pix_mp; pix_mp->width = frame->f_width; pix_mp->height = frame->f_height; pix_mp->field =V4L2_FIELD_NONE ; - pix_mp->pixelformat = frame->fmt->pixelformat; + pix_mp->pixelformat = fmt->pixelformat; pix_mp->colorspace =V4L2_COLORSPACE_REC709 ; - pix_mp->num_planes = frame->fmt->num_planes; + pix_mp->num_planes = fmt->num_planes;for (i =0 ; i < pix_mp->num_planes; ++i) { - pix_mp->plane_fmt[i].bytesperline = (frame->f_width * - frame->fmt->depth[i]) /8 ; - pix_mp->plane_fmt[i].sizeimage = - pix_mp->plane_fmt[i].bytesperline * frame->f_height; +get_format_size (pix_mp->width, pix_mp->height, fmt, i, + &pix_mp->plane_fmt[i].bytesperline, + &pix_mp->plane_fmt[i].sizeimage); }return 0 ;@@ -794,11 +823,12 @@ void gsc_ctrls_delete(struct gsc_ctx *ctx) } } -/* The color format (num_comp, num_planes) must be already configured. */ +/* The color format (num_planes, num_comp) must be already configured. */ int gsc_prepare_addr (struct gsc_ctx *ctx,struct vb2_buffer *vb,struct gsc_frame *frame,struct gsc_addr *addr) {int ret =0 ; +const struct gsc_fmt *fmt = frame->fmt;u32 pix_size;if ((vb ==NULL ) || (frame ==NULL ))@@ -810,46 +840,30 @@ int gsc_prepare_addr(struct gsc_ctx *ctx, struct vb2_buffer *vb, frame->fmt->num_planes, frame->fmt->num_comp, pix_size); addr->y =vb2_dma_contig_plane_dma_addr (vb,0 ); - -if (frame->fmt->num_planes ==1 ) { -switch (frame->fmt->num_comp) { -case 1 : - addr->cb =0 ; - addr->cr =0 ; -break ; -case 2 : -/* decompose Y into Y/Cb */ - addr->cb = (dma_addr_t)(addr->y + pix_size); - addr->cr =0 ; -break ; -case 3 : -/* decompose Y into Y/Cb/Cr */ - addr->cb = (dma_addr_t)(addr->y + pix_size); -if (GSC_YUV420 == frame->fmt->color) - addr->cr = (dma_addr_t)(addr->cb - + (pix_size >>2 )); -else /* 422 */ - addr->cr = (dma_addr_t)(addr->cb - + (pix_size >>1 )); -break ; -default : -pr_err ("Invalid the number of color planes" ); -return -EINVAL ; + addr->cb =0 ; + addr->cr =0 ; + +if (fmt->num_planes ==1 ) { +if (fmt->num_comp >=2 ) { + addr->cb = (dma_addr_t)(addr->y + + ((pix_size * fmt->depth[0 ]) / + (fmt->sampling[0 ][0 ] * + fmt->sampling[0 ][1 ]) /8 )); + } +if (fmt->num_comp >=3 ) { + addr->cr = (dma_addr_t)(addr->cb + + ((pix_size * fmt->depth[1 ]) / + (fmt->sampling[1 ][0 ] * + fmt->sampling[1 ][1 ]) /8 )); } }else { -if (frame->fmt->num_planes >=2 ) +if (fmt->num_comp >=2 ) addr->cb =vb2_dma_contig_plane_dma_addr (vb,1 ); - -if (frame->fmt->num_planes ==3 ) +if (fmt->num_comp ==3 ) addr->cr =vb2_dma_contig_plane_dma_addr (vb,2 ); }
Quoted 9 lines
drivers/media/platform/exynos-gsc/gsc-core.c int gsc_prepare_addr(struct gsc_ctx *ctx, struct vb2_buffer *vb, · line 866
Quoted 7 lines
drivers/media/platform/exynos-gsc/gsc-core.c +1
-6-if ((frame->fmt->pixelformat ==V4L2_PIX_FMT_VYUY ) || - (frame->fmt->pixelformat ==V4L2_PIX_FMT_YVYU ) || - (frame->fmt->pixelformat ==V4L2_PIX_FMT_NV61 ) || - (frame->fmt->pixelformat ==V4L2_PIX_FMT_YVU420 ) || - (frame->fmt->pixelformat ==V4L2_PIX_FMT_NV21 ) || - (frame->fmt->pixelformat ==V4L2_PIX_FMT_YVU420M )) +if (fmt->corder ==GSC_CRCB )if ((fmt->corder == GSC_CRCB) && (fmt->num_planes == 3))
sorry, it is....
if ((fmt->corder == GSC_CRCB) && (fmt->num_comp == 3))
Quoted 201 lines
I think it shoud only applicable to 3 component formats. for example, Incase of two component formats like
V4L2_PIX_FMT_NV61, chroma base address becomes zero.Regards,
Shaik Ameer BashaQuoted 192 lines
drivers/media/platform/exynos-gsc/gsc-core.c +0
-0swap (addr->cb, addr->cr); pr_debug("ADDR: y= 0x%X cb= 0x%X cr= 0x%X ret= %d",drivers/media/platform/exynos-gsc/gsc-core.h +8
-8@@ -106,27 +106,27 @@ enum gsc_yuv_fmt { container_of((__ctrl)->handler, struct gsc_ctx, ctrl_handler)/** * struct gsc_fmt - the driver's internal color format data -* @mbus_code: Media Bus pixel code, -1 if not applicable * @name: format description * @pixelformat: the fourcc code for this format, 0 if not applicable * @yorder: Y/C order * @corder: Chrominance order control * @num_planes: number of physically non-contiguous data planes -* @nr_comp: number of physically contiguous data planes -* @depth: per plane driver's private 'number of bits per pixel' -* @flags: flags indicating which operation mode format applies to +* @num_comp: number of physically contiguous data planes +* @depth: bit depth of each component +* @sampling: sampling frequency of each components, X and Y +* @mbus_code: Media Bus pixel code, -1 if not applicable */struct gsc_fmt { -enum v4l2_mbus_pixelcode mbus_code;char *name;u32 pixelformat;u32 color;u32 yorder;u32 corder; -u16 num_planes; -u16 num_comp; +u8 num_planes; +u8 num_comp;u8 depth[VIDEO_MAX_PLANES ]; -u32 flags; +u8 sampling[VIDEO_MAX_PLANES ][2 ]; +enum v4l2_mbus_pixelcode mbus_code; };/** drivers/media/platform/exynos-gsc/gsc-regs.c +22
-18@@ -167,6 +167,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx) {struct gsc_dev *dev = ctx->gsc_dev;struct gsc_frame *frame = &ctx->s_frame; +const struct gsc_fmt *fmt = frame->fmt;u32 i, depth =0 ;u32 cfg;@@ -176,21 +177,22 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx) GSC_IN_TILE_TYPE_MASK | GSC_IN_TILE_MODE);writel (cfg, dev->regs +GSC_IN_CON ); -if (is_rgb (frame->fmt->color)) { +if (is_rgb (fmt->color)) {gsc_hw_set_in_image_rgb (ctx);return ; } -for (i =0 ; i < frame->fmt->num_planes; i++) - depth += frame->fmt->depth[i]; +for (i =0 ; i < fmt->num_comp; i++) + depth += fmt->depth[i] / + (fmt->sampling[i][0 ] * fmt->sampling[i][1 ]); -switch (frame->fmt->num_comp) { +switch (fmt->num_comp) {case 1 : cfg |=GSC_IN_YUV422_1P ; -if (frame->fmt->yorder ==GSC_LSB_Y ) +if (fmt->yorder ==GSC_LSB_Y ) cfg |=GSC_IN_YUV422_1P_ORDER_LSB_Y ;else - cfg |=GSC_IN_YUV422_1P_OEDER_LSB_C ; -if (frame->fmt->corder ==GSC_CBCR ) + cfg |=GSC_IN_YUV422_1P_ORDER_LSB_C ; +if (fmt->corder ==GSC_CBCR ) cfg |=GSC_IN_CHROMA_ORDER_CBCR ;else cfg |=GSC_IN_CHROMA_ORDER_CRCB ;@@ -200,7 +202,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx) cfg |=GSC_IN_YUV420_2P ; else cfg |= GSC_IN_YUV422_2P; -if (frame->fmt->corder ==GSC_CBCR ) +if (fmt->corder ==GSC_CBCR ) cfg |=GSC_IN_CHROMA_ORDER_CBCR ;else cfg |=GSC_IN_CHROMA_ORDER_CRCB ;@@ -213,7 +215,7 @@ void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)break ; } -if (is_tiled (frame->fmt)) +if (is_tiled (fmt)) cfg |= GSC_IN_TILE_C_16x8 |GSC_IN_TILE_MODE ;writel (cfg, dev->regs +GSC_IN_CON );@@ -287,6 +289,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx) {struct gsc_dev *dev = ctx->gsc_dev;struct gsc_frame *frame = &ctx->d_frame; +const struct gsc_fmt *fmt = frame->fmt;u32 i, depth =0 ;u32 cfg;@@ -296,7 +299,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx) GSC_OUT_TILE_TYPE_MASK | GSC_OUT_TILE_MODE);writel (cfg, dev->regs +GSC_OUT_CON ); -if (is_rgb (frame->fmt->color)) { +if (is_rgb (fmt->color)) {gsc_hw_set_out_image_rgb (ctx);return ; }@@ -306,17 +309,18 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx) goto end_set; } -for (i =0 ; i < frame->fmt->num_planes; i++) - depth += frame->fmt->depth[i]; +for (i =0 ; i < fmt->num_comp; i++) + depth += fmt->depth[i] / + (fmt->sampling[i][0 ] * fmt->sampling[i][1 ]); -switch (frame->fmt->num_comp) { +switch (fmt->num_comp) {case 1 : cfg |=GSC_OUT_YUV422_1P ; -if (frame->fmt->yorder ==GSC_LSB_Y ) +if (fmt->yorder ==GSC_LSB_Y ) cfg |=GSC_OUT_YUV422_1P_ORDER_LSB_Y ;else - cfg |=GSC_OUT_YUV422_1P_OEDER_LSB_C ; -if (frame->fmt->corder ==GSC_CBCR ) + cfg |=GSC_OUT_YUV422_1P_ORDER_LSB_C ; +if (fmt->corder ==GSC_CBCR ) cfg |=GSC_OUT_CHROMA_ORDER_CBCR ;else cfg |=GSC_OUT_CHROMA_ORDER_CRCB ;@@ -326,7 +330,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx) cfg |=GSC_OUT_YUV420_2P ; else cfg |= GSC_OUT_YUV422_2P; -if (frame->fmt->corder ==GSC_CBCR ) +if (fmt->corder ==GSC_CBCR ) cfg |=GSC_OUT_CHROMA_ORDER_CBCR ;else cfg |=GSC_OUT_CHROMA_ORDER_CRCB ;@@ -336,7 +340,7 @@ void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)break ; } -if (is_tiled (frame->fmt)) +if (is_tiled (fmt)) cfg |= GSC_OUT_TILE_C_16x8 |GSC_OUT_TILE_MODE ; end_set:drivers/media/platform/exynos-gsc/gsc-regs.h +2
-3@@ -46,7 +46,7 @@#define GSC_IN_RGB_SD_WIDE (0 << 14)#define GSC_IN_YUV422_1P_ORDER_MASK (1 << 13)#define GSC_IN_YUV422_1P_ORDER_LSB_Y (0 << 13) -#define GSC_IN_YUV422_1P_OEDER_LSB_C (1 << 13) +#define GSC_IN_YUV422_1P_ORDER_LSB_C (1 << 13)#define GSC_IN_CHROMA_ORDER_MASK (1 << 12)#define GSC_IN_CHROMA_ORDER_CBCR (0 << 12)#define GSC_IN_CHROMA_ORDER_CRCB (1 << 12)@@ -91,7 +91,7 @@#define GSC_OUT_RGB_SD_NARROW (0 << 10)#define GSC_OUT_YUV422_1P_ORDER_MASK (1 << 9)#define GSC_OUT_YUV422_1P_ORDER_LSB_Y (0 << 9) -#define GSC_OUT_YUV422_1P_OEDER_LSB_C (1 << 9) +#define GSC_OUT_YUV422_1P_ORDER_LSB_C (1 << 9)#define GSC_OUT_CHROMA_ORDER_MASK (1 << 8)#define GSC_OUT_CHROMA_ORDER_CBCR (0 << 8)#define GSC_OUT_CHROMA_ORDER_CRCB (1 << 8) --1.9.0.279.gdc9e3eb
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 4/4 v4l2-mem2mem: allow reqbufs(0) with "in use" MMAP buffers
In reply to John Sheuv4l2-mem2mem presently does not allow VIDIOC_REQBUFS to destroy outstanding buffers if the queue is of type V4L2_MEMORY_MMAP, and if the buffers are considered "in use". This is different behavior than for other memory types, and prevents us for deallocating buffers in a few cases:
* In the case that there are outstanding mmap()ed views on the buffer, refcounting on the videobuf2 buffer backing the vm_area will track lifetime appropriately,
* In the case that the buffer has been exported as a DMABUF, refcounting on the videobuf2 bufer backing the DMABUF will track lifetime appropriately.
Remove the specific check for type V4L2_MEMOMRY_MMAP when freeing all buffers through VIDIOC_REQBUFS.
--- drivers/media/v4l2-core/videobuf2-core.c | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-)
drivers/media/v4l2-core/videobuf2-core.c +1 -25
@@ -414,8 +414,7 @@ static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b) }/** -* __buffer_in_use() - return true if the buffer is in use and -* the queue cannot be freed (by the means of REQBUFS(0)) call +* __buffer_in_use() - return true if the buffer is in use. */ static bool __buffer_in_use (struct vb2_queue *q,struct vb2_buffer *vb) {
@@ -435,20 +434,6 @@ static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb) }/** -* __buffers_in_use() - return true if any buffers on the queue are in use and -* the queue cannot be freed (by the means of REQBUFS(0)) call -*/ -static bool __buffers_in_use (struct vb2_queue *q) -{ -unsigned int buffer; -for (buffer =0 ; buffer < q->num_buffers; ++buffer) { -if (__buffer_in_use (q, q->bufs[buffer])) -return true; - } -return false; -} - -/** * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be * returned to userspace */
@@ -681,15 +666,6 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) }if (req->count ==0 || q->num_buffers !=0 || q->memory != req->memory) { -/* -* We already have buffers allocated, so first check if they -* are not in use and can be freed. -*/ -if (q->memory ==V4L2_MEMORY_MMAP &&__buffers_in_use (q)) { -dprintk (1 ,"reqbufs: memory in use, cannot free\n" ); -return -EBUSY ; - } - ret =__vb2_queue_free (q, q->num_buffers);if (ret)return ret;
Signature · 1 line
1.9.0.279.gdc9e3eb
RE: [PATCH 4/4] v4l2-mem2mem: allow reqbufs(0) with "in use" MMAP buffers
Pawel, Marek,
Before taking this to my tree I wanted to get an ACK from one of the videobuf2 maintainers. Could you spare a moment to look through this patch?
Best wishes,
Signature · 2 lines
Kamil Debski Samsung R&D Institute Poland
Quoted 90 lines
-----Original Message-----
From: John Sheu [mailto:[email protected]]
Sent: Tuesday, March 11, 2014 11:52 PM
To: [email protected]
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; John Sheu
Subject: [PATCH 4/4] v4l2-mem2mem: allow reqbufs(0) with "in use" MMAP buffersv4l2-mem2mem presently does not allow
VIDIOC_REQBUFSto destroy outstanding buffers if the queue is of typeV4L2_MEMORY_MMAP, and if the buffers are considered "in use". This is different behavior than for other memory types, and prevents us for deallocating buffers in a few
cases:* In the case that there are outstanding mmap()ed views on the buffer, refcounting on the videobuf2 buffer backing the
vm_areawill track lifetime appropriately,
* In the case that the buffer has been exported as a DMABUF, refcounting
on the videobuf2 bufer backing the DMABUF will track lifetime appropriately.Remove the specific check for type
V4L2_MEMOMRY_MMAPwhen freeing all buffers throughVIDIOC_REQBUFS.Signed-off-by John Sheu <[email protected]>--- drivers/media/v4l2-core/videobuf2-core.c | 26 +----------------------- -- 1 file changed, 1 insertion(+), 25 deletions(-)drivers/media/v4l2-core/videobuf2-core.c +1
-2@@ -414,8 +414,7 @@ static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b) }/** -* __buffer_in_use() - return true if the buffer is in use and -* the queue cannot be freed (by the means of REQBUFS(0)) call +* __buffer_in_use() - return true if the buffer is in use. */ static bool __buffer_in_use (struct vb2_queue *q,struct vb2_buffer *vb) { @@ -435,20 +434,6 @@ static bool __buffer_in_use(struct
vb2_queue*q, structvb2_buffer*vb) }/**
- *__buffers_in_use()- return true if any buffers on the queue are in use and
- * the queue cannot be freed (by the means of REQBUFS(0)) call
- */drivers/media/v4l2-core/videobuf2-core.c +0
-10-static bool __buffers_in_use(struct vb2_queue *q) -{ -unsigned int buffer; -for (buffer =0 ; buffer < q->num_buffers; ++buffer) { -if (__buffer_in_use (q, q->bufs[buffer])) -return true; - } -return false; -} - -/** * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
* returned to userspace
*/drivers/media/v4l2-core/videobuf2-core.c +0
-2@@ -681,15 +666,6 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) }if (req->count ==0 || q->num_buffers !=0 || q->memory != req- >memory) { -/* -* We already have buffers allocated, so first check if they
drivers/media/v4l2-core/videobuf2-core.c +0
-8-* are not in use and can be freed. -*/ -if (q->memory ==V4L2_MEMORY_MMAP &&__buffers_in_use (q)) { -dprintk (1 ,"reqbufs: memory in use, cannot free\n" ); -return -EBUSY ; - } - ret =__vb2_queue_free (q, q->num_buffers);if (ret)return ret; --1.9.0.279.gdc9e3eb
Re: [PATCH 4/4] v4l2-mem2mem: allow reqbufs(0) with "in use" MMAP buffers
Hello,
Quoted 5 lines · Kamil Debski
Pawel, Marek,
Before taking this to my tree I wanted to get an ACK from one of the videobuf2 maintainers. Could you spare a moment to look through this patch?
It's not a bug, it is a feature. This was one of the fundamental design requirements to allow applications to track if the memory is used or not.
Best regards
Signature · 2 lines
Marek Szyprowski, PhD Samsung R&D Institute Poland
Re: [PATCH 4/4] v4l2-mem2mem: allow reqbufs(0) with "in use" MMAP buffers
Quoted 11 lines · Marek Szyprowski
Hello,
Quoted 7 lines · Kamil Debski
Pawel, Marek,
Before taking this to my tree I wanted to get an ACK from one of the
videobuf2 maintainers. Could you spare a moment to look through this
patch?
Quoted 4 lines
It's not a bug, it is a feature. This was one of the fundamental design
requirements to allow applications to track if the memory is used or not.
I still have the impression it is not fully correct for the case buffers are exported using DMABUF. Like if the dmabuf was owning the vb2 buffer instead of the opposite ...
Nicolas
Re: [PATCH 4/4] v4l2-mem2mem: allow reqbufs(0) with "in use" MMAP buffers
Hi,
2015-11-02 19:31 GMT+01:00 Nicolas Dufresne <[email protected]>:
Quoted 12 lines · Marek Szyprowski
Quoted 11 lines
Hello,
Quoted 7 lines · Kamil Debski
Pawel, Marek,
Before taking this to my tree I wanted to get an ACK from one of the
videobuf2 maintainers. Could you spare a moment to look through this
patch?
Quoted 8 lines
Quoted 4 lines
It's not a bug, it is a feature. This was one of the fundamental design
requirements to allow applications to track if the memory is used or not.I still have the impression it is not fully correct for the case buffers are exported using DMABUF. Like if the dmabuf was owning the vb2 buffer instead of the opposite ...
I am observing this behaviour too... Tried it, but seems to not do the job on dmabuf buffers... with gstreamer at least ;-).
JM