aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Zabel <p.zabel@pengutronix.de>2014-10-02 13:08:28 -0400
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2014-10-28 13:01:05 -0400
commit2c11d1bdfc7175cc75a603e433367caaf038ab69 (patch)
tree1240519636dc02fb446ca4c5cba90ad28cc429b1
parentb2f91ae30edfa95500183179082f0568e3e9b38e (diff)
[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: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: Kamil Debski <k.debski@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
-rw-r--r--drivers/media/platform/coda/coda-common.c350
-rw-r--r--drivers/media/platform/coda/coda.h7
2 files changed, 204 insertions, 153 deletions
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index fb83c56afd26..45db1da2dbcf 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -43,6 +43,7 @@
43#define CODA_NAME "coda" 43#define CODA_NAME "coda"
44 44
45#define CODADX6_MAX_INSTANCES 4 45#define CODADX6_MAX_INSTANCES 4
46#define CODA_MAX_FORMATS 4
46 47
47#define CODA_PARA_BUF_SIZE (10 * 1024) 48#define CODA_PARA_BUF_SIZE (10 * 1024)
48#define CODA_ISRAM_SIZE (2048 * 2) 49#define CODA_ISRAM_SIZE (2048 * 2)
@@ -169,6 +170,58 @@ static const struct coda_codec coda9_codecs[] = {
169 CODA_CODEC(CODA9_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1088), 170 CODA_CODEC(CODA9_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1088),
170}; 171};
171 172
173struct coda_video_device {
174 const char *name;
175 enum coda_inst_type type;
176 const struct coda_context_ops *ops;
177 u32 src_formats[CODA_MAX_FORMATS];
178 u32 dst_formats[CODA_MAX_FORMATS];
179};
180
181static const struct coda_video_device coda_bit_encoder = {
182 .name = "coda-encoder",
183 .type = CODA_INST_ENCODER,
184 .ops = &coda_bit_encode_ops,
185 .src_formats = {
186 V4L2_PIX_FMT_YUV420,
187 V4L2_PIX_FMT_YVU420,
188 V4L2_PIX_FMT_NV12,
189 },
190 .dst_formats = {
191 V4L2_PIX_FMT_H264,
192 V4L2_PIX_FMT_MPEG4,
193 },
194};
195
196static const struct coda_video_device coda_bit_decoder = {
197 .name = "coda-decoder",
198 .type = CODA_INST_DECODER,
199 .ops = &coda_bit_decode_ops,
200 .src_formats = {
201 V4L2_PIX_FMT_H264,
202 V4L2_PIX_FMT_MPEG4,
203 },
204 .dst_formats = {
205 V4L2_PIX_FMT_YUV420,
206 V4L2_PIX_FMT_YVU420,
207 V4L2_PIX_FMT_NV12,
208 },
209};
210
211static const struct coda_video_device *codadx6_video_devices[] = {
212 &coda_bit_encoder,
213};
214
215static const struct coda_video_device *coda7_video_devices[] = {
216 &coda_bit_encoder,
217 &coda_bit_decoder,
218};
219
220static const struct coda_video_device *coda9_video_devices[] = {
221 &coda_bit_encoder,
222 &coda_bit_decoder,
223};
224
172static bool coda_format_is_yuv(u32 fourcc) 225static bool coda_format_is_yuv(u32 fourcc)
173{ 226{
174 switch (fourcc) { 227 switch (fourcc) {
@@ -182,6 +235,18 @@ static bool coda_format_is_yuv(u32 fourcc)
182 } 235 }
183} 236}
184 237
238static const char *coda_format_name(u32 fourcc)
239{
240 int i;
241
242 for (i = 0; i < ARRAY_SIZE(coda_formats); i++) {
243 if (coda_formats[i].fourcc == fourcc)
244 return coda_formats[i].name;
245 }
246
247 return NULL;
248}
249
185/* 250/*
186 * Normalize all supported YUV 4:2:0 formats to the value used in the codec 251 * Normalize all supported YUV 4:2:0 formats to the value used in the codec
187 * tables. 252 * tables.
@@ -240,6 +305,17 @@ static void coda_get_max_dimensions(struct coda_dev *dev,
240 *max_h = h; 305 *max_h = h;
241} 306}
242 307
308const struct coda_video_device *to_coda_video_device(struct video_device *vdev)
309{
310 struct coda_dev *dev = video_get_drvdata(vdev);
311 unsigned int i = vdev - dev->vfd;
312
313 if (i >= dev->devtype->num_vdevs)
314 return NULL;
315
316 return dev->devtype->vdevs[i];
317}
318
243const char *coda_product_name(int product) 319const char *coda_product_name(int product)
244{ 320{
245 static char buf[9]; 321 static char buf[9];
@@ -278,58 +354,28 @@ static int coda_querycap(struct file *file, void *priv,
278static int coda_enum_fmt(struct file *file, void *priv, 354static int coda_enum_fmt(struct file *file, void *priv,
279 struct v4l2_fmtdesc *f) 355 struct v4l2_fmtdesc *f)
280{ 356{
281 struct coda_ctx *ctx = fh_to_ctx(priv); 357 struct video_device *vdev = video_devdata(file);
282 const struct coda_codec *codecs = ctx->dev->devtype->codecs; 358 const struct coda_video_device *cvd = to_coda_video_device(vdev);
283 const struct coda_fmt *formats = coda_formats; 359 const u32 *formats;
284 const struct coda_fmt *fmt; 360 const char *name;
285 int num_codecs = ctx->dev->devtype->num_codecs; 361
286 int num_formats = ARRAY_SIZE(coda_formats); 362 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
287 int i, k, num = 0; 363 formats = cvd->src_formats;
288 bool yuv; 364 else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
289 365 formats = cvd->dst_formats;
290 if (ctx->inst_type == CODA_INST_ENCODER)
291 yuv = (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT);
292 else 366 else
293 yuv = (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE); 367 return -EINVAL;
294
295 for (i = 0; i < num_formats; i++) {
296 /* Skip either raw or compressed formats */
297 if (yuv != coda_format_is_yuv(formats[i].fourcc))
298 continue;
299 /* All uncompressed formats are always supported */
300 if (yuv) {
301 if (num == f->index)
302 break;
303 ++num;
304 continue;
305 }
306 /* Compressed formats may be supported, check the codec list */
307 for (k = 0; k < num_codecs; k++) {
308 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
309 formats[i].fourcc == codecs[k].dst_fourcc)
310 break;
311 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
312 formats[i].fourcc == codecs[k].src_fourcc)
313 break;
314 }
315 if (k < num_codecs) {
316 if (num == f->index)
317 break;
318 ++num;
319 }
320 }
321 368
322 if (i < num_formats) { 369 if (f->index >= CODA_MAX_FORMATS || formats[f->index] == 0)
323 fmt = &formats[i]; 370 return -EINVAL;
324 strlcpy(f->description, fmt->name, sizeof(f->description)); 371
325 f->pixelformat = fmt->fourcc; 372 name = coda_format_name(formats[f->index]);
326 if (!yuv) 373 strlcpy(f->description, name, sizeof(f->description));
327 f->flags |= V4L2_FMT_FLAG_COMPRESSED; 374 f->pixelformat = formats[f->index];
328 return 0; 375 if (!coda_format_is_yuv(formats[f->index]))
329 } 376 f->flags |= V4L2_FMT_FLAG_COMPRESSED;
330 377
331 /* Format not found */ 378 return 0;
332 return -EINVAL;
333} 379}
334 380
335static int coda_g_fmt(struct file *file, void *priv, 381static int coda_g_fmt(struct file *file, void *priv,
@@ -354,11 +400,37 @@ static int coda_g_fmt(struct file *file, void *priv,
354 return 0; 400 return 0;
355} 401}
356 402
403static int coda_try_pixelformat(struct coda_ctx *ctx, struct v4l2_format *f)
404{
405 struct coda_q_data *q_data;
406 const u32 *formats;
407 int i;
408
409 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
410 formats = ctx->cvd->src_formats;
411 else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
412 formats = ctx->cvd->dst_formats;
413 else
414 return -EINVAL;
415
416 for (i = 0; i < CODA_MAX_FORMATS; i++) {
417 if (formats[i] == f->fmt.pix.pixelformat) {
418 f->fmt.pix.pixelformat = formats[i];
419 return 0;
420 }
421 }
422
423 /* Fall back to currently set pixelformat */
424 q_data = get_q_data(ctx, f->type);
425 f->fmt.pix.pixelformat = q_data->fourcc;
426
427 return 0;
428}
429
357static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec, 430static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec,
358 struct v4l2_format *f) 431 struct v4l2_format *f)
359{ 432{
360 struct coda_dev *dev = ctx->dev; 433 struct coda_dev *dev = ctx->dev;
361 struct coda_q_data *q_data;
362 unsigned int max_w, max_h; 434 unsigned int max_w, max_h;
363 enum v4l2_field field; 435 enum v4l2_field field;
364 436
@@ -381,21 +453,6 @@ static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec,
381 case V4L2_PIX_FMT_YUV420: 453 case V4L2_PIX_FMT_YUV420:
382 case V4L2_PIX_FMT_YVU420: 454 case V4L2_PIX_FMT_YVU420:
383 case V4L2_PIX_FMT_NV12: 455 case V4L2_PIX_FMT_NV12:
384 case V4L2_PIX_FMT_H264:
385 case V4L2_PIX_FMT_MPEG4:
386 case V4L2_PIX_FMT_JPEG:
387 break;
388 default:
389 q_data = get_q_data(ctx, f->type);
390 if (!q_data)
391 return -EINVAL;
392 f->fmt.pix.pixelformat = q_data->fourcc;
393 }
394
395 switch (f->fmt.pix.pixelformat) {
396 case V4L2_PIX_FMT_YUV420:
397 case V4L2_PIX_FMT_YVU420:
398 case V4L2_PIX_FMT_NV12:
399 /* Frame stride must be multiple of 8, but 16 for h.264 */ 456 /* Frame stride must be multiple of 8, but 16 for h.264 */
400 f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16); 457 f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
401 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * 458 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
@@ -423,34 +480,35 @@ static int coda_try_fmt_vid_cap(struct file *file, void *priv,
423 struct v4l2_format *f) 480 struct v4l2_format *f)
424{ 481{
425 struct coda_ctx *ctx = fh_to_ctx(priv); 482 struct coda_ctx *ctx = fh_to_ctx(priv);
426 const struct coda_codec *codec = NULL; 483 const struct coda_q_data *q_data_src;
484 const struct coda_codec *codec;
427 struct vb2_queue *src_vq; 485 struct vb2_queue *src_vq;
428 int ret; 486 int ret;
429 487
488 ret = coda_try_pixelformat(ctx, f);
489 if (ret < 0)
490 return ret;
491
492 q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
493
430 /* 494 /*
431 * If the source format is already fixed, try to find a codec that 495 * If the source format is already fixed, only allow the same output
432 * converts to the given destination format 496 * resolution
433 */ 497 */
434 src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); 498 src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
435 if (vb2_is_streaming(src_vq)) { 499 if (vb2_is_streaming(src_vq)) {
436 struct coda_q_data *q_data_src;
437
438 q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
439 codec = coda_find_codec(ctx->dev, q_data_src->fourcc,
440 f->fmt.pix.pixelformat);
441 if (!codec)
442 return -EINVAL;
443
444 f->fmt.pix.width = q_data_src->width; 500 f->fmt.pix.width = q_data_src->width;
445 f->fmt.pix.height = q_data_src->height; 501 f->fmt.pix.height = q_data_src->height;
446 } else {
447 /* Otherwise determine codec by encoded format, if possible */
448 codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420,
449 f->fmt.pix.pixelformat);
450 } 502 }
451 503
452 f->fmt.pix.colorspace = ctx->colorspace; 504 f->fmt.pix.colorspace = ctx->colorspace;
453 505
506 q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
507 codec = coda_find_codec(ctx->dev, q_data_src->fourcc,
508 f->fmt.pix.pixelformat);
509 if (!codec)
510 return -EINVAL;
511
454 ret = coda_try_fmt(ctx, codec, f); 512 ret = coda_try_fmt(ctx, codec, f);
455 if (ret < 0) 513 if (ret < 0)
456 return ret; 514 return ret;
@@ -471,22 +529,21 @@ static int coda_try_fmt_vid_out(struct file *file, void *priv,
471 struct v4l2_format *f) 529 struct v4l2_format *f)
472{ 530{
473 struct coda_ctx *ctx = fh_to_ctx(priv); 531 struct coda_ctx *ctx = fh_to_ctx(priv);
474 const struct coda_codec *codec = NULL; 532 struct coda_dev *dev = ctx->dev;
533 const struct coda_q_data *q_data_dst;
534 const struct coda_codec *codec;
535 int ret;
475 536
476 /* Determine codec by encoded format, returns NULL if raw or invalid */ 537 ret = coda_try_pixelformat(ctx, f);
477 if (ctx->inst_type == CODA_INST_DECODER) { 538 if (ret < 0)
478 codec = coda_find_codec(ctx->dev, f->fmt.pix.pixelformat, 539 return ret;
479 V4L2_PIX_FMT_YUV420);
480 if (!codec)
481 codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_H264,
482 V4L2_PIX_FMT_YUV420);
483 if (!codec)
484 return -EINVAL;
485 }
486 540
487 if (!f->fmt.pix.colorspace) 541 if (!f->fmt.pix.colorspace)
488 f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; 542 f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
489 543
544 q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
545 codec = coda_find_codec(dev, f->fmt.pix.pixelformat, q_data_dst->fourcc);
546
490 return coda_try_fmt(ctx, codec, f); 547 return coda_try_fmt(ctx, codec, f);
491} 548}
492 549
@@ -907,18 +964,10 @@ static void coda_set_tiled_map_type(struct coda_ctx *ctx, int tiled_map_type)
907 964
908static void set_default_params(struct coda_ctx *ctx) 965static void set_default_params(struct coda_ctx *ctx)
909{ 966{
910 u32 src_fourcc, dst_fourcc; 967 int max_w, max_h;
911 int max_w;
912 int max_h;
913 968
914 if (ctx->inst_type == CODA_INST_ENCODER) { 969 ctx->codec = coda_find_codec(ctx->dev, ctx->cvd->src_formats[0],
915 src_fourcc = V4L2_PIX_FMT_YUV420; 970 ctx->cvd->dst_formats[0]);
916 dst_fourcc = V4L2_PIX_FMT_H264;
917 } else {
918 src_fourcc = V4L2_PIX_FMT_H264;
919 dst_fourcc = V4L2_PIX_FMT_YUV420;
920 }
921 ctx->codec = coda_find_codec(ctx->dev, src_fourcc, dst_fourcc);
922 max_w = ctx->codec->max_w; 971 max_w = ctx->codec->max_w;
923 max_h = ctx->codec->max_h; 972 max_h = ctx->codec->max_h;
924 973
@@ -1409,10 +1458,14 @@ static int coda_next_free_instance(struct coda_dev *dev)
1409 return idx; 1458 return idx;
1410} 1459}
1411 1460
1412static int coda_open(struct file *file, enum coda_inst_type inst_type, 1461/*
1413 const struct coda_context_ops *ctx_ops) 1462 * File operations
1463 */
1464
1465static int coda_open(struct file *file)
1414{ 1466{
1415 struct coda_dev *dev = video_drvdata(file); 1467 struct video_device *vdev = video_devdata(file);
1468 struct coda_dev *dev = video_get_drvdata(vdev);
1416 struct coda_ctx *ctx = NULL; 1469 struct coda_ctx *ctx = NULL;
1417 char *name; 1470 char *name;
1418 int ret; 1471 int ret;
@@ -1433,8 +1486,9 @@ static int coda_open(struct file *file, enum coda_inst_type inst_type,
1433 ctx->debugfs_entry = debugfs_create_dir(name, dev->debugfs_root); 1486 ctx->debugfs_entry = debugfs_create_dir(name, dev->debugfs_root);
1434 kfree(name); 1487 kfree(name);
1435 1488
1436 ctx->inst_type = inst_type; 1489 ctx->cvd = to_coda_video_device(vdev);
1437 ctx->ops = ctx_ops; 1490 ctx->inst_type = ctx->cvd->type;
1491 ctx->ops = ctx->cvd->ops;
1438 init_completion(&ctx->completion); 1492 init_completion(&ctx->completion);
1439 INIT_WORK(&ctx->pic_run_work, coda_pic_run_work); 1493 INIT_WORK(&ctx->pic_run_work, coda_pic_run_work);
1440 INIT_WORK(&ctx->seq_end_work, ctx->ops->seq_end_work); 1494 INIT_WORK(&ctx->seq_end_work, ctx->ops->seq_end_work);
@@ -1542,16 +1596,6 @@ err_coda_max:
1542 return ret; 1596 return ret;
1543} 1597}
1544 1598
1545static int coda_encoder_open(struct file *file)
1546{
1547 return coda_open(file, CODA_INST_ENCODER, &coda_bit_encode_ops);
1548}
1549
1550static int coda_decoder_open(struct file *file)
1551{
1552 return coda_open(file, CODA_INST_DECODER, &coda_bit_decode_ops);
1553}
1554
1555static int coda_release(struct file *file) 1599static int coda_release(struct file *file)
1556{ 1600{
1557 struct coda_dev *dev = video_drvdata(file); 1601 struct coda_dev *dev = video_drvdata(file);
@@ -1595,18 +1639,9 @@ static int coda_release(struct file *file)
1595 return 0; 1639 return 0;
1596} 1640}
1597 1641
1598static const struct v4l2_file_operations coda_encoder_fops = { 1642static const struct v4l2_file_operations coda_fops = {
1599 .owner = THIS_MODULE,
1600 .open = coda_encoder_open,
1601 .release = coda_release,
1602 .poll = v4l2_m2m_fop_poll,
1603 .unlocked_ioctl = video_ioctl2,
1604 .mmap = v4l2_m2m_fop_mmap,
1605};
1606
1607static const struct v4l2_file_operations coda_decoder_fops = {
1608 .owner = THIS_MODULE, 1643 .owner = THIS_MODULE,
1609 .open = coda_decoder_open, 1644 .open = coda_open,
1610 .release = coda_release, 1645 .release = coda_release,
1611 .poll = v4l2_m2m_fop_poll, 1646 .poll = v4l2_m2m_fop_poll,
1612 .unlocked_ioctl = video_ioctl2, 1647 .unlocked_ioctl = video_ioctl2,
@@ -1711,8 +1746,16 @@ err_clk_per:
1711 return ret; 1746 return ret;
1712} 1747}
1713 1748
1714static int coda_register_device(struct coda_dev *dev, struct video_device *vfd) 1749static int coda_register_device(struct coda_dev *dev, int i)
1715{ 1750{
1751 struct video_device *vfd = &dev->vfd[i];
1752
1753 if (i > ARRAY_SIZE(dev->vfd))
1754 return -EINVAL;
1755
1756 snprintf(vfd->name, sizeof(vfd->name), dev->devtype->vdevs[i]->name);
1757 vfd->fops = &coda_fops;
1758 vfd->ioctl_ops = &coda_ioctl_ops;
1716 vfd->release = video_device_release_empty, 1759 vfd->release = video_device_release_empty,
1717 vfd->lock = &dev->dev_mutex; 1760 vfd->lock = &dev->dev_mutex;
1718 vfd->v4l2_dev = &dev->v4l2_dev; 1761 vfd->v4l2_dev = &dev->v4l2_dev;
@@ -1731,7 +1774,7 @@ static void coda_fw_callback(const struct firmware *fw, void *context)
1731{ 1774{
1732 struct coda_dev *dev = context; 1775 struct coda_dev *dev = context;
1733 struct platform_device *pdev = dev->plat_dev; 1776 struct platform_device *pdev = dev->plat_dev;
1734 int ret; 1777 int i, ret;
1735 1778
1736 if (!fw) { 1779 if (!fw) {
1737 v4l2_err(&dev->v4l2_dev, "firmware request failed\n"); 1780 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 goto rel_ctx; 1815 goto rel_ctx;
1773 } 1816 }
1774 1817
1775 dev->vfd[0].fops = &coda_encoder_fops, 1818 for (i = 0; i < dev->devtype->num_vdevs; i++) {
1776 dev->vfd[0].ioctl_ops = &coda_ioctl_ops; 1819 ret = coda_register_device(dev, i);
1777 snprintf(dev->vfd[0].name, sizeof(dev->vfd[0].name), "coda-encoder"); 1820 if (ret) {
1778 ret = coda_register_device(dev, &dev->vfd[0]); 1821 v4l2_err(&dev->v4l2_dev,
1779 if (ret) { 1822 "Failed to register %s video device: %d\n",
1780 v4l2_err(&dev->v4l2_dev, 1823 dev->devtype->vdevs[i]->name, ret);
1781 "Failed to register encoder video device\n"); 1824 goto rel_vfd;
1782 goto rel_m2m; 1825 }
1783 }
1784
1785 dev->vfd[1].fops = &coda_decoder_fops,
1786 dev->vfd[1].ioctl_ops = &coda_ioctl_ops;
1787 snprintf(dev->vfd[1].name, sizeof(dev->vfd[1].name), "coda-decoder");
1788 ret = coda_register_device(dev, &dev->vfd[1]);
1789 if (ret) {
1790 v4l2_err(&dev->v4l2_dev,
1791 "Failed to register decoder video device\n");
1792 goto rel_m2m;
1793 } 1826 }
1794 1827
1795 v4l2_info(&dev->v4l2_dev, "codec registered as /dev/video[%d-%d]\n", 1828 v4l2_info(&dev->v4l2_dev, "codec registered as /dev/video[%d-%d]\n",
1796 dev->vfd[0].num, dev->vfd[1].num); 1829 dev->vfd[0].num, dev->vfd[i - 1].num);
1797 1830
1798 pm_runtime_put_sync(&pdev->dev); 1831 pm_runtime_put_sync(&pdev->dev);
1799 return; 1832 return;
1800 1833
1801rel_m2m: 1834rel_vfd:
1835 while (--i >= 0)
1836 video_unregister_device(&dev->vfd[i]);
1802 v4l2_m2m_release(dev->m2m_dev); 1837 v4l2_m2m_release(dev->m2m_dev);
1803rel_ctx: 1838rel_ctx:
1804 vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); 1839 vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
@@ -1830,6 +1865,8 @@ static const struct coda_devtype coda_devdata[] = {
1830 .product = CODA_DX6, 1865 .product = CODA_DX6,
1831 .codecs = codadx6_codecs, 1866 .codecs = codadx6_codecs,
1832 .num_codecs = ARRAY_SIZE(codadx6_codecs), 1867 .num_codecs = ARRAY_SIZE(codadx6_codecs),
1868 .vdevs = codadx6_video_devices,
1869 .num_vdevs = ARRAY_SIZE(codadx6_video_devices),
1833 .workbuf_size = 288 * 1024 + FMO_SLICE_SAVE_BUF_SIZE * 8 * 1024, 1870 .workbuf_size = 288 * 1024 + FMO_SLICE_SAVE_BUF_SIZE * 8 * 1024,
1834 .iram_size = 0xb000, 1871 .iram_size = 0xb000,
1835 }, 1872 },
@@ -1838,6 +1875,8 @@ static const struct coda_devtype coda_devdata[] = {
1838 .product = CODA_7541, 1875 .product = CODA_7541,
1839 .codecs = coda7_codecs, 1876 .codecs = coda7_codecs,
1840 .num_codecs = ARRAY_SIZE(coda7_codecs), 1877 .num_codecs = ARRAY_SIZE(coda7_codecs),
1878 .vdevs = coda7_video_devices,
1879 .num_vdevs = ARRAY_SIZE(coda7_video_devices),
1841 .workbuf_size = 128 * 1024, 1880 .workbuf_size = 128 * 1024,
1842 .tempbuf_size = 304 * 1024, 1881 .tempbuf_size = 304 * 1024,
1843 .iram_size = 0x14000, 1882 .iram_size = 0x14000,
@@ -1847,6 +1886,8 @@ static const struct coda_devtype coda_devdata[] = {
1847 .product = CODA_960, 1886 .product = CODA_960,
1848 .codecs = coda9_codecs, 1887 .codecs = coda9_codecs,
1849 .num_codecs = ARRAY_SIZE(coda9_codecs), 1888 .num_codecs = ARRAY_SIZE(coda9_codecs),
1889 .vdevs = coda9_video_devices,
1890 .num_vdevs = ARRAY_SIZE(coda9_video_devices),
1850 .workbuf_size = 80 * 1024, 1891 .workbuf_size = 80 * 1024,
1851 .tempbuf_size = 204 * 1024, 1892 .tempbuf_size = 204 * 1024,
1852 .iram_size = 0x21000, 1893 .iram_size = 0x21000,
@@ -1856,6 +1897,8 @@ static const struct coda_devtype coda_devdata[] = {
1856 .product = CODA_960, 1897 .product = CODA_960,
1857 .codecs = coda9_codecs, 1898 .codecs = coda9_codecs,
1858 .num_codecs = ARRAY_SIZE(coda9_codecs), 1899 .num_codecs = ARRAY_SIZE(coda9_codecs),
1900 .vdevs = coda9_video_devices,
1901 .num_vdevs = ARRAY_SIZE(coda9_video_devices),
1859 .workbuf_size = 80 * 1024, 1902 .workbuf_size = 80 * 1024,
1860 .tempbuf_size = 204 * 1024, 1903 .tempbuf_size = 204 * 1024,
1861 .iram_size = 0x20000, 1904 .iram_size = 0x20000,
@@ -2035,9 +2078,12 @@ static int coda_probe(struct platform_device *pdev)
2035static int coda_remove(struct platform_device *pdev) 2078static int coda_remove(struct platform_device *pdev)
2036{ 2079{
2037 struct coda_dev *dev = platform_get_drvdata(pdev); 2080 struct coda_dev *dev = platform_get_drvdata(pdev);
2081 int i;
2038 2082
2039 video_unregister_device(&dev->vfd[0]); 2083 for (i = 0; i < ARRAY_SIZE(dev->vfd); i++) {
2040 video_unregister_device(&dev->vfd[1]); 2084 if (video_get_drvdata(&dev->vfd[i]))
2085 video_unregister_device(&dev->vfd[i]);
2086 }
2041 if (dev->m2m_dev) 2087 if (dev->m2m_dev)
2042 v4l2_m2m_release(dev->m2m_dev); 2088 v4l2_m2m_release(dev->m2m_dev);
2043 pm_runtime_disable(&pdev->dev); 2089 pm_runtime_disable(&pdev->dev);
diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
index 76ba83c03191..07eaf58303ef 100644
--- a/drivers/media/platform/coda/coda.h
+++ b/drivers/media/platform/coda/coda.h
@@ -45,11 +45,15 @@ enum coda_product {
45 CODA_960 = 0xf020, 45 CODA_960 = 0xf020,
46}; 46};
47 47
48struct coda_video_device;
49
48struct coda_devtype { 50struct coda_devtype {
49 char *firmware; 51 char *firmware;
50 enum coda_product product; 52 enum coda_product product;
51 const struct coda_codec *codecs; 53 const struct coda_codec *codecs;
52 unsigned int num_codecs; 54 unsigned int num_codecs;
55 const struct coda_video_device **vdevs;
56 unsigned int num_vdevs;
53 size_t workbuf_size; 57 size_t workbuf_size;
54 size_t tempbuf_size; 58 size_t tempbuf_size;
55 size_t iram_size; 59 size_t iram_size;
@@ -65,7 +69,7 @@ struct coda_aux_buf {
65 69
66struct coda_dev { 70struct coda_dev {
67 struct v4l2_device v4l2_dev; 71 struct v4l2_device v4l2_dev;
68 struct video_device vfd[2]; 72 struct video_device vfd[3];
69 struct platform_device *plat_dev; 73 struct platform_device *plat_dev;
70 const struct coda_devtype *devtype; 74 const struct coda_devtype *devtype;
71 75
@@ -183,6 +187,7 @@ struct coda_ctx {
183 struct work_struct pic_run_work; 187 struct work_struct pic_run_work;
184 struct work_struct seq_end_work; 188 struct work_struct seq_end_work;
185 struct completion completion; 189 struct completion completion;
190 const struct coda_video_device *cvd;
186 const struct coda_context_ops *ops; 191 const struct coda_context_ops *ops;
187 int aborting; 192 int aborting;
188 int initialized; 193 int initialized;