Commit ddcaee9d authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

[media] vivid: add support for single buffer planar formats

Make vivid aware of the difference of planes and buffers. Note that
this does not yet add support for hor/vert downsampled formats.
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent 96c76efa
...@@ -334,7 +334,7 @@ struct vivid_dev { ...@@ -334,7 +334,7 @@ struct vivid_dev {
u32 ycbcr_enc_out; u32 ycbcr_enc_out;
u32 quantization_out; u32 quantization_out;
u32 service_set_out; u32 service_set_out;
u32 bytesperline_out[TPG_MAX_PLANES]; unsigned bytesperline_out[TPG_MAX_PLANES];
unsigned tv_field_out; unsigned tv_field_out;
unsigned tv_audio_output; unsigned tv_audio_output;
bool vbi_out_have_wss; bool vbi_out_have_wss;
......
...@@ -229,6 +229,20 @@ static void vivid_precalc_copy_rects(struct vivid_dev *dev) ...@@ -229,6 +229,20 @@ static void vivid_precalc_copy_rects(struct vivid_dev *dev)
dev->loop_vid_overlay_cap.left, dev->loop_vid_overlay_cap.top); dev->loop_vid_overlay_cap.left, dev->loop_vid_overlay_cap.top);
} }
static void *plane_vaddr(struct tpg_data *tpg, struct vivid_buffer *buf,
unsigned p, unsigned bpl[TPG_MAX_PLANES], unsigned h)
{
unsigned i;
void *vbuf;
if (p == 0 || tpg_g_buffers(tpg) > 1)
return vb2_plane_vaddr(&buf->vb, p);
vbuf = vb2_plane_vaddr(&buf->vb, 0);
for (i = 0; i < p; i++)
vbuf += bpl[i] * h / tpg->vdownsampling[i];
return vbuf;
}
static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf, static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
struct vivid_buffer *vid_cap_buf) struct vivid_buffer *vid_cap_buf)
{ {
...@@ -269,8 +283,10 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf, ...@@ -269,8 +283,10 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
vid_cap_buf->vb.v4l2_buf.field = vid_out_buf->vb.v4l2_buf.field; vid_cap_buf->vb.v4l2_buf.field = vid_out_buf->vb.v4l2_buf.field;
voutbuf = vb2_plane_vaddr(&vid_out_buf->vb, p) + voutbuf = plane_vaddr(tpg, vid_out_buf, p,
vid_out_buf->vb.v4l2_planes[p].data_offset; dev->bytesperline_out, dev->fmt_out_rect.height);
if (p < dev->fmt_out->buffers)
voutbuf += vid_out_buf->vb.v4l2_planes[p].data_offset;
voutbuf += dev->loop_vid_out.left * pixsize + dev->loop_vid_out.top * stride_out; voutbuf += dev->loop_vid_out.left * pixsize + dev->loop_vid_out.top * stride_out;
vcapbuf += dev->compose_cap.left * pixsize + dev->compose_cap.top * stride_cap; vcapbuf += dev->compose_cap.left * pixsize + dev->compose_cap.top * stride_cap;
...@@ -395,6 +411,7 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf, ...@@ -395,6 +411,7 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf) static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
{ {
struct tpg_data *tpg = &dev->tpg;
unsigned factor = V4L2_FIELD_HAS_T_OR_B(dev->field_cap) ? 2 : 1; unsigned factor = V4L2_FIELD_HAS_T_OR_B(dev->field_cap) ? 2 : 1;
unsigned line_height = 16 / factor; unsigned line_height = 16 / factor;
bool is_tv = vivid_is_sdtv_cap(dev); bool is_tv = vivid_is_sdtv_cap(dev);
...@@ -436,28 +453,29 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf) ...@@ -436,28 +453,29 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
} else { } else {
buf->vb.v4l2_buf.field = dev->field_cap; buf->vb.v4l2_buf.field = dev->field_cap;
} }
tpg_s_field(&dev->tpg, buf->vb.v4l2_buf.field, tpg_s_field(tpg, buf->vb.v4l2_buf.field,
dev->field_cap == V4L2_FIELD_ALTERNATE); dev->field_cap == V4L2_FIELD_ALTERNATE);
tpg_s_perc_fill_blank(&dev->tpg, dev->must_blank[buf->vb.v4l2_buf.index]); tpg_s_perc_fill_blank(tpg, dev->must_blank[buf->vb.v4l2_buf.index]);
vivid_precalc_copy_rects(dev); vivid_precalc_copy_rects(dev);
for (p = 0; p < tpg_g_planes(&dev->tpg); p++) { for (p = 0; p < tpg_g_planes(tpg); p++) {
void *vbuf = vb2_plane_vaddr(&buf->vb, p); void *vbuf = plane_vaddr(tpg, buf, p,
tpg->bytesperline, tpg->buf_height);
/* /*
* The first plane of a multiplanar format has a non-zero * The first plane of a multiplanar format has a non-zero
* data_offset. This helps testing whether the application * data_offset. This helps testing whether the application
* correctly supports non-zero data offsets. * correctly supports non-zero data offsets.
*/ */
if (dev->fmt_cap->data_offset[p]) { if (p < tpg_g_buffers(tpg) && dev->fmt_cap->data_offset[p]) {
memset(vbuf, dev->fmt_cap->data_offset[p] & 0xff, memset(vbuf, dev->fmt_cap->data_offset[p] & 0xff,
dev->fmt_cap->data_offset[p]); dev->fmt_cap->data_offset[p]);
vbuf += dev->fmt_cap->data_offset[p]; vbuf += dev->fmt_cap->data_offset[p];
} }
tpg_calc_text_basep(&dev->tpg, basep, p, vbuf); tpg_calc_text_basep(tpg, basep, p, vbuf);
if (!is_loop || vivid_copy_buffer(dev, p, vbuf, buf)) if (!is_loop || vivid_copy_buffer(dev, p, vbuf, buf))
tpg_fillbuffer(&dev->tpg, vivid_get_std_cap(dev), p, vbuf); tpg_fill_plane_buffer(tpg, vivid_get_std_cap(dev), p, vbuf);
} }
dev->must_blank[buf->vb.v4l2_buf.index] = false; dev->must_blank[buf->vb.v4l2_buf.index] = false;
...@@ -476,12 +494,12 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf) ...@@ -476,12 +494,12 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
(dev->field_cap == V4L2_FIELD_ALTERNATE) ? (dev->field_cap == V4L2_FIELD_ALTERNATE) ?
(buf->vb.v4l2_buf.field == V4L2_FIELD_TOP ? (buf->vb.v4l2_buf.field == V4L2_FIELD_TOP ?
" top" : " bottom") : ""); " top" : " bottom") : "");
tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str); tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
} }
if (dev->osd_mode == 0) { if (dev->osd_mode == 0) {
snprintf(str, sizeof(str), " %dx%d, input %d ", snprintf(str, sizeof(str), " %dx%d, input %d ",
dev->src_rect.width, dev->src_rect.height, dev->input); dev->src_rect.width, dev->src_rect.height, dev->input);
tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str); tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
gain = v4l2_ctrl_g_ctrl(dev->gain); gain = v4l2_ctrl_g_ctrl(dev->gain);
mutex_lock(dev->ctrl_hdl_user_vid.lock); mutex_lock(dev->ctrl_hdl_user_vid.lock);
...@@ -491,38 +509,38 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf) ...@@ -491,38 +509,38 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
dev->contrast->cur.val, dev->contrast->cur.val,
dev->saturation->cur.val, dev->saturation->cur.val,
dev->hue->cur.val); dev->hue->cur.val);
tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str); tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
snprintf(str, sizeof(str), snprintf(str, sizeof(str),
" autogain %d, gain %3d, alpha 0x%02x ", " autogain %d, gain %3d, alpha 0x%02x ",
dev->autogain->cur.val, gain, dev->alpha->cur.val); dev->autogain->cur.val, gain, dev->alpha->cur.val);
mutex_unlock(dev->ctrl_hdl_user_vid.lock); mutex_unlock(dev->ctrl_hdl_user_vid.lock);
tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str); tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
mutex_lock(dev->ctrl_hdl_user_aud.lock); mutex_lock(dev->ctrl_hdl_user_aud.lock);
snprintf(str, sizeof(str), snprintf(str, sizeof(str),
" volume %3d, mute %d ", " volume %3d, mute %d ",
dev->volume->cur.val, dev->mute->cur.val); dev->volume->cur.val, dev->mute->cur.val);
mutex_unlock(dev->ctrl_hdl_user_aud.lock); mutex_unlock(dev->ctrl_hdl_user_aud.lock);
tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str); tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
mutex_lock(dev->ctrl_hdl_user_gen.lock); mutex_lock(dev->ctrl_hdl_user_gen.lock);
snprintf(str, sizeof(str), " int32 %d, int64 %lld, bitmask %08x ", snprintf(str, sizeof(str), " int32 %d, int64 %lld, bitmask %08x ",
dev->int32->cur.val, dev->int32->cur.val,
*dev->int64->p_cur.p_s64, *dev->int64->p_cur.p_s64,
dev->bitmask->cur.val); dev->bitmask->cur.val);
tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str); tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ", snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ",
dev->boolean->cur.val, dev->boolean->cur.val,
dev->menu->qmenu[dev->menu->cur.val], dev->menu->qmenu[dev->menu->cur.val],
dev->string->p_cur.p_char); dev->string->p_cur.p_char);
tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str); tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
snprintf(str, sizeof(str), " integer_menu %lld, value %d ", snprintf(str, sizeof(str), " integer_menu %lld, value %d ",
dev->int_menu->qmenu_int[dev->int_menu->cur.val], dev->int_menu->qmenu_int[dev->int_menu->cur.val],
dev->int_menu->cur.val); dev->int_menu->cur.val);
mutex_unlock(dev->ctrl_hdl_user_gen.lock); mutex_unlock(dev->ctrl_hdl_user_gen.lock);
tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str); tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
if (dev->button_pressed) { if (dev->button_pressed) {
dev->button_pressed--; dev->button_pressed--;
snprintf(str, sizeof(str), " button pressed!"); snprintf(str, sizeof(str), " button pressed!");
tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str); tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
} }
} }
......
...@@ -100,7 +100,7 @@ static int vid_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f ...@@ -100,7 +100,7 @@ static int vid_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f
unsigned sizes[], void *alloc_ctxs[]) unsigned sizes[], void *alloc_ctxs[])
{ {
struct vivid_dev *dev = vb2_get_drv_priv(vq); struct vivid_dev *dev = vb2_get_drv_priv(vq);
unsigned planes = tpg_g_planes(&dev->tpg); unsigned buffers = tpg_g_buffers(&dev->tpg);
unsigned h = dev->fmt_cap_rect.height; unsigned h = dev->fmt_cap_rect.height;
unsigned p; unsigned p;
...@@ -133,39 +133,36 @@ static int vid_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f ...@@ -133,39 +133,36 @@ static int vid_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f
mp = &fmt->fmt.pix_mp; mp = &fmt->fmt.pix_mp;
/* /*
* Check if the number of planes in the specified format match * Check if the number of planes in the specified format match
* the number of planes in the current format. You can't mix that. * the number of buffers in the current format. You can't mix that.
*/ */
if (mp->num_planes != planes) if (mp->num_planes != buffers)
return -EINVAL; return -EINVAL;
vfmt = vivid_get_format(dev, mp->pixelformat); vfmt = vivid_get_format(dev, mp->pixelformat);
for (p = 0; p < planes; p++) { for (p = 0; p < buffers; p++) {
sizes[p] = mp->plane_fmt[p].sizeimage; sizes[p] = mp->plane_fmt[p].sizeimage;
if (sizes[0] < tpg_g_bytesperline(&dev->tpg, 0) * h + if (sizes[p] < tpg_g_line_width(&dev->tpg, p) * h +
vfmt->data_offset[p]) vfmt->data_offset[p])
return -EINVAL; return -EINVAL;
} }
} else { } else {
for (p = 0; p < planes; p++) for (p = 0; p < buffers; p++)
sizes[p] = tpg_g_bytesperline(&dev->tpg, p) * h + sizes[p] = tpg_g_line_width(&dev->tpg, p) * h +
dev->fmt_cap->data_offset[p]; dev->fmt_cap->data_offset[p];
} }
if (vq->num_buffers + *nbuffers < 2) if (vq->num_buffers + *nbuffers < 2)
*nbuffers = 2 - vq->num_buffers; *nbuffers = 2 - vq->num_buffers;
*nplanes = planes; *nplanes = buffers;
/* /*
* videobuf2-vmalloc allocator is context-less so no need to set * videobuf2-vmalloc allocator is context-less so no need to set
* alloc_ctxs array. * alloc_ctxs array.
*/ */
if (planes == 2) dprintk(dev, 1, "%s: count=%d\n", __func__, *nbuffers);
dprintk(dev, 1, "%s, count=%d, sizes=%u, %u\n", __func__, for (p = 0; p < buffers; p++)
*nbuffers, sizes[0], sizes[1]); dprintk(dev, 1, "%s: size[%u]=%u\n", __func__, p, sizes[p]);
else
dprintk(dev, 1, "%s, count=%d, size=%u\n", __func__,
*nbuffers, sizes[0]);
return 0; return 0;
} }
...@@ -174,7 +171,7 @@ static int vid_cap_buf_prepare(struct vb2_buffer *vb) ...@@ -174,7 +171,7 @@ static int vid_cap_buf_prepare(struct vb2_buffer *vb)
{ {
struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue); struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
unsigned long size; unsigned long size;
unsigned planes = tpg_g_planes(&dev->tpg); unsigned buffers = tpg_g_buffers(&dev->tpg);
unsigned p; unsigned p;
dprintk(dev, 1, "%s\n", __func__); dprintk(dev, 1, "%s\n", __func__);
...@@ -190,8 +187,8 @@ static int vid_cap_buf_prepare(struct vb2_buffer *vb) ...@@ -190,8 +187,8 @@ static int vid_cap_buf_prepare(struct vb2_buffer *vb)
dev->buf_prepare_error = false; dev->buf_prepare_error = false;
return -EINVAL; return -EINVAL;
} }
for (p = 0; p < planes; p++) { for (p = 0; p < buffers; p++) {
size = tpg_g_bytesperline(&dev->tpg, p) * dev->fmt_cap_rect.height + size = tpg_g_line_width(&dev->tpg, p) * dev->fmt_cap_rect.height +
dev->fmt_cap->data_offset[p]; dev->fmt_cap->data_offset[p];
if (vb2_plane_size(vb, p) < size) { if (vb2_plane_size(vb, p) < size) {
...@@ -532,11 +529,11 @@ int vivid_g_fmt_vid_cap(struct file *file, void *priv, ...@@ -532,11 +529,11 @@ int vivid_g_fmt_vid_cap(struct file *file, void *priv,
mp->colorspace = vivid_colorspace_cap(dev); mp->colorspace = vivid_colorspace_cap(dev);
mp->ycbcr_enc = vivid_ycbcr_enc_cap(dev); mp->ycbcr_enc = vivid_ycbcr_enc_cap(dev);
mp->quantization = vivid_quantization_cap(dev); mp->quantization = vivid_quantization_cap(dev);
mp->num_planes = dev->fmt_cap->planes; mp->num_planes = dev->fmt_cap->buffers;
for (p = 0; p < mp->num_planes; p++) { for (p = 0; p < mp->num_planes; p++) {
mp->plane_fmt[p].bytesperline = tpg_g_bytesperline(&dev->tpg, p); mp->plane_fmt[p].bytesperline = tpg_g_bytesperline(&dev->tpg, p);
mp->plane_fmt[p].sizeimage = mp->plane_fmt[p].sizeimage =
mp->plane_fmt[p].bytesperline * mp->height + tpg_g_line_width(&dev->tpg, p) * mp->height +
dev->fmt_cap->data_offset[p]; dev->fmt_cap->data_offset[p];
} }
return 0; return 0;
...@@ -602,18 +599,19 @@ int vivid_try_fmt_vid_cap(struct file *file, void *priv, ...@@ -602,18 +599,19 @@ int vivid_try_fmt_vid_cap(struct file *file, void *priv,
/* This driver supports custom bytesperline values */ /* This driver supports custom bytesperline values */
mp->num_planes = fmt->buffers;
for (p = 0; p < mp->num_planes; p++) {
/* Calculate the minimum supported bytesperline value */ /* Calculate the minimum supported bytesperline value */
bytesperline = (mp->width * fmt->bit_depth[0]) >> 3; bytesperline = (mp->width * fmt->bit_depth[p]) >> 3;
/* Calculate the maximum supported bytesperline value */ /* Calculate the maximum supported bytesperline value */
max_bpl = (MAX_ZOOM * MAX_WIDTH * fmt->bit_depth[0]) >> 3; max_bpl = (MAX_ZOOM * MAX_WIDTH * fmt->bit_depth[p]) >> 3;
mp->num_planes = fmt->planes;
for (p = 0; p < mp->num_planes; p++) {
if (pfmt[p].bytesperline > max_bpl) if (pfmt[p].bytesperline > max_bpl)
pfmt[p].bytesperline = max_bpl; pfmt[p].bytesperline = max_bpl;
if (pfmt[p].bytesperline < bytesperline) if (pfmt[p].bytesperline < bytesperline)
pfmt[p].bytesperline = bytesperline; pfmt[p].bytesperline = bytesperline;
pfmt[p].sizeimage = pfmt[p].bytesperline * mp->height + pfmt[p].sizeimage = tpg_calc_line_width(&dev->tpg, p, pfmt[p].bytesperline) *
fmt->data_offset[p]; mp->height + fmt->data_offset[p];
memset(pfmt[p].reserved, 0, sizeof(pfmt[p].reserved)); memset(pfmt[p].reserved, 0, sizeof(pfmt[p].reserved));
} }
mp->colorspace = vivid_colorspace_cap(dev); mp->colorspace = vivid_colorspace_cap(dev);
...@@ -633,6 +631,7 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv, ...@@ -633,6 +631,7 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv,
struct vb2_queue *q = &dev->vb_vid_cap_q; struct vb2_queue *q = &dev->vb_vid_cap_q;
int ret = vivid_try_fmt_vid_cap(file, priv, f); int ret = vivid_try_fmt_vid_cap(file, priv, f);
unsigned factor = 1; unsigned factor = 1;
unsigned p;
unsigned i; unsigned i;
if (ret < 0) if (ret < 0)
...@@ -735,16 +734,15 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv, ...@@ -735,16 +734,15 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv,
dev->fmt_cap_rect.width = mp->width; dev->fmt_cap_rect.width = mp->width;
dev->fmt_cap_rect.height = mp->height; dev->fmt_cap_rect.height = mp->height;
tpg_s_buf_height(&dev->tpg, mp->height); tpg_s_buf_height(&dev->tpg, mp->height);
tpg_s_bytesperline(&dev->tpg, 0, mp->plane_fmt[0].bytesperline); tpg_s_fourcc(&dev->tpg, dev->fmt_cap->fourcc);
if (tpg_g_planes(&dev->tpg) > 1) for (p = 0; p < tpg_g_buffers(&dev->tpg); p++)
tpg_s_bytesperline(&dev->tpg, 1, mp->plane_fmt[1].bytesperline); tpg_s_bytesperline(&dev->tpg, p, mp->plane_fmt[p].bytesperline);
dev->field_cap = mp->field; dev->field_cap = mp->field;
if (dev->field_cap == V4L2_FIELD_ALTERNATE) if (dev->field_cap == V4L2_FIELD_ALTERNATE)
tpg_s_field(&dev->tpg, V4L2_FIELD_TOP, true); tpg_s_field(&dev->tpg, V4L2_FIELD_TOP, true);
else else
tpg_s_field(&dev->tpg, dev->field_cap, false); tpg_s_field(&dev->tpg, dev->field_cap, false);
tpg_s_crop_compose(&dev->tpg, &dev->crop_cap, &dev->compose_cap); tpg_s_crop_compose(&dev->tpg, &dev->crop_cap, &dev->compose_cap);
tpg_s_fourcc(&dev->tpg, dev->fmt_cap->fourcc);
if (vivid_is_sdtv_cap(dev)) if (vivid_is_sdtv_cap(dev))
dev->tv_field_cap = mp->field; dev->tv_field_cap = mp->field;
tpg_update_mv_step(&dev->tpg); tpg_update_mv_step(&dev->tpg);
......
...@@ -234,7 +234,7 @@ const struct vivid_fmt *vivid_get_format(struct vivid_dev *dev, u32 pixelformat) ...@@ -234,7 +234,7 @@ const struct vivid_fmt *vivid_get_format(struct vivid_dev *dev, u32 pixelformat)
for (k = 0; k < ARRAY_SIZE(vivid_formats); k++) { for (k = 0; k < ARRAY_SIZE(vivid_formats); k++) {
fmt = &vivid_formats[k]; fmt = &vivid_formats[k];
if (fmt->fourcc == pixelformat) if (fmt->fourcc == pixelformat)
if (fmt->planes == 1 || dev->multiplanar) if (fmt->buffers == 1 || dev->multiplanar)
return fmt; return fmt;
} }
......
...@@ -36,9 +36,14 @@ static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f ...@@ -36,9 +36,14 @@ static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f
unsigned sizes[], void *alloc_ctxs[]) unsigned sizes[], void *alloc_ctxs[])
{ {
struct vivid_dev *dev = vb2_get_drv_priv(vq); struct vivid_dev *dev = vb2_get_drv_priv(vq);
unsigned planes = dev->fmt_out->planes; const struct vivid_fmt *vfmt = dev->fmt_out;
unsigned planes = vfmt->buffers;
unsigned h = dev->fmt_out_rect.height; unsigned h = dev->fmt_out_rect.height;
unsigned size = dev->bytesperline_out[0] * h; unsigned size = dev->bytesperline_out[0] * h;
unsigned p;
for (p = vfmt->buffers; p < vfmt->planes; p++)
size += dev->bytesperline_out[p] * h;
if (dev->field_out == V4L2_FIELD_ALTERNATE) { if (dev->field_out == V4L2_FIELD_ALTERNATE) {
/* /*
...@@ -74,21 +79,16 @@ static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f ...@@ -74,21 +79,16 @@ static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f
if (mp->num_planes != planes) if (mp->num_planes != planes)
return -EINVAL; return -EINVAL;
sizes[0] = mp->plane_fmt[0].sizeimage; sizes[0] = mp->plane_fmt[0].sizeimage;
if (planes == 2) { if (sizes[0] < size)
sizes[1] = mp->plane_fmt[1].sizeimage;
if (sizes[0] < dev->bytesperline_out[0] * h ||
sizes[1] < dev->bytesperline_out[1] * h)
return -EINVAL; return -EINVAL;
} else if (sizes[0] < size) { for (p = 1; p < planes; p++) {
sizes[p] = mp->plane_fmt[p].sizeimage;
if (sizes[p] < dev->bytesperline_out[p] * h)
return -EINVAL; return -EINVAL;
} }
} else { } else {
if (planes == 2) { for (p = 0; p < planes; p++)
sizes[0] = dev->bytesperline_out[0] * h; sizes[p] = p ? dev->bytesperline_out[p] * h : size;
sizes[1] = dev->bytesperline_out[1] * h;
} else {
sizes[0] = size;
}
} }
if (vq->num_buffers + *nbuffers < 2) if (vq->num_buffers + *nbuffers < 2)
...@@ -101,12 +101,9 @@ static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f ...@@ -101,12 +101,9 @@ static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f
* alloc_ctxs array. * alloc_ctxs array.
*/ */
if (planes == 2) dprintk(dev, 1, "%s: count=%d\n", __func__, *nbuffers);
dprintk(dev, 1, "%s, count=%d, sizes=%u, %u\n", __func__, for (p = 0; p < planes; p++)
*nbuffers, sizes[0], sizes[1]); dprintk(dev, 1, "%s: size[%u]=%u\n", __func__, p, sizes[p]);
else
dprintk(dev, 1, "%s, count=%d, size=%u\n", __func__,
*nbuffers, sizes[0]);
return 0; return 0;
} }
...@@ -222,7 +219,7 @@ const struct vb2_ops vivid_vid_out_qops = { ...@@ -222,7 +219,7 @@ const struct vb2_ops vivid_vid_out_qops = {
void vivid_update_format_out(struct vivid_dev *dev) void vivid_update_format_out(struct vivid_dev *dev)
{ {
struct v4l2_bt_timings *bt = &dev->dv_timings_out.bt; struct v4l2_bt_timings *bt = &dev->dv_timings_out.bt;
unsigned size; unsigned size, p;
switch (dev->output_type[dev->output]) { switch (dev->output_type[dev->output]) {
case SVID: case SVID:
...@@ -269,9 +266,9 @@ void vivid_update_format_out(struct vivid_dev *dev) ...@@ -269,9 +266,9 @@ void vivid_update_format_out(struct vivid_dev *dev)
if (V4L2_FIELD_HAS_T_OR_B(dev->field_out)) if (V4L2_FIELD_HAS_T_OR_B(dev->field_out))
dev->crop_out.height /= 2; dev->crop_out.height /= 2;
dev->fmt_out_rect = dev->crop_out; dev->fmt_out_rect = dev->crop_out;
dev->bytesperline_out[0] = (dev->sink_rect.width * dev->fmt_out->bit_depth[0]) / 8; for (p = 0; p < dev->fmt_out->planes; p++)
if (dev->fmt_out->planes == 2) dev->bytesperline_out[p] =
dev->bytesperline_out[1] = (dev->sink_rect.width * dev->fmt_out->bit_depth[0]) / 8; (dev->sink_rect.width * dev->fmt_out->bit_depth[p]) / 8;
} }
/* Map the field to something that is valid for the current output */ /* Map the field to something that is valid for the current output */
...@@ -315,21 +312,27 @@ int vivid_g_fmt_vid_out(struct file *file, void *priv, ...@@ -315,21 +312,27 @@ int vivid_g_fmt_vid_out(struct file *file, void *priv,
{ {
struct vivid_dev *dev = video_drvdata(file); struct vivid_dev *dev = video_drvdata(file);
struct v4l2_pix_format_mplane *mp = &f->fmt.pix_mp; struct v4l2_pix_format_mplane *mp = &f->fmt.pix_mp;
const struct vivid_fmt *fmt = dev->fmt_out;
unsigned p; unsigned p;
mp->width = dev->fmt_out_rect.width; mp->width = dev->fmt_out_rect.width;
mp->height = dev->fmt_out_rect.height; mp->height = dev->fmt_out_rect.height;
mp->field = dev->field_out; mp->field = dev->field_out;
mp->pixelformat = dev->fmt_out->fourcc; mp->pixelformat = fmt->fourcc;
mp->colorspace = dev->colorspace_out; mp->colorspace = dev->colorspace_out;
mp->ycbcr_enc = dev->ycbcr_enc_out; mp->ycbcr_enc = dev->ycbcr_enc_out;
mp->quantization = dev->quantization_out; mp->quantization = dev->quantization_out;
mp->num_planes = dev->fmt_out->planes; mp->num_planes = fmt->buffers;
for (p = 0; p < mp->num_planes; p++) { for (p = 0; p < mp->num_planes; p++) {
mp->plane_fmt[p].bytesperline = dev->bytesperline_out[p]; mp->plane_fmt[p].bytesperline = dev->bytesperline_out[p];
mp->plane_fmt[p].sizeimage = mp->plane_fmt[p].sizeimage =
mp->plane_fmt[p].bytesperline * mp->height; mp->plane_fmt[p].bytesperline * mp->height;
} }
for (p = fmt->buffers; p < fmt->planes; p++) {
unsigned stride = dev->bytesperline_out[p];
mp->plane_fmt[0].sizeimage += stride * mp->height;
}
return 0; return 0;
} }
...@@ -391,7 +394,7 @@ int vivid_try_fmt_vid_out(struct file *file, void *priv, ...@@ -391,7 +394,7 @@ int vivid_try_fmt_vid_out(struct file *file, void *priv,
bytesperline = (mp->width * fmt->bit_depth[0]) >> 3; bytesperline = (mp->width * fmt->bit_depth[0]) >> 3;
/* Calculate the maximum supported bytesperline value */ /* Calculate the maximum supported bytesperline value */
max_bpl = (MAX_ZOOM * MAX_WIDTH * fmt->bit_depth[0]) >> 3; max_bpl = (MAX_ZOOM * MAX_WIDTH * fmt->bit_depth[0]) >> 3;
mp->num_planes = fmt->planes; mp->num_planes = fmt->buffers;
for (p = 0; p < mp->num_planes; p++) { for (p = 0; p < mp->num_planes; p++) {
if (pfmt[p].bytesperline > max_bpl) if (pfmt[p].bytesperline > max_bpl)
pfmt[p].bytesperline = max_bpl; pfmt[p].bytesperline = max_bpl;
...@@ -400,6 +403,9 @@ int vivid_try_fmt_vid_out(struct file *file, void *priv, ...@@ -400,6 +403,9 @@ int vivid_try_fmt_vid_out(struct file *file, void *priv,
pfmt[p].sizeimage = pfmt[p].bytesperline * mp->height; pfmt[p].sizeimage = pfmt[p].bytesperline * mp->height;
memset(pfmt[p].reserved, 0, sizeof(pfmt[p].reserved)); memset(pfmt[p].reserved, 0, sizeof(pfmt[p].reserved));
} }
for (p = fmt->buffers; p < fmt->planes; p++)
pfmt[0].sizeimage += (pfmt[0].bytesperline * fmt->bit_depth[p]) /
fmt->bit_depth[0];
mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
mp->quantization = V4L2_QUANTIZATION_DEFAULT; mp->quantization = V4L2_QUANTIZATION_DEFAULT;
if (vivid_is_svid_out(dev)) { if (vivid_is_svid_out(dev)) {
...@@ -431,6 +437,7 @@ int vivid_s_fmt_vid_out(struct file *file, void *priv, ...@@ -431,6 +437,7 @@ int vivid_s_fmt_vid_out(struct file *file, void *priv,
struct vb2_queue *q = &dev->vb_vid_out_q; struct vb2_queue *q = &dev->vb_vid_out_q;
int ret = vivid_try_fmt_vid_out(file, priv, f); int ret = vivid_try_fmt_vid_out(file, priv, f);
unsigned factor = 1; unsigned factor = 1;
unsigned p;
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -526,9 +533,12 @@ int vivid_s_fmt_vid_out(struct file *file, void *priv, ...@@ -526,9 +533,12 @@ int vivid_s_fmt_vid_out(struct file *file, void *priv,
dev->fmt_out_rect.width = mp->width; dev->fmt_out_rect.width = mp->width;
dev->fmt_out_rect.height = mp->height; dev->fmt_out_rect.height = mp->height;
dev->bytesperline_out[0] = mp->plane_fmt[0].bytesperline; for (p = 0; p < mp->num_planes; p++)
if (mp->num_planes > 1) dev->bytesperline_out[p] = mp->plane_fmt[p].bytesperline;
dev->bytesperline_out[1] = mp->plane_fmt[1].bytesperline; for (p = dev->fmt_out->buffers; p < dev->fmt_out->planes; p++)
dev->bytesperline_out[p] =
(dev->bytesperline_out[0] * dev->fmt_out->bit_depth[p]) /
dev->fmt_out->bit_depth[0];
dev->field_out = mp->field; dev->field_out = mp->field;
if (vivid_is_svid_out(dev)) if (vivid_is_svid_out(dev))
dev->tv_field_out = mp->field; dev->tv_field_out = mp->field;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment