提交 2c11d1bd 编写于 作者: P Philipp Zabel 提交者: Mauro Carvalho Chehab

[media] coda: add coda_video_device descriptors

Each video device descriptor determines the name, callback ops, and input and
output formats on the corresponding video device. This simplifies coda_enum_fmt
and coda_try_fmt a bit and will simplify adding separate video devices for JPEG
codecs due to the slightly different behavior in the CodaDx6/CODA7542 case and
a separate hardware unit on CODA960.
Signed-off-by: NPhilipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: NKamil Debski <k.debski@samsung.com>
Signed-off-by: NMauro Carvalho Chehab <mchehab@osg.samsung.com>
上级 b2f91ae3
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#define CODA_NAME "coda" #define CODA_NAME "coda"
#define CODADX6_MAX_INSTANCES 4 #define CODADX6_MAX_INSTANCES 4
#define CODA_MAX_FORMATS 4
#define CODA_PARA_BUF_SIZE (10 * 1024) #define CODA_PARA_BUF_SIZE (10 * 1024)
#define CODA_ISRAM_SIZE (2048 * 2) #define CODA_ISRAM_SIZE (2048 * 2)
...@@ -169,6 +170,58 @@ static const struct coda_codec coda9_codecs[] = { ...@@ -169,6 +170,58 @@ static const struct coda_codec coda9_codecs[] = {
CODA_CODEC(CODA9_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1088), CODA_CODEC(CODA9_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1088),
}; };
struct coda_video_device {
const char *name;
enum coda_inst_type type;
const struct coda_context_ops *ops;
u32 src_formats[CODA_MAX_FORMATS];
u32 dst_formats[CODA_MAX_FORMATS];
};
static const struct coda_video_device coda_bit_encoder = {
.name = "coda-encoder",
.type = CODA_INST_ENCODER,
.ops = &coda_bit_encode_ops,
.src_formats = {
V4L2_PIX_FMT_YUV420,
V4L2_PIX_FMT_YVU420,
V4L2_PIX_FMT_NV12,
},
.dst_formats = {
V4L2_PIX_FMT_H264,
V4L2_PIX_FMT_MPEG4,
},
};
static const struct coda_video_device coda_bit_decoder = {
.name = "coda-decoder",
.type = CODA_INST_DECODER,
.ops = &coda_bit_decode_ops,
.src_formats = {
V4L2_PIX_FMT_H264,
V4L2_PIX_FMT_MPEG4,
},
.dst_formats = {
V4L2_PIX_FMT_YUV420,
V4L2_PIX_FMT_YVU420,
V4L2_PIX_FMT_NV12,
},
};
static const struct coda_video_device *codadx6_video_devices[] = {
&coda_bit_encoder,
};
static const struct coda_video_device *coda7_video_devices[] = {
&coda_bit_encoder,
&coda_bit_decoder,
};
static const struct coda_video_device *coda9_video_devices[] = {
&coda_bit_encoder,
&coda_bit_decoder,
};
static bool coda_format_is_yuv(u32 fourcc) static bool coda_format_is_yuv(u32 fourcc)
{ {
switch (fourcc) { switch (fourcc) {
...@@ -182,6 +235,18 @@ static bool coda_format_is_yuv(u32 fourcc) ...@@ -182,6 +235,18 @@ static bool coda_format_is_yuv(u32 fourcc)
} }
} }
static const char *coda_format_name(u32 fourcc)
{
int i;
for (i = 0; i < ARRAY_SIZE(coda_formats); i++) {
if (coda_formats[i].fourcc == fourcc)
return coda_formats[i].name;
}
return NULL;
}
/* /*
* Normalize all supported YUV 4:2:0 formats to the value used in the codec * Normalize all supported YUV 4:2:0 formats to the value used in the codec
* tables. * tables.
...@@ -240,6 +305,17 @@ static void coda_get_max_dimensions(struct coda_dev *dev, ...@@ -240,6 +305,17 @@ static void coda_get_max_dimensions(struct coda_dev *dev,
*max_h = h; *max_h = h;
} }
const struct coda_video_device *to_coda_video_device(struct video_device *vdev)
{
struct coda_dev *dev = video_get_drvdata(vdev);
unsigned int i = vdev - dev->vfd;
if (i >= dev->devtype->num_vdevs)
return NULL;
return dev->devtype->vdevs[i];
}
const char *coda_product_name(int product) const char *coda_product_name(int product)
{ {
static char buf[9]; static char buf[9];
...@@ -278,58 +354,28 @@ static int coda_querycap(struct file *file, void *priv, ...@@ -278,58 +354,28 @@ static int coda_querycap(struct file *file, void *priv,
static int coda_enum_fmt(struct file *file, void *priv, static int coda_enum_fmt(struct file *file, void *priv,
struct v4l2_fmtdesc *f) struct v4l2_fmtdesc *f)
{ {
struct coda_ctx *ctx = fh_to_ctx(priv); struct video_device *vdev = video_devdata(file);
const struct coda_codec *codecs = ctx->dev->devtype->codecs; const struct coda_video_device *cvd = to_coda_video_device(vdev);
const struct coda_fmt *formats = coda_formats; const u32 *formats;
const struct coda_fmt *fmt; const char *name;
int num_codecs = ctx->dev->devtype->num_codecs;
int num_formats = ARRAY_SIZE(coda_formats); if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
int i, k, num = 0; formats = cvd->src_formats;
bool yuv; else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
formats = cvd->dst_formats;
if (ctx->inst_type == CODA_INST_ENCODER)
yuv = (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT);
else else
yuv = (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE); return -EINVAL;
for (i = 0; i < num_formats; i++) {
/* Skip either raw or compressed formats */
if (yuv != coda_format_is_yuv(formats[i].fourcc))
continue;
/* All uncompressed formats are always supported */
if (yuv) {
if (num == f->index)
break;
++num;
continue;
}
/* Compressed formats may be supported, check the codec list */
for (k = 0; k < num_codecs; k++) {
if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
formats[i].fourcc == codecs[k].dst_fourcc)
break;
if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
formats[i].fourcc == codecs[k].src_fourcc)
break;
}
if (k < num_codecs) {
if (num == f->index)
break;
++num;
}
}
if (i < num_formats) { if (f->index >= CODA_MAX_FORMATS || formats[f->index] == 0)
fmt = &formats[i]; return -EINVAL;
strlcpy(f->description, fmt->name, sizeof(f->description));
f->pixelformat = fmt->fourcc; name = coda_format_name(formats[f->index]);
if (!yuv) strlcpy(f->description, name, sizeof(f->description));
f->flags |= V4L2_FMT_FLAG_COMPRESSED; f->pixelformat = formats[f->index];
return 0; if (!coda_format_is_yuv(formats[f->index]))
} f->flags |= V4L2_FMT_FLAG_COMPRESSED;
/* Format not found */ return 0;
return -EINVAL;
} }
static int coda_g_fmt(struct file *file, void *priv, static int coda_g_fmt(struct file *file, void *priv,
...@@ -354,11 +400,37 @@ static int coda_g_fmt(struct file *file, void *priv, ...@@ -354,11 +400,37 @@ static int coda_g_fmt(struct file *file, void *priv,
return 0; return 0;
} }
static int coda_try_pixelformat(struct coda_ctx *ctx, struct v4l2_format *f)
{
struct coda_q_data *q_data;
const u32 *formats;
int i;
if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
formats = ctx->cvd->src_formats;
else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
formats = ctx->cvd->dst_formats;
else
return -EINVAL;
for (i = 0; i < CODA_MAX_FORMATS; i++) {
if (formats[i] == f->fmt.pix.pixelformat) {
f->fmt.pix.pixelformat = formats[i];
return 0;
}
}
/* Fall back to currently set pixelformat */
q_data = get_q_data(ctx, f->type);
f->fmt.pix.pixelformat = q_data->fourcc;
return 0;
}
static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec, static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec,
struct v4l2_format *f) struct v4l2_format *f)
{ {
struct coda_dev *dev = ctx->dev; struct coda_dev *dev = ctx->dev;
struct coda_q_data *q_data;
unsigned int max_w, max_h; unsigned int max_w, max_h;
enum v4l2_field field; enum v4l2_field field;
...@@ -377,21 +449,6 @@ static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec, ...@@ -377,21 +449,6 @@ static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec,
&f->fmt.pix.height, MIN_H, max_h, H_ALIGN, &f->fmt.pix.height, MIN_H, max_h, H_ALIGN,
S_ALIGN); S_ALIGN);
switch (f->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_H264:
case V4L2_PIX_FMT_MPEG4:
case V4L2_PIX_FMT_JPEG:
break;
default:
q_data = get_q_data(ctx, f->type);
if (!q_data)
return -EINVAL;
f->fmt.pix.pixelformat = q_data->fourcc;
}
switch (f->fmt.pix.pixelformat) { switch (f->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420: case V4L2_PIX_FMT_YVU420:
...@@ -423,34 +480,35 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv, ...@@ -423,34 +480,35 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f) struct v4l2_format *f)
{ {
struct coda_ctx *ctx = fh_to_ctx(priv); struct coda_ctx *ctx = fh_to_ctx(priv);
const struct coda_codec *codec = NULL; const struct coda_q_data *q_data_src;
const struct coda_codec *codec;
struct vb2_queue *src_vq; struct vb2_queue *src_vq;
int ret; int ret;
ret = coda_try_pixelformat(ctx, f);
if (ret < 0)
return ret;
q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
/* /*
* If the source format is already fixed, try to find a codec that * If the source format is already fixed, only allow the same output
* converts to the given destination format * resolution
*/ */
src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
if (vb2_is_streaming(src_vq)) { if (vb2_is_streaming(src_vq)) {
struct coda_q_data *q_data_src;
q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
codec = coda_find_codec(ctx->dev, q_data_src->fourcc,
f->fmt.pix.pixelformat);
if (!codec)
return -EINVAL;
f->fmt.pix.width = q_data_src->width; f->fmt.pix.width = q_data_src->width;
f->fmt.pix.height = q_data_src->height; f->fmt.pix.height = q_data_src->height;
} else {
/* Otherwise determine codec by encoded format, if possible */
codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420,
f->fmt.pix.pixelformat);
} }
f->fmt.pix.colorspace = ctx->colorspace; f->fmt.pix.colorspace = ctx->colorspace;
q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
codec = coda_find_codec(ctx->dev, q_data_src->fourcc,
f->fmt.pix.pixelformat);
if (!codec)
return -EINVAL;
ret = coda_try_fmt(ctx, codec, f); ret = coda_try_fmt(ctx, codec, f);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -471,22 +529,21 @@ static int coda_try_fmt_vid_out(struct file *file, void *priv, ...@@ -471,22 +529,21 @@ static int coda_try_fmt_vid_out(struct file *file, void *priv,
struct v4l2_format *f) struct v4l2_format *f)
{ {
struct coda_ctx *ctx = fh_to_ctx(priv); struct coda_ctx *ctx = fh_to_ctx(priv);
const struct coda_codec *codec = NULL; struct coda_dev *dev = ctx->dev;
const struct coda_q_data *q_data_dst;
const struct coda_codec *codec;
int ret;
/* Determine codec by encoded format, returns NULL if raw or invalid */ ret = coda_try_pixelformat(ctx, f);
if (ctx->inst_type == CODA_INST_DECODER) { if (ret < 0)
codec = coda_find_codec(ctx->dev, f->fmt.pix.pixelformat, return ret;
V4L2_PIX_FMT_YUV420);
if (!codec)
codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_H264,
V4L2_PIX_FMT_YUV420);
if (!codec)
return -EINVAL;
}
if (!f->fmt.pix.colorspace) if (!f->fmt.pix.colorspace)
f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
codec = coda_find_codec(dev, f->fmt.pix.pixelformat, q_data_dst->fourcc);
return coda_try_fmt(ctx, codec, f); return coda_try_fmt(ctx, codec, f);
} }
...@@ -907,18 +964,10 @@ static void coda_set_tiled_map_type(struct coda_ctx *ctx, int tiled_map_type) ...@@ -907,18 +964,10 @@ static void coda_set_tiled_map_type(struct coda_ctx *ctx, int tiled_map_type)
static void set_default_params(struct coda_ctx *ctx) static void set_default_params(struct coda_ctx *ctx)
{ {
u32 src_fourcc, dst_fourcc; int max_w, max_h;
int max_w;
int max_h;
if (ctx->inst_type == CODA_INST_ENCODER) { ctx->codec = coda_find_codec(ctx->dev, ctx->cvd->src_formats[0],
src_fourcc = V4L2_PIX_FMT_YUV420; ctx->cvd->dst_formats[0]);
dst_fourcc = V4L2_PIX_FMT_H264;
} else {
src_fourcc = V4L2_PIX_FMT_H264;
dst_fourcc = V4L2_PIX_FMT_YUV420;
}
ctx->codec = coda_find_codec(ctx->dev, src_fourcc, dst_fourcc);
max_w = ctx->codec->max_w; max_w = ctx->codec->max_w;
max_h = ctx->codec->max_h; max_h = ctx->codec->max_h;
...@@ -1409,10 +1458,14 @@ static int coda_next_free_instance(struct coda_dev *dev) ...@@ -1409,10 +1458,14 @@ static int coda_next_free_instance(struct coda_dev *dev)
return idx; return idx;
} }
static int coda_open(struct file *file, enum coda_inst_type inst_type, /*
const struct coda_context_ops *ctx_ops) * File operations
*/
static int coda_open(struct file *file)
{ {
struct coda_dev *dev = video_drvdata(file); struct video_device *vdev = video_devdata(file);
struct coda_dev *dev = video_get_drvdata(vdev);
struct coda_ctx *ctx = NULL; struct coda_ctx *ctx = NULL;
char *name; char *name;
int ret; int ret;
...@@ -1433,8 +1486,9 @@ static int coda_open(struct file *file, enum coda_inst_type inst_type, ...@@ -1433,8 +1486,9 @@ static int coda_open(struct file *file, enum coda_inst_type inst_type,
ctx->debugfs_entry = debugfs_create_dir(name, dev->debugfs_root); ctx->debugfs_entry = debugfs_create_dir(name, dev->debugfs_root);
kfree(name); kfree(name);
ctx->inst_type = inst_type; ctx->cvd = to_coda_video_device(vdev);
ctx->ops = ctx_ops; ctx->inst_type = ctx->cvd->type;
ctx->ops = ctx->cvd->ops;
init_completion(&ctx->completion); init_completion(&ctx->completion);
INIT_WORK(&ctx->pic_run_work, coda_pic_run_work); INIT_WORK(&ctx->pic_run_work, coda_pic_run_work);
INIT_WORK(&ctx->seq_end_work, ctx->ops->seq_end_work); INIT_WORK(&ctx->seq_end_work, ctx->ops->seq_end_work);
...@@ -1542,16 +1596,6 @@ static int coda_open(struct file *file, enum coda_inst_type inst_type, ...@@ -1542,16 +1596,6 @@ static int coda_open(struct file *file, enum coda_inst_type inst_type,
return ret; return ret;
} }
static int coda_encoder_open(struct file *file)
{
return coda_open(file, CODA_INST_ENCODER, &coda_bit_encode_ops);
}
static int coda_decoder_open(struct file *file)
{
return coda_open(file, CODA_INST_DECODER, &coda_bit_decode_ops);
}
static int coda_release(struct file *file) static int coda_release(struct file *file)
{ {
struct coda_dev *dev = video_drvdata(file); struct coda_dev *dev = video_drvdata(file);
...@@ -1595,18 +1639,9 @@ static int coda_release(struct file *file) ...@@ -1595,18 +1639,9 @@ static int coda_release(struct file *file)
return 0; return 0;
} }
static const struct v4l2_file_operations coda_encoder_fops = { static const struct v4l2_file_operations coda_fops = {
.owner = THIS_MODULE,
.open = coda_encoder_open,
.release = coda_release,
.poll = v4l2_m2m_fop_poll,
.unlocked_ioctl = video_ioctl2,
.mmap = v4l2_m2m_fop_mmap,
};
static const struct v4l2_file_operations coda_decoder_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = coda_decoder_open, .open = coda_open,
.release = coda_release, .release = coda_release,
.poll = v4l2_m2m_fop_poll, .poll = v4l2_m2m_fop_poll,
.unlocked_ioctl = video_ioctl2, .unlocked_ioctl = video_ioctl2,
...@@ -1711,8 +1746,16 @@ static int coda_hw_init(struct coda_dev *dev) ...@@ -1711,8 +1746,16 @@ static int coda_hw_init(struct coda_dev *dev)
return ret; return ret;
} }
static int coda_register_device(struct coda_dev *dev, struct video_device *vfd) static int coda_register_device(struct coda_dev *dev, int i)
{ {
struct video_device *vfd = &dev->vfd[i];
if (i > ARRAY_SIZE(dev->vfd))
return -EINVAL;
snprintf(vfd->name, sizeof(vfd->name), dev->devtype->vdevs[i]->name);
vfd->fops = &coda_fops;
vfd->ioctl_ops = &coda_ioctl_ops;
vfd->release = video_device_release_empty, vfd->release = video_device_release_empty,
vfd->lock = &dev->dev_mutex; vfd->lock = &dev->dev_mutex;
vfd->v4l2_dev = &dev->v4l2_dev; vfd->v4l2_dev = &dev->v4l2_dev;
...@@ -1731,7 +1774,7 @@ static void coda_fw_callback(const struct firmware *fw, void *context) ...@@ -1731,7 +1774,7 @@ static void coda_fw_callback(const struct firmware *fw, void *context)
{ {
struct coda_dev *dev = context; struct coda_dev *dev = context;
struct platform_device *pdev = dev->plat_dev; struct platform_device *pdev = dev->plat_dev;
int ret; int i, ret;
if (!fw) { if (!fw) {
v4l2_err(&dev->v4l2_dev, "firmware request failed\n"); v4l2_err(&dev->v4l2_dev, "firmware request failed\n");
...@@ -1772,33 +1815,25 @@ static void coda_fw_callback(const struct firmware *fw, void *context) ...@@ -1772,33 +1815,25 @@ static void coda_fw_callback(const struct firmware *fw, void *context)
goto rel_ctx; goto rel_ctx;
} }
dev->vfd[0].fops = &coda_encoder_fops, for (i = 0; i < dev->devtype->num_vdevs; i++) {
dev->vfd[0].ioctl_ops = &coda_ioctl_ops; ret = coda_register_device(dev, i);
snprintf(dev->vfd[0].name, sizeof(dev->vfd[0].name), "coda-encoder"); if (ret) {
ret = coda_register_device(dev, &dev->vfd[0]); v4l2_err(&dev->v4l2_dev,
if (ret) { "Failed to register %s video device: %d\n",
v4l2_err(&dev->v4l2_dev, dev->devtype->vdevs[i]->name, ret);
"Failed to register encoder video device\n"); goto rel_vfd;
goto rel_m2m; }
}
dev->vfd[1].fops = &coda_decoder_fops,
dev->vfd[1].ioctl_ops = &coda_ioctl_ops;
snprintf(dev->vfd[1].name, sizeof(dev->vfd[1].name), "coda-decoder");
ret = coda_register_device(dev, &dev->vfd[1]);
if (ret) {
v4l2_err(&dev->v4l2_dev,
"Failed to register decoder video device\n");
goto rel_m2m;
} }
v4l2_info(&dev->v4l2_dev, "codec registered as /dev/video[%d-%d]\n", v4l2_info(&dev->v4l2_dev, "codec registered as /dev/video[%d-%d]\n",
dev->vfd[0].num, dev->vfd[1].num); dev->vfd[0].num, dev->vfd[i - 1].num);
pm_runtime_put_sync(&pdev->dev); pm_runtime_put_sync(&pdev->dev);
return; return;
rel_m2m: rel_vfd:
while (--i >= 0)
video_unregister_device(&dev->vfd[i]);
v4l2_m2m_release(dev->m2m_dev); v4l2_m2m_release(dev->m2m_dev);
rel_ctx: rel_ctx:
vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
...@@ -1830,6 +1865,8 @@ static const struct coda_devtype coda_devdata[] = { ...@@ -1830,6 +1865,8 @@ static const struct coda_devtype coda_devdata[] = {
.product = CODA_DX6, .product = CODA_DX6,
.codecs = codadx6_codecs, .codecs = codadx6_codecs,
.num_codecs = ARRAY_SIZE(codadx6_codecs), .num_codecs = ARRAY_SIZE(codadx6_codecs),
.vdevs = codadx6_video_devices,
.num_vdevs = ARRAY_SIZE(codadx6_video_devices),
.workbuf_size = 288 * 1024 + FMO_SLICE_SAVE_BUF_SIZE * 8 * 1024, .workbuf_size = 288 * 1024 + FMO_SLICE_SAVE_BUF_SIZE * 8 * 1024,
.iram_size = 0xb000, .iram_size = 0xb000,
}, },
...@@ -1838,6 +1875,8 @@ static const struct coda_devtype coda_devdata[] = { ...@@ -1838,6 +1875,8 @@ static const struct coda_devtype coda_devdata[] = {
.product = CODA_7541, .product = CODA_7541,
.codecs = coda7_codecs, .codecs = coda7_codecs,
.num_codecs = ARRAY_SIZE(coda7_codecs), .num_codecs = ARRAY_SIZE(coda7_codecs),
.vdevs = coda7_video_devices,
.num_vdevs = ARRAY_SIZE(coda7_video_devices),
.workbuf_size = 128 * 1024, .workbuf_size = 128 * 1024,
.tempbuf_size = 304 * 1024, .tempbuf_size = 304 * 1024,
.iram_size = 0x14000, .iram_size = 0x14000,
...@@ -1847,6 +1886,8 @@ static const struct coda_devtype coda_devdata[] = { ...@@ -1847,6 +1886,8 @@ static const struct coda_devtype coda_devdata[] = {
.product = CODA_960, .product = CODA_960,
.codecs = coda9_codecs, .codecs = coda9_codecs,
.num_codecs = ARRAY_SIZE(coda9_codecs), .num_codecs = ARRAY_SIZE(coda9_codecs),
.vdevs = coda9_video_devices,
.num_vdevs = ARRAY_SIZE(coda9_video_devices),
.workbuf_size = 80 * 1024, .workbuf_size = 80 * 1024,
.tempbuf_size = 204 * 1024, .tempbuf_size = 204 * 1024,
.iram_size = 0x21000, .iram_size = 0x21000,
...@@ -1856,6 +1897,8 @@ static const struct coda_devtype coda_devdata[] = { ...@@ -1856,6 +1897,8 @@ static const struct coda_devtype coda_devdata[] = {
.product = CODA_960, .product = CODA_960,
.codecs = coda9_codecs, .codecs = coda9_codecs,
.num_codecs = ARRAY_SIZE(coda9_codecs), .num_codecs = ARRAY_SIZE(coda9_codecs),
.vdevs = coda9_video_devices,
.num_vdevs = ARRAY_SIZE(coda9_video_devices),
.workbuf_size = 80 * 1024, .workbuf_size = 80 * 1024,
.tempbuf_size = 204 * 1024, .tempbuf_size = 204 * 1024,
.iram_size = 0x20000, .iram_size = 0x20000,
...@@ -2035,9 +2078,12 @@ static int coda_probe(struct platform_device *pdev) ...@@ -2035,9 +2078,12 @@ static int coda_probe(struct platform_device *pdev)
static int coda_remove(struct platform_device *pdev) static int coda_remove(struct platform_device *pdev)
{ {
struct coda_dev *dev = platform_get_drvdata(pdev); struct coda_dev *dev = platform_get_drvdata(pdev);
int i;
video_unregister_device(&dev->vfd[0]); for (i = 0; i < ARRAY_SIZE(dev->vfd); i++) {
video_unregister_device(&dev->vfd[1]); if (video_get_drvdata(&dev->vfd[i]))
video_unregister_device(&dev->vfd[i]);
}
if (dev->m2m_dev) if (dev->m2m_dev)
v4l2_m2m_release(dev->m2m_dev); v4l2_m2m_release(dev->m2m_dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
......
...@@ -45,11 +45,15 @@ enum coda_product { ...@@ -45,11 +45,15 @@ enum coda_product {
CODA_960 = 0xf020, CODA_960 = 0xf020,
}; };
struct coda_video_device;
struct coda_devtype { struct coda_devtype {
char *firmware; char *firmware;
enum coda_product product; enum coda_product product;
const struct coda_codec *codecs; const struct coda_codec *codecs;
unsigned int num_codecs; unsigned int num_codecs;
const struct coda_video_device **vdevs;
unsigned int num_vdevs;
size_t workbuf_size; size_t workbuf_size;
size_t tempbuf_size; size_t tempbuf_size;
size_t iram_size; size_t iram_size;
...@@ -65,7 +69,7 @@ struct coda_aux_buf { ...@@ -65,7 +69,7 @@ struct coda_aux_buf {
struct coda_dev { struct coda_dev {
struct v4l2_device v4l2_dev; struct v4l2_device v4l2_dev;
struct video_device vfd[2]; struct video_device vfd[3];
struct platform_device *plat_dev; struct platform_device *plat_dev;
const struct coda_devtype *devtype; const struct coda_devtype *devtype;
...@@ -183,6 +187,7 @@ struct coda_ctx { ...@@ -183,6 +187,7 @@ struct coda_ctx {
struct work_struct pic_run_work; struct work_struct pic_run_work;
struct work_struct seq_end_work; struct work_struct seq_end_work;
struct completion completion; struct completion completion;
const struct coda_video_device *cvd;
const struct coda_context_ops *ops; const struct coda_context_ops *ops;
int aborting; int aborting;
int initialized; int initialized;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册