From 7dfccff14f57c65f6ae4c49aea8eb5f7bf39a840 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 21 Feb 2019 08:21:14 -0500 Subject: [PATCH 001/218] media: cec: fill in cec chardev kobject to ease debugging The cec chardev kobject has no name, which made it hard to debug when kobject debugging is turned on. Signed-off-by: Hans Verkuil Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/cec/cec-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c index cc875dabd765..f5d1578e256a 100644 --- a/drivers/media/cec/cec-core.c +++ b/drivers/media/cec/cec-core.c @@ -126,6 +126,7 @@ static int __must_check cec_devnode_register(struct cec_devnode *devnode, /* Part 2: Initialize and register the character device */ cdev_init(&devnode->cdev, &cec_devnode_fops); devnode->cdev.owner = owner; + kobject_set_name(&devnode->cdev.kobj, "cec%d", devnode->minor); ret = cdev_device_add(&devnode->cdev, &devnode->dev); if (ret) { From 13deaec42578fb4da844b0c81d13a88b59fdae65 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 21 Feb 2019 08:22:41 -0500 Subject: [PATCH 002/218] media: media-devnode: fill in media chardev kobject to ease debugging The media chardev kobject has no name, which made it hard to debug when kobject debugging is turned on. Signed-off-by: Hans Verkuil Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-devnode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c index 6b87a721dc49..61dc05fcc55c 100644 --- a/drivers/media/media-devnode.c +++ b/drivers/media/media-devnode.c @@ -251,6 +251,7 @@ int __must_check media_devnode_register(struct media_device *mdev, /* Part 2: Initialize the character device */ cdev_init(&devnode->cdev, &media_devnode_fops); devnode->cdev.owner = owner; + kobject_set_name(&devnode->cdev.kobj, "media%d", devnode->minor); /* Part 3: Add the media and char device */ ret = cdev_device_add(&devnode->cdev, &devnode->dev); From 57ac534828798affcf13b6f9122dfac7bf135dd0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 21 Feb 2019 08:23:50 -0500 Subject: [PATCH 003/218] media: vivid: use vzalloc for dev->bitmap_out When vivid is unloaded it used vfree to free dev->bitmap_out, but it was actually allocated using kmalloc. Use vzalloc instead, conform what vivid-vid-cap.c does. Signed-off-by: Hans Verkuil Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vivid/vivid-vid-out.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c index e61b91b414f9..9350ca65dd91 100644 --- a/drivers/media/platform/vivid/vivid-vid-out.c +++ b/drivers/media/platform/vivid/vivid-vid-out.c @@ -798,7 +798,7 @@ int vivid_vid_out_s_selection(struct file *file, void *fh, struct v4l2_selection s->r.height *= factor; if (dev->bitmap_out && (compose->width != s->r.width || compose->height != s->r.height)) { - kfree(dev->bitmap_out); + vfree(dev->bitmap_out); dev->bitmap_out = NULL; } *compose = s->r; @@ -941,15 +941,19 @@ int vidioc_s_fmt_vid_out_overlay(struct file *file, void *priv, return ret; if (win->bitmap) { - new_bitmap = memdup_user(win->bitmap, bitmap_size); + new_bitmap = vzalloc(bitmap_size); - if (IS_ERR(new_bitmap)) - return PTR_ERR(new_bitmap); + if (!new_bitmap) + return -ENOMEM; + if (copy_from_user(new_bitmap, win->bitmap, bitmap_size)) { + vfree(new_bitmap); + return -EFAULT; + } } dev->overlay_out_top = win->w.top; dev->overlay_out_left = win->w.left; - kfree(dev->bitmap_out); + vfree(dev->bitmap_out); dev->bitmap_out = new_bitmap; dev->clipcount_out = win->clipcount; if (dev->clipcount_out) From ea6c7e34f3b28e165988aa7391310752969842e8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 21 Feb 2019 08:35:15 -0500 Subject: [PATCH 004/218] media: vim2m: replace devm_kzalloc by kzalloc It is not possible to use devm_kzalloc since that memory is freed immediately when the device instance is unbound. Various objects like the video device may still be in use since someone has the device node open, and when that is closed it expects the memory to be around. So use kzalloc and release it at the appropriate time. Signed-off-by: Hans Verkuil Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vim2m.c | 35 +++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c index 34dcaca45d8b..dd47821fc661 100644 --- a/drivers/media/platform/vim2m.c +++ b/drivers/media/platform/vim2m.c @@ -1262,6 +1262,15 @@ static int vim2m_release(struct file *file) return 0; } +static void vim2m_device_release(struct video_device *vdev) +{ + struct vim2m_dev *dev = container_of(vdev, struct vim2m_dev, vfd); + + v4l2_device_unregister(&dev->v4l2_dev); + v4l2_m2m_release(dev->m2m_dev); + kfree(dev); +} + static const struct v4l2_file_operations vim2m_fops = { .owner = THIS_MODULE, .open = vim2m_open, @@ -1277,7 +1286,7 @@ static const struct video_device vim2m_videodev = { .fops = &vim2m_fops, .ioctl_ops = &vim2m_ioctl_ops, .minor = -1, - .release = video_device_release_empty, + .release = vim2m_device_release, .device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING, }; @@ -1298,13 +1307,13 @@ static int vim2m_probe(struct platform_device *pdev) struct video_device *vfd; int ret; - dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return -ENOMEM; ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); if (ret) - return ret; + goto error_free; atomic_set(&dev->num_inst, 0); mutex_init(&dev->dev_mutex); @@ -1317,7 +1326,7 @@ static int vim2m_probe(struct platform_device *pdev) ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); if (ret) { v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); - goto unreg_v4l2; + goto error_v4l2; } video_set_drvdata(vfd, dev); @@ -1330,7 +1339,7 @@ static int vim2m_probe(struct platform_device *pdev) if (IS_ERR(dev->m2m_dev)) { v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n"); ret = PTR_ERR(dev->m2m_dev); - goto unreg_dev; + goto error_dev; } #ifdef CONFIG_MEDIA_CONTROLLER @@ -1346,27 +1355,29 @@ static int vim2m_probe(struct platform_device *pdev) MEDIA_ENT_F_PROC_VIDEO_SCALER); if (ret) { v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller\n"); - goto unreg_m2m; + goto error_m2m; } ret = media_device_register(&dev->mdev); if (ret) { v4l2_err(&dev->v4l2_dev, "Failed to register mem2mem media device\n"); - goto unreg_m2m_mc; + goto error_m2m_mc; } #endif return 0; #ifdef CONFIG_MEDIA_CONTROLLER -unreg_m2m_mc: +error_m2m_mc: v4l2_m2m_unregister_media_controller(dev->m2m_dev); -unreg_m2m: +error_m2m: v4l2_m2m_release(dev->m2m_dev); #endif -unreg_dev: +error_dev: video_unregister_device(&dev->vfd); -unreg_v4l2: +error_v4l2: v4l2_device_unregister(&dev->v4l2_dev); +error_free: + kfree(dev); return ret; } @@ -1382,9 +1393,7 @@ static int vim2m_remove(struct platform_device *pdev) v4l2_m2m_unregister_media_controller(dev->m2m_dev); media_device_cleanup(&dev->mdev); #endif - v4l2_m2m_release(dev->m2m_dev); video_unregister_device(&dev->vfd); - v4l2_device_unregister(&dev->v4l2_dev); return 0; } From 0e43734d4c46e156785bb1d2acc5b3c10b7d5dd5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 21 Feb 2019 08:37:42 -0500 Subject: [PATCH 005/218] media: v4l2-subdev: add release() internal op If the subdevice created a device node, then the v4l2_subdev cannot be freed until the last user of the device node closes it. This means that we need a release() callback in v4l2_subdev_internal_ops that is called from the video_device release function so the subdevice driver can postpone freeing memory until the that callback is called. If no video device node was created then the release callback can be called immediately when the subdev is unregistered. Signed-off-by: Hans Verkuil Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-device.c | 19 ++++++++++++++----- include/media/v4l2-subdev.h | 13 ++++++++++++- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c index e0ddb9a52bd1..7cca0de1b730 100644 --- a/drivers/media/v4l2-core/v4l2-device.c +++ b/drivers/media/v4l2-core/v4l2-device.c @@ -216,10 +216,18 @@ error_module: } EXPORT_SYMBOL_GPL(v4l2_device_register_subdev); +static void v4l2_subdev_release(struct v4l2_subdev *sd) +{ + struct module *owner = !sd->owner_v4l2_dev ? sd->owner : NULL; + + if (sd->internal_ops && sd->internal_ops->release) + sd->internal_ops->release(sd); + module_put(owner); +} + static void v4l2_device_release_subdev_node(struct video_device *vdev) { - struct v4l2_subdev *sd = video_get_drvdata(vdev); - sd->devnode = NULL; + v4l2_subdev_release(video_get_drvdata(vdev)); kfree(vdev); } @@ -318,8 +326,9 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd) media_device_unregister_entity(&sd->entity); } #endif - video_unregister_device(sd->devnode); - if (!sd->owner_v4l2_dev) - module_put(sd->owner); + if (sd->devnode) + video_unregister_device(sd->devnode); + else + v4l2_subdev_release(sd); } EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev); diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 349e1c18cf48..e807aa96ed3b 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -755,7 +755,17 @@ struct v4l2_subdev_ops { * * @open: called when the subdev device node is opened by an application. * - * @close: called when the subdev device node is closed. + * @close: called when the subdev device node is closed. Please note that + * it is possible for @close to be called after @unregistered! + * + * @release: called when the last user of the subdev device is gone. This + * happens after the @unregistered callback and when the last open + * filehandle to the v4l-subdevX device node was closed. If no device + * node was created for this sub-device, then the @release callback + * is called right after the @unregistered callback. + * The @release callback is typically used to free the memory containing + * the v4l2_subdev structure. It is almost certainly required for any + * sub-device that sets the V4L2_SUBDEV_FL_HAS_DEVNODE flag. * * .. note:: * Never call this from drivers, only the v4l2 framework can call @@ -766,6 +776,7 @@ struct v4l2_subdev_internal_ops { void (*unregistered)(struct v4l2_subdev *sd); int (*open)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh); int (*close)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh); + void (*release)(struct v4l2_subdev *sd); }; #define V4L2_SUBDEV_NAME_SIZE 32 From 218bf10e39ed5fb22a48dee40bfd2bbcb91693ba Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 1 Mar 2019 06:11:27 -0500 Subject: [PATCH 006/218] media: v4l2-subdev: handle module refcounting here The module ownership refcounting was done in media_entity_get/put, but that was very confusing and it did not work either in case an application had a v4l-subdevX device open and the module was unbound. When the v4l-subdevX device was closed the media_entity_put was never called and the module refcount was left one too high, making it impossible to unload it. Since v4l2-subdev.c was the only place where media_entity_get/put was called, just move the functionality to v4l2-subdev.c and drop those confusing entity functions. Store the module in subdev_fh so module_put no longer depends on the media_entity struct. Signed-off-by: Hans Verkuil Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-entity.c | 28 --------------------------- drivers/media/v4l2-core/v4l2-subdev.c | 22 +++++++++------------ include/media/media-entity.h | 24 ----------------------- include/media/v4l2-subdev.h | 2 ++ 4 files changed, 11 insertions(+), 65 deletions(-) diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index 0b1cb3559140..dd859d7b235a 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -17,7 +17,6 @@ */ #include -#include #include #include #include @@ -587,33 +586,6 @@ void media_pipeline_stop(struct media_entity *entity) } EXPORT_SYMBOL_GPL(media_pipeline_stop); -/* ----------------------------------------------------------------------------- - * Module use count - */ - -struct media_entity *media_entity_get(struct media_entity *entity) -{ - if (entity == NULL) - return NULL; - - if (entity->graph_obj.mdev->dev && - !try_module_get(entity->graph_obj.mdev->dev->driver->owner)) - return NULL; - - return entity; -} -EXPORT_SYMBOL_GPL(media_entity_get); - -void media_entity_put(struct media_entity *entity) -{ - if (entity == NULL) - return; - - if (entity->graph_obj.mdev->dev) - module_put(entity->graph_obj.mdev->dev->driver->owner); -} -EXPORT_SYMBOL_GPL(media_entity_put); - /* ----------------------------------------------------------------------------- * Links management */ diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index f5f0d71ec745..d75815ab0d7b 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -54,9 +55,6 @@ static int subdev_open(struct file *file) struct video_device *vdev = video_devdata(file); struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); struct v4l2_subdev_fh *subdev_fh; -#if defined(CONFIG_MEDIA_CONTROLLER) - struct media_entity *entity = NULL; -#endif int ret; subdev_fh = kzalloc(sizeof(*subdev_fh), GFP_KERNEL); @@ -73,12 +71,15 @@ static int subdev_open(struct file *file) v4l2_fh_add(&subdev_fh->vfh); file->private_data = &subdev_fh->vfh; #if defined(CONFIG_MEDIA_CONTROLLER) - if (sd->v4l2_dev->mdev) { - entity = media_entity_get(&sd->entity); - if (!entity) { + if (sd->v4l2_dev->mdev && sd->entity.graph_obj.mdev->dev) { + struct module *owner; + + owner = sd->entity.graph_obj.mdev->dev->driver->owner; + if (!try_module_get(owner)) { ret = -EBUSY; goto err; } + subdev_fh->owner = owner; } #endif @@ -91,9 +92,7 @@ static int subdev_open(struct file *file) return 0; err: -#if defined(CONFIG_MEDIA_CONTROLLER) - media_entity_put(entity); -#endif + module_put(subdev_fh->owner); v4l2_fh_del(&subdev_fh->vfh); v4l2_fh_exit(&subdev_fh->vfh); subdev_fh_free(subdev_fh); @@ -111,10 +110,7 @@ static int subdev_close(struct file *file) if (sd->internal_ops && sd->internal_ops->close) sd->internal_ops->close(sd, subdev_fh); -#if defined(CONFIG_MEDIA_CONTROLLER) - if (sd->v4l2_dev->mdev) - media_entity_put(&sd->entity); -#endif + module_put(subdev_fh->owner); v4l2_fh_del(vfh); v4l2_fh_exit(vfh); subdev_fh_free(subdev_fh); diff --git a/include/media/media-entity.h b/include/media/media-entity.h index e5f6960d92f6..3cbad42e3693 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -864,19 +864,6 @@ struct media_link *media_entity_find_link(struct media_pad *source, */ struct media_pad *media_entity_remote_pad(const struct media_pad *pad); -/** - * media_entity_get - Get a reference to the parent module - * - * @entity: The entity - * - * Get a reference to the parent media device module. - * - * The function will return immediately if @entity is %NULL. - * - * Return: returns a pointer to the entity on success or %NULL on failure. - */ -struct media_entity *media_entity_get(struct media_entity *entity); - /** * media_entity_get_fwnode_pad - Get pad number from fwnode * @@ -916,17 +903,6 @@ __must_check int media_graph_walk_init( */ void media_graph_walk_cleanup(struct media_graph *graph); -/** - * media_entity_put - Release the reference to the parent module - * - * @entity: The entity - * - * Release the reference count acquired by media_entity_get(). - * - * The function will return immediately if @entity is %NULL. - */ -void media_entity_put(struct media_entity *entity); - /** * media_graph_walk_start - Start walking the media graph at a * given entity diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index e807aa96ed3b..a7fa5b80915a 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -910,9 +910,11 @@ struct v4l2_subdev { * * @vfh: pointer to &struct v4l2_fh * @pad: pointer to &struct v4l2_subdev_pad_config + * @owner: module pointer to the owner of this file handle */ struct v4l2_subdev_fh { struct v4l2_fh vfh; + struct module *owner; #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) struct v4l2_subdev_pad_config *pad; #endif From f74267b51cb36321f777807b2e04ca02167ecc08 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 8 Mar 2019 08:02:26 -0500 Subject: [PATCH 007/218] media: vimc: zero the media_device on probe The media_device is part of a static global vimc_device struct. The media framework expects this to be zeroed before it is used, however, since this is a global this is not the case if vimc is unbound and then bound again. So call memset to ensure any left-over values are cleared. Signed-off-by: Hans Verkuil Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vimc/vimc-core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/vimc/vimc-core.c b/drivers/media/platform/vimc/vimc-core.c index 0fbb7914098f..3aa62d7e3d0e 100644 --- a/drivers/media/platform/vimc/vimc-core.c +++ b/drivers/media/platform/vimc/vimc-core.c @@ -304,6 +304,8 @@ static int vimc_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "probe"); + memset(&vimc->mdev, 0, sizeof(vimc->mdev)); + /* Create platform_device for each entity in the topology*/ vimc->subdevs = devm_kcalloc(&vimc->pdev.dev, vimc->pipe_cfg->num_ents, sizeof(*vimc->subdevs), GFP_KERNEL); From 3650a23eda89f99b964fbd63a20320fafaa73e33 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 21 Feb 2019 08:47:28 -0500 Subject: [PATCH 008/218] media: vimc: free vimc_cap_device when the last user disappears Don't free vimc_cap_device immediately, instead do this in the video_device release function which is called when the last user closes the video device. Only then is it safe to free the memory. Signed-off-by: Hans Verkuil Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vimc/vimc-capture.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/vimc/vimc-capture.c b/drivers/media/platform/vimc/vimc-capture.c index ea869631a3f6..54fda5b29dd0 100644 --- a/drivers/media/platform/vimc/vimc-capture.c +++ b/drivers/media/platform/vimc/vimc-capture.c @@ -338,6 +338,15 @@ static const struct media_entity_operations vimc_cap_mops = { .link_validate = vimc_link_validate, }; +static void vimc_cap_release(struct video_device *vdev) +{ + struct vimc_cap_device *vcap = + container_of(vdev, struct vimc_cap_device, vdev); + + vimc_pads_cleanup(vcap->ved.pads); + kfree(vcap); +} + static void vimc_cap_comp_unbind(struct device *comp, struct device *master, void *master_data) { @@ -348,8 +357,6 @@ static void vimc_cap_comp_unbind(struct device *comp, struct device *master, vb2_queue_release(&vcap->queue); media_entity_cleanup(ved->ent); video_unregister_device(&vcap->vdev); - vimc_pads_cleanup(vcap->ved.pads); - kfree(vcap); } static void *vimc_cap_process_frame(struct vimc_ent_device *ved, @@ -467,7 +474,7 @@ static int vimc_cap_comp_bind(struct device *comp, struct device *master, vdev = &vcap->vdev; vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; vdev->entity.ops = &vimc_cap_mops; - vdev->release = video_device_release_empty; + vdev->release = vimc_cap_release; vdev->fops = &vimc_cap_fops; vdev->ioctl_ops = &vimc_cap_ioctl_ops; vdev->lock = &vcap->lock; From 2b177f2849d23061508bb13594cc1bff1ccb46c9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 5 Mar 2019 03:36:20 -0500 Subject: [PATCH 009/218] media: vimc: use new release op Use the new v4l2_subdev_internal_ops release op to free the subdev memory only when the last user closed the file handle. Move v4l2_device_unregister_subdev() to the end of the vimc_ent_sd_unregister() function since now the unregister_subdev() call may free the vimc_ent_device struct which is used after the unregister_subdev() call. So this now has to be done last. Signed-off-by: Hans Verkuil Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vimc/vimc-common.c | 4 +++- drivers/media/platform/vimc/vimc-common.h | 2 ++ drivers/media/platform/vimc/vimc-debayer.c | 15 +++++++++++++-- drivers/media/platform/vimc/vimc-scaler.c | 15 +++++++++++++-- drivers/media/platform/vimc/vimc-sensor.c | 19 +++++++++++++++---- 5 files changed, 46 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/vimc/vimc-common.c b/drivers/media/platform/vimc/vimc-common.c index c1a74bb2df58..e8e6c6b95db9 100644 --- a/drivers/media/platform/vimc/vimc-common.c +++ b/drivers/media/platform/vimc/vimc-common.c @@ -380,6 +380,7 @@ int vimc_ent_sd_register(struct vimc_ent_device *ved, u32 function, u16 num_pads, const unsigned long *pads_flag, + const struct v4l2_subdev_internal_ops *sd_int_ops, const struct v4l2_subdev_ops *sd_ops) { int ret; @@ -394,6 +395,7 @@ int vimc_ent_sd_register(struct vimc_ent_device *ved, /* Initialize the subdev */ v4l2_subdev_init(sd, sd_ops); + sd->internal_ops = sd_int_ops; sd->entity.function = function; sd->entity.ops = &vimc_ent_sd_mops; sd->owner = THIS_MODULE; @@ -431,9 +433,9 @@ EXPORT_SYMBOL_GPL(vimc_ent_sd_register); void vimc_ent_sd_unregister(struct vimc_ent_device *ved, struct v4l2_subdev *sd) { - v4l2_device_unregister_subdev(sd); media_entity_cleanup(ved->ent); vimc_pads_cleanup(ved->pads); + v4l2_device_unregister_subdev(sd); } EXPORT_SYMBOL_GPL(vimc_ent_sd_unregister); diff --git a/drivers/media/platform/vimc/vimc-common.h b/drivers/media/platform/vimc/vimc-common.h index 84539430b5e7..c439cbf2f030 100644 --- a/drivers/media/platform/vimc/vimc-common.h +++ b/drivers/media/platform/vimc/vimc-common.h @@ -187,6 +187,7 @@ const struct vimc_pix_map *vimc_pix_map_by_pixelformat(u32 pixelformat); * @function: media entity function defined by MEDIA_ENT_F_* macros * @num_pads: number of pads to initialize * @pads_flag: flags to use in each pad + * @sd_int_ops: pointer to &struct v4l2_subdev_internal_ops * @sd_ops: pointer to &struct v4l2_subdev_ops. * * Helper function initialize and register the struct vimc_ent_device and struct @@ -199,6 +200,7 @@ int vimc_ent_sd_register(struct vimc_ent_device *ved, u32 function, u16 num_pads, const unsigned long *pads_flag, + const struct v4l2_subdev_internal_ops *sd_int_ops, const struct v4l2_subdev_ops *sd_ops); /** diff --git a/drivers/media/platform/vimc/vimc-debayer.c b/drivers/media/platform/vimc/vimc-debayer.c index 7d77c63b99d2..eaed4233ad1b 100644 --- a/drivers/media/platform/vimc/vimc-debayer.c +++ b/drivers/media/platform/vimc/vimc-debayer.c @@ -489,6 +489,18 @@ static void *vimc_deb_process_frame(struct vimc_ent_device *ved, } +static void vimc_deb_release(struct v4l2_subdev *sd) +{ + struct vimc_deb_device *vdeb = + container_of(sd, struct vimc_deb_device, sd); + + kfree(vdeb); +} + +static const struct v4l2_subdev_internal_ops vimc_deb_int_ops = { + .release = vimc_deb_release, +}; + static void vimc_deb_comp_unbind(struct device *comp, struct device *master, void *master_data) { @@ -497,7 +509,6 @@ static void vimc_deb_comp_unbind(struct device *comp, struct device *master, ved); vimc_ent_sd_unregister(ved, &vdeb->sd); - kfree(vdeb); } static int vimc_deb_comp_bind(struct device *comp, struct device *master, @@ -519,7 +530,7 @@ static int vimc_deb_comp_bind(struct device *comp, struct device *master, MEDIA_ENT_F_PROC_VIDEO_PIXEL_ENC_CONV, 2, (const unsigned long[2]) {MEDIA_PAD_FL_SINK, MEDIA_PAD_FL_SOURCE}, - &vimc_deb_ops); + &vimc_deb_int_ops, &vimc_deb_ops); if (ret) { kfree(vdeb); return ret; diff --git a/drivers/media/platform/vimc/vimc-scaler.c b/drivers/media/platform/vimc/vimc-scaler.c index 39b2a73dfcc1..2028afa4ef7a 100644 --- a/drivers/media/platform/vimc/vimc-scaler.c +++ b/drivers/media/platform/vimc/vimc-scaler.c @@ -348,6 +348,18 @@ static void *vimc_sca_process_frame(struct vimc_ent_device *ved, return vsca->src_frame; }; +static void vimc_sca_release(struct v4l2_subdev *sd) +{ + struct vimc_sca_device *vsca = + container_of(sd, struct vimc_sca_device, sd); + + kfree(vsca); +} + +static const struct v4l2_subdev_internal_ops vimc_sca_int_ops = { + .release = vimc_sca_release, +}; + static void vimc_sca_comp_unbind(struct device *comp, struct device *master, void *master_data) { @@ -356,7 +368,6 @@ static void vimc_sca_comp_unbind(struct device *comp, struct device *master, ved); vimc_ent_sd_unregister(ved, &vsca->sd); - kfree(vsca); } @@ -379,7 +390,7 @@ static int vimc_sca_comp_bind(struct device *comp, struct device *master, MEDIA_ENT_F_PROC_VIDEO_SCALER, 2, (const unsigned long[2]) {MEDIA_PAD_FL_SINK, MEDIA_PAD_FL_SOURCE}, - &vimc_sca_ops); + &vimc_sca_int_ops, &vimc_sca_ops); if (ret) { kfree(vsca); return ret; diff --git a/drivers/media/platform/vimc/vimc-sensor.c b/drivers/media/platform/vimc/vimc-sensor.c index 59195f262623..d7891d3bbeaa 100644 --- a/drivers/media/platform/vimc/vimc-sensor.c +++ b/drivers/media/platform/vimc/vimc-sensor.c @@ -301,6 +301,20 @@ static const struct v4l2_ctrl_ops vimc_sen_ctrl_ops = { .s_ctrl = vimc_sen_s_ctrl, }; +static void vimc_sen_release(struct v4l2_subdev *sd) +{ + struct vimc_sen_device *vsen = + container_of(sd, struct vimc_sen_device, sd); + + v4l2_ctrl_handler_free(&vsen->hdl); + tpg_free(&vsen->tpg); + kfree(vsen); +} + +static const struct v4l2_subdev_internal_ops vimc_sen_int_ops = { + .release = vimc_sen_release, +}; + static void vimc_sen_comp_unbind(struct device *comp, struct device *master, void *master_data) { @@ -309,9 +323,6 @@ static void vimc_sen_comp_unbind(struct device *comp, struct device *master, container_of(ved, struct vimc_sen_device, ved); vimc_ent_sd_unregister(ved, &vsen->sd); - v4l2_ctrl_handler_free(&vsen->hdl); - tpg_free(&vsen->tpg); - kfree(vsen); } /* Image Processing Controls */ @@ -371,7 +382,7 @@ static int vimc_sen_comp_bind(struct device *comp, struct device *master, pdata->entity_name, MEDIA_ENT_F_CAM_SENSOR, 1, (const unsigned long[1]) {MEDIA_PAD_FL_SOURCE}, - &vimc_sen_ops); + &vimc_sen_int_ops, &vimc_sen_ops); if (ret) goto err_free_hdl; From d950fd992ef89f39ff8908f389ed6cbd2fdc0513 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Wed, 13 Feb 2019 17:07:54 -0500 Subject: [PATCH 010/218] media: rcar-vin: Fix lockdep warning at stream on MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes to v4l2-fwnode in commit [1] triggered a lockdep warning in rcar-vin. The first attempt to solve this warning in the rcar-vin driver was incomplete and only pushed the warning to happen at stream on time instead of at probe time. This change reverts the incomplete fix and properly fixes the warning by removing the need to hold the rcar-vin specific group lock when calling v4l2_async_notifier_parse_fwnode_endpoints_by_port(). And instead takes it in the callback where it's really needed. [1] commit eae2aed1eab9bf08 ("media: v4l2-fwnode: Switch to v4l2_async_notifier_add_subdev") Fixes: 6458afc8c49148f0 ("media: rcar-vin: remove unneeded locking in async callbacks") Signed-off-by: Niklas Söderlund Reviewed-by: Kieran Bingham Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-core.c | 43 +++++++++++++++------ 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c index 594d80434004..abbb58202239 100644 --- a/drivers/media/platform/rcar-vin/rcar-core.c +++ b/drivers/media/platform/rcar-vin/rcar-core.c @@ -546,7 +546,9 @@ static void rvin_parallel_notify_unbind(struct v4l2_async_notifier *notifier, vin_dbg(vin, "unbind parallel subdev %s\n", subdev->name); + mutex_lock(&vin->lock); rvin_parallel_subdevice_detach(vin); + mutex_unlock(&vin->lock); } static int rvin_parallel_notify_bound(struct v4l2_async_notifier *notifier, @@ -556,7 +558,9 @@ static int rvin_parallel_notify_bound(struct v4l2_async_notifier *notifier, struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev); int ret; + mutex_lock(&vin->lock); ret = rvin_parallel_subdevice_attach(vin, subdev); + mutex_unlock(&vin->lock); if (ret) return ret; @@ -664,6 +668,7 @@ static int rvin_group_notify_complete(struct v4l2_async_notifier *notifier) } /* Create all media device links between VINs and CSI-2's. */ + mutex_lock(&vin->group->lock); for (route = vin->info->routes; route->mask; route++) { struct media_pad *source_pad, *sink_pad; struct media_entity *source, *sink; @@ -699,6 +704,7 @@ static int rvin_group_notify_complete(struct v4l2_async_notifier *notifier) break; } } + mutex_unlock(&vin->group->lock); return ret; } @@ -714,6 +720,8 @@ static void rvin_group_notify_unbind(struct v4l2_async_notifier *notifier, if (vin->group->vin[i]) rvin_v4l2_unregister(vin->group->vin[i]); + mutex_lock(&vin->group->lock); + for (i = 0; i < RVIN_CSI_MAX; i++) { if (vin->group->csi[i].fwnode != asd->match.fwnode) continue; @@ -721,6 +729,8 @@ static void rvin_group_notify_unbind(struct v4l2_async_notifier *notifier, vin_dbg(vin, "Unbind CSI-2 %s from slot %u\n", subdev->name, i); break; } + + mutex_unlock(&vin->group->lock); } static int rvin_group_notify_bound(struct v4l2_async_notifier *notifier, @@ -730,6 +740,8 @@ static int rvin_group_notify_bound(struct v4l2_async_notifier *notifier, struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev); unsigned int i; + mutex_lock(&vin->group->lock); + for (i = 0; i < RVIN_CSI_MAX; i++) { if (vin->group->csi[i].fwnode != asd->match.fwnode) continue; @@ -738,6 +750,8 @@ static int rvin_group_notify_bound(struct v4l2_async_notifier *notifier, break; } + mutex_unlock(&vin->group->lock); + return 0; } @@ -752,6 +766,7 @@ static int rvin_mc_parse_of_endpoint(struct device *dev, struct v4l2_async_subdev *asd) { struct rvin_dev *vin = dev_get_drvdata(dev); + int ret = 0; if (vep->base.port != 1 || vep->base.id >= RVIN_CSI_MAX) return -EINVAL; @@ -762,38 +777,48 @@ static int rvin_mc_parse_of_endpoint(struct device *dev, return -ENOTCONN; } + mutex_lock(&vin->group->lock); + if (vin->group->csi[vep->base.id].fwnode) { vin_dbg(vin, "OF device %pOF already handled\n", to_of_node(asd->match.fwnode)); - return -ENOTCONN; + ret = -ENOTCONN; + goto out; } vin->group->csi[vep->base.id].fwnode = asd->match.fwnode; vin_dbg(vin, "Add group OF device %pOF to slot %u\n", to_of_node(asd->match.fwnode), vep->base.id); +out: + mutex_unlock(&vin->group->lock); - return 0; + return ret; } static int rvin_mc_parse_of_graph(struct rvin_dev *vin) { - unsigned int count = 0; + unsigned int count = 0, vin_mask = 0; unsigned int i; int ret; mutex_lock(&vin->group->lock); /* If not all VIN's are registered don't register the notifier. */ - for (i = 0; i < RCAR_VIN_NUM; i++) - if (vin->group->vin[i]) + for (i = 0; i < RCAR_VIN_NUM; i++) { + if (vin->group->vin[i]) { count++; + vin_mask |= BIT(i); + } + } if (vin->group->count != count) { mutex_unlock(&vin->group->lock); return 0; } + mutex_unlock(&vin->group->lock); + v4l2_async_notifier_init(&vin->group->notifier); /* @@ -802,21 +827,17 @@ static int rvin_mc_parse_of_graph(struct rvin_dev *vin) * will only be registered once with the group notifier. */ for (i = 0; i < RCAR_VIN_NUM; i++) { - if (!vin->group->vin[i]) + if (!(vin_mask & BIT(i))) continue; ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port( vin->group->vin[i]->dev, &vin->group->notifier, sizeof(struct v4l2_async_subdev), 1, rvin_mc_parse_of_endpoint); - if (ret) { - mutex_unlock(&vin->group->lock); + if (ret) return ret; - } } - mutex_unlock(&vin->group->lock); - if (list_empty(&vin->group->notifier.asd_list)) return 0; From ce3c2433b074eb9d569a0f63a15d6fd5dbc87f02 Mon Sep 17 00:00:00 2001 From: Steve Longerbeam Date: Tue, 19 Feb 2019 20:09:38 -0500 Subject: [PATCH 011/218] media: imx: vdic: Restore default case to prepare_vdi_in_buffers() Restore a default case to prepare_vdi_in_buffers() to fix the following smatch errors: drivers/staging/media/imx/imx-media-vdic.c:236 prepare_vdi_in_buffers() error: uninitialized symbol 'prev_phys'. drivers/staging/media/imx/imx-media-vdic.c:237 prepare_vdi_in_buffers() error: uninitialized symbol 'curr_phys'. drivers/staging/media/imx/imx-media-vdic.c:238 prepare_vdi_in_buffers() error: uninitialized symbol 'next_phys'. Fixes: 6e537b58de772 ("media: imx: vdic: rely on VDIC for correct field order") Reported-by: Hans Verkuil Signed-off-by: Steve Longerbeam Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx-media-vdic.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/staging/media/imx/imx-media-vdic.c b/drivers/staging/media/imx/imx-media-vdic.c index 2808662e2597..37bfbd4a1c39 100644 --- a/drivers/staging/media/imx/imx-media-vdic.c +++ b/drivers/staging/media/imx/imx-media-vdic.c @@ -231,6 +231,12 @@ static void __maybe_unused prepare_vdi_in_buffers(struct vdic_priv *priv, curr_phys = vb2_dma_contig_plane_dma_addr(curr_vb, 0); next_phys = vb2_dma_contig_plane_dma_addr(curr_vb, 0) + is; break; + default: + /* + * can't get here, priv->fieldtype can only be one of + * the above. This is to quiet smatch errors. + */ + return; } ipu_cpmem_set_buffer(priv->vdi_in_ch_p, 0, prev_phys); From 3bb7b493198353142c0acb4ed95cddd17a2c5d16 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 20 Feb 2019 03:59:00 -0500 Subject: [PATCH 012/218] media: imx7: fix smatch error Fixes this smatch error: drivers/staging/media/imx/imx7-mipi-csis.c:716 mipi_csis_set_fmt() error: we previously assumed 'fmt' could be null (see line 709) fmt is never NULL, so remove the 'fmt &&' condition. Signed-off-by: Hans Verkuil Reviewed-by: Rui Miguel Silva Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx7-mipi-csis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c index 2ddcc42ab8ff..e1f2ef1fa76d 100644 --- a/drivers/staging/media/imx/imx7-mipi-csis.c +++ b/drivers/staging/media/imx/imx7-mipi-csis.c @@ -706,7 +706,7 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *mipi_sd, fmt = mipi_csis_get_format(state, cfg, sdformat->which, sdformat->pad); mutex_lock(&state->lock); - if (fmt && sdformat->pad == CSIS_PAD_SOURCE) { + if (sdformat->pad == CSIS_PAD_SOURCE) { sdformat->format = *fmt; goto unlock; } From 904371f90b2c0c749a5ab75478c129a4682ac3d8 Mon Sep 17 00:00:00 2001 From: Steve Longerbeam Date: Wed, 20 Feb 2019 18:53:29 -0500 Subject: [PATCH 013/218] media: imx: csi: Allow unknown nearest upstream entities On i.MX6, the nearest upstream entity to the CSI can only be the CSI video muxes or the Synopsys DW MIPI CSI-2 receiver. However the i.MX53 has no CSI video muxes or a MIPI CSI-2 receiver. So allow for the nearest upstream entity to the CSI to be something other than those. Fixes: bf3cfaa712e5c ("media: staging/imx: get CSI bus type from nearest upstream entity") Signed-off-by: Steve Longerbeam Cc: stable@vger.kernel.org Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx-media-csi.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index 3b7517348666..41965d8b56c4 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c @@ -154,9 +154,10 @@ static inline bool requires_passthrough(struct v4l2_fwnode_endpoint *ep, /* * Parses the fwnode endpoint from the source pad of the entity * connected to this CSI. This will either be the entity directly - * upstream from the CSI-2 receiver, or directly upstream from the - * video mux. The endpoint is needed to determine the bus type and - * bus config coming into the CSI. + * upstream from the CSI-2 receiver, directly upstream from the + * video mux, or directly upstream from the CSI itself. The endpoint + * is needed to determine the bus type and bus config coming into + * the CSI. */ static int csi_get_upstream_endpoint(struct csi_priv *priv, struct v4l2_fwnode_endpoint *ep) @@ -172,7 +173,8 @@ static int csi_get_upstream_endpoint(struct csi_priv *priv, if (!priv->src_sd) return -EPIPE; - src = &priv->src_sd->entity; + sd = priv->src_sd; + src = &sd->entity; if (src->function == MEDIA_ENT_F_VID_MUX) { /* @@ -186,6 +188,14 @@ static int csi_get_upstream_endpoint(struct csi_priv *priv, src = &sd->entity; } + /* + * If the source is neither the video mux nor the CSI-2 receiver, + * get the source pad directly upstream from CSI itself. + */ + if (src->function != MEDIA_ENT_F_VID_MUX && + sd->grp_id != IMX_MEDIA_GRP_ID_CSI2) + src = &priv->sd.entity; + /* get source pad of entity directly upstream from src */ pad = imx_media_find_upstream_pad(priv->md, src, 0); if (IS_ERR(pad)) From 107927fa597c99eaeee4f51865ca0956ec71b6a2 Mon Sep 17 00:00:00 2001 From: Steve Longerbeam Date: Wed, 20 Feb 2019 18:53:30 -0500 Subject: [PATCH 014/218] media: imx: Clear fwnode link struct for each endpoint iteration In imx_media_create_csi_of_links(), the 'struct v4l2_fwnode_link' must be cleared for each endpoint iteration, otherwise if the remote port has no "reg" property, link.remote_port will not be reset to zero. This was discovered on the i.MX53 SMD board, since the OV5642 connects directly to ipu1_csi0 and has a single source port with no "reg" property. Fixes: 621b08eabcddb ("media: staging/imx: remove static media link arrays") Signed-off-by: Steve Longerbeam Cc: stable@vger.kernel.org Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx-media-of.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/staging/media/imx/imx-media-of.c b/drivers/staging/media/imx/imx-media-of.c index 03446335ac03..a26bdeb1af34 100644 --- a/drivers/staging/media/imx/imx-media-of.c +++ b/drivers/staging/media/imx/imx-media-of.c @@ -145,15 +145,18 @@ int imx_media_create_csi_of_links(struct imx_media_dev *imxmd, struct v4l2_subdev *csi) { struct device_node *csi_np = csi->dev->of_node; - struct fwnode_handle *fwnode, *csi_ep; - struct v4l2_fwnode_link link; struct device_node *ep; - int ret; - - link.local_node = of_fwnode_handle(csi_np); - link.local_port = CSI_SINK_PAD; for_each_child_of_node(csi_np, ep) { + struct fwnode_handle *fwnode, *csi_ep; + struct v4l2_fwnode_link link; + int ret; + + memset(&link, 0, sizeof(link)); + + link.local_node = of_fwnode_handle(csi_np); + link.local_port = CSI_SINK_PAD; + csi_ep = of_fwnode_handle(ep); fwnode = fwnode_graph_get_remote_endpoint(csi_ep); From 085b26da62211cb77622008082adff56aefa771d Mon Sep 17 00:00:00 2001 From: Steve Longerbeam Date: Wed, 20 Feb 2019 18:53:31 -0500 Subject: [PATCH 015/218] media: imx: Rename functions that add IPU-internal subdevs For the functions that add and remove the internal IPU subdevice descriptors, rename them to make clear they are the subdevs internal to the IPU. Also rename the platform data structure for the internal IPU subdevices. No functional changes. Signed-off-by: Steve Longerbeam Acked-by: Philipp Zabel Cc: stable@vger.kernel.org Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx-ic-common.c | 2 +- drivers/staging/media/imx/imx-media-dev.c | 8 ++++---- drivers/staging/media/imx/imx-media-internal-sd.c | 12 ++++++------ drivers/staging/media/imx/imx-media-vdic.c | 2 +- drivers/staging/media/imx/imx-media.h | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/staging/media/imx/imx-ic-common.c b/drivers/staging/media/imx/imx-ic-common.c index 765919487a73..90a926891eb9 100644 --- a/drivers/staging/media/imx/imx-ic-common.c +++ b/drivers/staging/media/imx/imx-ic-common.c @@ -26,7 +26,7 @@ static struct imx_ic_ops *ic_ops[IC_NUM_OPS] = { static int imx_ic_probe(struct platform_device *pdev) { - struct imx_media_internal_sd_platformdata *pdata; + struct imx_media_ipu_internal_sd_pdata *pdata; struct imx_ic_priv *priv; int ret; diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c index 28a3d23aad5b..fc35508d9396 100644 --- a/drivers/staging/media/imx/imx-media-dev.c +++ b/drivers/staging/media/imx/imx-media-dev.c @@ -477,10 +477,10 @@ static int imx_media_probe(struct platform_device *pdev) goto cleanup; } - ret = imx_media_add_internal_subdevs(imxmd); + ret = imx_media_add_ipu_internal_subdevs(imxmd); if (ret) { v4l2_err(&imxmd->v4l2_dev, - "add_internal_subdevs failed with %d\n", ret); + "add_ipu_internal_subdevs failed with %d\n", ret); goto cleanup; } @@ -491,7 +491,7 @@ static int imx_media_probe(struct platform_device *pdev) return 0; del_int: - imx_media_remove_internal_subdevs(imxmd); + imx_media_remove_ipu_internal_subdevs(imxmd); cleanup: v4l2_async_notifier_cleanup(&imxmd->notifier); v4l2_device_unregister(&imxmd->v4l2_dev); @@ -508,7 +508,7 @@ static int imx_media_remove(struct platform_device *pdev) v4l2_info(&imxmd->v4l2_dev, "Removing imx-media\n"); v4l2_async_notifier_unregister(&imxmd->notifier); - imx_media_remove_internal_subdevs(imxmd); + imx_media_remove_ipu_internal_subdevs(imxmd); v4l2_async_notifier_cleanup(&imxmd->notifier); media_device_unregister(&imxmd->md); v4l2_device_unregister(&imxmd->v4l2_dev); diff --git a/drivers/staging/media/imx/imx-media-internal-sd.c b/drivers/staging/media/imx/imx-media-internal-sd.c index 5e10d95e5529..e620f4adb755 100644 --- a/drivers/staging/media/imx/imx-media-internal-sd.c +++ b/drivers/staging/media/imx/imx-media-internal-sd.c @@ -1,7 +1,7 @@ /* * Media driver for Freescale i.MX5/6 SOC * - * Adds the internal subdevices and the media links between them. + * Adds the IPU internal subdevices and the media links between them. * * Copyright (c) 2016 Mentor Graphics Inc. * @@ -192,7 +192,7 @@ static struct v4l2_subdev *find_sink(struct imx_media_dev *imxmd, /* * retrieve IPU id from subdev name, note: can't get this from - * struct imx_media_internal_sd_platformdata because if src is + * struct imx_media_ipu_internal_sd_pdata because if src is * a CSI, it has different struct ipu_client_platformdata which * does not contain IPU id. */ @@ -270,7 +270,7 @@ static int add_internal_subdev(struct imx_media_dev *imxmd, const struct internal_subdev *isd, int ipu_id) { - struct imx_media_internal_sd_platformdata pdata; + struct imx_media_ipu_internal_sd_pdata pdata; struct platform_device_info pdevinfo = {}; struct platform_device *pdev; @@ -328,7 +328,7 @@ static int add_ipu_internal_subdevs(struct imx_media_dev *imxmd, int ipu_id) return 0; } -int imx_media_add_internal_subdevs(struct imx_media_dev *imxmd) +int imx_media_add_ipu_internal_subdevs(struct imx_media_dev *imxmd) { int ret; @@ -343,11 +343,11 @@ int imx_media_add_internal_subdevs(struct imx_media_dev *imxmd) return 0; remove: - imx_media_remove_internal_subdevs(imxmd); + imx_media_remove_ipu_internal_subdevs(imxmd); return ret; } -void imx_media_remove_internal_subdevs(struct imx_media_dev *imxmd) +void imx_media_remove_ipu_internal_subdevs(struct imx_media_dev *imxmd) { struct imx_media_async_subdev *imxasd; struct v4l2_async_subdev *asd; diff --git a/drivers/staging/media/imx/imx-media-vdic.c b/drivers/staging/media/imx/imx-media-vdic.c index 37bfbd4a1c39..8cdd3daa6c5f 100644 --- a/drivers/staging/media/imx/imx-media-vdic.c +++ b/drivers/staging/media/imx/imx-media-vdic.c @@ -940,7 +940,7 @@ static const struct v4l2_subdev_internal_ops vdic_internal_ops = { static int imx_vdic_probe(struct platform_device *pdev) { - struct imx_media_internal_sd_platformdata *pdata; + struct imx_media_ipu_internal_sd_pdata *pdata; struct vdic_priv *priv; int ret; diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h index ae964c8d5be1..ccbfc4438c85 100644 --- a/drivers/staging/media/imx/imx-media.h +++ b/drivers/staging/media/imx/imx-media.h @@ -115,7 +115,7 @@ struct imx_media_pad_vdev { struct list_head list; }; -struct imx_media_internal_sd_platformdata { +struct imx_media_ipu_internal_sd_pdata { char sd_name[V4L2_SUBDEV_NAME_SIZE]; u32 grp_id; int ipu_id; @@ -252,10 +252,10 @@ struct imx_media_fim *imx_media_fim_init(struct v4l2_subdev *sd); void imx_media_fim_free(struct imx_media_fim *fim); /* imx-media-internal-sd.c */ -int imx_media_add_internal_subdevs(struct imx_media_dev *imxmd); +int imx_media_add_ipu_internal_subdevs(struct imx_media_dev *imxmd); int imx_media_create_ipu_internal_links(struct imx_media_dev *imxmd, struct v4l2_subdev *sd); -void imx_media_remove_internal_subdevs(struct imx_media_dev *imxmd); +void imx_media_remove_ipu_internal_subdevs(struct imx_media_dev *imxmd); /* imx-media-of.c */ int imx_media_add_of_subdevs(struct imx_media_dev *dev, From dee747f88167124884a918855c1f438e2f7f39e2 Mon Sep 17 00:00:00 2001 From: Steve Longerbeam Date: Wed, 20 Feb 2019 18:53:32 -0500 Subject: [PATCH 016/218] media: imx: Don't register IPU subdevs/links if CSI port missing The second IPU internal sub-devices were being registered and links to them created even when the second IPU is not present. This is wrong for i.MX6 S/DL and i.MX53 which have only a single IPU. Fixes: e130291212df5 ("[media] media: Add i.MX media core driver") Signed-off-by: Steve Longerbeam Reviewed-by: Philipp Zabel Cc: stable@vger.kernel.org Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx-media-dev.c | 7 --- .../staging/media/imx/imx-media-internal-sd.c | 22 ++----- drivers/staging/media/imx/imx-media-of.c | 58 +++++++++++++------ drivers/staging/media/imx/imx-media.h | 3 +- drivers/staging/media/imx/imx7-media-csi.c | 2 +- 5 files changed, 46 insertions(+), 46 deletions(-) diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c index fc35508d9396..10a63a4fa90b 100644 --- a/drivers/staging/media/imx/imx-media-dev.c +++ b/drivers/staging/media/imx/imx-media-dev.c @@ -477,13 +477,6 @@ static int imx_media_probe(struct platform_device *pdev) goto cleanup; } - ret = imx_media_add_ipu_internal_subdevs(imxmd); - if (ret) { - v4l2_err(&imxmd->v4l2_dev, - "add_ipu_internal_subdevs failed with %d\n", ret); - goto cleanup; - } - ret = imx_media_dev_notifier_register(imxmd); if (ret) goto del_int; diff --git a/drivers/staging/media/imx/imx-media-internal-sd.c b/drivers/staging/media/imx/imx-media-internal-sd.c index e620f4adb755..dc510dcfe160 100644 --- a/drivers/staging/media/imx/imx-media-internal-sd.c +++ b/drivers/staging/media/imx/imx-media-internal-sd.c @@ -298,13 +298,14 @@ static int add_internal_subdev(struct imx_media_dev *imxmd, } /* adds the internal subdevs in one ipu */ -static int add_ipu_internal_subdevs(struct imx_media_dev *imxmd, int ipu_id) +int imx_media_add_ipu_internal_subdevs(struct imx_media_dev *imxmd, + int ipu_id) { enum isd_enum i; + int ret; for (i = 0; i < num_isd; i++) { const struct internal_subdev *isd = &int_subdev[i]; - int ret; /* * the CSIs are represented in the device-tree, so those @@ -322,25 +323,10 @@ static int add_ipu_internal_subdevs(struct imx_media_dev *imxmd, int ipu_id) } if (ret) - return ret; + goto remove; } return 0; -} - -int imx_media_add_ipu_internal_subdevs(struct imx_media_dev *imxmd) -{ - int ret; - - ret = add_ipu_internal_subdevs(imxmd, 0); - if (ret) - goto remove; - - ret = add_ipu_internal_subdevs(imxmd, 1); - if (ret) - goto remove; - - return 0; remove: imx_media_remove_ipu_internal_subdevs(imxmd); diff --git a/drivers/staging/media/imx/imx-media-of.c b/drivers/staging/media/imx/imx-media-of.c index a26bdeb1af34..12383f4785ad 100644 --- a/drivers/staging/media/imx/imx-media-of.c +++ b/drivers/staging/media/imx/imx-media-of.c @@ -23,36 +23,25 @@ int imx_media_of_add_csi(struct imx_media_dev *imxmd, struct device_node *csi_np) { - int ret; - if (!of_device_is_available(csi_np)) { dev_dbg(imxmd->md.dev, "%s: %pOFn not enabled\n", __func__, csi_np); - /* unavailable is not an error */ - return 0; + return -ENODEV; } /* add CSI fwnode to async notifier */ - ret = imx_media_add_async_subdev(imxmd, of_fwnode_handle(csi_np), NULL); - if (ret) { - if (ret == -EEXIST) { - /* already added, everything is fine */ - return 0; - } - - /* other error, can't continue */ - return ret; - } - - return 0; + return imx_media_add_async_subdev(imxmd, of_fwnode_handle(csi_np), + NULL); } EXPORT_SYMBOL_GPL(imx_media_of_add_csi); int imx_media_add_of_subdevs(struct imx_media_dev *imxmd, struct device_node *np) { + bool ipu_found[2] = {false, false}; struct device_node *csi_np; int i, ret; + u32 ipu_id; for (i = 0; ; i++) { csi_np = of_parse_phandle(np, "ports", i); @@ -60,12 +49,43 @@ int imx_media_add_of_subdevs(struct imx_media_dev *imxmd, break; ret = imx_media_of_add_csi(imxmd, csi_np); - of_node_put(csi_np); - if (ret) - return ret; + if (ret) { + /* unavailable or already added is not an error */ + if (ret == -ENODEV || ret == -EEXIST) { + of_node_put(csi_np); + continue; + } + + /* other error, can't continue */ + goto err_out; + } + + ret = of_alias_get_id(csi_np->parent, "ipu"); + if (ret < 0) + goto err_out; + if (ret > 1) { + ret = -EINVAL; + goto err_out; + } + + ipu_id = ret; + + if (!ipu_found[ipu_id]) { + ret = imx_media_add_ipu_internal_subdevs(imxmd, + ipu_id); + if (ret) + goto err_out; + } + + ipu_found[ipu_id] = true; } return 0; + +err_out: + imx_media_remove_ipu_internal_subdevs(imxmd); + of_node_put(csi_np); + return ret; } /* diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h index ccbfc4438c85..dd603a6b3a70 100644 --- a/drivers/staging/media/imx/imx-media.h +++ b/drivers/staging/media/imx/imx-media.h @@ -252,7 +252,8 @@ struct imx_media_fim *imx_media_fim_init(struct v4l2_subdev *sd); void imx_media_fim_free(struct imx_media_fim *fim); /* imx-media-internal-sd.c */ -int imx_media_add_ipu_internal_subdevs(struct imx_media_dev *imxmd); +int imx_media_add_ipu_internal_subdevs(struct imx_media_dev *imxmd, + int ipu_id); int imx_media_create_ipu_internal_links(struct imx_media_dev *imxmd, struct v4l2_subdev *sd); void imx_media_remove_ipu_internal_subdevs(struct imx_media_dev *imxmd); diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c index 3fba7c27c0ec..1ba62fcdcae8 100644 --- a/drivers/staging/media/imx/imx7-media-csi.c +++ b/drivers/staging/media/imx/imx7-media-csi.c @@ -1271,7 +1271,7 @@ static int imx7_csi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, &csi->sd); ret = imx_media_of_add_csi(imxmd, node); - if (ret < 0) + if (ret < 0 && ret != -ENODEV && ret != -EEXIST) goto cleanup; ret = imx_media_dev_notifier_register(imxmd); From 1fc79c4bb19ba5068fc42d3a66655c3b175f9934 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 22 Feb 2019 01:32:26 -0500 Subject: [PATCH 017/218] media: staging/imx7: Fix an error code in mipi_csis_clk_get() We accidentally return IS_ERR(), which is 1, instead of the PTR_ERR() which is the negative error code. Fixes: 7807063b862b ("media: staging/imx7: add MIPI CSI-2 receiver subdev for i.MX7") Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx7-mipi-csis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c index e1f2ef1fa76d..a1f36be2e844 100644 --- a/drivers/staging/media/imx/imx7-mipi-csis.c +++ b/drivers/staging/media/imx/imx7-mipi-csis.c @@ -491,7 +491,7 @@ static int mipi_csis_clk_get(struct csi_state *state) state->wrap_clk = devm_clk_get(dev, "wrap"); if (IS_ERR(state->wrap_clk)) - return IS_ERR(state->wrap_clk); + return PTR_ERR(state->wrap_clk); /* Set clock rate */ ret = clk_set_rate(state->wrap_clk, state->clk_frequency); From 5eaa30aedd7fc4e6a9f077b7ae5b42c9965d5b98 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Fri, 22 Feb 2019 05:17:10 -0500 Subject: [PATCH 018/218] media: imx7-media-csi: don't store a floating pointer if imx7_csi_try_fmt() fails, cc variable won't be initialized and csi->cc[sdformat->pad] would be pointing to a random location. Reported-by: Dan Carpenter Signed-off-by: Rui Miguel Silva Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx7-media-csi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c index 1ba62fcdcae8..18eb5d3ecf10 100644 --- a/drivers/staging/media/imx/imx7-media-csi.c +++ b/drivers/staging/media/imx/imx7-media-csi.c @@ -1051,7 +1051,9 @@ static int imx7_csi_set_fmt(struct v4l2_subdev *sd, goto out_unlock; } - imx7_csi_try_fmt(csi, cfg, sdformat, &cc); + ret = imx7_csi_try_fmt(csi, cfg, sdformat, &cc); + if (ret < 0) + goto out_unlock; fmt = imx7_csi_get_format(csi, cfg, sdformat->pad, sdformat->which); if (!fmt) { From 2dba3de6e77fdf66ba33bd28c7698d0304a35a25 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 1 Mar 2019 04:38:31 -0500 Subject: [PATCH 019/218] media: rcar_drif: Remove devm_ioremap_resource() error printing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit devm_ioremap_resource() already prints an error message on failure, so there is no need to repeat that. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Reviewed-by: Simon Horman Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar_drif.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/rcar_drif.c b/drivers/media/platform/rcar_drif.c index c417ff8f6fe5..608e5217ccd5 100644 --- a/drivers/media/platform/rcar_drif.c +++ b/drivers/media/platform/rcar_drif.c @@ -1405,11 +1405,9 @@ static int rcar_drif_probe(struct platform_device *pdev) /* Register map */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ch->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(ch->base)) { - ret = PTR_ERR(ch->base); - dev_err(&pdev->dev, "ioremap failed (%d)\n", ret); - return ret; - } + if (IS_ERR(ch->base)) + return PTR_ERR(ch->base); + ch->start = res->start; platform_set_drvdata(pdev, ch); From 29f6c4227e450cd9d20615c08478bd4d3e04a711 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Fri, 1 Mar 2019 10:45:33 -0500 Subject: [PATCH 020/218] media: dt-bindings: media: rcar-csi2: Add r8a774a1 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document RZ/G2M (R8A774A1) SoC bindings. The RZ/G2M SoC is similar to R-Car M3-W (R8A7796). Signed-off-by: Biju Das Reviewed-by: Fabrizio Castro Acked-by: Niklas Söderlund Reviewed-by: Simon Horman Reviewed-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt b/Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt index d63275e17afd..9932458a0a45 100644 --- a/Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt +++ b/Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt @@ -8,6 +8,7 @@ R-Car VIN module, which provides the video capture capabilities. Mandatory properties -------------------- - compatible: Must be one or more of the following + - "renesas,r8a774a1-csi2" for the R8A774A1 device. - "renesas,r8a774c0-csi2" for the R8A774C0 device. - "renesas,r8a7795-csi2" for the R8A7795 device. - "renesas,r8a7796-csi2" for the R8A7796 device. From d4b87d459a4cfc8009ec4ee92893d84cef277f61 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Fri, 1 Mar 2019 10:45:34 -0500 Subject: [PATCH 021/218] media: rcar-csi2: Enable support for r8a774a1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the MIPI CSI-2 driver support for RZ/G2M(r8a774a1) SoC. The CSI-2 module of RZ/G2M is similar to R-Car M3-W. Signed-off-by: Biju Das Reviewed-by: Fabrizio Castro Acked-by: Niklas Söderlund Reviewed-by: Simon Horman Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-csi2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index f64528d2be3c..a438ec2c218f 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -985,6 +985,10 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a77990 = { }; static const struct of_device_id rcar_csi2_of_table[] = { + { + .compatible = "renesas,r8a774a1-csi2", + .data = &rcar_csi2_info_r8a7796, + }, { .compatible = "renesas,r8a774c0-csi2", .data = &rcar_csi2_info_r8a77990, From b8f92200d16e68e51c55f8ea7c2e251c423aac76 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Fri, 1 Mar 2019 10:45:35 -0500 Subject: [PATCH 022/218] media: dt-bindings: media: rcar_vin: Add r8a774a1 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document RZ/G2M (R8A774A1) SoC bindings. The RZ/G2M SoC is similar to R-Car M3-W (R8A7796). Signed-off-by: Biju Das Reviewed-by: Fabrizio Castro Acked-by: Niklas Söderlund Reviewed-by: Simon Horman Reviewed-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/rcar_vin.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt b/Documentation/devicetree/bindings/media/rcar_vin.txt index 224a4615b418..aa217b096279 100644 --- a/Documentation/devicetree/bindings/media/rcar_vin.txt +++ b/Documentation/devicetree/bindings/media/rcar_vin.txt @@ -13,6 +13,7 @@ on Gen3 and RZ/G2 platforms to a CSI-2 receiver. - "renesas,vin-r8a7743" for the R8A7743 device - "renesas,vin-r8a7744" for the R8A7744 device - "renesas,vin-r8a7745" for the R8A7745 device + - "renesas,vin-r8a774a1" for the R8A774A1 device - "renesas,vin-r8a774c0" for the R8A774C0 device - "renesas,vin-r8a7778" for the R8A7778 device - "renesas,vin-r8a7779" for the R8A7779 device From f29a317b9c33be536ab516a89a921719f907137e Mon Sep 17 00:00:00 2001 From: Biju Das Date: Fri, 1 Mar 2019 10:45:36 -0500 Subject: [PATCH 023/218] media: rcar-vin: Enable support for r8a774a1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the SoC specific information for RZ/G2M(r8a774a1) SoC. The VIN module of RZ/G2M is similar to R-Car M3-W. Signed-off-by: Biju Das Reviewed-by: Fabrizio Castro Acked-by: Niklas Söderlund Reviewed-by: Simon Horman Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c index abbb58202239..64f9cf790445 100644 --- a/drivers/media/platform/rcar-vin/rcar-core.c +++ b/drivers/media/platform/rcar-vin/rcar-core.c @@ -1156,6 +1156,10 @@ static const struct rvin_info rcar_info_r8a77995 = { }; static const struct of_device_id rvin_of_id_table[] = { + { + .compatible = "renesas,vin-r8a774a1", + .data = &rcar_info_r8a7796, + }, { .compatible = "renesas,vin-r8a774c0", .data = &rcar_info_r8a77990, From 3235d3946429f64b19addfd89fc926a36eaec06a Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Wed, 6 Mar 2019 01:15:02 -0500 Subject: [PATCH 024/218] media: mtk-vcodec: fix access to vb2_v4l2_buffer struct Commit 0650a91499e0 ("media: mtk-vcodec: Correct return type for mem2mem buffer helpers") fixed the return types for mem2mem buffer helper functions, but omitted two occurrences that are accessed in the mtk_v4l2_debug() macro. These only trigger compiler errors when DEBUG is defined. Fixes: 0650a91499e0 ("media: mtk-vcodec: Correct return type for mem2mem buffer helpers") Signed-off-by: Alexandre Courbot Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c index d022c65bb34c..a85c7cc8328e 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c @@ -1158,7 +1158,7 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) src_mem.size = (size_t)src_buf->planes[0].bytesused; mtk_v4l2_debug(2, "[%d] buf id=%d va=%p dma=%pad size=%zx", - ctx->id, src_buf->index, + ctx->id, src_buf->vb2_buf.index, src_mem.va, &src_mem.dma_addr, src_mem.size); @@ -1182,7 +1182,7 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) } mtk_v4l2_debug(ret ? 0 : 1, "[%d] vdec_if_decode() src_buf=%d, size=%zu, fail=%d, res_chg=%d", - ctx->id, src_buf->index, + ctx->id, src_buf->vb2_buf.index, src_mem.size, ret, res_chg); return; } From dea37a97265588da604c6ba80160a287b72c7bfd Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 6 Mar 2019 07:45:08 -0500 Subject: [PATCH 025/218] media: cpia2: Fix use-after-free in cpia2_exit Syzkaller report this: BUG: KASAN: use-after-free in sysfs_remove_file_ns+0x5f/0x70 fs/sysfs/file.c:468 Read of size 8 at addr ffff8881f59a6b70 by task syz-executor.0/8363 CPU: 0 PID: 8363 Comm: syz-executor.0 Not tainted 5.0.0-rc8+ #3 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0xfa/0x1ce lib/dump_stack.c:113 print_address_description+0x65/0x270 mm/kasan/report.c:187 kasan_report+0x149/0x18d mm/kasan/report.c:317 sysfs_remove_file_ns+0x5f/0x70 fs/sysfs/file.c:468 sysfs_remove_file include/linux/sysfs.h:519 [inline] driver_remove_file+0x40/0x50 drivers/base/driver.c:122 usb_remove_newid_files drivers/usb/core/driver.c:212 [inline] usb_deregister+0x12a/0x3b0 drivers/usb/core/driver.c:1005 cpia2_exit+0xa/0x16 [cpia2] __do_sys_delete_module kernel/module.c:1018 [inline] __se_sys_delete_module kernel/module.c:961 [inline] __x64_sys_delete_module+0x3dc/0x5e0 kernel/module.c:961 do_syscall_64+0x147/0x600 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x462e99 Code: f7 d8 64 89 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 bc ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007f86f3754c58 EFLAGS: 00000246 ORIG_RAX: 00000000000000b0 RAX: ffffffffffffffda RBX: 000000000073bf00 RCX: 0000000000462e99 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000020000300 RBP: 0000000000000002 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 00007f86f37556bc R13: 00000000004bcca9 R14: 00000000006f6b48 R15: 00000000ffffffff Allocated by task 8363: set_track mm/kasan/common.c:85 [inline] __kasan_kmalloc.constprop.3+0xa0/0xd0 mm/kasan/common.c:495 kmalloc include/linux/slab.h:545 [inline] kzalloc include/linux/slab.h:740 [inline] bus_add_driver+0xc0/0x610 drivers/base/bus.c:651 driver_register+0x1bb/0x3f0 drivers/base/driver.c:170 usb_register_driver+0x267/0x520 drivers/usb/core/driver.c:965 0xffffffffc1b4817c do_one_initcall+0xfa/0x5ca init/main.c:887 do_init_module+0x204/0x5f6 kernel/module.c:3460 load_module+0x66b2/0x8570 kernel/module.c:3808 __do_sys_finit_module+0x238/0x2a0 kernel/module.c:3902 do_syscall_64+0x147/0x600 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe Freed by task 8363: set_track mm/kasan/common.c:85 [inline] __kasan_slab_free+0x130/0x180 mm/kasan/common.c:457 slab_free_hook mm/slub.c:1430 [inline] slab_free_freelist_hook mm/slub.c:1457 [inline] slab_free mm/slub.c:3005 [inline] kfree+0xe1/0x270 mm/slub.c:3957 kobject_cleanup lib/kobject.c:662 [inline] kobject_release lib/kobject.c:691 [inline] kref_put include/linux/kref.h:67 [inline] kobject_put+0x146/0x240 lib/kobject.c:708 bus_remove_driver+0x10e/0x220 drivers/base/bus.c:732 driver_unregister+0x6c/0xa0 drivers/base/driver.c:197 usb_register_driver+0x341/0x520 drivers/usb/core/driver.c:980 0xffffffffc1b4817c do_one_initcall+0xfa/0x5ca init/main.c:887 do_init_module+0x204/0x5f6 kernel/module.c:3460 load_module+0x66b2/0x8570 kernel/module.c:3808 __do_sys_finit_module+0x238/0x2a0 kernel/module.c:3902 do_syscall_64+0x147/0x600 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe The buggy address belongs to the object at ffff8881f59a6b40 which belongs to the cache kmalloc-256 of size 256 The buggy address is located 48 bytes inside of 256-byte region [ffff8881f59a6b40, ffff8881f59a6c40) The buggy address belongs to the page: page:ffffea0007d66980 count:1 mapcount:0 mapping:ffff8881f6c02e00 index:0x0 flags: 0x2fffc0000000200(slab) raw: 02fffc0000000200 dead000000000100 dead000000000200 ffff8881f6c02e00 raw: 0000000000000000 00000000800c000c 00000001ffffffff 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff8881f59a6a00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ffff8881f59a6a80: 00 00 00 00 00 00 00 00 00 00 fc fc fc fc fc fc >ffff8881f59a6b00: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb ^ ffff8881f59a6b80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff8881f59a6c00: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc cpia2_init does not check return value of cpia2_init, if it failed in usb_register_driver, there is already cleanup using driver_unregister. No need call cpia2_usb_cleanup on module exit. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cpia2/cpia2_v4l.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c index 95c0bd4a19dc..45caf78119c4 100644 --- a/drivers/media/usb/cpia2/cpia2_v4l.c +++ b/drivers/media/usb/cpia2/cpia2_v4l.c @@ -1240,8 +1240,7 @@ static int __init cpia2_init(void) LOG("%s v%s\n", ABOUT, CPIA_VERSION); check_parameters(); - cpia2_usb_init(); - return 0; + return cpia2_usb_init(); } From 2c2a8dc32cebb71e42cfc2ed1bd433cbec792207 Mon Sep 17 00:00:00 2001 From: Shaobo He Date: Thu, 28 Feb 2019 17:54:06 -0500 Subject: [PATCH 026/218] media: platform/sh_veu.c: remove redundant NULL pointer checks Function `sh_veu_find_fmt` returns an address that is an addition of a base pointer `sh_veu_fmt` and an offset. The base pointer refers to a global variable of which address cannot be NULL. Therefore, this commit removes the NULL pointer checks on the return values of function `sh_veu_find_fmt`. Signed-off-by: Shaobo He Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/sh_veu.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c index d277cc674349..5a9ba05c996e 100644 --- a/drivers/media/platform/sh_veu.c +++ b/drivers/media/platform/sh_veu.c @@ -493,9 +493,6 @@ static int sh_veu_try_fmt_vid_cap(struct file *file, void *priv, const struct sh_veu_format *fmt; fmt = sh_veu_find_fmt(f); - if (!fmt) - /* wrong buffer type */ - return -EINVAL; return sh_veu_try_fmt(f, fmt); } @@ -506,9 +503,6 @@ static int sh_veu_try_fmt_vid_out(struct file *file, void *priv, const struct sh_veu_format *fmt; fmt = sh_veu_find_fmt(f); - if (!fmt) - /* wrong buffer type */ - return -EINVAL; return sh_veu_try_fmt(f, fmt); } From ab41b99e7e55c85f29ff7b54718ccbbe051905e7 Mon Sep 17 00:00:00 2001 From: Hugues Fruchet Date: Thu, 28 Feb 2019 12:09:17 -0500 Subject: [PATCH 027/218] media: stm32-dcmi: fix check of pm_runtime_get_sync return value Start streaming was sometimes failing because of pm_runtime_get_sync() non-0 return value. In fact return value was not an error but a positive value (1), indicating that PM was already enabled. Fix this by going to error path only with negative return value. Signed-off-by: Hugues Fruchet Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/stm32/stm32-dcmi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c index 5fe5b38fa901..37e9fb08918a 100644 --- a/drivers/media/platform/stm32/stm32-dcmi.c +++ b/drivers/media/platform/stm32/stm32-dcmi.c @@ -570,9 +570,9 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count) int ret; ret = pm_runtime_get_sync(dcmi->dev); - if (ret) { - dev_err(dcmi->dev, "%s: Failed to start streaming, cannot get sync\n", - __func__); + if (ret < 0) { + dev_err(dcmi->dev, "%s: Failed to start streaming, cannot get sync (%d)\n", + __func__, ret); goto err_release_buffers; } From b3ce6f6ff3c260ee53b0f2236e5fd950d46957da Mon Sep 17 00:00:00 2001 From: Hugues Fruchet Date: Thu, 28 Feb 2019 12:10:53 -0500 Subject: [PATCH 028/218] media: stm32-dcmi: fix DMA corruption when stopping streaming Avoid call of dmaengine_terminate_all() between dmaengine_prep_slave_single() and dmaengine_submit() by locking the whole DMA submission sequence. Signed-off-by: Hugues Fruchet Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/stm32/stm32-dcmi.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c index 37e9fb08918a..098431d927ac 100644 --- a/drivers/media/platform/stm32/stm32-dcmi.c +++ b/drivers/media/platform/stm32/stm32-dcmi.c @@ -164,6 +164,9 @@ struct stm32_dcmi { int errors_count; int overrun_count; int buffers_count; + + /* Ensure DMA operations atomicity */ + struct mutex dma_lock; }; static inline struct stm32_dcmi *notifier_to_dcmi(struct v4l2_async_notifier *n) @@ -314,6 +317,13 @@ static int dcmi_start_dma(struct stm32_dcmi *dcmi, return ret; } + /* + * Avoid call of dmaengine_terminate_all() between + * dmaengine_prep_slave_single() and dmaengine_submit() + * by locking the whole DMA submission sequence + */ + mutex_lock(&dcmi->dma_lock); + /* Prepare a DMA transaction */ desc = dmaengine_prep_slave_single(dcmi->dma_chan, buf->paddr, buf->size, @@ -322,6 +332,7 @@ static int dcmi_start_dma(struct stm32_dcmi *dcmi, if (!desc) { dev_err(dcmi->dev, "%s: DMA dmaengine_prep_slave_single failed for buffer phy=%pad size=%zu\n", __func__, &buf->paddr, buf->size); + mutex_unlock(&dcmi->dma_lock); return -EINVAL; } @@ -333,9 +344,12 @@ static int dcmi_start_dma(struct stm32_dcmi *dcmi, dcmi->dma_cookie = dmaengine_submit(desc); if (dma_submit_error(dcmi->dma_cookie)) { dev_err(dcmi->dev, "%s: DMA submission failed\n", __func__); + mutex_unlock(&dcmi->dma_lock); return -ENXIO; } + mutex_unlock(&dcmi->dma_lock); + dma_async_issue_pending(dcmi->dma_chan); return 0; @@ -720,7 +734,9 @@ static void dcmi_stop_streaming(struct vb2_queue *vq) spin_unlock_irq(&dcmi->irqlock); /* Stop all pending DMA operations */ + mutex_lock(&dcmi->dma_lock); dmaengine_terminate_all(dcmi->dma_chan); + mutex_unlock(&dcmi->dma_lock); pm_runtime_put(dcmi->dev); @@ -1711,6 +1727,7 @@ static int dcmi_probe(struct platform_device *pdev) spin_lock_init(&dcmi->irqlock); mutex_init(&dcmi->lock); + mutex_init(&dcmi->dma_lock); init_completion(&dcmi->complete); INIT_LIST_HEAD(&dcmi->buffers); From 0cd25448a198677d4ccd25ec4aeb946d514b1d5b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 28 Feb 2019 07:35:45 -0500 Subject: [PATCH 029/218] media: cobalt: replace VB2_BUF_STATE_REQUEUEING by _ERROR The cobalt driver is the only driver that uses VB2_BUF_STATE_REQUEUEING. Replace it by VB2_BUF_STATE_ERROR so we can drop support for the REQUEUEING state. The requeueing state was used in the cobalt driver to optimize buffer handling while waiting for a valid signal: by requeueing buffers internally there was no need for userspace to handle and requeue buffers with the ERROR flag set. However, requeueing also makes the buffer handling unordered, which is generally a bad idea. Requeueing also does not work with requests and any future fence support. Since it is really a minor optimization in the cobalt driver it is best to just return the buffer in an ERROR state. With this change support for requeueing can now be removed in vb2. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cobalt/cobalt-irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/cobalt/cobalt-irq.c b/drivers/media/pci/cobalt/cobalt-irq.c index 04783e78cc12..a518927abae1 100644 --- a/drivers/media/pci/cobalt/cobalt-irq.c +++ b/drivers/media/pci/cobalt/cobalt-irq.c @@ -128,7 +128,7 @@ done: cb->vb.sequence = s->sequence++; vb2_buffer_done(&cb->vb.vb2_buf, (skip || s->unstable_frame) ? - VB2_BUF_STATE_REQUEUEING : VB2_BUF_STATE_DONE); + VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); } irqreturn_t cobalt_irq_handler(int irq, void *dev_id) From c6e4e2c403b22c7733738a5008c4eeba9ad8478d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 28 Feb 2019 07:35:46 -0500 Subject: [PATCH 030/218] media: vb2: drop VB2_BUF_STATE_REQUEUEING The last user of this state has been converted, so we can now drop this. Requeueing causes the queue to become unordered, which causes problems with requests and (in the future) fences. Since it is no longer needed, just get rid of this. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/common/videobuf2/videobuf2-core.c | 15 +++---------- .../media/common/videobuf2/videobuf2-v4l2.c | 1 - include/media/videobuf2-core.h | 21 ++++++------------- 3 files changed, 9 insertions(+), 28 deletions(-) diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index 15b6b9c0a2e4..678a31a2b549 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c +++ b/drivers/media/common/videobuf2/videobuf2-core.c @@ -915,8 +915,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state) if (WARN_ON(state != VB2_BUF_STATE_DONE && state != VB2_BUF_STATE_ERROR && - state != VB2_BUF_STATE_QUEUED && - state != VB2_BUF_STATE_REQUEUEING)) + state != VB2_BUF_STATE_QUEUED)) state = VB2_BUF_STATE_ERROR; #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -929,8 +928,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state) dprintk(4, "done processing on buffer %d, state: %d\n", vb->index, state); - if (state != VB2_BUF_STATE_QUEUED && - state != VB2_BUF_STATE_REQUEUEING) { + if (state != VB2_BUF_STATE_QUEUED) { /* sync buffers */ for (plane = 0; plane < vb->num_planes; ++plane) call_void_memop(vb, finish, vb->planes[plane].mem_priv); @@ -938,8 +936,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state) } spin_lock_irqsave(&q->done_lock, flags); - if (state == VB2_BUF_STATE_QUEUED || - state == VB2_BUF_STATE_REQUEUEING) { + if (state == VB2_BUF_STATE_QUEUED) { vb->state = VB2_BUF_STATE_QUEUED; } else { /* Add the buffer to the done buffers list */ @@ -949,8 +946,6 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state) atomic_dec(&q->owned_by_drv_count); if (state != VB2_BUF_STATE_QUEUED && vb->req_obj.req) { - /* This is not supported at the moment */ - WARN_ON(state == VB2_BUF_STATE_REQUEUEING); media_request_object_unbind(&vb->req_obj); media_request_object_put(&vb->req_obj); } @@ -962,10 +957,6 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state) switch (state) { case VB2_BUF_STATE_QUEUED: return; - case VB2_BUF_STATE_REQUEUEING: - if (q->start_streaming_called) - __enqueue_in_driver(vb); - return; default: /* Inform any processes that may be waiting for buffers */ wake_up(&q->done_wq); diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c index d09dee20e421..74d3abf33b50 100644 --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c @@ -543,7 +543,6 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb) break; case VB2_BUF_STATE_PREPARING: case VB2_BUF_STATE_DEQUEUED: - case VB2_BUF_STATE_REQUEUEING: /* nothing */ break; } diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index 910f3d469005..c02af6370e9b 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -207,7 +207,6 @@ enum vb2_io_modes { * @VB2_BUF_STATE_IN_REQUEST: buffer is queued in media request. * @VB2_BUF_STATE_PREPARING: buffer is being prepared in videobuf. * @VB2_BUF_STATE_QUEUED: buffer queued in videobuf, but not in driver. - * @VB2_BUF_STATE_REQUEUEING: re-queue a buffer to the driver. * @VB2_BUF_STATE_ACTIVE: buffer queued in driver and possibly used * in a hardware operation. * @VB2_BUF_STATE_DONE: buffer returned from driver to videobuf, but @@ -221,7 +220,6 @@ enum vb2_buffer_state { VB2_BUF_STATE_IN_REQUEST, VB2_BUF_STATE_PREPARING, VB2_BUF_STATE_QUEUED, - VB2_BUF_STATE_REQUEUEING, VB2_BUF_STATE_ACTIVE, VB2_BUF_STATE_DONE, VB2_BUF_STATE_ERROR, @@ -384,10 +382,10 @@ struct vb2_buffer { * driver can return an error if hardware fails, in that * case all buffers that have been already given by * the @buf_queue callback are to be returned by the driver - * by calling vb2_buffer_done() with %VB2_BUF_STATE_QUEUED - * or %VB2_BUF_STATE_REQUEUEING. If you need a minimum - * number of buffers before you can start streaming, then - * set &vb2_queue->min_buffers_needed. If that is non-zero + * by calling vb2_buffer_done() with %VB2_BUF_STATE_QUEUED. + * If you need a minimum number of buffers before you can + * start streaming, then set + * &vb2_queue->min_buffers_needed. If that is non-zero * then @start_streaming won't be called until at least * that many buffers have been queued up by userspace. * @stop_streaming: called when 'streaming' state must be disabled; driver @@ -648,9 +646,7 @@ void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no); * @state: state of the buffer, as defined by &enum vb2_buffer_state. * Either %VB2_BUF_STATE_DONE if the operation finished * successfully, %VB2_BUF_STATE_ERROR if the operation finished - * with an error or any of %VB2_BUF_STATE_QUEUED or - * %VB2_BUF_STATE_REQUEUEING if the driver wants to - * requeue buffers (see below). + * with an error or %VB2_BUF_STATE_QUEUED. * * This function should be called by the driver after a hardware operation on * a buffer is finished and the buffer may be returned to userspace. The driver @@ -661,12 +657,7 @@ void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no); * While streaming a buffer can only be returned in state DONE or ERROR. * The &vb2_ops->start_streaming op can also return them in case the DMA engine * cannot be started for some reason. In that case the buffers should be - * returned with state QUEUED or REQUEUEING to put them back into the queue. - * - * %VB2_BUF_STATE_REQUEUEING is like %VB2_BUF_STATE_QUEUED, but it also calls - * &vb2_ops->buf_queue to queue buffers back to the driver. Note that calling - * vb2_buffer_done(..., VB2_BUF_STATE_REQUEUEING) from interrupt context will - * result in &vb2_ops->buf_queue being called in interrupt context as well. + * returned with state QUEUED to put them back into the queue. */ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state); From dfecb7b2564dcb5fa0c36a615b0d5960eff413ac Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 28 Jan 2019 15:54:59 -0500 Subject: [PATCH 031/218] media: dt-bindings: media: cedrus: Add H6 compatible This adds a compatible for H6. H6 VPU supports 10-bit HEVC decoding and additional AFBC output format for HEVC. Signed-off-by: Jernej Skrabec Acked-by: Maxime Ripard Reviewed-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/cedrus.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/media/cedrus.txt b/Documentation/devicetree/bindings/media/cedrus.txt index bce0705df953..20c82fb0c343 100644 --- a/Documentation/devicetree/bindings/media/cedrus.txt +++ b/Documentation/devicetree/bindings/media/cedrus.txt @@ -13,6 +13,7 @@ Required properties: - "allwinner,sun8i-h3-video-engine" - "allwinner,sun50i-a64-video-engine" - "allwinner,sun50i-h5-video-engine" + - "allwinner,sun50i-h6-video-engine" - reg : register base and length of VE; - clocks : list of clock specifiers, corresponding to entries in the clock-names property; From 70a4f5cda82f7197c350099b66fd23506620810e Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 28 Jan 2019 15:55:00 -0500 Subject: [PATCH 032/218] media: cedrus: Add a quirk for not setting DMA offset H6 VPU doesn't work if DMA offset is set. Add a quirk for it. Signed-off-by: Jernej Skrabec Acked-by: Maxime Ripard Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/sunxi/cedrus/cedrus.h | 3 +++ drivers/staging/media/sunxi/cedrus/cedrus_hw.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h index 4aedd24a9848..c57c04b41d2e 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus.h +++ b/drivers/staging/media/sunxi/cedrus/cedrus.h @@ -28,6 +28,8 @@ #define CEDRUS_CAPABILITY_UNTILED BIT(0) +#define CEDRUS_QUIRK_NO_DMA_OFFSET BIT(0) + enum cedrus_codec { CEDRUS_CODEC_MPEG2, @@ -91,6 +93,7 @@ struct cedrus_dec_ops { struct cedrus_variant { unsigned int capabilities; + unsigned int quirks; }; struct cedrus_dev { diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c index 0acf219a8c91..fbfff7c1c771 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c @@ -177,7 +177,8 @@ int cedrus_hw_probe(struct cedrus_dev *dev) */ #ifdef PHYS_PFN_OFFSET - dev->dev->dma_pfn_offset = PHYS_PFN_OFFSET; + if (!(variant->quirks & CEDRUS_QUIRK_NO_DMA_OFFSET)) + dev->dev->dma_pfn_offset = PHYS_PFN_OFFSET; #endif ret = of_reserved_mem_device_init(dev->dev); From dea255334c97c61b112dc29b77cd1d0ed4b79fca Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Mon, 28 Jan 2019 15:55:01 -0500 Subject: [PATCH 033/218] media: cedrus: Add support for H6 H6 has improved VPU. It supports 10-bit HEVC decoding and AFBC output format for HEVC. Signed-off-by: Jernej Skrabec Acked-by: Maxime Ripard Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/sunxi/cedrus/cedrus.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c index ff11cbeba205..b98add3cdedd 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus.c @@ -396,6 +396,11 @@ static const struct cedrus_variant sun50i_h5_cedrus_variant = { .capabilities = CEDRUS_CAPABILITY_UNTILED, }; +static const struct cedrus_variant sun50i_h6_cedrus_variant = { + .capabilities = CEDRUS_CAPABILITY_UNTILED, + .quirks = CEDRUS_QUIRK_NO_DMA_OFFSET, +}; + static const struct of_device_id cedrus_dt_match[] = { { .compatible = "allwinner,sun4i-a10-video-engine", @@ -425,6 +430,10 @@ static const struct of_device_id cedrus_dt_match[] = { .compatible = "allwinner,sun50i-h5-video-engine", .data = &sun50i_h5_cedrus_variant, }, + { + .compatible = "allwinner,sun50i-h6-video-engine", + .data = &sun50i_h6_cedrus_variant, + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, cedrus_dt_match); From d30c4ffc06113d280fd7b5294ab384658a70c1f1 Mon Sep 17 00:00:00 2001 From: Ken Sloat Date: Mon, 4 Feb 2019 09:18:13 -0500 Subject: [PATCH 034/218] media: atmel-isc: Add support for BT656 with CRC decoding The ISC driver currently supports ITU-R 601 encoding which utilizes the external hsync and vsync signals. ITU-R 656 format removes the need for these pins by embedding the sync pulses within the data packet. To support this feature, enable necessary register bits when this feature is enabled via device tree. Signed-off-by: Ken Sloat Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/atmel/atmel-isc-regs.h | 2 ++ drivers/media/platform/atmel/atmel-isc.c | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/atmel/atmel-isc-regs.h b/drivers/media/platform/atmel/atmel-isc-regs.h index 2aadc19235ea..d730693f299c 100644 --- a/drivers/media/platform/atmel/atmel-isc-regs.h +++ b/drivers/media/platform/atmel/atmel-isc-regs.h @@ -24,6 +24,8 @@ #define ISC_PFE_CFG0_HPOL_LOW BIT(0) #define ISC_PFE_CFG0_VPOL_LOW BIT(1) #define ISC_PFE_CFG0_PPOL_LOW BIT(2) +#define ISC_PFE_CFG0_CCIR656 BIT(9) +#define ISC_PFE_CFG0_CCIR_CRC BIT(10) #define ISC_PFE_CFG0_MODE_PROGRESSIVE (0x0 << 4) #define ISC_PFE_CFG0_MODE_MASK GENMASK(6, 4) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 50178968b8a6..9a399aa7ca92 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -1095,7 +1095,8 @@ static int isc_configure(struct isc_device *isc) pfe_cfg0 |= subdev->pfe_cfg0 | ISC_PFE_CFG0_MODE_PROGRESSIVE; mask = ISC_PFE_CFG0_BPS_MASK | ISC_PFE_CFG0_HPOL_LOW | ISC_PFE_CFG0_VPOL_LOW | ISC_PFE_CFG0_PPOL_LOW | - ISC_PFE_CFG0_MODE_MASK; + ISC_PFE_CFG0_MODE_MASK | ISC_PFE_CFG0_CCIR_CRC | + ISC_PFE_CFG0_CCIR656; regmap_update_bits(regmap, ISC_PFE_CFG0, mask, pfe_cfg0); @@ -2084,6 +2085,10 @@ static int isc_parse_dt(struct device *dev, struct isc_device *isc) if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_PPOL_LOW; + if (v4l2_epn.bus_type == V4L2_MBUS_BT656) + subdev_entity->pfe_cfg0 |= ISC_PFE_CFG0_CCIR_CRC | + ISC_PFE_CFG0_CCIR656; + subdev_entity->asd->match_type = V4L2_ASYNC_MATCH_FWNODE; subdev_entity->asd->match.fwnode = of_fwnode_handle(rem); From 03aa4f191a36f33fce015387f84efa0eee94408e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 19 Feb 2019 12:01:56 -0500 Subject: [PATCH 035/218] media: saa7146: avoid high stack usage with clang Two saa7146/hexium files contain a construct that causes a warning when built with clang: drivers/media/pci/saa7146/hexium_orion.c:210:12: error: stack frame size of 2272 bytes in function 'hexium_probe' [-Werror,-Wframe-larger-than=] static int hexium_probe(struct saa7146_dev *dev) ^ drivers/media/pci/saa7146/hexium_gemini.c:257:12: error: stack frame size of 2304 bytes in function 'hexium_attach' [-Werror,-Wframe-larger-than=] static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) ^ This one happens regardless of KASAN, and the problem is that a constructor to initialize a dynamically allocated structure leads to a copy of that structure on the stack, whereas gcc initializes it in place. Link: https://bugs.llvm.org/show_bug.cgi?id=40776 Signed-off-by: Arnd Bergmann Reviewed-by: Nick Desaulniers Signed-off-by: Hans Verkuil [hverkuil-cisco@xs4all.nl: fix checkpatch warnings] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7146/hexium_gemini.c | 5 ++--- drivers/media/pci/saa7146/hexium_orion.c | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/media/pci/saa7146/hexium_gemini.c b/drivers/media/pci/saa7146/hexium_gemini.c index 5817d9cde4d0..6d8e4afe9673 100644 --- a/drivers/media/pci/saa7146/hexium_gemini.c +++ b/drivers/media/pci/saa7146/hexium_gemini.c @@ -270,9 +270,8 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d /* enable i2c-port pins */ saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26)); - hexium->i2c_adapter = (struct i2c_adapter) { - .name = "hexium gemini", - }; + strscpy(hexium->i2c_adapter.name, "hexium gemini", + sizeof(hexium->i2c_adapter.name)); saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); if (i2c_add_adapter(&hexium->i2c_adapter) < 0) { DEB_S("cannot register i2c-device. skipping.\n"); diff --git a/drivers/media/pci/saa7146/hexium_orion.c b/drivers/media/pci/saa7146/hexium_orion.c index 0a05176c18ab..a794f9e5f990 100644 --- a/drivers/media/pci/saa7146/hexium_orion.c +++ b/drivers/media/pci/saa7146/hexium_orion.c @@ -231,9 +231,8 @@ static int hexium_probe(struct saa7146_dev *dev) saa7146_write(dev, DD1_STREAM_B, 0x00000000); saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); - hexium->i2c_adapter = (struct i2c_adapter) { - .name = "hexium orion", - }; + strscpy(hexium->i2c_adapter.name, "hexium orion", + sizeof(hexium->i2c_adapter.name)); saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); if (i2c_add_adapter(&hexium->i2c_adapter) < 0) { DEB_S("cannot register i2c-device. skipping.\n"); From ed713a4a1367aca5c0f2f329579465db00c17995 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 19 Feb 2019 12:01:58 -0500 Subject: [PATCH 036/218] media: go7007: avoid clang frame overflow warning with KASAN clang-8 warns about one function here when KASAN is enabled, even without the 'asan-stack' option: drivers/media/usb/go7007/go7007-fw.c:1551:5: warning: stack frame size of 2656 bytes in function I have reported this issue in the llvm bugzilla, but to make it work with the clang-8 release, a small annotation is still needed. Link: https://bugs.llvm.org/show_bug.cgi?id=38809 Signed-off-by: Arnd Bergmann Signed-off-by: Hans Verkuil [hverkuil-cisco@xs4all.nl: fix checkpatch warning] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/go7007/go7007-fw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/go7007/go7007-fw.c b/drivers/media/usb/go7007/go7007-fw.c index 24f5b615dc7a..dfa9f899d0c2 100644 --- a/drivers/media/usb/go7007/go7007-fw.c +++ b/drivers/media/usb/go7007/go7007-fw.c @@ -1499,8 +1499,8 @@ static int modet_to_package(struct go7007 *go, __le16 *code, int space) return cnt; } -static int do_special(struct go7007 *go, u16 type, __le16 *code, int space, - int *framelen) +static noinline_for_stack int do_special(struct go7007 *go, u16 type, + __le16 *code, int space, int *framelen) { switch (type) { case SPECIAL_FRM_HEAD: From f8e579f3ca0973daef263f513da5edff520a6c0d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 22 Feb 2019 01:36:41 -0500 Subject: [PATCH 037/218] media: ivtv: update *pos correctly in ivtv_read_pos() We had intended to update *pos, but the current code is a no-op. Fixes: 1a0adaf37c30 ("V4L/DVB (5345): ivtv driver for Conexant cx23416/cx23415 MPEG encoder/decoder") Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/ivtv/ivtv-fileops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/ivtv/ivtv-fileops.c b/drivers/media/pci/ivtv/ivtv-fileops.c index 6196daae4b3e..043ac0ae9ed0 100644 --- a/drivers/media/pci/ivtv/ivtv-fileops.c +++ b/drivers/media/pci/ivtv/ivtv-fileops.c @@ -420,7 +420,7 @@ static ssize_t ivtv_read_pos(struct ivtv_stream *s, char __user *ubuf, size_t co IVTV_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc); if (rc > 0) - pos += rc; + *pos += rc; return rc; } From 7afb0df554292dca7568446f619965fb8153085d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 22 Feb 2019 01:37:02 -0500 Subject: [PATCH 038/218] media: cx18: update *pos correctly in cx18_read_pos() We should be updating *pos. The current code is a no-op. Fixes: 1c1e45d17b66 ("V4L/DVB (7786): cx18: new driver for the Conexant CX23418 MPEG encoder chip") Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx18/cx18-fileops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/cx18/cx18-fileops.c b/drivers/media/pci/cx18/cx18-fileops.c index f778965a2eb8..59e78fb17575 100644 --- a/drivers/media/pci/cx18/cx18-fileops.c +++ b/drivers/media/pci/cx18/cx18-fileops.c @@ -484,7 +484,7 @@ static ssize_t cx18_read_pos(struct cx18_stream *s, char __user *ubuf, CX18_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc); if (rc > 0) - pos += rc; + *pos += rc; return rc; } From e855165f3dae6f71da859a5f00b85d5368641d61 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 22 Feb 2019 09:50:03 -0500 Subject: [PATCH 039/218] media: vicodec: avoid clang frame size warning Clang-9 makes some different inlining decisions compared to gcc, which leads to a warning about a possible stack overflow problem when building with CONFIG_KASAN, including when setting asan-stack=0, which avoids most other frame overflow warnings: drivers/media/platform/vicodec/codec-fwht.c:673:12: error: stack frame size of 2224 bytes in function 'encode_plane' Manually adding noinline_for_stack annotations in those functions called by encode_plane() or decode_plane() that require a significant amount of kernel stack makes this impossible to happen with any compiler. Signed-off-by: Arnd Bergmann Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vicodec/codec-fwht.c | 29 +++++++++++++-------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/media/platform/vicodec/codec-fwht.c b/drivers/media/platform/vicodec/codec-fwht.c index d1d6085da9f1..cf469a1191aa 100644 --- a/drivers/media/platform/vicodec/codec-fwht.c +++ b/drivers/media/platform/vicodec/codec-fwht.c @@ -46,8 +46,12 @@ static const uint8_t zigzag[64] = { 63, }; - -static int rlc(const s16 *in, __be16 *output, int blocktype) +/* + * noinline_for_stack to work around + * https://bugs.llvm.org/show_bug.cgi?id=38809 + */ +static int noinline_for_stack +rlc(const s16 *in, __be16 *output, int blocktype) { s16 block[8 * 8]; s16 *wp = block; @@ -106,8 +110,8 @@ static int rlc(const s16 *in, __be16 *output, int blocktype) * This function will worst-case increase rlc_in by 65*2 bytes: * one s16 value for the header and 8 * 8 coefficients of type s16. */ -static u16 derlc(const __be16 **rlc_in, s16 *dwht_out, - const __be16 *end_of_input) +static noinline_for_stack u16 +derlc(const __be16 **rlc_in, s16 *dwht_out, const __be16 *end_of_input) { /* header */ const __be16 *input = *rlc_in; @@ -240,8 +244,9 @@ static void dequantize_inter(s16 *coeff) *coeff <<= *quant; } -static void fwht(const u8 *block, s16 *output_block, unsigned int stride, - unsigned int input_step, bool intra) +static void noinline_for_stack fwht(const u8 *block, s16 *output_block, + unsigned int stride, + unsigned int input_step, bool intra) { /* we'll need more than 8 bits for the transformed coefficients */ s32 workspace1[8], workspace2[8]; @@ -373,7 +378,8 @@ static void fwht(const u8 *block, s16 *output_block, unsigned int stride, * Furthermore values can be negative... This is just a version that * works with 16 signed data */ -static void fwht16(const s16 *block, s16 *output_block, int stride, int intra) +static void noinline_for_stack +fwht16(const s16 *block, s16 *output_block, int stride, int intra) { /* we'll need more than 8 bits for the transformed coefficients */ s32 workspace1[8], workspace2[8]; @@ -456,7 +462,8 @@ static void fwht16(const s16 *block, s16 *output_block, int stride, int intra) } } -static void ifwht(const s16 *block, s16 *output_block, int intra) +static noinline_for_stack void +ifwht(const s16 *block, s16 *output_block, int intra) { /* * we'll need more than 8 bits for the transformed coefficients @@ -604,9 +611,9 @@ static int var_inter(const s16 *old, const s16 *new) return ret; } -static int decide_blocktype(const u8 *cur, const u8 *reference, - s16 *deltablock, unsigned int stride, - unsigned int input_step) +static noinline_for_stack int +decide_blocktype(const u8 *cur, const u8 *reference, s16 *deltablock, + unsigned int stride, unsigned int input_step) { s16 tmp[64]; s16 old[64]; From 3eb87773dee63309967b1d4d8b9896f4e4fdd640 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Fri, 22 Feb 2019 19:17:09 -0500 Subject: [PATCH 040/218] media: replace WARN_ON in __media_pipeline_start() __media_pipeline_start() does WARN_ON() when active pipe doesn't match the input arg entity's pipe. Replace WARN_ON with a conditional and error message that includes names of both entities. Signed-off-by: Shuah Khan Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-entity.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index dd859d7b235a..a998a2e0ea1d 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -435,7 +435,10 @@ __must_check int __media_pipeline_start(struct media_entity *entity, entity->stream_count++; - if (WARN_ON(entity->pipe && entity->pipe != pipe)) { + if (entity->pipe && entity->pipe != pipe) { + pr_err("Pipe active for %s. Can't start for %s\n", + entity->name, + entity_err->name); ret = -EBUSY; goto error; } From f712e5358d430fe9a7d7d4848f7dbff84b47de3a Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Mon, 25 Feb 2019 10:32:27 -0500 Subject: [PATCH 041/218] media: au0828: minor fix to a misleading comment in _close() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a misleading comment in _close() and a spelling error. Reviewed-by: Niklas Söderlund Signed-off-by: Shuah Khan Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828-video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 7876c897cc1d..e17047b94b87 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -1065,7 +1065,7 @@ static int au0828_v4l2_close(struct file *filp) * streaming. * * On most USB devices like au0828 the tuner can - * be safely put in sleep stare here if ALSA isn't + * be safely put in sleep state here if ALSA isn't * streaming. Exceptions are some very old USB tuner * models such as em28xx-based WinTV USB2 which have * a separate audio output jack. The devices that have @@ -1074,7 +1074,7 @@ static int au0828_v4l2_close(struct file *filp) * so the s_power callback are silently ignored. * So, the current logic here does the following: * Disable (put tuner to sleep) when - * - ALSA and DVB aren't not streaming; + * - ALSA and DVB aren't streaming. * - the last V4L2 file handler is closed. * * FIXME: From e6f8bd59c28f758feea403a70d6c3ef28c50959f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 26 Feb 2019 07:54:22 -0500 Subject: [PATCH 042/218] media: gspca: do not resubmit URBs when streaming has stopped When streaming is stopped all URBs are killed, but in fill_frame and in bulk_irq this results in an attempt to resubmit the killed URB. That is not what you want and causes spurious kernel messages. So check if streaming has stopped before resubmitting. Also check against gspca_dev->streaming rather than vb2_start_streaming_called() since vb2_start_streaming_called() will return true when in stop_streaming, but gspca_dev->streaming is set to false when stop_streaming is called. Fixes: 6992effe5344 ("gspca: Kill all URBs before releasing any of them") Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/gspca/gspca.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index ac70b36d67b7..9448ac0b8bc9 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -314,6 +314,8 @@ static void fill_frame(struct gspca_dev *gspca_dev, } resubmit: + if (!gspca_dev->streaming) + return; /* resubmit the URB */ st = usb_submit_urb(urb, GFP_ATOMIC); if (st < 0) @@ -330,7 +332,7 @@ static void isoc_irq(struct urb *urb) struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context; gspca_dbg(gspca_dev, D_PACK, "isoc irq\n"); - if (!vb2_start_streaming_called(&gspca_dev->queue)) + if (!gspca_dev->streaming) return; fill_frame(gspca_dev, urb); } @@ -344,7 +346,7 @@ static void bulk_irq(struct urb *urb) int st; gspca_dbg(gspca_dev, D_PACK, "bulk irq\n"); - if (!vb2_start_streaming_called(&gspca_dev->queue)) + if (!gspca_dev->streaming) return; switch (urb->status) { case 0: @@ -367,6 +369,8 @@ static void bulk_irq(struct urb *urb) urb->actual_length); resubmit: + if (!gspca_dev->streaming) + return; /* resubmit the URB */ if (gspca_dev->cam.bulk_nurbs != 0) { st = usb_submit_urb(urb, GFP_ATOMIC); From f14f6aa0b4423632ab76f3eed3a28159049451ef Mon Sep 17 00:00:00 2001 From: Souptick Joarder Date: Mon, 4 Feb 2019 10:01:43 -0500 Subject: [PATCH 043/218] media: videobuf2: Return error after allocation failure There is no point to continuing assignment after memory allocation failed, rather throw error immediately. Signed-off-by: Souptick Joarder Signed-off-by: Hans Verkuil [hverkuil-cisco@xs4all.nl: rebase and remove empty line before the if] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/videobuf2/videobuf2-vmalloc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/common/videobuf2/videobuf2-vmalloc.c b/drivers/media/common/videobuf2/videobuf2-vmalloc.c index 6dfbd5b05907..1c6659f7c394 100644 --- a/drivers/media/common/videobuf2/videobuf2-vmalloc.c +++ b/drivers/media/common/videobuf2/videobuf2-vmalloc.c @@ -46,17 +46,17 @@ static void *vb2_vmalloc_alloc(struct device *dev, unsigned long attrs, buf->size = size; buf->vaddr = vmalloc_user(buf->size); - buf->dma_dir = dma_dir; - buf->handler.refcount = &buf->refcount; - buf->handler.put = vb2_vmalloc_put; - buf->handler.arg = buf; - if (!buf->vaddr) { pr_debug("vmalloc of size %ld failed\n", buf->size); kfree(buf); return ERR_PTR(-ENOMEM); } + buf->dma_dir = dma_dir; + buf->handler.refcount = &buf->refcount; + buf->handler.put = vb2_vmalloc_put; + buf->handler.arg = buf; + refcount_set(&buf->refcount, 1); return buf; } From 85ab1aa1fac17bcd79d6d08f835957b46870d0d0 Mon Sep 17 00:00:00 2001 From: Helen Fornazier Date: Wed, 6 Mar 2019 17:42:37 -0500 Subject: [PATCH 044/218] media: vimc: deb: fix default sink bayer format The format of the sink pad should be a bayer mbus format. This fixes a kernel NULL pointer dereference error that was caused when the stream starts because the configured format was not found in the pixelmap table. Reported-by: Hans Verkuil Signed-off-by: Helen Koike Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vimc/vimc-debayer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/vimc/vimc-debayer.c b/drivers/media/platform/vimc/vimc-debayer.c index eaed4233ad1b..20826f209731 100644 --- a/drivers/media/platform/vimc/vimc-debayer.c +++ b/drivers/media/platform/vimc/vimc-debayer.c @@ -66,7 +66,7 @@ struct vimc_deb_device { static const struct v4l2_mbus_framefmt sink_fmt_default = { .width = 640, .height = 480, - .code = MEDIA_BUS_FMT_RGB888_1X24, + .code = MEDIA_BUS_FMT_SRGGB8_1X8, .field = V4L2_FIELD_NONE, .colorspace = V4L2_COLORSPACE_DEFAULT, }; From 2978a505aaa981b279ef359f74ba93d25098e0a0 Mon Sep 17 00:00:00 2001 From: Helen Fornazier Date: Wed, 6 Mar 2019 17:42:38 -0500 Subject: [PATCH 045/218] media: vimc: stream: fix thread state before sleep The state TASK_UNINTERRUPTIBLE should be set just before schedule_timeout() call, so it knows the sleep mode it should enter. There is no point in setting TASK_UNINTERRUPTIBLE at the initialization of the thread as schedule_timeout() will set the state back to TASK_RUNNING. This fixes a warning in __might_sleep() call, as it's expecting the task to be in TASK_RUNNING state just before changing the state to a sleeping state. Reported-by: Hans Verkuil Signed-off-by: Helen Koike Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vimc/vimc-streamer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/vimc/vimc-streamer.c b/drivers/media/platform/vimc/vimc-streamer.c index fcc897fb247b..392754c18046 100644 --- a/drivers/media/platform/vimc/vimc-streamer.c +++ b/drivers/media/platform/vimc/vimc-streamer.c @@ -120,7 +120,6 @@ static int vimc_streamer_thread(void *data) int i; set_freezable(); - set_current_state(TASK_UNINTERRUPTIBLE); for (;;) { try_to_freeze(); @@ -137,6 +136,7 @@ static int vimc_streamer_thread(void *data) break; } //wait for 60hz + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ / 60); } From 5efbc65faeda3577d58c820557a0a57d2994b01b Mon Sep 17 00:00:00 2001 From: Helen Fornazier Date: Wed, 6 Mar 2019 17:42:39 -0500 Subject: [PATCH 046/218] media: vimc: cap: fix step width/height in enum framesize The type V4L2_FRMSIZE_TYPE_CONTINUOUS expects a step of 1. This fixes v4l2-compliance test error: fail: v4l2-test-formats.cpp(184): invalid step_width/height for continuous framesize test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: FAIL Signed-off-by: Helen Koike Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vimc/vimc-capture.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/vimc/vimc-capture.c b/drivers/media/platform/vimc/vimc-capture.c index 54fda5b29dd0..290b08ebb1b6 100644 --- a/drivers/media/platform/vimc/vimc-capture.c +++ b/drivers/media/platform/vimc/vimc-capture.c @@ -187,8 +187,8 @@ static int vimc_cap_enum_framesizes(struct file *file, void *fh, fsize->stepwise.max_width = VIMC_FRAME_MAX_WIDTH; fsize->stepwise.min_height = VIMC_FRAME_MIN_HEIGHT; fsize->stepwise.max_height = VIMC_FRAME_MAX_HEIGHT; - fsize->stepwise.step_width = 2; - fsize->stepwise.step_height = 2; + fsize->stepwise.step_width = 1; + fsize->stepwise.step_height = 1; return 0; } From b72e449521247a463572c8398a7517d231207f00 Mon Sep 17 00:00:00 2001 From: Helen Fornazier Date: Wed, 6 Mar 2019 17:42:41 -0500 Subject: [PATCH 047/218] media: vimc: stream: cleanup frame field from struct vimc_stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need to have the frame field in the vimc_stream struct. Signed-off-by: Helen Koike Tested-by: André Almeida Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vimc/vimc-streamer.c | 10 ++++------ drivers/media/platform/vimc/vimc-streamer.h | 1 - 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/media/platform/vimc/vimc-streamer.c b/drivers/media/platform/vimc/vimc-streamer.c index 392754c18046..b7c1fdef5f0d 100644 --- a/drivers/media/platform/vimc/vimc-streamer.c +++ b/drivers/media/platform/vimc/vimc-streamer.c @@ -117,6 +117,7 @@ static int vimc_streamer_pipeline_init(struct vimc_stream *stream, static int vimc_streamer_thread(void *data) { struct vimc_stream *stream = data; + u8 *frame = NULL; int i; set_freezable(); @@ -127,12 +128,9 @@ static int vimc_streamer_thread(void *data) break; for (i = stream->pipe_size - 1; i >= 0; i--) { - stream->frame = stream->ved_pipeline[i]->process_frame( - stream->ved_pipeline[i], - stream->frame); - if (!stream->frame) - break; - if (IS_ERR(stream->frame)) + frame = stream->ved_pipeline[i]->process_frame( + stream->ved_pipeline[i], frame); + if (!frame || IS_ERR(frame)) break; } //wait for 60hz diff --git a/drivers/media/platform/vimc/vimc-streamer.h b/drivers/media/platform/vimc/vimc-streamer.h index 752af2e2d5a2..dc1d0be431cb 100644 --- a/drivers/media/platform/vimc/vimc-streamer.h +++ b/drivers/media/platform/vimc/vimc-streamer.h @@ -19,7 +19,6 @@ struct vimc_stream { struct media_pipeline pipe; struct vimc_ent_device *ved_pipeline[VIMC_STREAMER_PIPELINE_MAX_SIZE]; unsigned int pipe_size; - u8 *frame; struct task_struct *kthread; }; From 43e3b726f5e1b34e4d6bdacc72fdde84cfffaf13 Mon Sep 17 00:00:00 2001 From: Helen Fornazier Date: Wed, 6 Mar 2019 17:42:42 -0500 Subject: [PATCH 048/218] media: vimc: stream: add docs to struct vimc_stream Add missing documentation for struct vimc_stream Signed-off-by: Helen Koike Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vimc/vimc-streamer.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/media/platform/vimc/vimc-streamer.h b/drivers/media/platform/vimc/vimc-streamer.h index dc1d0be431cb..a7c5ac5ace4f 100644 --- a/drivers/media/platform/vimc/vimc-streamer.h +++ b/drivers/media/platform/vimc/vimc-streamer.h @@ -15,6 +15,21 @@ #define VIMC_STREAMER_PIPELINE_MAX_SIZE 16 +/** + * struct vimc_stream - struct that represents a stream in the pipeline + * + * @pipe: the media pipeline object associated with this stream + * @ved_pipeline: array containing all the entities participating in the + * stream. The order is from a video device (usually a capture device) where + * stream_on was called, to the entity generating the first base image to be + * processed in the pipeline. + * @pipe_size: size of @ved_pipeline + * @kthread: thread that generates the frames of the stream. + * + * When the user call stream_on in a video device, struct vimc_stream is + * used to keep track of all entities and subdevices that generates and + * process frames for the stream. + */ struct vimc_stream { struct media_pipeline pipe; struct vimc_ent_device *ved_pipeline[VIMC_STREAMER_PIPELINE_MAX_SIZE]; From 6f3f3e11999b192e39404c49b584b7aca4cb1ecd Mon Sep 17 00:00:00 2001 From: Helen Fornazier Date: Wed, 6 Mar 2019 17:42:43 -0500 Subject: [PATCH 049/218] media: vimc: stream: init/terminate the first entity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The s_stream callback was not being called for the first entity in the stream pipeline array. Instead of verifying the type of the node (video or subdevice) and calling s_stream from the second entity in the pipeline, do this process for all the entities in the pipeline for consistency. The previous code was not a problem because the first entity is a video device and not a subdevice, but this patch prepares vimc to allow setting some configuration in the entity before calling s_stream. Signed-off-by: Helen Koike Tested-by: André Almeida Signed-off-by: Hans Verkuil [hverkuil-cisco@xs4all.nl: fix line-too-long warning] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vimc/vimc-streamer.c | 26 +++++++++++++-------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/media/platform/vimc/vimc-streamer.c b/drivers/media/platform/vimc/vimc-streamer.c index b7c1fdef5f0d..6fc18fea2e45 100644 --- a/drivers/media/platform/vimc/vimc-streamer.c +++ b/drivers/media/platform/vimc/vimc-streamer.c @@ -46,19 +46,18 @@ static struct media_entity *vimc_get_source_entity(struct media_entity *ent) */ static void vimc_streamer_pipeline_terminate(struct vimc_stream *stream) { - struct media_entity *entity; + struct vimc_ent_device *ved; struct v4l2_subdev *sd; while (stream->pipe_size) { stream->pipe_size--; - entity = stream->ved_pipeline[stream->pipe_size]->ent; - entity = vimc_get_source_entity(entity); + ved = stream->ved_pipeline[stream->pipe_size]; stream->ved_pipeline[stream->pipe_size] = NULL; - if (!is_media_entity_v4l2_subdev(entity)) + if (!is_media_entity_v4l2_subdev(ved->ent)) continue; - sd = media_entity_to_v4l2_subdev(entity); + sd = media_entity_to_v4l2_subdev(ved->ent); v4l2_subdev_call(sd, video, s_stream, 0); } } @@ -89,18 +88,25 @@ static int vimc_streamer_pipeline_init(struct vimc_stream *stream, } stream->ved_pipeline[stream->pipe_size++] = ved; + if (is_media_entity_v4l2_subdev(ved->ent)) { + sd = media_entity_to_v4l2_subdev(ved->ent); + ret = v4l2_subdev_call(sd, video, s_stream, 1); + if (ret && ret != -ENOIOCTLCMD) { + pr_err("subdev_call error %s\n", + ved->ent->name); + vimc_streamer_pipeline_terminate(stream); + return ret; + } + } + entity = vimc_get_source_entity(ved->ent); /* Check if the end of the pipeline was reached*/ if (!entity) return 0; + /* Get the next device in the pipeline */ if (is_media_entity_v4l2_subdev(entity)) { sd = media_entity_to_v4l2_subdev(entity); - ret = v4l2_subdev_call(sd, video, s_stream, 1); - if (ret && ret != -ENOIOCTLCMD) { - vimc_streamer_pipeline_terminate(stream); - return ret; - } ved = v4l2_get_subdevdata(sd); } else { vdev = container_of(entity, From e7dd89cef16021ad0dd5a590d3d2090bf65e3ec2 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Fri, 25 Jan 2019 08:01:46 -0500 Subject: [PATCH 050/218] media: strscpy() returns a negative value on failure unlike strlcpy(). strscpy() returns a negative value on failure unlike strlcpy(), so fix the WARN_ON accordingly. Signed-off-by: Hans Petter Selasky Signed-off-by: Hans Verkuil [hverkuil-cisco@xs4all.nl: added commit message] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index f6d663934648..038739584a84 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1373,7 +1373,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) } if (descr) - WARN_ON(strscpy(fmt->description, descr, sz) >= sz); + WARN_ON(strscpy(fmt->description, descr, sz) < 0); fmt->flags = flags; } From 0576385acb89fdb361dbdbd62e7cfd0bc35bc6ba Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 27 Feb 2019 00:57:23 -0500 Subject: [PATCH 051/218] media: rockchip-vpu: Remove duplicated include from rockchip_vpu_drv.c Remove duplicated include. Signed-off-by: YueHaibing Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/rockchip/vpu/rockchip_vpu_drv.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/media/rockchip/vpu/rockchip_vpu_drv.c b/drivers/staging/media/rockchip/vpu/rockchip_vpu_drv.c index 962412c79b91..57611464ad07 100644 --- a/drivers/staging/media/rockchip/vpu/rockchip_vpu_drv.c +++ b/drivers/staging/media/rockchip/vpu/rockchip_vpu_drv.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include "rockchip_vpu_common.h" From 55dde50946988db8d05f84d2ec7750140542730f Mon Sep 17 00:00:00 2001 From: Steve Longerbeam Date: Fri, 1 Mar 2019 18:27:17 -0500 Subject: [PATCH 052/218] media: imx: vdic: Fix wrong CSI group ID The i.MX7 capture support forgot to change the group ID for the CSI to the IPU CSI in VDIC sub-device, it was left at the i.MX7 CSI group ID. Fixes: 67673ed55084 ("media: staging/imx: rearrange group id to take in account IPU") Signed-off-by: Steve Longerbeam Reviewed-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx-media-vdic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/imx/imx-media-vdic.c b/drivers/staging/media/imx/imx-media-vdic.c index 8cdd3daa6c5f..f8c84a07dad9 100644 --- a/drivers/staging/media/imx/imx-media-vdic.c +++ b/drivers/staging/media/imx/imx-media-vdic.c @@ -750,7 +750,7 @@ static int vdic_link_setup(struct media_entity *entity, remote_sd = media_entity_to_v4l2_subdev(remote->entity); /* direct pad must connect to a CSI */ - if (!(remote_sd->grp_id & IMX_MEDIA_GRP_ID_CSI) || + if (!(remote_sd->grp_id & IMX_MEDIA_GRP_ID_IPU_CSI) || remote->index != CSI_SRC_PAD_DIRECT) { ret = -EINVAL; goto out; From 6685d515157c7d00461f0d0e77fe172d03817c87 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 5 Mar 2019 08:23:13 -0500 Subject: [PATCH 053/218] media: i2c: adv748x: select V4L2_FWNODE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Building adv748x fails now unless V4L2_FWNODE is selected: drivers/media/i2c/adv748x/adv748x-core.o: In function `adv748x_probe': adv748x-core.c:(.text+0x1b2c): undefined reference to `v4l2_fwnode_endpoint_parse' Fixes: 6a18865da8e3 ("media: i2c: adv748x: store number of CSI-2 lanes described in device tree") Signed-off-by: Arnd Bergmann Reviewed-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 6d32f8dcf83b..3f5dd80e14f8 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -221,6 +221,7 @@ config VIDEO_ADV748X depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API depends on OF select REGMAP_I2C + select V4L2_FWNODE ---help--- V4L2 subdevice driver for the Analog Devices ADV7481 and ADV7482 HDMI/Analog video decoders. From 49dc762cffd8305a861ca649e82dc5533b3e3344 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 5 Mar 2019 08:29:48 -0500 Subject: [PATCH 054/218] media: staging: davinci_vpfe: disallow building with COMPILE_TEST The driver should really call dm365_isif_setup_pinmux() through a callback, but uses a hack to include a davinci specific machine header file when compile testing instead. This works almost everywhere, but not on the ARM omap1 platform, which has another header named mach/mux.h. This causes a build failure: drivers/staging/media/davinci_vpfe/dm365_isif.c:2028:2: error: implicit declaration of function 'davinci_cfg_reg' [-Werror,-Wimplicit-function-declaration] davinci_cfg_reg(DM365_VIN_CAM_WEN); ^ drivers/staging/media/davinci_vpfe/dm365_isif.c:2028:2: error: this function declaration is not a prototype [-Werror,-Wstrict-prototypes] drivers/staging/media/davinci_vpfe/dm365_isif.c:2028:18: error: use of undeclared identifier 'DM365_VIN_CAM_WEN' davinci_cfg_reg(DM365_VIN_CAM_WEN); ^ drivers/staging/media/davinci_vpfe/dm365_isif.c:2029:18: error: use of undeclared identifier 'DM365_VIN_CAM_VD' davinci_cfg_reg(DM365_VIN_CAM_VD); ^ drivers/staging/media/davinci_vpfe/dm365_isif.c:2030:18: error: use of undeclared identifier 'DM365_VIN_CAM_HD' davinci_cfg_reg(DM365_VIN_CAM_HD); ^ drivers/staging/media/davinci_vpfe/dm365_isif.c:2031:18: error: use of undeclared identifier 'DM365_VIN_YIN4_7_EN' davinci_cfg_reg(DM365_VIN_YIN4_7_EN); ^ drivers/staging/media/davinci_vpfe/dm365_isif.c:2032:18: error: use of undeclared identifier 'DM365_VIN_YIN0_3_EN' davinci_cfg_reg(DM365_VIN_YIN0_3_EN); ^ 7 errors generated. Exclude omap1 from compile-testing, under the assumption that all others still work. Fixes: 4907c73deefe ("media: staging: davinci_vpfe: allow building with COMPILE_TEST") Signed-off-by: Arnd Bergmann Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/davinci_vpfe/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/davinci_vpfe/Kconfig b/drivers/staging/media/davinci_vpfe/Kconfig index aea449a8dbf8..76818cc48ddc 100644 --- a/drivers/staging/media/davinci_vpfe/Kconfig +++ b/drivers/staging/media/davinci_vpfe/Kconfig @@ -1,7 +1,7 @@ config VIDEO_DM365_VPFE tristate "DM365 VPFE Media Controller Capture Driver" depends on VIDEO_V4L2 - depends on (ARCH_DAVINCI_DM365 && !VIDEO_DM365_ISIF) || COMPILE_TEST + depends on (ARCH_DAVINCI_DM365 && !VIDEO_DM365_ISIF) || (COMPILE_TEST && !ARCH_OMAP1) depends on VIDEO_V4L2_SUBDEV_API depends on VIDEO_DAVINCI_VPBE_DISPLAY select VIDEOBUF2_DMA_CONTIG From 3f7f41d706658f08240742787542cfff7673ea71 Mon Sep 17 00:00:00 2001 From: claudiojpaz Date: Sat, 9 Mar 2019 12:50:00 -0500 Subject: [PATCH 055/218] media: staging: media: zoran: Fixes a checkpatch.pl error in videocodec.c ERROR: do not initialise statics to NULL Signed-off-by: claudiojpaz Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/zoran/videocodec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/zoran/videocodec.c b/drivers/staging/media/zoran/videocodec.c index 4427ae7126e2..044ef8455ba8 100644 --- a/drivers/staging/media/zoran/videocodec.c +++ b/drivers/staging/media/zoran/videocodec.c @@ -63,7 +63,7 @@ struct codec_list { struct codec_list *next; }; -static struct codec_list *codeclist_top = NULL; +static struct codec_list *codeclist_top; /* ================================================= */ /* function prototypes of the master/slave interface */ From c1a65ebd05a9a6b9ae753fbc9f6ed2a8f0f4f09f Mon Sep 17 00:00:00 2001 From: Mao Wenan Date: Mon, 11 Mar 2019 10:37:39 -0400 Subject: [PATCH 056/218] media: staging: davinci: drop pointless static qualifier in vpfe_resizer_init() There is no need to have the 'T *v' variable static since new value always be assigned before use it. Signed-off-by: Mao Wenan Reviewed-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/davinci_vpfe/dm365_resizer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c index 9d726298b406..3a9879d2f337 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c +++ b/drivers/staging/media/davinci_vpfe/dm365_resizer.c @@ -1881,7 +1881,7 @@ int vpfe_resizer_init(struct vpfe_resizer_device *vpfe_rsz, struct v4l2_subdev *sd = &vpfe_rsz->crop_resizer.subdev; struct media_pad *pads = &vpfe_rsz->crop_resizer.pads[0]; struct media_entity *me = &sd->entity; - static resource_size_t res_len; + resource_size_t res_len; struct resource *res; int ret; From ef4bb63dc1f7213c08e13f6943c69cd27f69e4a3 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 6 Mar 2019 02:27:43 -0500 Subject: [PATCH 057/218] media: wl128x: Fix an error code in fm_download_firmware() We forgot to set "ret" on this error path. Fixes: e8454ff7b9a4 ("[media] drivers:media:radio: wl128x: FM Driver Common sources") Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/wl128x/fmdrv_common.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c index 3c8987af3772..1614809f7d35 100644 --- a/drivers/media/radio/wl128x/fmdrv_common.c +++ b/drivers/media/radio/wl128x/fmdrv_common.c @@ -1268,8 +1268,9 @@ static int fm_download_firmware(struct fmdev *fmdev, const u8 *fw_name) switch (action->type) { case ACTION_SEND_COMMAND: /* Send */ - if (fmc_send_cmd(fmdev, 0, 0, action->data, - action->size, NULL, NULL)) + ret = fmc_send_cmd(fmdev, 0, 0, action->data, + action->size, NULL, NULL); + if (ret) goto rel_fw; cmd_cnt++; From fdfa59cd63b184e1e96d51ff170fcac739bc6f6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Br=C3=BCns?= Date: Sat, 19 Jan 2019 20:30:04 -0500 Subject: [PATCH 058/218] media: dvbsky: Avoid leaking dvb frontend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 14f4eaeddabc ("media: dvbsky: fix driver unregister logic") fixed a use-after-free by removing the reference to the frontend after deleting the backing i2c device. This has the unfortunate side effect the frontend device is never freed in the dvb core leaving a dangling device, leading to errors when the dvb core tries to register the frontend after e.g. a replug as reported here: https://www.spinics.net/lists/linux-media/msg138181.html media: dvbsky: issues with DVBSky T680CI === [ 561.119145] sp2 8-0040: CIMaX SP2 successfully attached [ 561.119161] usb 2-3: DVB: registering adapter 0 frontend 0 (Silicon Labs Si2168)... [ 561.119174] sysfs: cannot create duplicate filename '/class/dvb/ dvb0.frontend0' === The use after free happened as dvb_usbv2_disconnect calls in this order: - dvb_usb_device::props->exit(...) - dvb_usbv2_adapter_frontend_exit(...) + if (fe) dvb_unregister_frontend(fe) + dvb_usb_device::props->frontend_detach(...) Moving the release of the i2c device from exit() to frontend_detach() avoids the dangling pointer access and allows the core to unregister the frontend. This was originally reported for a DVBSky T680CI, but it also affects the MyGica T230C. As all supported devices structure the registration/ unregistration identically, apply the change for all device types. Signed-off-by: Stefan Brüns Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/dvbsky.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c index e28bd8836751..ae0814dd202a 100644 --- a/drivers/media/usb/dvb-usb-v2/dvbsky.c +++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c @@ -615,16 +615,18 @@ static int dvbsky_init(struct dvb_usb_device *d) return 0; } -static void dvbsky_exit(struct dvb_usb_device *d) +static int dvbsky_frontend_detach(struct dvb_usb_adapter *adap) { + struct dvb_usb_device *d = adap_to_d(adap); struct dvbsky_state *state = d_to_priv(d); - struct dvb_usb_adapter *adap = &d->adapter[0]; + + dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, adap->id); dvb_module_release(state->i2c_client_tuner); dvb_module_release(state->i2c_client_demod); dvb_module_release(state->i2c_client_ci); - adap->fe[0] = NULL; + return 0; } /* DVB USB Driver stuff */ @@ -640,11 +642,11 @@ static struct dvb_usb_device_properties dvbsky_s960_props = { .i2c_algo = &dvbsky_i2c_algo, .frontend_attach = dvbsky_s960_attach, + .frontend_detach = dvbsky_frontend_detach, .init = dvbsky_init, .get_rc_config = dvbsky_get_rc_config, .streaming_ctrl = dvbsky_streaming_ctrl, .identify_state = dvbsky_identify_state, - .exit = dvbsky_exit, .read_mac_address = dvbsky_read_mac_addr, .num_adapters = 1, @@ -667,11 +669,11 @@ static struct dvb_usb_device_properties dvbsky_s960c_props = { .i2c_algo = &dvbsky_i2c_algo, .frontend_attach = dvbsky_s960c_attach, + .frontend_detach = dvbsky_frontend_detach, .init = dvbsky_init, .get_rc_config = dvbsky_get_rc_config, .streaming_ctrl = dvbsky_streaming_ctrl, .identify_state = dvbsky_identify_state, - .exit = dvbsky_exit, .read_mac_address = dvbsky_read_mac_addr, .num_adapters = 1, @@ -694,11 +696,11 @@ static struct dvb_usb_device_properties dvbsky_t680c_props = { .i2c_algo = &dvbsky_i2c_algo, .frontend_attach = dvbsky_t680c_attach, + .frontend_detach = dvbsky_frontend_detach, .init = dvbsky_init, .get_rc_config = dvbsky_get_rc_config, .streaming_ctrl = dvbsky_streaming_ctrl, .identify_state = dvbsky_identify_state, - .exit = dvbsky_exit, .read_mac_address = dvbsky_read_mac_addr, .num_adapters = 1, @@ -721,11 +723,11 @@ static struct dvb_usb_device_properties dvbsky_t330_props = { .i2c_algo = &dvbsky_i2c_algo, .frontend_attach = dvbsky_t330_attach, + .frontend_detach = dvbsky_frontend_detach, .init = dvbsky_init, .get_rc_config = dvbsky_get_rc_config, .streaming_ctrl = dvbsky_streaming_ctrl, .identify_state = dvbsky_identify_state, - .exit = dvbsky_exit, .read_mac_address = dvbsky_read_mac_addr, .num_adapters = 1, @@ -748,11 +750,11 @@ static struct dvb_usb_device_properties mygica_t230c_props = { .i2c_algo = &dvbsky_i2c_algo, .frontend_attach = dvbsky_mygica_t230c_attach, + .frontend_detach = dvbsky_frontend_detach, .init = dvbsky_init, .get_rc_config = dvbsky_get_rc_config, .streaming_ctrl = dvbsky_streaming_ctrl, .identify_state = dvbsky_identify_state, - .exit = dvbsky_exit, .num_adapters = 1, .adapter = { From 981fbe3da20a6f35f17977453bce7dfc1664d74f Mon Sep 17 00:00:00 2001 From: James Hutchinson Date: Sun, 13 Jan 2019 16:13:47 -0500 Subject: [PATCH 059/218] media: m88ds3103: serialize reset messages in m88ds3103_set_frontend Ref: https://bugzilla.kernel.org/show_bug.cgi?id=199323 Users are experiencing problems with the DVBSky S960/S960C USB devices since the following commit: 9d659ae: ("locking/mutex: Add lock handoff to avoid starvation") The device malfunctions after running for an indeterminable period of time, and the problem can only be cleared by rebooting the machine. It is possible to encourage the problem to surface by blocking the signal to the LNB. Further debugging revealed the cause of the problem. In the following capture: - thread #1325 is running m88ds3103_set_frontend - thread #42 is running ts2020_stat_work a> [1325] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 07 80 [1325] usb 1-1: dvb_usb_v2_generic_io: <<< 08 [42] usb 1-1: dvb_usb_v2_generic_io: >>> 09 01 01 68 3f [42] usb 1-1: dvb_usb_v2_generic_io: <<< 08 ff [42] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 03 11 [42] usb 1-1: dvb_usb_v2_generic_io: <<< 07 [42] usb 1-1: dvb_usb_v2_generic_io: >>> 09 01 01 60 3d [42] usb 1-1: dvb_usb_v2_generic_io: <<< 07 ff b> [1325] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 07 00 [1325] usb 1-1: dvb_usb_v2_generic_io: <<< 07 [42] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 03 11 [42] usb 1-1: dvb_usb_v2_generic_io: <<< 07 [42] usb 1-1: dvb_usb_v2_generic_io: >>> 09 01 01 60 21 [42] usb 1-1: dvb_usb_v2_generic_io: <<< 07 ff [42] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 03 11 [42] usb 1-1: dvb_usb_v2_generic_io: <<< 07 [42] usb 1-1: dvb_usb_v2_generic_io: >>> 09 01 01 60 66 [42] usb 1-1: dvb_usb_v2_generic_io: <<< 07 ff [1325] usb 1-1: dvb_usb_v2_generic_io: >>> 08 68 02 03 11 [1325] usb 1-1: dvb_usb_v2_generic_io: <<< 07 [1325] usb 1-1: dvb_usb_v2_generic_io: >>> 08 60 02 10 0b [1325] usb 1-1: dvb_usb_v2_generic_io: <<< 07 Two i2c messages are sent to perform a reset in m88ds3103_set_frontend: a. 0x07, 0x80 b. 0x07, 0x00 However, as shown in the capture, the regmap mutex is being handed over to another thread (ts2020_stat_work) in between these two messages. >From here, the device responds to every i2c message with an 07 message, and will only return to normal operation following a power cycle. Use regmap_multi_reg_write to group the two reset messages, ensuring both are processed before the regmap mutex is unlocked. Signed-off-by: James Hutchinson Reviewed-by: Antti Palosaari Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/m88ds3103.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c index 123f2a33738b..403f42806455 100644 --- a/drivers/media/dvb-frontends/m88ds3103.c +++ b/drivers/media/dvb-frontends/m88ds3103.c @@ -309,6 +309,9 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) u16 u16tmp; u32 tuner_frequency_khz, target_mclk; s32 s32tmp; + static const struct reg_sequence reset_buf[] = { + {0x07, 0x80}, {0x07, 0x00} + }; dev_dbg(&client->dev, "delivery_system=%d modulation=%d frequency=%u symbol_rate=%d inversion=%d pilot=%d rolloff=%d\n", @@ -321,11 +324,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) } /* reset */ - ret = regmap_write(dev->regmap, 0x07, 0x80); - if (ret) - goto err; - - ret = regmap_write(dev->regmap, 0x07, 0x00); + ret = regmap_multi_reg_write(dev->regmap, reset_buf, 2); if (ret) goto err; From a3d7f22ef34ec4206b50ee121384d5c8bebd5591 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Sat, 19 Jan 2019 22:52:23 -0500 Subject: [PATCH 060/218] media: cx23885: check allocation return Checking of kmalloc() seems to have been committed - as cx23885_dvb_register() is checking for != 0 return, returning -ENOMEM should be fine here. While at it address the coccicheck suggestion to move to kmemdup rather than using kmalloc+memcpy. Fixes: 46b21bbaa8a8 ("[media] Add support for DViCO FusionHDTV DVB-T Dual Express2") Signed-off-by: Nicholas Mc Guire Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx23885/cx23885-dvb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c index 0d0929c54f93..e2e63f05645e 100644 --- a/drivers/media/pci/cx23885/cx23885-dvb.c +++ b/drivers/media/pci/cx23885/cx23885-dvb.c @@ -1474,8 +1474,9 @@ static int dvb_register(struct cx23885_tsport *port) if (fe0->dvb.frontend != NULL) { struct i2c_adapter *tun_i2c; - fe0->dvb.frontend->sec_priv = kmalloc(sizeof(dib7000p_ops), GFP_KERNEL); - memcpy(fe0->dvb.frontend->sec_priv, &dib7000p_ops, sizeof(dib7000p_ops)); + fe0->dvb.frontend->sec_priv = kmemdup(&dib7000p_ops, sizeof(dib7000p_ops), GFP_KERNEL); + if (!fe0->dvb.frontend->sec_priv) + return -ENOMEM; tun_i2c = dib7000p_ops.get_i2c_master(fe0->dvb.frontend, DIBX000_I2C_INTERFACE_TUNER, 1); if (!dvb_attach(dib0070_attach, fe0->dvb.frontend, tun_i2c, &dib7070p_dib0070_config)) return -ENODEV; From 3c73b8a40d49f798d189f20b0f9ad4bff7766a0e Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 20 Feb 2019 20:32:55 -0500 Subject: [PATCH 061/218] media: rc: remove unused including Remove including that don't need it. Signed-off-by: YueHaibing Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/ir-rcmm-decoder.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/rc/ir-rcmm-decoder.c b/drivers/media/rc/ir-rcmm-decoder.c index f1096ac1e5c5..64fb65a9a19f 100644 --- a/drivers/media/rc/ir-rcmm-decoder.c +++ b/drivers/media/rc/ir-rcmm-decoder.c @@ -5,7 +5,6 @@ #include "rc-core-priv.h" #include -#include #define RCMM_UNIT 166667 /* nanosecs */ #define RCMM_PREFIX_PULSE 416666 /* 166666.666666666*2.5 */ From 56cd26b618855c9af48c8301aa6754ced8dd0beb Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Tue, 5 Mar 2019 00:40:26 -0500 Subject: [PATCH 062/218] media: serial_ir: Fix use-after-free in serial_ir_init_module Syzkaller report this: BUG: KASAN: use-after-free in sysfs_remove_file_ns+0x5f/0x70 fs/sysfs/file.c:468 Read of size 8 at addr ffff8881dc7ae030 by task syz-executor.0/6249 CPU: 1 PID: 6249 Comm: syz-executor.0 Not tainted 5.0.0-rc8+ #3 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0xfa/0x1ce lib/dump_stack.c:113 print_address_description+0x65/0x270 mm/kasan/report.c:187 kasan_report+0x149/0x18d mm/kasan/report.c:317 ? 0xffffffffc1728000 sysfs_remove_file_ns+0x5f/0x70 fs/sysfs/file.c:468 sysfs_remove_file include/linux/sysfs.h:519 [inline] driver_remove_file+0x40/0x50 drivers/base/driver.c:122 remove_bind_files drivers/base/bus.c:585 [inline] bus_remove_driver+0x186/0x220 drivers/base/bus.c:725 driver_unregister+0x6c/0xa0 drivers/base/driver.c:197 serial_ir_init_module+0x169/0x1000 [serial_ir] do_one_initcall+0xfa/0x5ca init/main.c:887 do_init_module+0x204/0x5f6 kernel/module.c:3460 load_module+0x66b2/0x8570 kernel/module.c:3808 __do_sys_finit_module+0x238/0x2a0 kernel/module.c:3902 do_syscall_64+0x147/0x600 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x462e99 Code: f7 d8 64 89 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 bc ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007f9450132c58 EFLAGS: 00000246 ORIG_RAX: 0000000000000139 RAX: ffffffffffffffda RBX: 000000000073bf00 RCX: 0000000000462e99 RDX: 0000000000000000 RSI: 0000000020000100 RDI: 0000000000000003 RBP: 00007f9450132c70 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 00007f94501336bc R13: 00000000004bcefa R14: 00000000006f6fb0 R15: 0000000000000004 Allocated by task 6249: set_track mm/kasan/common.c:85 [inline] __kasan_kmalloc.constprop.3+0xa0/0xd0 mm/kasan/common.c:495 kmalloc include/linux/slab.h:545 [inline] kzalloc include/linux/slab.h:740 [inline] bus_add_driver+0xc0/0x610 drivers/base/bus.c:651 driver_register+0x1bb/0x3f0 drivers/base/driver.c:170 serial_ir_init_module+0xe8/0x1000 [serial_ir] do_one_initcall+0xfa/0x5ca init/main.c:887 do_init_module+0x204/0x5f6 kernel/module.c:3460 load_module+0x66b2/0x8570 kernel/module.c:3808 __do_sys_finit_module+0x238/0x2a0 kernel/module.c:3902 do_syscall_64+0x147/0x600 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe Freed by task 6249: set_track mm/kasan/common.c:85 [inline] __kasan_slab_free+0x130/0x180 mm/kasan/common.c:457 slab_free_hook mm/slub.c:1430 [inline] slab_free_freelist_hook mm/slub.c:1457 [inline] slab_free mm/slub.c:3005 [inline] kfree+0xe1/0x270 mm/slub.c:3957 kobject_cleanup lib/kobject.c:662 [inline] kobject_release lib/kobject.c:691 [inline] kref_put include/linux/kref.h:67 [inline] kobject_put+0x146/0x240 lib/kobject.c:708 bus_remove_driver+0x10e/0x220 drivers/base/bus.c:732 driver_unregister+0x6c/0xa0 drivers/base/driver.c:197 serial_ir_init_module+0x14c/0x1000 [serial_ir] do_one_initcall+0xfa/0x5ca init/main.c:887 do_init_module+0x204/0x5f6 kernel/module.c:3460 load_module+0x66b2/0x8570 kernel/module.c:3808 __do_sys_finit_module+0x238/0x2a0 kernel/module.c:3902 do_syscall_64+0x147/0x600 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe The buggy address belongs to the object at ffff8881dc7ae000 which belongs to the cache kmalloc-256 of size 256 The buggy address is located 48 bytes inside of 256-byte region [ffff8881dc7ae000, ffff8881dc7ae100) The buggy address belongs to the page: page:ffffea000771eb80 count:1 mapcount:0 mapping:ffff8881f6c02e00 index:0x0 flags: 0x2fffc0000000200(slab) raw: 02fffc0000000200 ffffea0007d14800 0000000400000002 ffff8881f6c02e00 raw: 0000000000000000 00000000800c000c 00000001ffffffff 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff8881dc7adf00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ffff8881dc7adf80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 >ffff8881dc7ae000: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ^ ffff8881dc7ae080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff8881dc7ae100: fc fc fc fc fc fc fc fc 00 00 00 00 00 00 00 00 There are already cleanup handlings in serial_ir_init error path, no need to call serial_ir_exit do it again in serial_ir_init_module, otherwise will trigger a use-after-free issue. Fixes: fa5dc29c1fcc ("[media] lirc_serial: move out of staging and rename to serial_ir") Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/serial_ir.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/media/rc/serial_ir.c b/drivers/media/rc/serial_ir.c index ffe2c672d105..3998ba29beb6 100644 --- a/drivers/media/rc/serial_ir.c +++ b/drivers/media/rc/serial_ir.c @@ -773,8 +773,6 @@ static void serial_ir_exit(void) static int __init serial_ir_init_module(void) { - int result; - switch (type) { case IR_HOMEBREW: case IR_IRDEO: @@ -802,12 +800,7 @@ static int __init serial_ir_init_module(void) if (sense != -1) sense = !!sense; - result = serial_ir_init(); - if (!result) - return 0; - - serial_ir_exit(); - return result; + return serial_ir_init(); } static void __exit serial_ir_exit_module(void) From 0ab34a08812a3334350dbaf69a018ee0ab3d2ddd Mon Sep 17 00:00:00 2001 From: Kangjie Lu Date: Thu, 20 Dec 2018 23:54:03 -0500 Subject: [PATCH 063/218] media: si2165: fix a missing check of return value si2165_readreg8() may fail. Looking into si2165_readreg8(), we will find that "val_tmp" will be an uninitialized value when regmap_read() fails. "val_tmp" is then assigned to "val". So if si2165_readreg8() fails, "val" will be a random value. Further use will lead to undefined behaviors. The fix checks if si2165_readreg8() fails, and if so, returns its error code upstream. Signed-off-by: Kangjie Lu Reviewed-by: Matthias Schwarzott Tested-by: Matthias Schwarzott Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2165.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb-frontends/si2165.c b/drivers/media/dvb-frontends/si2165.c index feacd8da421d..d55d8f169dca 100644 --- a/drivers/media/dvb-frontends/si2165.c +++ b/drivers/media/dvb-frontends/si2165.c @@ -275,18 +275,20 @@ static u32 si2165_get_fe_clk(struct si2165_state *state) static int si2165_wait_init_done(struct si2165_state *state) { - int ret = -EINVAL; + int ret; u8 val = 0; int i; for (i = 0; i < 3; ++i) { - si2165_readreg8(state, REG_INIT_DONE, &val); + ret = si2165_readreg8(state, REG_INIT_DONE, &val); + if (ret < 0) + return ret; if (val == 0x01) return 0; usleep_range(1000, 50000); } dev_err(&state->client->dev, "init_done was not set\n"); - return ret; + return -EINVAL; } static int si2165_upload_firmware_block(struct si2165_state *state, From 1cb11bfaa1e0a5933fb56bdaa60beb18721a2e2d Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Thu, 7 Mar 2019 18:11:58 -0500 Subject: [PATCH 064/218] media: dvb: init i2c already in it930x_frontend_attach i2c bus is already needed when the frontend is probed, so init it already in it930x_frontend_attach. That prevents errors like: si2168: probe of 6-0067 failed with error -5 Signed-off-by: Andreas Kemnade Signed-off-by: Jose Alberto Reguero Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/af9035.c | 84 +++++++++++++-------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index 80d3bd3a0f24..e8ec53249db0 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -1218,6 +1218,48 @@ static int it930x_frontend_attach(struct dvb_usb_adapter *adap) dev_dbg(&intf->dev, "adap->id=%d\n", adap->id); + /* I2C master bus 2 clock speed 300k */ + ret = af9035_wr_reg(d, 0x00f6a7, 0x07); + if (ret < 0) + goto err; + + /* I2C master bus 1,3 clock speed 300k */ + ret = af9035_wr_reg(d, 0x00f103, 0x07); + if (ret < 0) + goto err; + + /* set gpio11 low */ + ret = af9035_wr_reg_mask(d, 0xd8d4, 0x01, 0x01); + if (ret < 0) + goto err; + + ret = af9035_wr_reg_mask(d, 0xd8d5, 0x01, 0x01); + if (ret < 0) + goto err; + + ret = af9035_wr_reg_mask(d, 0xd8d3, 0x01, 0x01); + if (ret < 0) + goto err; + + /* Tuner enable using gpiot2_en, gpiot2_on and gpiot2_o (reset) */ + ret = af9035_wr_reg_mask(d, 0xd8b8, 0x01, 0x01); + if (ret < 0) + goto err; + + ret = af9035_wr_reg_mask(d, 0xd8b9, 0x01, 0x01); + if (ret < 0) + goto err; + + ret = af9035_wr_reg_mask(d, 0xd8b7, 0x00, 0x01); + if (ret < 0) + goto err; + + msleep(200); + + ret = af9035_wr_reg_mask(d, 0xd8b7, 0x01, 0x01); + if (ret < 0) + goto err; + memset(&si2168_config, 0, sizeof(si2168_config)); si2168_config.i2c_adapter = &adapter; si2168_config.fe = &adap->fe[0]; @@ -1575,48 +1617,6 @@ static int it930x_tuner_attach(struct dvb_usb_adapter *adap) dev_dbg(&intf->dev, "adap->id=%d\n", adap->id); - /* I2C master bus 2 clock speed 300k */ - ret = af9035_wr_reg(d, 0x00f6a7, 0x07); - if (ret < 0) - goto err; - - /* I2C master bus 1,3 clock speed 300k */ - ret = af9035_wr_reg(d, 0x00f103, 0x07); - if (ret < 0) - goto err; - - /* set gpio11 low */ - ret = af9035_wr_reg_mask(d, 0xd8d4, 0x01, 0x01); - if (ret < 0) - goto err; - - ret = af9035_wr_reg_mask(d, 0xd8d5, 0x01, 0x01); - if (ret < 0) - goto err; - - ret = af9035_wr_reg_mask(d, 0xd8d3, 0x01, 0x01); - if (ret < 0) - goto err; - - /* Tuner enable using gpiot2_en, gpiot2_on and gpiot2_o (reset) */ - ret = af9035_wr_reg_mask(d, 0xd8b8, 0x01, 0x01); - if (ret < 0) - goto err; - - ret = af9035_wr_reg_mask(d, 0xd8b9, 0x01, 0x01); - if (ret < 0) - goto err; - - ret = af9035_wr_reg_mask(d, 0xd8b7, 0x00, 0x01); - if (ret < 0) - goto err; - - msleep(200); - - ret = af9035_wr_reg_mask(d, 0xd8b7, 0x01, 0x01); - if (ret < 0) - goto err; - memset(&si2157_config, 0, sizeof(si2157_config)); si2157_config.fe = adap->fe[0]; si2157_config.if_port = 1; From c51f3b7f25dedca3f988defeee9d07f04e4f5401 Mon Sep 17 00:00:00 2001 From: Jose Alberto Reguero Date: Thu, 7 Mar 2019 18:12:18 -0500 Subject: [PATCH 065/218] media: dvb: Add support for the Avermedia TD310 This patch add support for Avermedia TD310 usb stick. Signed-off-by: Jose Alberto Reguero Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/af9035.c | 20 ++++++++++++++------ drivers/media/usb/dvb-usb-v2/af9035.h | 12 ++++++++++++ include/media/dvb-usb-ids.h | 1 + 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index e8ec53249db0..1b7f1af399fb 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -846,6 +846,7 @@ static int af9035_read_config(struct dvb_usb_device *d) state->af9033_config[1].adc_multiplier = AF9033_ADC_MULTIPLIER_2X; state->af9033_config[0].ts_mode = AF9033_TS_MODE_USB; state->af9033_config[1].ts_mode = AF9033_TS_MODE_SERIAL; + state->it930x_addresses = 0; if (state->chip_type == 0x9135) { /* feed clock for integrated RF tuner */ @@ -872,6 +873,10 @@ static int af9035_read_config(struct dvb_usb_device *d) * IT930x is an USB bridge, only single demod-single tuner * configurations seen so far. */ + if ((le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_AVERMEDIA) && + (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_AVERMEDIA_TD310)) { + state->it930x_addresses = 1; + } return 0; } @@ -1267,8 +1272,9 @@ static int it930x_frontend_attach(struct dvb_usb_adapter *adap) state->af9033_config[adap->id].fe = &adap->fe[0]; state->af9033_config[adap->id].ops = &state->ops; - ret = af9035_add_i2c_dev(d, "si2168", 0x67, &si2168_config, - &d->i2c_adap); + ret = af9035_add_i2c_dev(d, "si2168", + it930x_addresses_table[state->it930x_addresses].frontend_i2c_addr, + &si2168_config, &d->i2c_adap); if (ret) goto err; @@ -1619,10 +1625,10 @@ static int it930x_tuner_attach(struct dvb_usb_adapter *adap) memset(&si2157_config, 0, sizeof(si2157_config)); si2157_config.fe = adap->fe[0]; - si2157_config.if_port = 1; - ret = af9035_add_i2c_dev(d, "si2157", 0x63, - &si2157_config, state->i2c_adapter_demod); - + si2157_config.if_port = it930x_addresses_table[state->it930x_addresses].tuner_if_port; + ret = af9035_add_i2c_dev(d, "si2157", + it930x_addresses_table[state->it930x_addresses].tuner_i2c_addr, + &si2157_config, state->i2c_adapter_demod); if (ret) goto err; @@ -2128,6 +2134,8 @@ static const struct usb_device_id af9035_id_table[] = { /* IT930x devices */ { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9303, &it930x_props, "ITE 9303 Generic", NULL) }, + { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TD310, + &it930x_props, "AVerMedia TD310 DVB-T2", NULL) }, { } }; MODULE_DEVICE_TABLE(usb, af9035_id_table); diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h b/drivers/media/usb/dvb-usb-v2/af9035.h index a76e6bf0ab1e..bc41c16f9727 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.h +++ b/drivers/media/usb/dvb-usb-v2/af9035.h @@ -69,6 +69,7 @@ struct state { u8 dual_mode:1; u8 no_read:1; u8 af9033_i2c_addr[2]; + u8 it930x_addresses; struct af9033_config af9033_config[2]; struct af9033_ops ops; #define AF9035_I2C_CLIENT_MAX 4 @@ -77,6 +78,17 @@ struct state { struct platform_device *platform_device_tuner[2]; }; +struct address_table { + u8 frontend_i2c_addr; + u8 tuner_i2c_addr; + u8 tuner_if_port; +}; + +static const struct address_table it930x_addresses_table[] = { + { 0x67, 0x63, 1 }, + { 0x64, 0x60, 0 }, +}; + static const u32 clock_lut_af9035[] = { 20480000, /* FPGA */ 16384000, /* 16.38 MHz */ diff --git a/include/media/dvb-usb-ids.h b/include/media/dvb-usb-ids.h index f9e73b4a6e89..52875e3eee71 100644 --- a/include/media/dvb-usb-ids.h +++ b/include/media/dvb-usb-ids.h @@ -258,6 +258,7 @@ #define USB_PID_AVERMEDIA_A867 0xa867 #define USB_PID_AVERMEDIA_H335 0x0335 #define USB_PID_AVERMEDIA_TD110 0xa110 +#define USB_PID_AVERMEDIA_TD310 0x1871 #define USB_PID_AVERMEDIA_TWINSTAR 0x0825 #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 #define USB_PID_TECHNOTREND_CONNECT_S2400_8KEEPROM 0x3009 From 6fe59b7eec391ad2e340f7727781cede099ab4c9 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 8 Mar 2019 05:30:17 -0500 Subject: [PATCH 066/218] media: em28xx-input: make const array addr_list static Don't populate the array addr_list on the stack but instead make it static. Makes the object code smaller by 20 bytes Before: text data bss dec hex filename^M 16929 3626 384 20939 51cb ../usb/em28xx/em28xx-input.o After: text data bss dec hex filename^M 16829 3706 384 20919 51b7 ../usb/em28xx/em28xx-input.o (gcc version 8.3.0, aarch64) Signed-off-by: Colin Ian King Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index f84a1208d5d3..d85ea1af6aa1 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c @@ -499,7 +499,7 @@ static int em28xx_probe_i2c_ir(struct em28xx *dev) * at address 0x18, so if that address is needed for another board in * the future, please put it after 0x1f. */ - const unsigned short addr_list[] = { + static const unsigned short addr_list[] = { 0x1f, 0x30, 0x47, I2C_CLIENT_END }; From f221b84ee13c5a6af837f497a2a89732472ad27c Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 13 Mar 2019 10:46:42 -0400 Subject: [PATCH 067/218] media: vicodec: remove WARN_ON(1) from get_q_data() Some functions like enum_fmt use the buffer type as was passed from userspace, which might cause the switch to fall into the default case. Just drop the WARN_ON(1) to avoid kernel log pollution. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vicodec/vicodec-core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index d7636fe9e174..075927dba614 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -148,7 +148,6 @@ static struct vicodec_q_data *get_q_data(struct vicodec_ctx *ctx, case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: return &ctx->q_data[V4L2_M2M_DST]; default: - WARN_ON(1); break; } return NULL; From 76eb24fc233b8c94b2156ead5811e08d2046ad58 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 13 Mar 2019 10:47:13 -0400 Subject: [PATCH 068/218] media: vicodec: reset last_src/dst_buf based on the IS_OUTPUT When start_streaming was called both last_src_buf and last_dst_buf pointers were set to NULL, but this depends on whether the capture or output queue starts streaming. When decoding with resolution changes in between the capture queue has to restart streaming whenever a resolution change occurs. And that would reset last_src_buf as well, which causes a problem if the decoder was stopped by the application. Since last_src_buf is now NULL, the LAST flag is never set for the last capture buffer. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vicodec/vicodec-core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index 075927dba614..39433ffdf417 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -1337,8 +1337,11 @@ static int vicodec_start_streaming(struct vb2_queue *q, chroma_div = info->width_div * info->height_div; q_data->sequence = 0; - ctx->last_src_buf = NULL; - ctx->last_dst_buf = NULL; + if (V4L2_TYPE_IS_OUTPUT(q->type)) + ctx->last_src_buf = NULL; + else + ctx->last_dst_buf = NULL; + state->gop_cnt = 0; if ((V4L2_TYPE_IS_OUTPUT(q->type) && !ctx->is_enc) || From 6d5f26f2e045f2377b524516194657c00efbbce8 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 4 Mar 2019 15:28:42 -0500 Subject: [PATCH 069/218] media: staging/intel-ipu3-v4l: reduce kernel stack usage The v4l2_pix_format_mplane structure is too large to be put on the kernel stack, as we can see in 32-bit builds: drivers/staging/media/ipu3/ipu3-v4l2.c: In function 'imgu_fmt': drivers/staging/media/ipu3/ipu3-v4l2.c:753:1: error: the frame size of 1028 bytes is larger than 1024 bytes [-Werror=frame-larger-than=] By dynamically allocating this array, the stack usage goes down to an acceptable 272 bytes for the same x86-32 configuration. Fixes: a0ca1627b450 ("media: staging/intel-ipu3: Add v4l2 driver based on media framework") Signed-off-by: Arnd Bergmann Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/ipu3/ipu3-v4l2.c | 40 ++++++++++++++++---------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/drivers/staging/media/ipu3/ipu3-v4l2.c b/drivers/staging/media/ipu3/ipu3-v4l2.c index 9c0352b193a7..c34b433539c4 100644 --- a/drivers/staging/media/ipu3/ipu3-v4l2.c +++ b/drivers/staging/media/ipu3/ipu3-v4l2.c @@ -664,12 +664,11 @@ static int imgu_fmt(struct imgu_device *imgu, unsigned int pipe, int node, struct v4l2_format *f, bool try) { struct device *dev = &imgu->pci_dev->dev; - struct v4l2_pix_format_mplane try_fmts[IPU3_CSS_QUEUES]; struct v4l2_pix_format_mplane *fmts[IPU3_CSS_QUEUES] = { NULL }; struct v4l2_rect *rects[IPU3_CSS_RECTS] = { NULL }; struct v4l2_mbus_framefmt pad_fmt; unsigned int i, css_q; - int r; + int ret; struct imgu_css_pipe *css_pipe = &imgu->css.pipes[pipe]; struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[pipe]; struct imgu_v4l2_subdev *imgu_sd = &imgu_pipe->imgu_sd; @@ -698,9 +697,13 @@ static int imgu_fmt(struct imgu_device *imgu, unsigned int pipe, int node, continue; if (try) { - try_fmts[i] = - imgu_pipe->nodes[inode].vdev_fmt.fmt.pix_mp; - fmts[i] = &try_fmts[i]; + fmts[i] = kmemdup(&imgu_pipe->nodes[inode].vdev_fmt.fmt.pix_mp, + sizeof(struct v4l2_pix_format_mplane), + GFP_KERNEL); + if (!fmts[i]) { + ret = -ENOMEM; + goto out; + } } else { fmts[i] = &imgu_pipe->nodes[inode].vdev_fmt.fmt.pix_mp; } @@ -730,26 +733,33 @@ static int imgu_fmt(struct imgu_device *imgu, unsigned int pipe, int node, * before we return success from this function, so set it here. */ css_q = imgu_node_to_queue(node); - if (fmts[css_q]) - *fmts[css_q] = f->fmt.pix_mp; - else - return -EINVAL; + if (!fmts[css_q]) { + ret = -EINVAL; + goto out; + } + *fmts[css_q] = f->fmt.pix_mp; if (try) - r = imgu_css_fmt_try(&imgu->css, fmts, rects, pipe); + ret = imgu_css_fmt_try(&imgu->css, fmts, rects, pipe); else - r = imgu_css_fmt_set(&imgu->css, fmts, rects, pipe); + ret = imgu_css_fmt_set(&imgu->css, fmts, rects, pipe); - /* r is the binary number in the firmware blob */ - if (r < 0) - return r; + /* ret is the binary number in the firmware blob */ + if (ret < 0) + goto out; if (try) f->fmt.pix_mp = *fmts[css_q]; else f->fmt = imgu_pipe->nodes[node].vdev_fmt.fmt; - return 0; +out: + if (try) { + for (i = 0; i < IPU3_CSS_QUEUES; i++) + kfree(fmts[i]); + } + + return ret; } static int imgu_try_fmt(struct file *file, void *fh, struct v4l2_format *f) From 948dff7cfa1d7653e7828e7b905863bd24ca5c02 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 4 Mar 2019 15:29:10 -0500 Subject: [PATCH 070/218] media: staging/intel-ipu3: mark PM function as __maybe_unused The imgu_rpm_dummy_cb() looks like an API misuse that is explained in the comment above it. Aside from that, it also causes a warning when power management support is disabled: drivers/staging/media/ipu3/ipu3.c:794:12: error: 'imgu_rpm_dummy_cb' defined but not used [-Werror=unused-function] The warning is at least easy to fix by marking the function as __maybe_unused. Fixes: 7fc7af649ca7 ("media: staging/intel-ipu3: Add imgu top level pci device driver") Signed-off-by: Arnd Bergmann Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/ipu3/ipu3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/ipu3/ipu3.c b/drivers/staging/media/ipu3/ipu3.c index d575ac78c8f0..d00d26264c37 100644 --- a/drivers/staging/media/ipu3/ipu3.c +++ b/drivers/staging/media/ipu3/ipu3.c @@ -791,7 +791,7 @@ out: * PCI rpm framework checks the existence of driver rpm callbacks. * Place a dummy callback here to avoid rpm going into error state. */ -static int imgu_rpm_dummy_cb(struct device *dev) +static __maybe_unused int imgu_rpm_dummy_cb(struct device *dev) { return 0; } From c3c2eca87dcded3626bc8f3a1b8bfa4b9f078fb1 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 5 Mar 2019 08:26:29 -0500 Subject: [PATCH 071/218] media: staging/intel-ipu3: reduce kernel stack usage The imgu_css_queue structure is too large to be put on the kernel stack, as we can see in 32-bit builds: drivers/staging/media/ipu3/ipu3-css.c: In function 'imgu_css_fmt_try': drivers/staging/media/ipu3/ipu3-css.c:1863:1: error: the frame size of 1172 bytes is larger than 1024 bytes [-Werror=frame-larger-than=] By dynamically allocating this array, the stack usage goes down to an acceptable 140 bytes for the same x86-32 configuration. Fixes: f5f2e4273518 ("media: staging/intel-ipu3: Add css pipeline programming") Signed-off-by: Arnd Bergmann Reviewed-by: Cao, Bingbu Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/ipu3/ipu3-css.c | 35 ++++++++++++++++++--------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/drivers/staging/media/ipu3/ipu3-css.c b/drivers/staging/media/ipu3/ipu3-css.c index 15ab77e4b766..e7f1898874fd 100644 --- a/drivers/staging/media/ipu3/ipu3-css.c +++ b/drivers/staging/media/ipu3/ipu3-css.c @@ -3,6 +3,7 @@ #include #include +#include #include "ipu3-css.h" #include "ipu3-css-fw.h" @@ -1744,15 +1745,18 @@ int imgu_css_fmt_try(struct imgu_css *css, struct v4l2_rect *const bds = &r[IPU3_CSS_RECT_BDS]; struct v4l2_rect *const env = &r[IPU3_CSS_RECT_ENVELOPE]; struct v4l2_rect *const gdc = &r[IPU3_CSS_RECT_GDC]; - struct imgu_css_queue q[IPU3_CSS_QUEUES]; - struct v4l2_pix_format_mplane *const in = - &q[IPU3_CSS_QUEUE_IN].fmt.mpix; - struct v4l2_pix_format_mplane *const out = - &q[IPU3_CSS_QUEUE_OUT].fmt.mpix; - struct v4l2_pix_format_mplane *const vf = - &q[IPU3_CSS_QUEUE_VF].fmt.mpix; + struct imgu_css_queue *q; + struct v4l2_pix_format_mplane *in, *out, *vf; int i, s, ret; + q = kcalloc(IPU3_CSS_QUEUES, sizeof(struct imgu_css_queue), GFP_KERNEL); + if (!q) + return -ENOMEM; + + in = &q[IPU3_CSS_QUEUE_IN].fmt.mpix; + out = &q[IPU3_CSS_QUEUE_OUT].fmt.mpix; + vf = &q[IPU3_CSS_QUEUE_VF].fmt.mpix; + /* Adjust all formats, get statistics buffer sizes and formats */ for (i = 0; i < IPU3_CSS_QUEUES; i++) { if (fmts[i]) @@ -1766,7 +1770,8 @@ int imgu_css_fmt_try(struct imgu_css *css, IPU3_CSS_QUEUE_TO_FLAGS(i))) { dev_notice(css->dev, "can not initialize queue %s\n", qnames[i]); - return -EINVAL; + ret = -EINVAL; + goto out; } } for (i = 0; i < IPU3_CSS_RECTS; i++) { @@ -1788,7 +1793,8 @@ int imgu_css_fmt_try(struct imgu_css *css, if (!imgu_css_queue_enabled(&q[IPU3_CSS_QUEUE_IN]) || !imgu_css_queue_enabled(&q[IPU3_CSS_QUEUE_OUT])) { dev_warn(css->dev, "required queues are disabled\n"); - return -EINVAL; + ret = -EINVAL; + goto out; } if (!imgu_css_queue_enabled(&q[IPU3_CSS_QUEUE_OUT])) { @@ -1829,7 +1835,8 @@ int imgu_css_fmt_try(struct imgu_css *css, ret = imgu_css_find_binary(css, pipe, q, r); if (ret < 0) { dev_err(css->dev, "failed to find suitable binary\n"); - return -EINVAL; + ret = -EINVAL; + goto out; } css->pipes[pipe].bindex = ret; @@ -1843,7 +1850,8 @@ int imgu_css_fmt_try(struct imgu_css *css, IPU3_CSS_QUEUE_TO_FLAGS(i))) { dev_err(css->dev, "final resolution adjustment failed\n"); - return -EINVAL; + ret = -EINVAL; + goto out; } *fmts[i] = q[i].fmt.mpix; } @@ -1859,7 +1867,10 @@ int imgu_css_fmt_try(struct imgu_css *css, bds->width, bds->height, gdc->width, gdc->height, out->width, out->height, vf->width, vf->height); - return 0; + ret = 0; +out: + kfree(q); + return ret; } int imgu_css_fmt_set(struct imgu_css *css, From 32ab688b280301f7cee9e547564cb74e33e06322 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 11 Mar 2019 11:36:02 -0400 Subject: [PATCH 072/218] media: ov7670: restore default settings after power-up Since commit 3d6a8fe25605 ("media: ov7670: hook s_power onto v4l2 core"), the device is actually powered off while the video stream is stopped. The frame format and framerate are restored right after power-up, but restoring the default register settings is forgotten. Fixes: 3d6a8fe25605 ("media: ov7670: hook s_power onto v4l2 core") Cc: Jonathan Corbet Signed-off-by: Akinobu Mita Reviewed-by: Lubomir Rintel Tested-by: Lubomir Rintel Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov7670.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index a7d26b294eb5..e65693c2aad5 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -1664,6 +1664,7 @@ static int ov7670_s_power(struct v4l2_subdev *sd, int on) if (on) { ov7670_power_on (sd); + ov7670_init(sd, 0); ov7670_apply_fmt(sd); ov7675_apply_framerate(sd); v4l2_ctrl_handler_setup(&info->hdl); From 12f6153d4555450bdb93d115bdbf28bbd92ea426 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 11 Mar 2019 11:36:03 -0400 Subject: [PATCH 073/218] media: ov7670: don't access registers when the device is powered off Since commit 3d6a8fe25605 ("media: ov7670: hook s_power onto v4l2 core"), the device is actually powered off while the video stream is stopped. So now set_format and s_frame_interval could be called while the device is powered off, but these callbacks try to change the register settings at this time. The frame format and framerate will be restored right after power-up, so we can just postpone applying these changes at these callbacks if the device is not powered up. Fixes: 3d6a8fe25605 ("media: ov7670: hook s_power onto v4l2 core") Cc: Jonathan Corbet Signed-off-by: Akinobu Mita Reviewed-by: Lubomir Rintel Tested-by: Lubomir Rintel Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov7670.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index e65693c2aad5..44c3eed8a858 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -864,7 +864,15 @@ static int ov7675_set_framerate(struct v4l2_subdev *sd, /* Recalculate frame rate */ ov7675_get_framerate(sd, tpf); - return ov7675_apply_framerate(sd); + /* + * If the device is not powered up by the host driver do + * not apply any changes to H/W at this time. Instead + * the framerate will be restored right after power-up. + */ + if (info->on) + return ov7675_apply_framerate(sd); + + return 0; } static void ov7670_get_framerate_legacy(struct v4l2_subdev *sd, @@ -895,7 +903,16 @@ static int ov7670_set_framerate_legacy(struct v4l2_subdev *sd, info->clkrc = (info->clkrc & 0x80) | div; tpf->numerator = 1; tpf->denominator = info->clock_speed / div; - return ov7670_write(sd, REG_CLKRC, info->clkrc); + + /* + * If the device is not powered up by the host driver do + * not apply any changes to H/W at this time. Instead + * the framerate will be restored right after power-up. + */ + if (info->on) + return ov7670_write(sd, REG_CLKRC, info->clkrc); + + return 0; } /* @@ -1105,9 +1122,13 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd, if (ret) return ret; - ret = ov7670_apply_fmt(sd); - if (ret) - return ret; + /* + * If the device is not powered up by the host driver do + * not apply any changes to H/W at this time. Instead + * the frame format will be restored right after power-up. + */ + if (info->on) + return ov7670_apply_fmt(sd); return 0; } From 9d3863736a267068a0ae67c6695af8770ef330b7 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 1 Mar 2019 08:48:38 -0500 Subject: [PATCH 074/218] media: v4l2-fwnode: Defaults may not override endpoint configuration in firmware The lack of defaults provided by the caller to v4l2_fwnode_endpoint_parse() signals the use of the default lane mapping. The default lane mapping must not be used however if the firmmare contains the lane mapping. Disable the default lane mapping in that case, and improve the debug messages telling of the use of the defaults. This was missed previously since the default mapping will only unsed in this case if the bus type is set, and no driver did both while still needing the lane mapping configuration. Fixes: b4357d21d674 ("media: v4l: fwnode: Support default CSI-2 lane mapping for drivers") Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-fwnode.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c index 20571846e636..c5b2dbf38e95 100644 --- a/drivers/media/v4l2-core/v4l2-fwnode.c +++ b/drivers/media/v4l2-core/v4l2-fwnode.c @@ -163,7 +163,7 @@ static int v4l2_fwnode_endpoint_parse_csi2_bus(struct fwnode_handle *fwnode, } if (use_default_lane_mapping) - pr_debug("using default lane mapping\n"); + pr_debug("no lane mapping given, using defaults\n"); } rval = fwnode_property_read_u32_array(fwnode, "data-lanes", NULL, 0); @@ -175,6 +175,10 @@ static int v4l2_fwnode_endpoint_parse_csi2_bus(struct fwnode_handle *fwnode, num_data_lanes); have_data_lanes = true; + if (use_default_lane_mapping) { + pr_debug("data-lanes property exists; disabling default mapping\n"); + use_default_lane_mapping = false; + } } for (i = 0; i < num_data_lanes; i++) { From fff35d45e16fae125c6000cb87e254cb634ac7fb Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Sat, 2 Mar 2019 10:23:12 -0500 Subject: [PATCH 075/218] media: v4l2-fwnode: The first default data lane is 0 on C-PHY C-PHY has no clock lanes. Therefore the first data lane is 0 by default. Fixes: edc6d56c2e7e ("media: v4l: fwnode: Support parsing of CSI-2 C-PHY endpoints") Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-fwnode.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c index c5b2dbf38e95..ccefa55813ad 100644 --- a/drivers/media/v4l2-core/v4l2-fwnode.c +++ b/drivers/media/v4l2-core/v4l2-fwnode.c @@ -229,6 +229,10 @@ static int v4l2_fwnode_endpoint_parse_csi2_bus(struct fwnode_handle *fwnode, if (bus_type == V4L2_MBUS_CSI2_DPHY || bus_type == V4L2_MBUS_CSI2_CPHY || lanes_used || have_clk_lane || (flags & ~V4L2_MBUS_CSI2_CONTINUOUS_CLOCK)) { + /* Only D-PHY has a clock lane. */ + unsigned int dfl_data_lane_index = + bus_type == V4L2_MBUS_CSI2_DPHY; + bus->flags = flags; if (bus_type == V4L2_MBUS_UNKNOWN) vep->bus_type = V4L2_MBUS_CSI2_DPHY; @@ -237,7 +241,7 @@ static int v4l2_fwnode_endpoint_parse_csi2_bus(struct fwnode_handle *fwnode, if (use_default_lane_mapping) { bus->clock_lane = 0; for (i = 0; i < num_data_lanes; i++) - bus->data_lanes[i] = 1 + i; + bus->data_lanes[i] = dfl_data_lane_index + i; } else { bus->clock_lane = clock_lane; for (i = 0; i < num_data_lanes; i++) From c1ee825686a4bab4fc3ef6b6edac535a32e0bc29 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Sat, 2 Dec 2017 15:29:46 -0500 Subject: [PATCH 076/218] media: pxa-camera: Match with device node, not the port node V4L2 fwnode matching right now still works based on device nodes, not port nodes. Fix this. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/pxa_camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/pxa_camera.c b/drivers/media/platform/pxa_camera.c index 4fe228752a43..a632f06d9fff 100644 --- a/drivers/media/platform/pxa_camera.c +++ b/drivers/media/platform/pxa_camera.c @@ -2350,7 +2350,7 @@ static int pxa_camera_pdata_from_dt(struct device *dev, pcdev->platform_flags |= PXA_CAMERA_PCLK_EN; asd->match_type = V4L2_ASYNC_MATCH_FWNODE; - remote = of_graph_get_remote_port(np); + remote = of_graph_get_remote_port_parent(np); if (remote) asd->match.fwnode = of_fwnode_handle(remote); else From f1ef70ffbfe7acf4141f6365c6504d374aada34a Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Sat, 2 Dec 2017 15:36:01 -0500 Subject: [PATCH 077/218] media: ti-vpe: Parse local endpoint for properties, not the remote one ti-vpe driver parsed the remote endpoints for properties but ignored the local ones. Fix this by parsing the local endpoint properties instead. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/ti-vpe/cal.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c index fc3c212b96e1..8d075683e448 100644 --- a/drivers/media/platform/ti-vpe/cal.c +++ b/drivers/media/platform/ti-vpe/cal.c @@ -1643,8 +1643,7 @@ of_get_next_endpoint(const struct device_node *parent, static int of_cal_create_instance(struct cal_ctx *ctx, int inst) { struct platform_device *pdev = ctx->dev->pdev; - struct device_node *ep_node, *port, *remote_ep, - *sensor_node, *parent; + struct device_node *ep_node, *port, *sensor_node, *parent; struct v4l2_fwnode_endpoint *endpoint; struct v4l2_async_subdev *asd; u32 regval = 0; @@ -1657,7 +1656,6 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst) ep_node = NULL; port = NULL; - remote_ep = NULL; sensor_node = NULL; ret = -EINVAL; @@ -1703,12 +1701,7 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst) asd->match_type = V4L2_ASYNC_MATCH_FWNODE; asd->match.fwnode = of_fwnode_handle(sensor_node); - remote_ep = of_graph_get_remote_endpoint(ep_node); - if (!remote_ep) { - ctx_dbg(3, ctx, "can't get remote-endpoint\n"); - goto cleanup_exit; - } - v4l2_fwnode_endpoint_parse(of_fwnode_handle(remote_ep), endpoint); + v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_node), endpoint); if (endpoint->bus_type != V4L2_MBUS_CSI2_DPHY) { ctx_err(ctx, "Port:%d sub-device %pOFn is not a CSI2 device\n", @@ -1759,7 +1752,6 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst) sensor_node = NULL; cleanup_exit: - of_node_put(remote_ep); of_node_put(sensor_node); of_node_put(ep_node); of_node_put(port); From 0d0d87fbf4c583c3c5ed86318c7338cc3f655d85 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 18 Mar 2019 11:21:13 -0400 Subject: [PATCH 078/218] media: v4l: i2c: Regroup lens drivers under their own section The lens drivers had ended up under the video decoder section; add a new one just for them, between the camera sensors and flash drivers. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/Kconfig | 76 ++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 3f5dd80e14f8..1ef6335463c1 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -321,43 +321,6 @@ config VIDEO_ML86V7667 To compile this driver as a module, choose M here: the module will be called ml86v7667. -config VIDEO_AD5820 - tristate "AD5820 lens voice coil support" - depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER - ---help--- - This is a driver for the AD5820 camera lens voice coil. - It is used for example in Nokia N900 (RX-51). - -config VIDEO_AK7375 - tristate "AK7375 lens voice coil support" - depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER - depends on VIDEO_V4L2_SUBDEV_API - help - This is a driver for the AK7375 camera lens voice coil. - AK7375 is a 12 bit DAC with 120mA output current sink - capability. This is designed for linear control of - voice coil motors, controlled via I2C serial interface. - -config VIDEO_DW9714 - tristate "DW9714 lens voice coil support" - depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER - depends on VIDEO_V4L2_SUBDEV_API - ---help--- - This is a driver for the DW9714 camera lens voice coil. - DW9714 is a 10 bit DAC with 120mA output current sink - capability. This is designed for linear control of - voice coil motors, controlled via I2C serial interface. - -config VIDEO_DW9807_VCM - tristate "DW9807 lens voice coil support" - depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER - depends on VIDEO_V4L2_SUBDEV_API - ---help--- - This is a driver for the DW9807 camera lens voice coil. - DW9807 is a 10 bit DAC with 100mA output current sink - capability. This is designed for linear control of - voice coil motors, controlled via I2C serial interface. - config VIDEO_SAA7110 tristate "Philips SAA7110 video decoder" depends on VIDEO_V4L2 && I2C @@ -1021,6 +984,45 @@ config VIDEO_S5C73M3 This is a V4L2 sensor driver for Samsung S5C73M3 8 Mpixel camera. +comment "Lens drivers" + +config VIDEO_AD5820 + tristate "AD5820 lens voice coil support" + depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER + ---help--- + This is a driver for the AD5820 camera lens voice coil. + It is used for example in Nokia N900 (RX-51). + +config VIDEO_AK7375 + tristate "AK7375 lens voice coil support" + depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER + depends on VIDEO_V4L2_SUBDEV_API + help + This is a driver for the AK7375 camera lens voice coil. + AK7375 is a 12 bit DAC with 120mA output current sink + capability. This is designed for linear control of + voice coil motors, controlled via I2C serial interface. + +config VIDEO_DW9714 + tristate "DW9714 lens voice coil support" + depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER + depends on VIDEO_V4L2_SUBDEV_API + ---help--- + This is a driver for the DW9714 camera lens voice coil. + DW9714 is a 10 bit DAC with 120mA output current sink + capability. This is designed for linear control of + voice coil motors, controlled via I2C serial interface. + +config VIDEO_DW9807_VCM + tristate "DW9807 lens voice coil support" + depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER + depends on VIDEO_V4L2_SUBDEV_API + ---help--- + This is a driver for the DW9807 camera lens voice coil. + DW9807 is a 10 bit DAC with 100mA output current sink + capability. This is designed for linear control of + voice coil motors, controlled via I2C serial interface. + comment "Flash devices" config VIDEO_ADP1653 From a5c7caa15a9da7ed6c9d658fffb0b37baf72ac23 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 18 Mar 2019 11:44:32 -0400 Subject: [PATCH 079/218] media: ipu3-cio2: Set CSI-2 receiver sub-device entity function Set the entity function for the four CSI-2 receiver sub-devices the driver creates. This avoids a kernel warning from each as well. Signed-off-by: Sakari Ailus Reviewed-by: Bingbu Cao Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/intel/ipu3/ipu3-cio2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c index f8020ebe9f05..2a52a393fe74 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -1601,6 +1601,7 @@ static int cio2_queue_init(struct cio2_device *cio2, struct cio2_queue *q) subdev->owner = THIS_MODULE; snprintf(subdev->name, sizeof(subdev->name), CIO2_ENTITY_NAME " %td", q - cio2->queue); + subdev->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; v4l2_set_subdevdata(subdev, cio2); r = v4l2_device_register_subdev(&cio2->v4l2_dev, subdev); if (r) { From 8a3946cad244e8453e26f3ded5fe40bf2627bb30 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 19 Mar 2019 04:07:32 -0400 Subject: [PATCH 080/218] media: v4l2-fwnode: Add a deprecation note in the old ACPI parsing example This is not how ACPI tables are written. Add a deprecation note and refer to the proper documentation. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-fwnode.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c index ccefa55813ad..ea1ed88f9dc8 100644 --- a/drivers/media/v4l2-core/v4l2-fwnode.c +++ b/drivers/media/v4l2-core/v4l2-fwnode.c @@ -828,7 +828,10 @@ error: * underneath the fwnode identified by the previous tuple, etc. until you * reached the fwnode you need. * - * An example with a graph, as defined in Documentation/acpi/dsd/graph.txt: + * THIS EXAMPLE EXISTS MERELY TO DOCUMENT THIS FUNCTION. DO NOT USE IT AS A + * REFERENCE IN HOW ACPI TABLES SHOULD BE WRITTEN!! See documentation under + * Documentation/acpi/dsd instead and especially graph.txt, + * data-node-references.txt and leds.txt . * * Scope (\_SB.PCI0.I2C2) * { From b60a5b8dcf49af9f2c60ae82e0383ee8e62a9a52 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 20 Mar 2019 06:39:44 -0400 Subject: [PATCH 081/218] media: Kconfig files: use the right help coding style Checkpatch wants to use 'help' instead of '---help---': WARNING: prefer 'help' over '---help---' for new help texts Let's change it globally at the media subsystem, as otherwise people would keep using the old way. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/Kconfig | 20 +- drivers/media/cec/Kconfig | 4 +- drivers/media/common/siano/Kconfig | 4 +- drivers/media/i2c/Kconfig | 184 +++++++++---------- drivers/media/i2c/cx25840/Kconfig | 2 +- drivers/media/i2c/et8ek8/Kconfig | 2 +- drivers/media/i2c/m5mols/Kconfig | 2 +- drivers/media/i2c/smiapp/Kconfig | 2 +- drivers/media/mmc/siano/Kconfig | 2 +- drivers/media/pci/bt8xx/Kconfig | 2 +- drivers/media/pci/cobalt/Kconfig | 2 +- drivers/media/pci/cx18/Kconfig | 4 +- drivers/media/pci/cx23885/Kconfig | 4 +- drivers/media/pci/cx25821/Kconfig | 4 +- drivers/media/pci/cx88/Kconfig | 10 +- drivers/media/pci/ddbridge/Kconfig | 4 +- drivers/media/pci/dt3155/Kconfig | 2 +- drivers/media/pci/intel/ipu3/Kconfig | 2 +- drivers/media/pci/ivtv/Kconfig | 10 +- drivers/media/pci/meye/Kconfig | 2 +- drivers/media/pci/netup_unidvb/Kconfig | 2 +- drivers/media/pci/ngene/Kconfig | 2 +- drivers/media/pci/saa7134/Kconfig | 10 +- drivers/media/pci/saa7146/Kconfig | 6 +- drivers/media/pci/saa7164/Kconfig | 2 +- drivers/media/pci/solo6x10/Kconfig | 2 +- drivers/media/pci/tw5864/Kconfig | 2 +- drivers/media/pci/tw68/Kconfig | 2 +- drivers/media/platform/Kconfig | 72 ++++---- drivers/media/platform/atmel/Kconfig | 2 +- drivers/media/platform/marvell-ccic/Kconfig | 4 +- drivers/media/platform/omap/Kconfig | 2 +- drivers/media/platform/rcar-vin/Kconfig | 2 +- drivers/media/platform/sti/c8sectpfe/Kconfig | 2 +- drivers/media/platform/vimc/Kconfig | 2 +- drivers/media/platform/vivid/Kconfig | 6 +- drivers/media/platform/xilinx/Kconfig | 6 +- drivers/media/radio/Kconfig | 54 +++--- drivers/media/radio/si470x/Kconfig | 6 +- drivers/media/radio/si4713/Kconfig | 6 +- drivers/media/rc/Kconfig | 80 ++++---- drivers/media/rc/keymaps/Kconfig | 2 +- drivers/media/spi/Kconfig | 2 +- drivers/media/usb/airspy/Kconfig | 2 +- drivers/media/usb/au0828/Kconfig | 6 +- drivers/media/usb/cpia2/Kconfig | 2 +- drivers/media/usb/cx231xx/Kconfig | 8 +- drivers/media/usb/em28xx/Kconfig | 8 +- drivers/media/usb/go7007/Kconfig | 8 +- drivers/media/usb/gspca/Kconfig | 2 +- drivers/media/usb/hackrf/Kconfig | 2 +- drivers/media/usb/hdpvr/Kconfig | 2 +- drivers/media/usb/pulse8-cec/Kconfig | 2 +- drivers/media/usb/pvrusb2/Kconfig | 8 +- drivers/media/usb/pwc/Kconfig | 4 +- drivers/media/usb/rainshadow-cec/Kconfig | 2 +- drivers/media/usb/siano/Kconfig | 2 +- drivers/media/usb/stk1160/Kconfig | 2 +- drivers/media/usb/stkwebcam/Kconfig | 2 +- drivers/media/usb/tm6000/Kconfig | 4 +- drivers/media/usb/usbtv/Kconfig | 2 +- drivers/media/usb/usbvision/Kconfig | 2 +- drivers/media/usb/uvc/Kconfig | 4 +- drivers/media/usb/zr364xx/Kconfig | 2 +- drivers/media/v4l2-core/Kconfig | 8 +- drivers/staging/media/Kconfig | 2 +- drivers/staging/media/bcm2048/Kconfig | 2 +- drivers/staging/media/imx/Kconfig | 4 +- drivers/staging/media/ipu3/Kconfig | 2 +- drivers/staging/media/omap4iss/Kconfig | 2 +- 70 files changed, 320 insertions(+), 320 deletions(-) diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 102eb35fcf3f..8efaf99243e0 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -31,14 +31,14 @@ comment "Multimedia core support" # config MEDIA_CAMERA_SUPPORT bool "Cameras/video grabbers support" - ---help--- + help Enable support for webcams and video grabbers. Say Y when you have a webcam or a video capture grabber board. config MEDIA_ANALOG_TV_SUPPORT bool "Analog TV support" - ---help--- + help Enable analog TV support. Say Y when you have a TV board with analog support or with a @@ -50,7 +50,7 @@ config MEDIA_ANALOG_TV_SUPPORT config MEDIA_DIGITAL_TV_SUPPORT bool "Digital TV support" - ---help--- + help Enable digital TV support. Say Y when you have a board with digital support or a board with @@ -58,7 +58,7 @@ config MEDIA_DIGITAL_TV_SUPPORT config MEDIA_RADIO_SUPPORT bool "AM/FM radio receivers/transmitters support" - ---help--- + help Enable AM/FM radio support. Additional info and docs are available on the web at @@ -72,14 +72,14 @@ config MEDIA_RADIO_SUPPORT config MEDIA_SDR_SUPPORT bool "Software defined radio support" - ---help--- + help Enable software defined radio support. Say Y when you have a software defined radio device. config MEDIA_CEC_SUPPORT bool "HDMI CEC support" - ---help--- + help Enable support for HDMI CEC (Consumer Electronics Control), which is an optional HDMI feature. @@ -96,7 +96,7 @@ source "drivers/media/cec/Kconfig" config MEDIA_CONTROLLER bool "Media Controller API" depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT - ---help--- + help Enable the media controller API used to query media devices internal topology and configure it dynamically. @@ -105,7 +105,7 @@ config MEDIA_CONTROLLER config MEDIA_CONTROLLER_DVB bool "Enable Media controller for DVB (EXPERIMENTAL)" depends on MEDIA_CONTROLLER && DVB_CORE - ---help--- + help Enable the media controller API support for DVB. This is currently experimental. @@ -114,7 +114,7 @@ config MEDIA_CONTROLLER_REQUEST_API bool "Enable Media controller Request API (EXPERIMENTAL)" depends on MEDIA_CONTROLLER && STAGING_MEDIA default n - ---help--- + help DO NOT ENABLE THIS OPTION UNLESS YOU KNOW WHAT YOU'RE DOING. This option enables the Request API for the Media controller and V4L2 @@ -137,7 +137,7 @@ config VIDEO_DEV config VIDEO_V4L2_SUBDEV_API bool "V4L2 sub-device userspace API" depends on VIDEO_DEV && MEDIA_CONTROLLER - ---help--- + help Enables the V4L2 sub-device pad-level userspace API used to configure video format, size and frame rate between hardware blocks. diff --git a/drivers/media/cec/Kconfig b/drivers/media/cec/Kconfig index 9c2b108c613a..b5aadacf335a 100644 --- a/drivers/media/cec/Kconfig +++ b/drivers/media/cec/Kconfig @@ -2,11 +2,11 @@ config MEDIA_CEC_RC bool "HDMI CEC RC integration" depends on CEC_CORE && RC_CORE depends on CEC_CORE=m || RC_CORE=y - ---help--- + help Pass on CEC remote control messages to the RC framework. config CEC_PIN_ERROR_INJ bool "Enable CEC error injection support" depends on CEC_PIN && DEBUG_FS - ---help--- + help This option enables CEC error injection using debugfs. diff --git a/drivers/media/common/siano/Kconfig b/drivers/media/common/siano/Kconfig index 4bfbd5f463d1..577880b133eb 100644 --- a/drivers/media/common/siano/Kconfig +++ b/drivers/media/common/siano/Kconfig @@ -15,7 +15,7 @@ config SMS_SIANO_RC depends on SMS_USB_DRV || SMS_SDIO_DRV depends on MEDIA_COMMON_OPTIONS default y - ---help--- + help Choose Y to select Remote Controller support for Siano driver. config SMS_SIANO_DEBUGFS @@ -24,7 +24,7 @@ config SMS_SIANO_DEBUGFS depends on DEBUG_FS depends on SMS_USB_DRV = SMS_SDIO_DRV - ---help--- + help Choose Y to enable visualizing a dump of the frontend statistics response packets via debugfs. Currently, works only with Siano USB devices. diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 1ef6335463c1..1a1746b3db91 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -8,7 +8,7 @@ config VIDEO_IR_I2C tristate "I2C module for IR" if !MEDIA_SUBDRV_AUTOSELECT depends on I2C && RC_CORE default y - ---help--- + help Most boards have an IR chip directly connected via GPIO. However, some video boards have the IR connected via I2C bus. @@ -29,7 +29,7 @@ comment "Audio decoders, processors and mixers" config VIDEO_TVAUDIO tristate "Simple audio decoder chips" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for several audio decoder chips found on some bt8xx boards: Philips: tda9840, tda9873h, tda9874h/a, tda9850, tda985x, tea6300, tea6320, tea6420, tda8425, ta8874z. @@ -41,7 +41,7 @@ config VIDEO_TVAUDIO config VIDEO_TDA7432 tristate "Philips TDA7432 audio processor" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for tda7432 audio decoder chip found on some bt8xx boards. To compile this driver as a module, choose M here: the @@ -50,7 +50,7 @@ config VIDEO_TDA7432 config VIDEO_TDA9840 tristate "Philips TDA9840 audio processor" depends on I2C - ---help--- + help Support for tda9840 audio decoder chip found on some Zoran boards. To compile this driver as a module, choose M here: the @@ -62,7 +62,7 @@ config VIDEO_TDA1997X depends on SND_SOC select SND_PCM select HDMI - ---help--- + help V4L2 subdevice driver for the NXP TDA1997x HDMI receivers. To compile this driver as a module, choose M here: the @@ -71,7 +71,7 @@ config VIDEO_TDA1997X config VIDEO_TEA6415C tristate "Philips TEA6415C audio processor" depends on I2C - ---help--- + help Support for tea6415c audio decoder chip found on some bt8xx boards. To compile this driver as a module, choose M here: the @@ -80,7 +80,7 @@ config VIDEO_TEA6415C config VIDEO_TEA6420 tristate "Philips TEA6420 audio processor" depends on I2C - ---help--- + help Support for tea6420 audio decoder chip found on some bt8xx boards. To compile this driver as a module, choose M here: the @@ -89,7 +89,7 @@ config VIDEO_TEA6420 config VIDEO_MSP3400 tristate "Micronas MSP34xx audio decoders" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Micronas MSP34xx series of audio decoders. To compile this driver as a module, choose M here: the @@ -98,7 +98,7 @@ config VIDEO_MSP3400 config VIDEO_CS3308 tristate "Cirrus Logic CS3308 audio ADC" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Cirrus Logic CS3308 High Performance 8-Channel Analog Volume Control @@ -108,7 +108,7 @@ config VIDEO_CS3308 config VIDEO_CS5345 tristate "Cirrus Logic CS5345 audio ADC" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Cirrus Logic CS5345 24-bit, 192 kHz stereo A/D converter. @@ -118,7 +118,7 @@ config VIDEO_CS5345 config VIDEO_CS53L32A tristate "Cirrus Logic CS53L32A audio ADC" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Cirrus Logic CS53L32A low voltage stereo A/D converter. @@ -128,7 +128,7 @@ config VIDEO_CS53L32A config VIDEO_TLV320AIC23B tristate "Texas Instruments TLV320AIC23B audio codec" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Texas Instruments TLV320AIC23B audio codec. To compile this driver as a module, choose M here: the @@ -137,7 +137,7 @@ config VIDEO_TLV320AIC23B config VIDEO_UDA1342 tristate "Philips UDA1342 audio codec" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Philips UDA1342 audio codec. To compile this driver as a module, choose M here: the @@ -146,7 +146,7 @@ config VIDEO_UDA1342 config VIDEO_WM8775 tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Wolfson Microelectronics WM8775 high performance stereo A/D Converter with a 4 channel input mixer. @@ -156,7 +156,7 @@ config VIDEO_WM8775 config VIDEO_WM8739 tristate "Wolfson Microelectronics WM8739 stereo audio ADC" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Wolfson Microelectronics WM8739 stereo A/D Converter. @@ -166,7 +166,7 @@ config VIDEO_WM8739 config VIDEO_VP27SMPX tristate "Panasonic VP27's internal MPX" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the internal MPX of the Panasonic VP27s tuner. To compile this driver as a module, choose M here: the @@ -200,7 +200,7 @@ comment "Video decoders" config VIDEO_ADV7180 tristate "Analog Devices ADV7180 decoder" depends on GPIOLIB && VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API - ---help--- + help Support for the Analog Devices ADV7180 video decoder. To compile this driver as a module, choose M here: the @@ -209,7 +209,7 @@ config VIDEO_ADV7180 config VIDEO_ADV7183 tristate "Analog Devices ADV7183 decoder" depends on VIDEO_V4L2 && I2C - ---help--- + help V4l2 subdevice driver for the Analog Devices ADV7183 video decoder. @@ -222,7 +222,7 @@ config VIDEO_ADV748X depends on OF select REGMAP_I2C select V4L2_FWNODE - ---help--- + help V4L2 subdevice driver for the Analog Devices ADV7481 and ADV7482 HDMI/Analog video decoders. @@ -235,7 +235,7 @@ config VIDEO_ADV7604 depends on GPIOLIB || COMPILE_TEST select HDMI select V4L2_FWNODE - ---help--- + help Support for the Analog Devices ADV7604 video decoder. This is a Analog Devices Component/Graphics Digitizer @@ -248,7 +248,7 @@ config VIDEO_ADV7604_CEC bool "Enable Analog Devices ADV7604 CEC support" depends on VIDEO_ADV7604 select CEC_CORE - ---help--- + help When selected the adv7604 will support the optional HDMI CEC feature. @@ -256,7 +256,7 @@ config VIDEO_ADV7842 tristate "Analog Devices ADV7842 decoder" depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API select HDMI - ---help--- + help Support for the Analog Devices ADV7842 video decoder. This is a Analog Devices Component/Graphics/SD Digitizer @@ -269,14 +269,14 @@ config VIDEO_ADV7842_CEC bool "Enable Analog Devices ADV7842 CEC support" depends on VIDEO_ADV7842 select CEC_CORE - ---help--- + help When selected the adv7842 will support the optional HDMI CEC feature. config VIDEO_BT819 tristate "BT819A VideoStream decoder" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for BT819A video decoder. To compile this driver as a module, choose M here: the @@ -285,7 +285,7 @@ config VIDEO_BT819 config VIDEO_BT856 tristate "BT856 VideoStream decoder" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for BT856 video decoder. To compile this driver as a module, choose M here: the @@ -294,7 +294,7 @@ config VIDEO_BT856 config VIDEO_BT866 tristate "BT866 VideoStream decoder" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for BT866 video decoder. To compile this driver as a module, choose M here: the @@ -303,7 +303,7 @@ config VIDEO_BT866 config VIDEO_KS0127 tristate "KS0127 video decoder" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for KS0127 video decoder. This chip is used on AverMedia AVS6EYES Zoran-based MJPEG @@ -315,7 +315,7 @@ config VIDEO_KS0127 config VIDEO_ML86V7667 tristate "OKI ML86V7667 video decoder" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the OKI Semiconductor ML86V7667 video decoder. To compile this driver as a module, choose M here: the @@ -324,7 +324,7 @@ config VIDEO_ML86V7667 config VIDEO_SAA7110 tristate "Philips SAA7110 video decoder" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Philips SAA7110 video decoders. To compile this driver as a module, choose M here: the @@ -333,7 +333,7 @@ config VIDEO_SAA7110 config VIDEO_SAA711X tristate "Philips SAA7111/3/4/5 video decoders" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Philips SAA7111/3/4/5 video decoders. To compile this driver as a module, choose M here: the @@ -344,7 +344,7 @@ config VIDEO_TC358743 depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API select HDMI select V4L2_FWNODE - ---help--- + help Support for the Toshiba TC358743 HDMI to MIPI CSI-2 bridge. To compile this driver as a module, choose M here: the @@ -354,7 +354,7 @@ config VIDEO_TC358743_CEC bool "Enable Toshiba TC358743 CEC support" depends on VIDEO_TC358743 select CEC_CORE - ---help--- + help When selected the tc358743 will support the optional HDMI CEC feature. @@ -362,7 +362,7 @@ config VIDEO_TVP514X tristate "Texas Instruments TVP514x video decoder" depends on VIDEO_V4L2 && I2C select V4L2_FWNODE - ---help--- + help This is a Video4Linux2 sensor driver for the TI TVP5146/47 decoder. It is currently working with the TI OMAP3 camera controller. @@ -374,7 +374,7 @@ config VIDEO_TVP5150 tristate "Texas Instruments TVP5150 video decoder" depends on VIDEO_V4L2 && I2C select V4L2_FWNODE - ---help--- + help Support for the Texas Instruments TVP5150 video decoder. To compile this driver as a module, choose M here: the @@ -384,7 +384,7 @@ config VIDEO_TVP7002 tristate "Texas Instruments TVP7002 video decoder" depends on VIDEO_V4L2 && I2C select V4L2_FWNODE - ---help--- + help Support for the Texas Instruments TVP7002 video decoder. To compile this driver as a module, choose M here: the @@ -393,7 +393,7 @@ config VIDEO_TVP7002 config VIDEO_TW2804 tristate "Techwell TW2804 multiple video decoder" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Techwell tw2804 multiple video decoder. To compile this driver as a module, choose M here: the @@ -402,7 +402,7 @@ config VIDEO_TW2804 config VIDEO_TW9903 tristate "Techwell TW9903 video decoder" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Techwell tw9903 multi-standard video decoder with high quality down scaler. @@ -412,7 +412,7 @@ config VIDEO_TW9903 config VIDEO_TW9906 tristate "Techwell TW9906 video decoder" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Techwell tw9906 enhanced multi-standard comb filter video decoder with YCbCr input support. @@ -422,7 +422,7 @@ config VIDEO_TW9906 config VIDEO_TW9910 tristate "Techwell TW9910 video decoder" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for Techwell TW9910 NTSC/PAL/SECAM video decoder. To compile this driver as a module, choose M here: the @@ -431,7 +431,7 @@ config VIDEO_TW9910 config VIDEO_VPX3220 tristate "vpx3220a, vpx3216b & vpx3214c video decoders" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for VPX322x video decoders. To compile this driver as a module, choose M here: the @@ -442,7 +442,7 @@ comment "Video and audio decoders" config VIDEO_SAA717X tristate "Philips SAA7171/3/4 audio/video decoders" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Philips SAA7171/3/4 audio/video decoders. To compile this driver as a module, choose M here: the @@ -455,7 +455,7 @@ comment "Video encoders" config VIDEO_SAA7127 tristate "Philips SAA7127/9 digital video encoders" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Philips SAA7127/9 digital video encoders. To compile this driver as a module, choose M here: the @@ -464,7 +464,7 @@ config VIDEO_SAA7127 config VIDEO_SAA7185 tristate "Philips SAA7185 video encoder" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Philips SAA7185 video encoder. To compile this driver as a module, choose M here: the @@ -473,7 +473,7 @@ config VIDEO_SAA7185 config VIDEO_ADV7170 tristate "Analog Devices ADV7170 video encoder" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Analog Devices ADV7170 video encoder driver To compile this driver as a module, choose M here: the @@ -482,7 +482,7 @@ config VIDEO_ADV7170 config VIDEO_ADV7175 tristate "Analog Devices ADV7175 video encoder" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Analog Devices ADV7175 video encoder driver To compile this driver as a module, choose M here: the @@ -510,7 +510,7 @@ config VIDEO_ADV7511 tristate "Analog Devices ADV7511 encoder" depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API select HDMI - ---help--- + help Support for the Analog Devices ADV7511 video encoder. This is a Analog Devices HDMI transmitter. @@ -522,14 +522,14 @@ config VIDEO_ADV7511_CEC bool "Enable Analog Devices ADV7511 CEC support" depends on VIDEO_ADV7511 select CEC_CORE - ---help--- + help When selected the adv7511 will support the optional HDMI CEC feature. config VIDEO_AD9389B tristate "Analog Devices AD9389B encoder" depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API - ---help--- + help Support for the Analog Devices AD9389B video encoder. This is a Analog Devices HDMI transmitter. @@ -546,7 +546,7 @@ config VIDEO_AK881X config VIDEO_THS8200 tristate "Texas Instruments THS8200 video encoder" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Texas Instruments THS8200 video encoder. To compile this driver as a module, choose M here: the @@ -576,7 +576,7 @@ config VIDEO_IMX258 tristate "Sony IMX258 sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on MEDIA_CAMERA_SUPPORT - ---help--- + help This is a Video4Linux2 sensor driver for the Sony IMX258 camera. @@ -588,7 +588,7 @@ config VIDEO_IMX274 depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on MEDIA_CAMERA_SUPPORT select REGMAP_I2C - ---help--- + help This is a V4L2 sensor driver for the Sony IMX274 CMOS image sensor. @@ -630,7 +630,7 @@ config VIDEO_OV2659 depends on VIDEO_V4L2 && I2C depends on MEDIA_CAMERA_SUPPORT select V4L2_FWNODE - ---help--- + help This is a Video4Linux2 sensor driver for the OmniVision OV2659 camera. @@ -642,7 +642,7 @@ config VIDEO_OV2680 depends on VIDEO_V4L2 && I2C && MEDIA_CONTROLLER depends on MEDIA_CAMERA_SUPPORT select V4L2_FWNODE - ---help--- + help This is a Video4Linux2 sensor driver for the OmniVision OV2680 camera. @@ -654,7 +654,7 @@ config VIDEO_OV2685 depends on VIDEO_V4L2 && I2C && MEDIA_CONTROLLER depends on MEDIA_CAMERA_SUPPORT select V4L2_FWNODE - ---help--- + help This is a Video4Linux2 sensor driver for the OmniVision OV2685 camera. @@ -667,7 +667,7 @@ config VIDEO_OV5640 depends on GPIOLIB && VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API depends on MEDIA_CAMERA_SUPPORT select V4L2_FWNODE - ---help--- + help This is a Video4Linux2 sensor driver for the Omnivision OV5640 camera sensor with a MIPI CSI-2 interface. @@ -677,7 +677,7 @@ config VIDEO_OV5645 depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on MEDIA_CAMERA_SUPPORT select V4L2_FWNODE - ---help--- + help This is a Video4Linux2 sensor driver for the OmniVision OV5645 camera. @@ -689,7 +689,7 @@ config VIDEO_OV5647 depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on MEDIA_CAMERA_SUPPORT select V4L2_FWNODE - ---help--- + help This is a Video4Linux2 sensor driver for the OmniVision OV5647 camera. @@ -700,7 +700,7 @@ config VIDEO_OV6650 tristate "OmniVision OV6650 sensor support" depends on I2C && VIDEO_V4L2 depends on MEDIA_CAMERA_SUPPORT - ---help--- + help This is a Video4Linux2 sensor driver for the OmniVision OV6650 camera. @@ -713,7 +713,7 @@ config VIDEO_OV5670 depends on MEDIA_CAMERA_SUPPORT depends on MEDIA_CONTROLLER select V4L2_FWNODE - ---help--- + help This is a Video4Linux2 sensor driver for the OmniVision OV5670 camera. @@ -724,7 +724,7 @@ config VIDEO_OV5695 tristate "OmniVision OV5695 sensor support" depends on I2C && VIDEO_V4L2 depends on MEDIA_CAMERA_SUPPORT - ---help--- + help This is a Video4Linux2 sensor driver for the OmniVision OV5695 camera. @@ -748,7 +748,7 @@ config VIDEO_OV772X depends on I2C && VIDEO_V4L2 depends on MEDIA_CAMERA_SUPPORT select REGMAP_SCCB - ---help--- + help This is a Video4Linux2 sensor driver for the OmniVision OV772x camera. @@ -759,7 +759,7 @@ config VIDEO_OV7640 tristate "OmniVision OV7640 sensor support" depends on I2C && VIDEO_V4L2 depends on MEDIA_CAMERA_SUPPORT - ---help--- + help This is a Video4Linux2 sensor driver for the OmniVision OV7640 camera. @@ -771,7 +771,7 @@ config VIDEO_OV7670 depends on I2C && VIDEO_V4L2 depends on MEDIA_CAMERA_SUPPORT select V4L2_FWNODE - ---help--- + help This is a Video4Linux2 sensor driver for the OmniVision OV7670 VGA camera. It currently only works with the M88ALP01 controller. @@ -780,7 +780,7 @@ config VIDEO_OV7740 tristate "OmniVision OV7740 sensor support" depends on I2C && VIDEO_V4L2 depends on MEDIA_CAMERA_SUPPORT - ---help--- + help This is a Video4Linux2 sensor driver for the OmniVision OV7740 VGA camera sensor. @@ -807,7 +807,7 @@ config VIDEO_OV9650 tristate "OmniVision OV9650/OV9652 sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API select REGMAP_SCCB - ---help--- + help This is a V4L2 sensor driver for the Omnivision OV9650 and OV9652 camera sensors. @@ -816,7 +816,7 @@ config VIDEO_OV13858 depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on MEDIA_CAMERA_SUPPORT select V4L2_FWNODE - ---help--- + help This is a Video4Linux2 sensor driver for the OmniVision OV13858 camera. @@ -824,7 +824,7 @@ config VIDEO_VS6624 tristate "ST VS6624 sensor support" depends on VIDEO_V4L2 && I2C depends on MEDIA_CAMERA_SUPPORT - ---help--- + help This is a Video4Linux2 sensor driver for the ST VS6624 camera. @@ -844,7 +844,7 @@ config VIDEO_MT9M032 depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on MEDIA_CAMERA_SUPPORT select VIDEO_APTINA_PLL - ---help--- + help This driver supports MT9M032 camera sensors from Aptina, monochrome models only. @@ -861,7 +861,7 @@ config VIDEO_MT9P031 depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on MEDIA_CAMERA_SUPPORT select VIDEO_APTINA_PLL - ---help--- + help This is a Video4Linux2 sensor driver for the Aptina (Micron) mt9p031 5 Mpixel camera. @@ -869,7 +869,7 @@ config VIDEO_MT9T001 tristate "Aptina MT9T001 support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on MEDIA_CAMERA_SUPPORT - ---help--- + help This is a Video4Linux2 sensor driver for the Aptina (Micron) mt0t001 3 Mpixel camera. @@ -877,7 +877,7 @@ config VIDEO_MT9T112 tristate "Aptina MT9T111/MT9T112 support" depends on I2C && VIDEO_V4L2 depends on MEDIA_CAMERA_SUPPORT - ---help--- + help This is a Video4Linux2 sensor driver for the Aptina (Micron) MT9T111 and MT9T112 3 Mpixel camera. @@ -888,7 +888,7 @@ config VIDEO_MT9V011 tristate "Micron mt9v011 sensor support" depends on I2C && VIDEO_V4L2 depends on MEDIA_CAMERA_SUPPORT - ---help--- + help This is a Video4Linux2 sensor driver for the Micron mt0v011 1.3 Mpixel camera. It currently only works with the em28xx driver. @@ -899,7 +899,7 @@ config VIDEO_MT9V032 depends on MEDIA_CAMERA_SUPPORT select REGMAP_I2C select V4L2_FWNODE - ---help--- + help This is a Video4Linux2 sensor driver for the Micron MT9V032 752x480 CMOS sensor. @@ -918,14 +918,14 @@ config VIDEO_SR030PC30 tristate "Siliconfile SR030PC30 sensor support" depends on I2C && VIDEO_V4L2 depends on MEDIA_CAMERA_SUPPORT - ---help--- + help This driver supports SR030PC30 VGA camera from Siliconfile config VIDEO_NOON010PC30 tristate "Siliconfile NOON010PC30 sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on MEDIA_CAMERA_SUPPORT - ---help--- + help This driver supports NOON010PC30 CIF camera from Siliconfile source "drivers/media/i2c/m5mols/Kconfig" @@ -945,7 +945,7 @@ config VIDEO_S5K6AA tristate "Samsung S5K6AAFX sensor support" depends on MEDIA_CAMERA_SUPPORT depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API - ---help--- + help This is a V4L2 sensor driver for Samsung S5K6AA(FX) 1.3M camera sensor with an embedded SoC image signal processor. @@ -953,7 +953,7 @@ config VIDEO_S5K6A3 tristate "Samsung S5K6A3 sensor support" depends on MEDIA_CAMERA_SUPPORT depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API - ---help--- + help This is a V4L2 sensor driver for Samsung S5K6A3 raw camera sensor. @@ -961,7 +961,7 @@ config VIDEO_S5K4ECGX tristate "Samsung S5K4ECGX sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API select CRC32 - ---help--- + help This is a V4L2 sensor driver for Samsung S5K4ECGX 5M camera sensor with an embedded SoC image signal processor. @@ -969,7 +969,7 @@ config VIDEO_S5K5BAF tristate "Samsung S5K5BAF sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API select V4L2_FWNODE - ---help--- + help This is a V4L2 sensor driver for Samsung S5K5BAF 2M camera sensor with an embedded SoC image signal processor. @@ -980,7 +980,7 @@ config VIDEO_S5C73M3 tristate "Samsung S5C73M3 sensor support" depends on I2C && SPI && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API select V4L2_FWNODE - ---help--- + help This is a V4L2 sensor driver for Samsung S5C73M3 8 Mpixel camera. @@ -989,7 +989,7 @@ comment "Lens drivers" config VIDEO_AD5820 tristate "AD5820 lens voice coil support" depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER - ---help--- + help This is a driver for the AD5820 camera lens voice coil. It is used for example in Nokia N900 (RX-51). @@ -1007,7 +1007,7 @@ config VIDEO_DW9714 tristate "DW9714 lens voice coil support" depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER depends on VIDEO_V4L2_SUBDEV_API - ---help--- + help This is a driver for the DW9714 camera lens voice coil. DW9714 is a 10 bit DAC with 120mA output current sink capability. This is designed for linear control of @@ -1017,7 +1017,7 @@ config VIDEO_DW9807_VCM tristate "DW9807 lens voice coil support" depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER depends on VIDEO_V4L2_SUBDEV_API - ---help--- + help This is a driver for the DW9807 camera lens voice coil. DW9807 is a 10 bit DAC with 100mA output current sink capability. This is designed for linear control of @@ -1029,7 +1029,7 @@ config VIDEO_ADP1653 tristate "ADP1653 flash support" depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER depends on MEDIA_CAMERA_SUPPORT - ---help--- + help This is a driver for the ADP1653 flash controller. It is used for example in Nokia N900. @@ -1038,7 +1038,7 @@ config VIDEO_LM3560 depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER depends on MEDIA_CAMERA_SUPPORT select REGMAP_I2C - ---help--- + help This is a driver for the lm3560 dual flash controllers. It controls flash, torch LEDs. @@ -1047,7 +1047,7 @@ config VIDEO_LM3646 depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER depends on MEDIA_CAMERA_SUPPORT select REGMAP_I2C - ---help--- + help This is a driver for the lm3646 dual flash controllers. It controls flash, torch LEDs. @@ -1056,7 +1056,7 @@ comment "Video improvement chips" config VIDEO_UPD64031A tristate "NEC Electronics uPD64031A Ghost Reduction" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the NEC Electronics uPD64031A Ghost Reduction video chip. It is most often found in NTSC TV cards made for Japan and is used to reduce the 'ghosting' effect that can @@ -1068,7 +1068,7 @@ config VIDEO_UPD64031A config VIDEO_UPD64083 tristate "NEC Electronics uPD64083 3-Dimensional Y/C separation" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the NEC Electronics uPD64083 3-Dimensional Y/C separation video chip. It is used to improve the quality of the colors of a composite signal. @@ -1082,7 +1082,7 @@ config VIDEO_SAA6752HS tristate "Philips SAA6752HS MPEG-2 Audio/Video Encoder" depends on VIDEO_V4L2 && I2C select CRC32 - ---help--- + help Support for the Philips SAA6752HS MPEG-2 video and MPEG-audio/AC-3 audio encoder with multiplexer. @@ -1094,7 +1094,7 @@ comment "SDR tuner chips" config SDR_MAX2175 tristate "Maxim 2175 RF to Bits tuner" depends on VIDEO_V4L2 && MEDIA_SDR_SUPPORT && I2C - ---help--- + help Support for Maxim 2175 tuner. It is an advanced analog/digital radio receiver with RF-to-Bits front-end designed for SDR solutions. @@ -1115,7 +1115,7 @@ config VIDEO_THS7303 config VIDEO_M52790 tristate "Mitsubishi M52790 A/V switch" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Mitsubishi M52790 A/V switch. To compile this driver as a module, choose M here: the @@ -1126,7 +1126,7 @@ config VIDEO_I2C depends on VIDEO_V4L2 && I2C select VIDEOBUF2_VMALLOC imply HWMON - ---help--- + help Enable the I2C transport video support which supports the following: * Panasonic AMG88xx Grid-Eye Sensors diff --git a/drivers/media/i2c/cx25840/Kconfig b/drivers/media/i2c/cx25840/Kconfig index 451133ad41ff..f4b31d7cb440 100644 --- a/drivers/media/i2c/cx25840/Kconfig +++ b/drivers/media/i2c/cx25840/Kconfig @@ -1,7 +1,7 @@ config VIDEO_CX25840 tristate "Conexant CX2584x audio/video decoders" depends on VIDEO_V4L2 && I2C - ---help--- + help Support for the Conexant CX2584x audio/video decoders. To compile this driver as a module, choose M here: the diff --git a/drivers/media/i2c/et8ek8/Kconfig b/drivers/media/i2c/et8ek8/Kconfig index 9fe409e95666..ab23b41bf353 100644 --- a/drivers/media/i2c/et8ek8/Kconfig +++ b/drivers/media/i2c/et8ek8/Kconfig @@ -2,6 +2,6 @@ config VIDEO_ET8EK8 tristate "ET8EK8 camera sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API select V4L2_FWNODE - ---help--- + help This is a driver for the Toshiba ET8EK8 5 MP camera sensor. It is used for example in Nokia N900 (RX-51). diff --git a/drivers/media/i2c/m5mols/Kconfig b/drivers/media/i2c/m5mols/Kconfig index dc8c2505907e..be0bb3f1bc22 100644 --- a/drivers/media/i2c/m5mols/Kconfig +++ b/drivers/media/i2c/m5mols/Kconfig @@ -2,5 +2,5 @@ config VIDEO_M5MOLS tristate "Fujitsu M-5MOLS 8MP sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on MEDIA_CAMERA_SUPPORT - ---help--- + help This driver supports Fujitsu M-5MOLS camera sensor with ISP diff --git a/drivers/media/i2c/smiapp/Kconfig b/drivers/media/i2c/smiapp/Kconfig index f59718d8e51e..26b54f2aa95b 100644 --- a/drivers/media/i2c/smiapp/Kconfig +++ b/drivers/media/i2c/smiapp/Kconfig @@ -4,5 +4,5 @@ config VIDEO_SMIAPP depends on MEDIA_CAMERA_SUPPORT select VIDEO_SMIAPP_PLL select V4L2_FWNODE - ---help--- + help This is a generic driver for SMIA++/SMIA camera modules. diff --git a/drivers/media/mmc/siano/Kconfig b/drivers/media/mmc/siano/Kconfig index 7693487e2f63..3941ee8352bb 100644 --- a/drivers/media/mmc/siano/Kconfig +++ b/drivers/media/mmc/siano/Kconfig @@ -9,5 +9,5 @@ config SMS_SDIO_DRV depends on !RC_CORE || RC_CORE select MEDIA_COMMON_OPTIONS select SMS_SIANO_MDTV - ---help--- + help Choose if you would like to have Siano's support for SDIO interface diff --git a/drivers/media/pci/bt8xx/Kconfig b/drivers/media/pci/bt8xx/Kconfig index bc89e37608cd..0f46db7d5ffc 100644 --- a/drivers/media/pci/bt8xx/Kconfig +++ b/drivers/media/pci/bt8xx/Kconfig @@ -13,7 +13,7 @@ config VIDEO_BT848 select VIDEO_SAA6588 if MEDIA_SUBDRV_AUTOSELECT select RADIO_ADAPTERS select RADIO_TEA575X - ---help--- + help Support for BT848 based frame grabber/overlay boards. This includes the Miro, Hauppauge and STB boards. Please read the material in for more information. diff --git a/drivers/media/pci/cobalt/Kconfig b/drivers/media/pci/cobalt/Kconfig index aa35cbc0a904..9a544bab3178 100644 --- a/drivers/media/pci/cobalt/Kconfig +++ b/drivers/media/pci/cobalt/Kconfig @@ -11,7 +11,7 @@ config VIDEO_COBALT select VIDEO_ADV7511 select VIDEO_ADV7842 select VIDEOBUF2_DMA_SG - ---help--- + help This is a video4linux driver for the Cisco PCIe Cobalt card. This board is sadly not available outside of Cisco, but it is diff --git a/drivers/media/pci/cx18/Kconfig b/drivers/media/pci/cx18/Kconfig index c675b83c43a9..96477bba0d5c 100644 --- a/drivers/media/pci/cx18/Kconfig +++ b/drivers/media/pci/cx18/Kconfig @@ -13,7 +13,7 @@ config VIDEO_CX18 select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT - ---help--- + help This is a video4linux driver for Conexant cx23418 based PCI combo video recorder devices. @@ -27,7 +27,7 @@ config VIDEO_CX18_ALSA tristate "Conexant 23418 DMA audio support" depends on VIDEO_CX18 && SND select SND_PCM - ---help--- + help This is a video4linux driver for direct (DMA) audio on Conexant 23418 based TV cards using ALSA. diff --git a/drivers/media/pci/cx23885/Kconfig b/drivers/media/pci/cx23885/Kconfig index 3435bbaa3167..1bba9e497915 100644 --- a/drivers/media/pci/cx23885/Kconfig +++ b/drivers/media/pci/cx23885/Kconfig @@ -43,7 +43,7 @@ config VIDEO_CX23885 select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_M88RS6000T if MEDIA_SUBDRV_AUTOSELECT select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT - ---help--- + help This is a video4linux driver for Conexant 23885 based TV cards. @@ -54,7 +54,7 @@ config MEDIA_ALTERA_CI tristate "Altera FPGA based CI module" depends on VIDEO_CX23885 && DVB_CORE select ALTERA_STAPL - ---help--- + help An Altera FPGA CI module for NetUP Dual DVB-T/C RF CI card. To compile this driver as a module, choose M here: the diff --git a/drivers/media/pci/cx25821/Kconfig b/drivers/media/pci/cx25821/Kconfig index 1755d3d2feaa..a64fa9a6d5d5 100644 --- a/drivers/media/pci/cx25821/Kconfig +++ b/drivers/media/pci/cx25821/Kconfig @@ -3,7 +3,7 @@ config VIDEO_CX25821 depends on VIDEO_DEV && PCI && I2C select I2C_ALGOBIT select VIDEOBUF2_DMA_SG - ---help--- + help This is a video4linux driver for Conexant 25821 based TV cards. @@ -14,7 +14,7 @@ config VIDEO_CX25821_ALSA tristate "Conexant 25821 DMA audio support" depends on VIDEO_CX25821 && SND select SND_PCM - ---help--- + help This is a video4linux driver for direct (DMA) audio on Conexant 25821 based capture cards using ALSA. diff --git a/drivers/media/pci/cx88/Kconfig b/drivers/media/pci/cx88/Kconfig index 14b813d634a8..fbb17ddb6bc3 100644 --- a/drivers/media/pci/cx88/Kconfig +++ b/drivers/media/pci/cx88/Kconfig @@ -6,7 +6,7 @@ config VIDEO_CX88 select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_WM8775 if MEDIA_SUBDRV_AUTOSELECT - ---help--- + help This is a video4linux driver for Conexant 2388x based TV cards. @@ -17,7 +17,7 @@ config VIDEO_CX88_ALSA tristate "Conexant 2388x DMA audio support" depends on VIDEO_CX88 && SND select SND_PCM - ---help--- + help This is a video4linux driver for direct (DMA) audio on Conexant 2388x based TV cards using ALSA. @@ -33,7 +33,7 @@ config VIDEO_CX88_BLACKBIRD tristate "Blackbird MPEG encoder support (cx2388x + cx23416)" depends on VIDEO_CX88 select VIDEO_CX2341X - ---help--- + help This adds support for MPEG encoder cards based on the Blackbird reference design, using the Conexant 2388x and 23416 chips. @@ -64,7 +64,7 @@ config VIDEO_CX88_DVB select DVB_DS3000 if MEDIA_SUBDRV_AUTOSELECT select DVB_TS2020 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT - ---help--- + help This adds support for DVB/ATSC cards based on the Conexant 2388x chip. @@ -75,7 +75,7 @@ config VIDEO_CX88_ENABLE_VP3054 bool "VP-3054 Secondary I2C Bus Support" default y depends on VIDEO_CX88_DVB && DVB_MT352 - ---help--- + help This adds DVB-T support for cards based on the Conexant 2388x chip and the MT352 demodulator, which also require support for the VP-3054 diff --git a/drivers/media/pci/ddbridge/Kconfig b/drivers/media/pci/ddbridge/Kconfig index 16faef265e97..fc98b6d575d9 100644 --- a/drivers/media/pci/ddbridge/Kconfig +++ b/drivers/media/pci/ddbridge/Kconfig @@ -15,7 +15,7 @@ config DVB_DDBRIDGE select DVB_MXL5XX if MEDIA_SUBDRV_AUTOSELECT select DVB_CXD2099 if MEDIA_SUBDRV_AUTOSELECT select DVB_DUMMY_FE if MEDIA_SUBDRV_AUTOSELECT - ---help--- + help Support for cards with the Digital Devices PCI express bridge: - Octopus PCIe Bridge - Octopus mini PCIe Bridge @@ -36,7 +36,7 @@ config DVB_DDBRIDGE_MSIENABLE depends on DVB_DDBRIDGE depends on PCI_MSI default n - ---help--- + help Use PCI MSI (Message Signaled Interrupts) per default. Enabling this might lead to I2C errors originating from the bridge in conjunction with certain SATA controllers, requiring a reload of the ddbridge diff --git a/drivers/media/pci/dt3155/Kconfig b/drivers/media/pci/dt3155/Kconfig index 858b0f2f15be..d770eec541d4 100644 --- a/drivers/media/pci/dt3155/Kconfig +++ b/drivers/media/pci/dt3155/Kconfig @@ -3,7 +3,7 @@ config VIDEO_DT3155 depends on PCI && VIDEO_DEV && VIDEO_V4L2 select VIDEOBUF2_DMA_CONTIG default n - ---help--- + help Enables dt3155 device driver for the DataTranslation DT3155 frame grabber. Say Y here if you have this hardware. In doubt, say N. diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig index 715f77651482..bd518bdc9f5f 100644 --- a/drivers/media/pci/intel/ipu3/Kconfig +++ b/drivers/media/pci/intel/ipu3/Kconfig @@ -7,7 +7,7 @@ config VIDEO_IPU3_CIO2 select V4L2_FWNODE select VIDEOBUF2_DMA_SG - ---help--- + help This is the Intel IPU3 CIO2 CSI-2 receiver unit, found in Intel Skylake and Kaby Lake SoCs and used for capturing images and video from a camera sensor. diff --git a/drivers/media/pci/ivtv/Kconfig b/drivers/media/pci/ivtv/Kconfig index 06ca4e23f9fb..e96b3c182a2f 100644 --- a/drivers/media/pci/ivtv/Kconfig +++ b/drivers/media/pci/ivtv/Kconfig @@ -18,7 +18,7 @@ config VIDEO_IVTV select VIDEO_VP27SMPX select VIDEO_UPD64031A select VIDEO_UPD64083 - ---help--- + help This is a video4linux driver for Conexant cx23416 or cx23415 based PCI personal video recorder devices. @@ -32,7 +32,7 @@ config VIDEO_IVTV_DEPRECATED_IOCTLS bool "enable the DVB ioctls abuse on ivtv driver" depends on VIDEO_IVTV default n - ---help--- + help Enable the usage of the a DVB set of ioctls that were abused by IVTV driver for a while. @@ -45,7 +45,7 @@ config VIDEO_IVTV_ALSA tristate "Conexant cx23415/cx23416 ALSA interface for PCM audio capture" depends on VIDEO_IVTV && SND select SND_PCM - ---help--- + help This driver provides an ALSA interface as another method for user applications to obtain PCM audio data from Conexant cx23415/cx23416 based PCI TV cards supported by the ivtv driver. @@ -63,7 +63,7 @@ config VIDEO_FB_IVTV select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - ---help--- + help This is a framebuffer driver for the Conexant cx23415 MPEG encoder/decoder. @@ -77,7 +77,7 @@ config VIDEO_FB_IVTV_FORCE_PAT bool "force cx23415 framebuffer init with x86 PAT enabled" depends on VIDEO_FB_IVTV && X86_PAT default n - ---help--- + help With PAT enabled, the cx23415 framebuffer driver does not utilize write-combined caching on the framebuffer memory. For this reason, the driver will by default disable itself diff --git a/drivers/media/pci/meye/Kconfig b/drivers/media/pci/meye/Kconfig index 9a50f54231ad..ce0463c81886 100644 --- a/drivers/media/pci/meye/Kconfig +++ b/drivers/media/pci/meye/Kconfig @@ -2,7 +2,7 @@ config VIDEO_MEYE tristate "Sony Vaio Picturebook Motion Eye Video For Linux" depends on PCI && VIDEO_V4L2 depends on SONY_LAPTOP || COMPILE_TEST - ---help--- + help This is the video4linux driver for the Motion Eye camera found in the Vaio Picturebook laptops. Please read the material in for more information. diff --git a/drivers/media/pci/netup_unidvb/Kconfig b/drivers/media/pci/netup_unidvb/Kconfig index b663154d0cc4..60057585f04c 100644 --- a/drivers/media/pci/netup_unidvb/Kconfig +++ b/drivers/media/pci/netup_unidvb/Kconfig @@ -8,7 +8,7 @@ config DVB_NETUP_UNIDVB select DVB_HELENE if MEDIA_SUBDRV_AUTOSELECT select DVB_LNBH25 if MEDIA_SUBDRV_AUTOSELECT select DVB_CXD2841ER if MEDIA_SUBDRV_AUTOSELECT - ---help--- + help Support for NetUP PCI express Universal DVB card. Say Y when you want to support NetUP Dual Universal DVB card. diff --git a/drivers/media/pci/ngene/Kconfig b/drivers/media/pci/ngene/Kconfig index e06d019996f3..8a80a5bab8e9 100644 --- a/drivers/media/pci/ngene/Kconfig +++ b/drivers/media/pci/ngene/Kconfig @@ -15,6 +15,6 @@ config DVB_NGENE select DVB_STV6111 if MEDIA_SUBDRV_AUTOSELECT select DVB_LNBH25 if MEDIA_SUBDRV_AUTOSELECT select DVB_CXD2099 if MEDIA_SUBDRV_AUTOSELECT - ---help--- + help Support for Micronas PCI express cards with nGene bridge. diff --git a/drivers/media/pci/saa7134/Kconfig b/drivers/media/pci/saa7134/Kconfig index b44e0d70907e..8b28783b3fcd 100644 --- a/drivers/media/pci/saa7134/Kconfig +++ b/drivers/media/pci/saa7134/Kconfig @@ -7,7 +7,7 @@ config VIDEO_SAA7134 select CRC32 select VIDEO_SAA6588 if MEDIA_SUBDRV_AUTOSELECT select VIDEO_SAA6752HS if MEDIA_SUBDRV_AUTOSELECT - ---help--- + help This is a video4linux driver for Philips SAA713x based TV cards. @@ -18,7 +18,7 @@ config VIDEO_SAA7134_ALSA tristate "Philips SAA7134 DMA audio support" depends on VIDEO_SAA7134 && SND select SND_PCM - ---help--- + help This is a video4linux driver for direct (DMA) audio in Philips SAA713x based TV cards using ALSA @@ -31,7 +31,7 @@ config VIDEO_SAA7134_RC depends on VIDEO_SAA7134 depends on !(RC_CORE=m && VIDEO_SAA7134=y) default y - ---help--- + help Enables Remote Controller support on saa7134 driver. config VIDEO_SAA7134_DVB @@ -57,7 +57,7 @@ config VIDEO_SAA7134_DVB select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT select DVB_ZL10039 if MEDIA_SUBDRV_AUTOSELECT - ---help--- + help This adds support for DVB cards based on the Philips saa7134 chip. @@ -68,6 +68,6 @@ config VIDEO_SAA7134_GO7007 tristate "go7007 support for saa7134 based TV cards" depends on VIDEO_SAA7134 depends on VIDEO_GO7007 - ---help--- + help Enables saa7134 driver support for boards with go7007 MPEG encoder (WIS Voyager or compatible). diff --git a/drivers/media/pci/saa7146/Kconfig b/drivers/media/pci/saa7146/Kconfig index da88b77a916c..60d9862580ff 100644 --- a/drivers/media/pci/saa7146/Kconfig +++ b/drivers/media/pci/saa7146/Kconfig @@ -2,7 +2,7 @@ config VIDEO_HEXIUM_GEMINI tristate "Hexium Gemini frame grabber" depends on PCI && VIDEO_V4L2 && I2C select VIDEO_SAA7146_VV - ---help--- + help This is a video4linux driver for the Hexium Gemini frame grabber card by Hexium. Please note that the Gemini Dual card is *not* fully supported. @@ -14,7 +14,7 @@ config VIDEO_HEXIUM_ORION tristate "Hexium HV-PCI6 and Orion frame grabber" depends on PCI && VIDEO_V4L2 && I2C select VIDEO_SAA7146_VV - ---help--- + help This is a video4linux driver for the Hexium HV-PCI6 and Orion frame grabber cards by Hexium. @@ -30,7 +30,7 @@ config VIDEO_MXB select VIDEO_TDA9840 if MEDIA_SUBDRV_AUTOSELECT select VIDEO_TEA6415C if MEDIA_SUBDRV_AUTOSELECT select VIDEO_TEA6420 if MEDIA_SUBDRV_AUTOSELECT - ---help--- + help This is a video4linux driver for the 'Multimedia eXtension Board' TV card by Siemens-Nixdorf. diff --git a/drivers/media/pci/saa7164/Kconfig b/drivers/media/pci/saa7164/Kconfig index 9098ef5feca4..265c5a4fd823 100644 --- a/drivers/media/pci/saa7164/Kconfig +++ b/drivers/media/pci/saa7164/Kconfig @@ -8,7 +8,7 @@ config VIDEO_SAA7164 select DVB_TDA10048 if MEDIA_SUBDRV_AUTOSELECT select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT - ---help--- + help This is a video4linux driver for NXP SAA7164 based TV cards. diff --git a/drivers/media/pci/solo6x10/Kconfig b/drivers/media/pci/solo6x10/Kconfig index d9e06a6bf1eb..2061d02a82d0 100644 --- a/drivers/media/pci/solo6x10/Kconfig +++ b/drivers/media/pci/solo6x10/Kconfig @@ -8,7 +8,7 @@ config VIDEO_SOLO6X10 select VIDEOBUF2_DMA_CONTIG select SND_PCM select FONT_8x16 - ---help--- + help This driver supports the Bluecherry H.264 and MPEG-4 hardware compression capture cards and other Softlogic-based ones. diff --git a/drivers/media/pci/tw5864/Kconfig b/drivers/media/pci/tw5864/Kconfig index 760fb11dfeae..e5d52f076232 100644 --- a/drivers/media/pci/tw5864/Kconfig +++ b/drivers/media/pci/tw5864/Kconfig @@ -2,7 +2,7 @@ config VIDEO_TW5864 tristate "Techwell TW5864 video/audio grabber and encoder" depends on VIDEO_DEV && PCI && VIDEO_V4L2 select VIDEOBUF2_DMA_CONTIG - ---help--- + help Support for boards based on Techwell TW5864 chip which provides multichannel video & audio grabbing and encoding (H.264, MJPEG, ADPCM G.726). diff --git a/drivers/media/pci/tw68/Kconfig b/drivers/media/pci/tw68/Kconfig index 95d5d5202048..4bfc4fa416e5 100644 --- a/drivers/media/pci/tw68/Kconfig +++ b/drivers/media/pci/tw68/Kconfig @@ -2,7 +2,7 @@ config VIDEO_TW68 tristate "Techwell tw68x Video For Linux" depends on VIDEO_DEV && PCI && VIDEO_V4L2 select VIDEOBUF2_DMA_SG - ---help--- + help Support for Techwell tw68xx based frame grabber boards. To compile this driver as a module, choose M here: the diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 4acbed189644..1611ec23d733 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -6,7 +6,7 @@ menuconfig V4L_PLATFORM_DRIVERS bool "V4L platform devices" depends on MEDIA_CAMERA_SUPPORT default n - ---help--- + help Say Y here to enable support for platform-specific V4L drivers. if V4L_PLATFORM_DRIVERS @@ -55,7 +55,7 @@ config VIDEO_VIU depends on VIDEO_V4L2 && (PPC_MPC512x || COMPILE_TEST) && I2C select VIDEOBUF_DMA_CONTIG default y - ---help--- + help Support for Freescale VIU video driver. This device captures video data, or overlays video on DIU frame buffer. @@ -80,13 +80,13 @@ config VIDEO_OMAP3 select VIDEOBUF2_DMA_CONTIG select MFD_SYSCON select V4L2_FWNODE - ---help--- + help Driver for an OMAP 3 camera controller. config VIDEO_OMAP3_DEBUG bool "OMAP 3 Camera debug messages" depends on VIDEO_OMAP3 - ---help--- + help Enable debug messages on OMAP 3 camera controller driver. config VIDEO_PXA27x @@ -96,7 +96,7 @@ config VIDEO_PXA27x select VIDEOBUF2_DMA_SG select SG_SPLIT select V4L2_FWNODE - ---help--- + help This is a v4l2 driver for the PXA27x Quick Capture Interface config VIDEO_QCOM_CAMSS @@ -112,7 +112,7 @@ config VIDEO_S3C_CAMIF depends on PM depends on ARCH_S3C64XX || PLAT_S3C24XX || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG - ---help--- + help This is a v4l2 driver for s3c24xx and s3c64xx SoC series camera host interface (CAMIF). @@ -125,7 +125,7 @@ config VIDEO_STM32_DCMI depends on ARCH_STM32 || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG select V4L2_FWNODE - ---help--- + help This module makes the STM32 Digital Camera Memory Interface (DCMI) available as a v4l2 device. @@ -138,7 +138,7 @@ config VIDEO_RENESAS_CEU depends on ARCH_SHMOBILE || ARCH_R7S72100 || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG select V4L2_FWNODE - ---help--- + help This is a v4l2 driver for the Renesas CEU Interface source "drivers/media/platform/exynos4-is/Kconfig" @@ -155,7 +155,7 @@ config VIDEO_TI_CAL select VIDEOBUF2_DMA_CONTIG select V4L2_FWNODE default n - ---help--- + help Support for the TI CAL (Camera Adaptation Layer) block found on DRA72X SoC. In TI Technical Reference Manual this module is referred as @@ -168,7 +168,7 @@ menuconfig V4L_MEM2MEM_DRIVERS depends on VIDEO_V4L2 depends on MEDIA_CAMERA_SUPPORT default n - ---help--- + help Say Y here to enable selecting drivers for V4L devices that use system memory for both source and destination buffers, as opposed to capture and output drivers, which use memory buffers for just @@ -184,7 +184,7 @@ config VIDEO_CODA select VIDEOBUF2_VMALLOC select V4L2_MEM2MEM_DEV select GENERIC_ALLOCATOR - ---help--- + help Coda is a range of video codec IPs that supports H.264, MPEG-4, and other video formats. @@ -207,7 +207,7 @@ config VIDEO_MEDIATEK_JPEG depends on ARCH_MEDIATEK || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG select V4L2_MEM2MEM_DEV - ---help--- + help Mediatek jpeg codec driver provides HW capability to decode JPEG format @@ -218,7 +218,7 @@ config VIDEO_MEDIATEK_VPU tristate "Mediatek Video Processor Unit" depends on VIDEO_DEV && VIDEO_V4L2 depends on ARCH_MEDIATEK || COMPILE_TEST - ---help--- + help This driver provides downloading VPU firmware and communicating with VPU. This driver for hw video codec embedded in Mediatek's MT8173 SOCs. It is able @@ -236,7 +236,7 @@ config VIDEO_MEDIATEK_MDP select V4L2_MEM2MEM_DEV select VIDEO_MEDIATEK_VPU default n - ---help--- + help It is a v4l2 driver and present in Mediatek MT8173 SoCs. The driver supports for scaling and color space conversion. @@ -252,7 +252,7 @@ config VIDEO_MEDIATEK_VCODEC select V4L2_MEM2MEM_DEV select VIDEO_MEDIATEK_VPU default n - ---help--- + help Mediatek video codec driver provides HW capability to encode and decode in a range of video formats This driver rely on VPU driver to communicate with VPU. @@ -276,7 +276,7 @@ config VIDEO_SAMSUNG_S5P_G2D select VIDEOBUF2_DMA_CONTIG select V4L2_MEM2MEM_DEV default n - ---help--- + help This is a v4l2 driver for Samsung S5P and EXYNOS4 G2D 2d graphics accelerator. @@ -286,7 +286,7 @@ config VIDEO_SAMSUNG_S5P_JPEG depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG select V4L2_MEM2MEM_DEV - ---help--- + help This is a v4l2 driver for Samsung S5P, EXYNOS3250 and EXYNOS4 JPEG codec @@ -407,7 +407,7 @@ config VIDEO_RENESAS_FDP1 depends on (!ARM64 && !VIDEO_RENESAS_FCP) || VIDEO_RENESAS_FCP select VIDEOBUF2_DMA_CONTIG select V4L2_MEM2MEM_DEV - ---help--- + help This is a V4L2 driver for the Renesas Fine Display Processor providing colour space conversion, and de-interlacing features. @@ -420,7 +420,7 @@ config VIDEO_RENESAS_JPU depends on ARCH_RENESAS || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG select V4L2_MEM2MEM_DEV - ---help--- + help This is a V4L2 driver for the Renesas JPEG Processing Unit. To compile this driver as a module, choose M here: the module @@ -430,7 +430,7 @@ config VIDEO_RENESAS_FCP tristate "Renesas Frame Compression Processor" depends on ARCH_RENESAS || COMPILE_TEST depends on OF - ---help--- + help This is a driver for the Renesas Frame Compression Processor (FCP). The FCP is a companion module of video processing modules in the Renesas R-Car Gen3 SoCs. It handles memory access for the codec, @@ -446,7 +446,7 @@ config VIDEO_RENESAS_VSP1 depends on (!ARM64 && !VIDEO_RENESAS_FCP) || VIDEO_RENESAS_FCP select VIDEOBUF2_DMA_CONTIG select VIDEOBUF2_VMALLOC - ---help--- + help This is a V4L2 driver for the Renesas VSP1 video processing engine. To compile this driver as a module, choose M here: the module @@ -459,7 +459,7 @@ config VIDEO_ROCKCHIP_RGA select VIDEOBUF2_DMA_SG select V4L2_MEM2MEM_DEV default n - ---help--- + help This is a v4l2 driver for Rockchip SOC RGA 2d graphics accelerator. Rockchip RGA is a separate 2D raster graphic acceleration unit. It accelerates 2D graphics operations, such as point/line drawing, @@ -477,14 +477,14 @@ config VIDEO_TI_VPE select VIDEO_TI_SC select VIDEO_TI_CSC default n - ---help--- + help Support for the TI VPE(Video Processing Engine) block found on DRA7XX SoC. config VIDEO_TI_VPE_DEBUG bool "VPE debug messages" depends on VIDEO_TI_VPE - ---help--- + help Enable debug messages on VPE driver. config VIDEO_QCOM_VENUS @@ -495,7 +495,7 @@ config VIDEO_QCOM_VENUS select QCOM_SCM if ARCH_QCOM select VIDEOBUF2_DMA_SG select V4L2_MEM2MEM_DEV - ---help--- + help This is a V4L2 driver for Qualcomm Venus video accelerator hardware. It accelerates encoding and decoding operations on various Qualcomm SoCs. @@ -530,7 +530,7 @@ config VIDEO_VIM2M select VIDEOBUF2_VMALLOC select V4L2_MEM2MEM_DEV default n - ---help--- + help This is a virtual test device for the memory-to-memory driver framework. @@ -542,7 +542,7 @@ menuconfig DVB_PLATFORM_DRIVERS bool "DVB platform devices" depends on MEDIA_DIGITAL_TV_SUPPORT default n - ---help--- + help Say Y here to enable support for platform-specific Digital TV drivers. if DVB_PLATFORM_DRIVERS @@ -562,7 +562,7 @@ config VIDEO_CROS_EC_CEC select CEC_NOTIFIER select CHROME_PLATFORMS select CROS_EC_PROTO - ---help--- + help If you say yes here you will get support for the ChromeOS Embedded Controller's CEC. The CEC bus is present in the HDMI connector and enables communication @@ -573,7 +573,7 @@ config VIDEO_MESON_AO_CEC depends on ARCH_MESON || COMPILE_TEST select CEC_CORE select CEC_NOTIFIER - ---help--- + help This is a driver for Amlogic Meson SoCs AO CEC interface. It uses the generic CEC framework interface. CEC bus is present in the HDMI connector and enables communication @@ -584,7 +584,7 @@ config CEC_GPIO select CEC_CORE select CEC_PIN select GPIOLIB - ---help--- + help This is a generic GPIO-based CEC driver. The CEC bus is present in the HDMI connector and enables communication between compatible devices. @@ -594,7 +594,7 @@ config VIDEO_SAMSUNG_S5P_CEC depends on ARCH_EXYNOS || COMPILE_TEST select CEC_CORE select CEC_NOTIFIER - ---help--- + help This is a driver for Samsung S5P HDMI CEC interface. It uses the generic CEC framework interface. CEC bus is present in the HDMI connector and enables communication @@ -605,7 +605,7 @@ config VIDEO_STI_HDMI_CEC depends on ARCH_STI || COMPILE_TEST select CEC_CORE select CEC_NOTIFIER - ---help--- + help This is a driver for STIH4xx HDMI CEC interface. It uses the generic CEC framework interface. CEC bus is present in the HDMI connector and enables communication @@ -617,7 +617,7 @@ config VIDEO_STM32_HDMI_CEC select REGMAP select REGMAP_MMIO select CEC_CORE - ---help--- + help This is a driver for STM32 interface. It uses the generic CEC framework interface. CEC bus is present in the HDMI connector and enables communication @@ -628,7 +628,7 @@ config VIDEO_TEGRA_HDMI_CEC depends on ARCH_TEGRA || COMPILE_TEST select CEC_CORE select CEC_NOTIFIER - ---help--- + help This is a driver for the Tegra HDMI CEC interface. It uses the generic CEC framework interface. The CEC bus is present in the HDMI connector and enables communication @@ -662,7 +662,7 @@ menuconfig SDR_PLATFORM_DRIVERS bool "SDR platform devices" depends on MEDIA_SDR_SUPPORT default n - ---help--- + help Say Y here to enable support for platform-specific SDR Drivers. if SDR_PLATFORM_DRIVERS @@ -672,7 +672,7 @@ config VIDEO_RCAR_DRIF depends on VIDEO_V4L2 depends on ARCH_RENESAS || COMPILE_TEST select VIDEOBUF2_VMALLOC - ---help--- + help Say Y if you want to enable R-Car Gen3 DRIF support. DRIF is Digital Radio Interface that interfaces with an RF front end chip. It is a receiver of digital data which uses DMA to transfer received data to diff --git a/drivers/media/platform/atmel/Kconfig b/drivers/media/platform/atmel/Kconfig index a211ef20f77e..c3f6a47cdc0e 100644 --- a/drivers/media/platform/atmel/Kconfig +++ b/drivers/media/platform/atmel/Kconfig @@ -15,6 +15,6 @@ config VIDEO_ATMEL_ISI depends on ARCH_AT91 || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG select V4L2_FWNODE - ---help--- + help This module makes the ATMEL Image Sensor Interface available as a v4l2 device. diff --git a/drivers/media/platform/marvell-ccic/Kconfig b/drivers/media/platform/marvell-ccic/Kconfig index cf12e077203a..cd88e2eed749 100644 --- a/drivers/media/platform/marvell-ccic/Kconfig +++ b/drivers/media/platform/marvell-ccic/Kconfig @@ -5,7 +5,7 @@ config VIDEO_CAFE_CCIC select VIDEOBUF2_VMALLOC select VIDEOBUF2_DMA_CONTIG select VIDEOBUF2_DMA_SG - ---help--- + help This is a video4linux2 driver for the Marvell 88ALP01 integrated CMOS camera controller. This is the controller found on first- generation OLPC systems. @@ -19,7 +19,7 @@ config VIDEO_MMP_CAMERA select VIDEOBUF2_VMALLOC select VIDEOBUF2_DMA_CONTIG select VIDEOBUF2_DMA_SG - ---help--- + help This is a Video4Linux2 driver for the integrated camera controller found on Marvell Armada 610 application processors (and likely beyond). This is the controller found diff --git a/drivers/media/platform/omap/Kconfig b/drivers/media/platform/omap/Kconfig index 4b5e55d41ad4..30ce2ba120a1 100644 --- a/drivers/media/platform/omap/Kconfig +++ b/drivers/media/platform/omap/Kconfig @@ -14,5 +14,5 @@ config VIDEO_OMAP2_VOUT select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3 select FRAME_VECTOR default n - ---help--- + help V4L2 Display driver support for OMAP2/3 based boards. diff --git a/drivers/media/platform/rcar-vin/Kconfig b/drivers/media/platform/rcar-vin/Kconfig index e3eb8fee2536..2433ec960010 100644 --- a/drivers/media/platform/rcar-vin/Kconfig +++ b/drivers/media/platform/rcar-vin/Kconfig @@ -17,7 +17,7 @@ config VIDEO_RCAR_VIN depends on ARCH_RENESAS || COMPILE_TEST select VIDEOBUF2_DMA_CONTIG select V4L2_FWNODE - ---help--- + help Support for Renesas R-Car Video Input (VIN) driver. Supports R-Car Gen2 and Gen3 SoCs. diff --git a/drivers/media/platform/sti/c8sectpfe/Kconfig b/drivers/media/platform/sti/c8sectpfe/Kconfig index 7420a50572d3..93eaabfd5437 100644 --- a/drivers/media/platform/sti/c8sectpfe/Kconfig +++ b/drivers/media/platform/sti/c8sectpfe/Kconfig @@ -12,7 +12,7 @@ config DVB_C8SECTPFE select DVB_STV0367 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_TDA18212 if MEDIA_SUBDRV_AUTOSELECT - ---help--- + help This adds support for DVB front-end cards connected to TS inputs of STiH407/410 SoC. diff --git a/drivers/media/platform/vimc/Kconfig b/drivers/media/platform/vimc/Kconfig index 71c9fe7d3370..1de9bc9aa49b 100644 --- a/drivers/media/platform/vimc/Kconfig +++ b/drivers/media/platform/vimc/Kconfig @@ -4,7 +4,7 @@ config VIDEO_VIMC select VIDEOBUF2_VMALLOC select VIDEO_V4L2_TPG default n - ---help--- + help Skeleton driver for Virtual Media Controller This driver can be compared to the vivid driver for emulating diff --git a/drivers/media/platform/vivid/Kconfig b/drivers/media/platform/vivid/Kconfig index 154de92dd809..4b51d4d6cf93 100644 --- a/drivers/media/platform/vivid/Kconfig +++ b/drivers/media/platform/vivid/Kconfig @@ -11,7 +11,7 @@ config VIDEO_VIVID select VIDEOBUF2_DMA_CONTIG select VIDEO_V4L2_TPG default n - ---help--- + help Enables a virtual video driver. This driver emulates a webcam, TV, S-Video and HDMI capture hardware, including VBI support for the SDTV inputs. Also video output, VBI output, radio receivers, @@ -28,7 +28,7 @@ config VIDEO_VIVID_CEC bool "Enable CEC emulation support" depends on VIDEO_VIVID select CEC_CORE - ---help--- + help When selected the vivid module will emulate the optional HDMI CEC feature. @@ -36,6 +36,6 @@ config VIDEO_VIVID_MAX_DEVS int "Maximum number of devices" depends on VIDEO_VIVID default "64" - ---help--- + help This allows you to specify the maximum number of devices supported by the vivid driver. diff --git a/drivers/media/platform/xilinx/Kconfig b/drivers/media/platform/xilinx/Kconfig index 74ec8aaa5ae0..a2773ad7c185 100644 --- a/drivers/media/platform/xilinx/Kconfig +++ b/drivers/media/platform/xilinx/Kconfig @@ -5,7 +5,7 @@ config VIDEO_XILINX depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && OF && HAS_DMA select VIDEOBUF2_DMA_CONTIG select V4L2_FWNODE - ---help--- + help Driver for Xilinx Video IP Pipelines if VIDEO_XILINX @@ -14,13 +14,13 @@ config VIDEO_XILINX_TPG tristate "Xilinx Video Test Pattern Generator" depends on VIDEO_XILINX select VIDEO_XILINX_VTC - ---help--- + help Driver for the Xilinx Video Test Pattern Generator config VIDEO_XILINX_VTC tristate "Xilinx Video Timing Controller" depends on VIDEO_XILINX - ---help--- + help Driver for the Xilinx Video Timing Controller endif #VIDEO_XILINX diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 9b99dfb2d0c6..9cd00f64af32 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -7,7 +7,7 @@ menuconfig RADIO_ADAPTERS depends on VIDEO_V4L2 depends on MEDIA_RADIO_SUPPORT default y - ---help--- + help Say Y here to enable selecting AM/FM radio adapters. if RADIO_ADAPTERS && VIDEO_V4L2 @@ -29,7 +29,7 @@ config RADIO_SI476X depends on MFD_SI476X_CORE depends on SND_SOC select SND_SOC_SI476X - ---help--- + help Choose Y here if you have this FM radio chip. In order to control your radio card, you will need to use programs @@ -43,7 +43,7 @@ config RADIO_SI476X config USB_MR800 tristate "AverMedia MR 800 USB FM radio support" depends on USB && VIDEO_V4L2 - ---help--- + help Say Y here if you want to connect this type of radio to your computer's USB port. Note that the audio is not digital, and you must connect the line out connector to a sound card or a @@ -55,7 +55,7 @@ config USB_MR800 config USB_DSBR tristate "D-Link/GemTek USB FM radio support" depends on USB && VIDEO_V4L2 - ---help--- + help Say Y here if you want to connect this type of radio to your computer's USB port. Note that the audio is not digital, and you must connect the line out connector to a sound card or a @@ -68,7 +68,7 @@ config RADIO_MAXIRADIO tristate "Guillemot MAXI Radio FM 2000 radio" depends on VIDEO_V4L2 && PCI select RADIO_TEA575X - ---help--- + help Choose Y here if you have this radio card. This card may also be found as Gemtek PCI FM. @@ -84,7 +84,7 @@ config RADIO_SHARK tristate "Griffin radioSHARK USB radio receiver" depends on USB select RADIO_TEA575X - ---help--- + help Choose Y here if you have this radio receiver. There are 2 versions of this device, this driver is for version 1, @@ -101,7 +101,7 @@ config RADIO_SHARK config RADIO_SHARK2 tristate "Griffin radioSHARK2 USB radio receiver" depends on USB - ---help--- + help Choose Y here if you have this radio receiver. There are 2 versions of this device, this driver is for version 2, @@ -118,7 +118,7 @@ config RADIO_SHARK2 config USB_KEENE tristate "Keene FM Transmitter USB support" depends on USB && VIDEO_V4L2 - ---help--- + help Say Y here if you want to connect this type of FM transmitter to your computer's USB port. @@ -128,7 +128,7 @@ config USB_KEENE config USB_RAREMONO tristate "Thanko's Raremono AM/FM/SW radio support" depends on USB && VIDEO_V4L2 - ---help--- + help The 'Thanko's Raremono' device contains the Si4734 chip from Silicon Labs Inc. It is one of the very few or perhaps the only consumer USB radio device to receive the AM/FM/SW bands. @@ -142,7 +142,7 @@ config USB_RAREMONO config USB_MA901 tristate "Masterkit MA901 USB FM radio support" depends on USB && VIDEO_V4L2 - ---help--- + help Say Y here if you want to connect this type of radio to your computer's USB port. Note that the audio is not digital, and you must connect the line out connector to a sound card or a @@ -154,7 +154,7 @@ config USB_MA901 config RADIO_TEA5764 tristate "TEA5764 I2C FM radio support" depends on I2C && VIDEO_V4L2 - ---help--- + help Say Y here if you want to use the TEA5764 FM chip found in EZX phones. This FM chip is present in EZX phones from Motorola, connected to internal pxa I2C bus. @@ -173,7 +173,7 @@ config RADIO_TEA5764_XTAL config RADIO_SAA7706H tristate "SAA7706H Car Radio DSP" depends on I2C && VIDEO_V4L2 - ---help--- + help Say Y here if you want to use the SAA7706H Car radio Digital Signal Processor, found for instance on the Russellville development board. On the russellville the device is connected to internal @@ -185,7 +185,7 @@ config RADIO_SAA7706H config RADIO_TEF6862 tristate "TEF6862 Car Radio Enhanced Selectivity Tuner" depends on I2C && VIDEO_V4L2 - ---help--- + help Say Y here if you want to use the TEF6862 Car Radio Enhanced Selectivity Tuner, found for instance on the Russellville development board. On the russellville the device is connected to internal @@ -200,7 +200,7 @@ config RADIO_TIMBERDALE depends on I2C # for RADIO_SAA7706H select RADIO_TEF6862 select RADIO_SAA7706H - ---help--- + help This is a kind of umbrella driver for the Radio Tuner and DSP found behind the Timberdale FPGA on the Russellville board. Enabling this driver will automatically select the DSP and tuner. @@ -211,7 +211,7 @@ config RADIO_WL1273 select MFD_CORE select MFD_WL1273_CORE select FW_LOADER - ---help--- + help Choose Y here if you have this FM radio chip. In order to control your radio card, you will need to use programs @@ -233,7 +233,7 @@ menuconfig V4L_RADIO_ISA_DRIVERS bool "ISA radio devices" depends on ISA || COMPILE_TEST default n - ---help--- + help Say Y here to enable support for these ISA drivers. if V4L_RADIO_ISA_DRIVERS @@ -246,7 +246,7 @@ config RADIO_CADET tristate "ADS Cadet AM/FM Tuner" depends on ISA || COMPILE_TEST depends on VIDEO_V4L2 - ---help--- + help Choose Y here if you have one of these AM/FM radio cards, and then fill in the port address below. @@ -258,7 +258,7 @@ config RADIO_RTRACK depends on ISA || COMPILE_TEST depends on VIDEO_V4L2 select RADIO_ISA - ---help--- + help Choose Y here if you have one of these FM radio cards, and then fill in the port address below. @@ -290,7 +290,7 @@ config RADIO_RTRACK2 depends on ISA || COMPILE_TEST depends on VIDEO_V4L2 select RADIO_ISA - ---help--- + help Choose Y here if you have this FM radio card, and then fill in the port address below. @@ -314,7 +314,7 @@ config RADIO_AZTECH depends on ISA || COMPILE_TEST depends on VIDEO_V4L2 select RADIO_ISA - ---help--- + help Choose Y here if you have one of these FM radio cards, and then fill in the port address below. @@ -335,7 +335,7 @@ config RADIO_GEMTEK depends on ISA || COMPILE_TEST depends on VIDEO_V4L2 select RADIO_ISA - ---help--- + help Choose Y here if you have this FM radio card, and then fill in the I/O port address and settings below. The following cards either have GemTek Radio tuner or are rebranded GemTek Radio cards: @@ -377,7 +377,7 @@ config RADIO_MIROPCM20 depends on ISA_DMA_API && VIDEO_V4L2 && SND select SND_ISA select SND_MIRO - ---help--- + help Choose Y here if you have this FM radio card. You also need to enable the ALSA sound system. This choice automatically selects the ALSA sound card driver "Miro miroSOUND PCM1pro/PCM12/PCM20radio" as this @@ -390,7 +390,7 @@ config RADIO_SF16FMI tristate "SF16-FMI/SF16-FMP/SF16-FMD Radio" depends on ISA || COMPILE_TEST depends on VIDEO_V4L2 - ---help--- + help Choose Y here if you have one of these FM radio cards. To compile this driver as a module, choose M here: the @@ -401,7 +401,7 @@ config RADIO_SF16FMR2 depends on ISA || COMPILE_TEST depends on VIDEO_V4L2 select RADIO_TEA575X - ---help--- + help Choose Y here if you have one of these FM radio cards. To compile this driver as a module, choose M here: the @@ -412,7 +412,7 @@ config RADIO_TERRATEC depends on ISA || COMPILE_TEST depends on VIDEO_V4L2 select RADIO_ISA - ---help--- + help Choose Y here if you have this FM radio card. Note: this driver hasn't been tested since a long time due to lack @@ -451,7 +451,7 @@ config RADIO_TYPHOON depends on ISA || COMPILE_TEST depends on VIDEO_V4L2 select RADIO_ISA - ---help--- + help Choose Y here if you have one of these FM radio cards, and then fill in the port address and the frequency used for muting below. @@ -486,7 +486,7 @@ config RADIO_ZOLTRIX depends on ISA || COMPILE_TEST depends on VIDEO_V4L2 select RADIO_ISA - ---help--- + help Choose Y here if you have one of these FM radio cards, and then fill in the port address below. diff --git a/drivers/media/radio/si470x/Kconfig b/drivers/media/radio/si470x/Kconfig index 6dbb158cd2a0..21026488de90 100644 --- a/drivers/media/radio/si470x/Kconfig +++ b/drivers/media/radio/si470x/Kconfig @@ -1,7 +1,7 @@ config RADIO_SI470X tristate "Silicon Labs Si470x FM Radio Receiver support" depends on VIDEO_V4L2 - ---help--- + help This is a driver for devices with the Silicon Labs SI470x chip (either via USB or I2C buses). @@ -15,7 +15,7 @@ config RADIO_SI470X config USB_SI470X tristate "Silicon Labs Si470x FM Radio Receiver support with USB" depends on USB && RADIO_SI470X - ---help--- + help This is a driver for USB devices with the Silicon Labs SI470x chip. Currently these devices are known to work: - 10c4:818a: Silicon Labs USB FM Radio Reference Design @@ -40,7 +40,7 @@ config USB_SI470X config I2C_SI470X tristate "Silicon Labs Si470x FM Radio Receiver support with I2C" depends on I2C && RADIO_SI470X - ---help--- + help This is a driver for I2C devices with the Silicon Labs SI470x chip. diff --git a/drivers/media/radio/si4713/Kconfig b/drivers/media/radio/si4713/Kconfig index 9c8b887cff75..17567c917554 100644 --- a/drivers/media/radio/si4713/Kconfig +++ b/drivers/media/radio/si4713/Kconfig @@ -2,7 +2,7 @@ config USB_SI4713 tristate "Silicon Labs Si4713 FM Radio Transmitter support with USB" depends on USB && I2C && RADIO_SI4713 select I2C_SI4713 - ---help--- + help This is a driver for USB devices with the Silicon Labs SI4713 chip. Currently these devices are known to work. - 10c4:8244: Silicon Labs FM Transmitter USB device. @@ -17,7 +17,7 @@ config PLATFORM_SI4713 tristate "Silicon Labs Si4713 FM Radio Transmitter support with I2C" depends on I2C && RADIO_SI4713 select I2C_SI4713 - ---help--- + help This is a driver for I2C devices with the Silicon Labs SI4713 chip. @@ -30,7 +30,7 @@ config PLATFORM_SI4713 config I2C_SI4713 tristate "Silicon Labs Si4713 FM Radio Transmitter support" depends on I2C && RADIO_SI4713 - ---help--- + help Say Y here if you want support to Si4713 FM Radio Transmitter. This device can transmit audio through FM. It can transmit RDS and RBDS signals as well. This module is the v4l2 radio diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 96ce3e5524e0..3fc6ac15c66d 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -2,7 +2,7 @@ menuconfig RC_CORE tristate "Remote Controller support" depends on INPUT - ---help--- + help Enable support for Remote Controllers on Linux. This is needed in order to support several video capture adapters, standalone IR receivers/transmitters, and RF receivers. @@ -19,7 +19,7 @@ source "drivers/media/rc/keymaps/Kconfig" config LIRC bool "LIRC user interface" depends on RC_CORE - ---help--- + help Enable this option to enable the Linux Infrared Remote Control user interface (e.g. /dev/lirc*). This interface passes raw IR to and from userspace, which is needed for @@ -48,7 +48,7 @@ config IR_NEC_DECODER depends on RC_CORE select BITREVERSE - ---help--- + help Enable this option if you have IR with NEC protocol, and if the IR is decoded in software @@ -57,7 +57,7 @@ config IR_RC5_DECODER depends on RC_CORE select BITREVERSE - ---help--- + help Enable this option if you have IR with RC-5 protocol, and if the IR is decoded in software @@ -66,7 +66,7 @@ config IR_RC6_DECODER depends on RC_CORE select BITREVERSE - ---help--- + help Enable this option if you have an infrared remote control which uses the RC6 protocol, and you need software decoding support. @@ -75,7 +75,7 @@ config IR_JVC_DECODER depends on RC_CORE select BITREVERSE - ---help--- + help Enable this option if you have an infrared remote control which uses the JVC protocol, and you need software decoding support. @@ -84,7 +84,7 @@ config IR_SONY_DECODER depends on RC_CORE select BITREVERSE - ---help--- + help Enable this option if you have an infrared remote control which uses the Sony protocol, and you need software decoding support. @@ -92,7 +92,7 @@ config IR_SANYO_DECODER tristate "Enable IR raw decoder for the Sanyo protocol" depends on RC_CORE - ---help--- + help Enable this option if you have an infrared remote control which uses the Sanyo protocol (Sanyo, Aiwa, Chinon remotes), and you need software decoding support. @@ -101,7 +101,7 @@ config IR_SHARP_DECODER tristate "Enable IR raw decoder for the Sharp protocol" depends on RC_CORE - ---help--- + help Enable this option if you have an infrared remote control which uses the Sharp protocol (Sharp, Denon), and you need software decoding support. @@ -111,7 +111,7 @@ config IR_MCE_KBD_DECODER depends on RC_CORE select BITREVERSE - ---help--- + help Enable this option if you have a Microsoft Remote Keyboard for Windows Media Center Edition, which you would like to use with a raw IR receiver in your system. @@ -121,14 +121,14 @@ config IR_XMP_DECODER depends on RC_CORE select BITREVERSE - ---help--- + help Enable this option if you have IR with XMP protocol, and if the IR is decoded in software config IR_IMON_DECODER tristate "Enable IR raw decoder for the iMON protocol" depends on RC_CORE - ---help--- + help Enable this option if you have iMON PAD or Antec Veris infrared remote control and you would like to use it with a raw IR receiver, or if you wish to use an encoder to transmit this IR. @@ -177,7 +177,7 @@ config IR_ENE tristate "ENE eHome Receiver/Transceiver (pnp id: ENE0100/ENE02xxx)" depends on PNP || COMPILE_TEST depends on RC_CORE - ---help--- + help Say Y here to enable support for integrated infrared receiver /transceiver made by ENE. @@ -203,7 +203,7 @@ config IR_IMON depends on USB_ARCH_HAS_HCD depends on RC_CORE select USB - ---help--- + help Say Y here if you want to use a SoundGraph iMON (aka Antec Veris) IR Receiver and/or LCD/VFD/VGA display. @@ -215,7 +215,7 @@ config IR_IMON_RAW depends on USB_ARCH_HAS_HCD depends on RC_CORE select USB - ---help--- + help Say Y here if you want to use a SoundGraph iMON IR Receiver, early raw models. @@ -227,7 +227,7 @@ config IR_MCEUSB depends on USB_ARCH_HAS_HCD depends on RC_CORE select USB - ---help--- + help Say Y here if you want to use a Windows Media Center Edition eHome Infrared Transceiver. @@ -238,7 +238,7 @@ config IR_ITE_CIR tristate "ITE Tech Inc. IT8712/IT8512 Consumer Infrared Transceiver" depends on PNP || COMPILE_TEST depends on RC_CORE - ---help--- + help Say Y here to enable support for integrated infrared receivers /transceivers made by ITE Tech Inc. These are found in several ASUS devices, like the ASUS Digimatrix or the ASUS @@ -251,7 +251,7 @@ config IR_FINTEK tristate "Fintek Consumer Infrared Transceiver" depends on PNP || COMPILE_TEST depends on RC_CORE - ---help--- + help Say Y here to enable support for integrated infrared receiver /transceiver made by Fintek. This chip is found on assorted Jetway motherboards (and of course, possibly others). @@ -263,7 +263,7 @@ config IR_MESON tristate "Amlogic Meson IR remote receiver" depends on RC_CORE depends on ARCH_MESON || COMPILE_TEST - ---help--- + help Say Y if you want to use the IR remote receiver available on Amlogic Meson SoCs. @@ -274,7 +274,7 @@ config IR_MTK tristate "Mediatek IR remote receiver" depends on RC_CORE depends on ARCH_MEDIATEK || COMPILE_TEST - ---help--- + help Say Y if you want to use the IR remote receiver available on Mediatek SoCs. @@ -285,7 +285,7 @@ config IR_NUVOTON tristate "Nuvoton w836x7hg Consumer Infrared Transceiver" depends on PNP || COMPILE_TEST depends on RC_CORE - ---help--- + help Say Y here to enable support for integrated infrared receiver /transceiver made by Nuvoton (formerly Winbond). This chip is found in the ASRock ION 330HT, as well as assorted Intel @@ -301,7 +301,7 @@ config IR_REDRAT3 select NEW_LEDS select LEDS_CLASS select USB - ---help--- + help Say Y here if you want to use a RedRat3 Infrared Transceiver. To compile this driver as a module, choose M here: the @@ -311,7 +311,7 @@ config IR_SPI tristate "SPI connected IR LED" depends on SPI && LIRC depends on OF || COMPILE_TEST - ---help--- + help Say Y if you want to use an IR LED connected through SPI bus. To compile this driver as a module, choose M here: the module will be @@ -322,7 +322,7 @@ config IR_STREAMZAP depends on USB_ARCH_HAS_HCD depends on RC_CORE select USB - ---help--- + help Say Y here if you want to use a Streamzap PC Remote Infrared Receiver. @@ -336,7 +336,7 @@ config IR_WINBOND_CIR select NEW_LEDS select LEDS_CLASS select BITREVERSE - ---help--- + help Say Y here if you want to use the IR remote functionality found in some Winbond SuperI/O chips. Currently only the WPCD376I chip is supported (included in some Intel Media series @@ -350,7 +350,7 @@ config IR_IGORPLUGUSB depends on USB_ARCH_HAS_HCD depends on RC_CORE select USB - ---help--- + help Say Y here if you want to use the IgorPlug-USB IR Receiver by Igor Cesko. This device is included on the Fit-PC2. @@ -365,7 +365,7 @@ config IR_IGUANA depends on USB_ARCH_HAS_HCD depends on RC_CORE select USB - ---help--- + help Say Y here if you want to use the IguanaWorks USB IR Transceiver. Both infrared receive and send are supported. If you want to change the ID or the pin config, use the user space driver from @@ -383,7 +383,7 @@ config IR_TTUSBIR select USB select NEW_LEDS select LEDS_CLASS - ---help--- + help Say Y here if you want to use the TechnoTrend USB IR Receiver. The driver can control the led. @@ -393,7 +393,7 @@ config IR_TTUSBIR config IR_RX51 tristate "Nokia N900 IR transmitter diode" depends on (OMAP_DM_TIMER && PWM_OMAP_DMTIMER && ARCH_OMAP2PLUS || COMPILE_TEST) && RC_CORE - ---help--- + help Say Y or M here if you want to enable support for the IR transmitter diode built in the Nokia N900 (RX51) device. @@ -405,7 +405,7 @@ source "drivers/media/rc/img-ir/Kconfig" config RC_LOOPBACK tristate "Remote Control Loopback Driver" depends on RC_CORE - ---help--- + help Say Y here if you want support for the remote control loopback driver which allows TX data to be sent back as RX data. This is mostly useful for debugging purposes. @@ -419,7 +419,7 @@ config IR_GPIO_CIR tristate "GPIO IR remote control" depends on RC_CORE depends on (OF && GPIOLIB) || COMPILE_TEST - ---help--- + help Say Y if you want to use GPIO based IR Receiver. To compile this driver as a module, choose M here: the module will @@ -430,7 +430,7 @@ config IR_GPIO_TX depends on RC_CORE depends on LIRC depends on (OF && GPIOLIB) || COMPILE_TEST - ---help--- + help Say Y if you want to a GPIO based IR transmitter. This is a bit banging driver. @@ -443,7 +443,7 @@ config IR_PWM_TX depends on LIRC depends on PWM depends on OF || COMPILE_TEST - ---help--- + help Say Y if you want to use a PWM based IR transmitter. This is more power efficient than the bit banging gpio driver. @@ -454,7 +454,7 @@ config RC_ST tristate "ST remote control receiver" depends on RC_CORE depends on ARCH_STI || COMPILE_TEST - ---help--- + help Say Y here if you want support for ST remote control driver which allows both IR and UHF RX. The driver passes raw pulse and space information to the LIRC decoder. @@ -465,7 +465,7 @@ config IR_SUNXI tristate "SUNXI IR remote control" depends on RC_CORE depends on ARCH_SUNXI || COMPILE_TEST - ---help--- + help Say Y if you want to use sunXi internal IR Controller To compile this driver as a module, choose M here: the module will @@ -474,7 +474,7 @@ config IR_SUNXI config IR_SERIAL tristate "Homebrew Serial Port Receiver" depends on RC_CORE - ---help--- + help Say Y if you want to use Homebrew Serial Port Receivers and Transceivers. @@ -484,13 +484,13 @@ config IR_SERIAL config IR_SERIAL_TRANSMITTER bool "Serial Port Transmitter" depends on IR_SERIAL - ---help--- + help Serial Port Transmitter support config IR_SIR tristate "Built-in SIR IrDA port" depends on RC_CORE - ---help--- + help Say Y if you want to use a IrDA SIR port Transceivers. To compile this driver as a module, choose M here: the module will @@ -500,7 +500,7 @@ config IR_TANGO tristate "Sigma Designs SMP86xx IR decoder" depends on RC_CORE depends on ARCH_TANGO || COMPILE_TEST - ---help--- + help Adds support for the HW IR decoder embedded on Sigma Designs Tango-based systems (SMP86xx, SMP87xx). The HW decoder supports NEC, RC-5, RC-6 IR protocols. @@ -522,7 +522,7 @@ config IR_ZX tristate "ZTE ZX IR remote control" depends on RC_CORE depends on ARCH_ZX || COMPILE_TEST - ---help--- + help Say Y if you want to use the IR remote control available on ZTE ZX family SoCs. diff --git a/drivers/media/rc/keymaps/Kconfig b/drivers/media/rc/keymaps/Kconfig index 767423bbbdd0..f459096d8e9c 100644 --- a/drivers/media/rc/keymaps/Kconfig +++ b/drivers/media/rc/keymaps/Kconfig @@ -3,7 +3,7 @@ config RC_MAP depends on RC_CORE default y - ---help--- + help This option enables the compilation of lots of Remote Controller tables. They are short tables, but if you don't use a remote controller, or prefer to load the diff --git a/drivers/media/spi/Kconfig b/drivers/media/spi/Kconfig index b07ac86fc53c..df169ecf0c27 100644 --- a/drivers/media/spi/Kconfig +++ b/drivers/media/spi/Kconfig @@ -6,7 +6,7 @@ menu "SPI helper chips" config VIDEO_GS1662 tristate "Gennum Serializers video" depends on SPI && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API - ---help--- + help Enable the GS1662 driver which serializes video streams. endmenu diff --git a/drivers/media/usb/airspy/Kconfig b/drivers/media/usb/airspy/Kconfig index 10b204cf4dbc..67578511bb9a 100644 --- a/drivers/media/usb/airspy/Kconfig +++ b/drivers/media/usb/airspy/Kconfig @@ -2,7 +2,7 @@ config USB_AIRSPY tristate "AirSpy" depends on VIDEO_V4L2 select VIDEOBUF2_VMALLOC - ---help--- + help This is a video4linux2 driver for AirSpy SDR device. To compile this driver as a module, choose M here: the diff --git a/drivers/media/usb/au0828/Kconfig b/drivers/media/usb/au0828/Kconfig index 65fc067eb864..ab4092bdff69 100644 --- a/drivers/media/usb/au0828/Kconfig +++ b/drivers/media/usb/au0828/Kconfig @@ -9,7 +9,7 @@ config VIDEO_AU0828 select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT - ---help--- + help This is a hybrid analog/digital tv capture driver for Auvitek's AU0828 USB device. @@ -23,7 +23,7 @@ config VIDEO_AU0828_V4L2 select DVB_AU8522_V4L if MEDIA_SUBDRV_AUTOSELECT select VIDEO_TUNER default y - ---help--- + help This is a video4linux driver for Auvitek's USB device. Choose Y here to include support for v4l2 analog video @@ -34,5 +34,5 @@ config VIDEO_AU0828_RC depends on RC_CORE depends on !(RC_CORE=m && VIDEO_AU0828=y) depends on VIDEO_AU0828 - ---help--- + help Enables Remote Controller support on au0828 driver. diff --git a/drivers/media/usb/cpia2/Kconfig b/drivers/media/usb/cpia2/Kconfig index 66e9283f5993..7029a04f3ffd 100644 --- a/drivers/media/usb/cpia2/Kconfig +++ b/drivers/media/usb/cpia2/Kconfig @@ -1,7 +1,7 @@ config VIDEO_CPIA2 tristate "CPiA2 Video For Linux" depends on VIDEO_DEV && USB && VIDEO_V4L2 - ---help--- + help This is the video4linux driver for cameras based on Vision's CPiA2 (Colour Processor Interface ASIC), such as the Digital Blue QX5 Microscope. If you have one of these cameras, say Y here diff --git a/drivers/media/usb/cx231xx/Kconfig b/drivers/media/usb/cx231xx/Kconfig index 9e5b3e7c3ef5..9262d0d7439a 100644 --- a/drivers/media/usb/cx231xx/Kconfig +++ b/drivers/media/usb/cx231xx/Kconfig @@ -7,7 +7,7 @@ config VIDEO_CX231XX select VIDEO_CX25840 select VIDEO_CX2341X - ---help--- + help This is a video4linux driver for Conexant 231xx USB based TV cards. To compile this driver as a module, choose M here: the @@ -18,7 +18,7 @@ config VIDEO_CX231XX_RC depends on RC_CORE=y || RC_CORE=VIDEO_CX231XX depends on VIDEO_CX231XX default y - ---help--- + help cx231xx hardware has a builtin RX/TX support. However, a few designs opted to not use it, but, instead, some other hardware. This module enables the usage of those other hardware, like the @@ -31,7 +31,7 @@ config VIDEO_CX231XX_ALSA depends on VIDEO_CX231XX && SND select SND_PCM - ---help--- + help This is an ALSA driver for Cx231xx USB based TV cards. To compile this driver as a module, choose M here: the @@ -52,6 +52,6 @@ config VIDEO_CX231XX_DVB select DVB_MN88473 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_R820T if MEDIA_SUBDRV_AUTOSELECT - ---help--- + help This adds support for DVB cards based on the Conexant cx231xx chips. diff --git a/drivers/media/usb/em28xx/Kconfig b/drivers/media/usb/em28xx/Kconfig index 451e076525d3..639da7e24066 100644 --- a/drivers/media/usb/em28xx/Kconfig +++ b/drivers/media/usb/em28xx/Kconfig @@ -13,7 +13,7 @@ config VIDEO_EM28XX_V4L2 select VIDEO_MSP3400 if MEDIA_SUBDRV_AUTOSELECT select VIDEO_MT9V011 if MEDIA_SUBDRV_AUTOSELECT && MEDIA_CAMERA_SUPPORT select VIDEO_OV2640 if MEDIA_SUBDRV_AUTOSELECT && MEDIA_CAMERA_SUPPORT - ---help--- + help This is a video4linux driver for Empia 28xx based TV cards. To compile this driver as a module, choose M here: the @@ -23,7 +23,7 @@ config VIDEO_EM28XX_ALSA depends on VIDEO_EM28XX && SND select SND_PCM tristate "Empia EM28xx ALSA audio module" - ---help--- + help This is an ALSA driver for some Empia 28xx based TV cards. This is not required for em2800/em2820/em2821 boards. However, @@ -66,7 +66,7 @@ config VIDEO_EM28XX_DVB select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT - ---help--- + help This adds support for DVB cards based on the Empiatech em28xx chips. @@ -76,5 +76,5 @@ config VIDEO_EM28XX_RC depends on VIDEO_EM28XX depends on !(RC_CORE=m && VIDEO_EM28XX=y) default VIDEO_EM28XX - ---help--- + help Enables Remote Controller support on em28xx driver. diff --git a/drivers/media/usb/go7007/Kconfig b/drivers/media/usb/go7007/Kconfig index af1d02430931..beab257c092f 100644 --- a/drivers/media/usb/go7007/Kconfig +++ b/drivers/media/usb/go7007/Kconfig @@ -13,7 +13,7 @@ config VIDEO_GO7007 select VIDEO_TW9906 if MEDIA_SUBDRV_AUTOSELECT select VIDEO_OV7640 if MEDIA_SUBDRV_AUTOSELECT && MEDIA_CAMERA_SUPPORT select VIDEO_UDA1342 if MEDIA_SUBDRV_AUTOSELECT - ---help--- + help This is a video4linux driver for the WIS GO7007 MPEG encoder chip. @@ -23,7 +23,7 @@ config VIDEO_GO7007 config VIDEO_GO7007_USB tristate "WIS GO7007 USB support" depends on VIDEO_GO7007 && USB - ---help--- + help This is a video4linux driver for the WIS GO7007 MPEG encoder chip over USB. @@ -34,7 +34,7 @@ config VIDEO_GO7007_LOADER tristate "WIS GO7007 Loader support" depends on VIDEO_GO7007 default y - ---help--- + help This is a go7007 firmware loader driver for the WIS GO7007 MPEG encoder chip over USB. @@ -44,7 +44,7 @@ config VIDEO_GO7007_LOADER config VIDEO_GO7007_USB_S2250_BOARD tristate "Sensoray 2250/2251 support" depends on VIDEO_GO7007_USB && USB - ---help--- + help This is a video4linux driver for the Sensoray 2250/2251 device. To compile this driver as a module, choose M here: the diff --git a/drivers/media/usb/gspca/Kconfig b/drivers/media/usb/gspca/Kconfig index 088566e88467..0e6f36cb46e6 100644 --- a/drivers/media/usb/gspca/Kconfig +++ b/drivers/media/usb/gspca/Kconfig @@ -4,7 +4,7 @@ menuconfig USB_GSPCA depends on INPUT || INPUT=n select VIDEOBUF2_VMALLOC default m - ---help--- + help Say Y here if you want to enable selecting webcams based on the GSPCA framework. diff --git a/drivers/media/usb/hackrf/Kconfig b/drivers/media/usb/hackrf/Kconfig index 937e6f5c1e8e..072e186018f5 100644 --- a/drivers/media/usb/hackrf/Kconfig +++ b/drivers/media/usb/hackrf/Kconfig @@ -2,7 +2,7 @@ config USB_HACKRF tristate "HackRF" depends on VIDEO_V4L2 select VIDEOBUF2_VMALLOC - ---help--- + help This is a video4linux2 driver for HackRF SDR device. To compile this driver as a module, choose M here: the diff --git a/drivers/media/usb/hdpvr/Kconfig b/drivers/media/usb/hdpvr/Kconfig index d73d9a1952b4..9e78c0c32651 100644 --- a/drivers/media/usb/hdpvr/Kconfig +++ b/drivers/media/usb/hdpvr/Kconfig @@ -2,7 +2,7 @@ config VIDEO_HDPVR tristate "Hauppauge HD PVR support" depends on VIDEO_DEV && VIDEO_V4L2 - ---help--- + help This is a video4linux driver for Hauppauge's HD PVR USB device. To compile this driver as a module, choose M here: the diff --git a/drivers/media/usb/pulse8-cec/Kconfig b/drivers/media/usb/pulse8-cec/Kconfig index 18ead44824ba..11f1b75d3efd 100644 --- a/drivers/media/usb/pulse8-cec/Kconfig +++ b/drivers/media/usb/pulse8-cec/Kconfig @@ -4,7 +4,7 @@ config USB_PULSE8_CEC select CEC_CORE select SERIO select SERIO_SERPORT - ---help--- + help This is a cec driver for the Pulse Eight HDMI CEC device. To compile this driver as a module, choose M here: the diff --git a/drivers/media/usb/pvrusb2/Kconfig b/drivers/media/usb/pvrusb2/Kconfig index 1ad913fc30bf..ac6612cf1bec 100644 --- a/drivers/media/usb/pvrusb2/Kconfig +++ b/drivers/media/usb/pvrusb2/Kconfig @@ -9,7 +9,7 @@ config VIDEO_PVRUSB2 select VIDEO_MSP3400 select VIDEO_WM8775 select VIDEO_CS53L32A - ---help--- + help This is a video4linux driver for Conexant 23416 based usb2 personal video recorder devices. @@ -20,7 +20,7 @@ config VIDEO_PVRUSB2_SYSFS bool "pvrusb2 sysfs support" default y depends on VIDEO_PVRUSB2 && SYSFS - ---help--- + help This option enables the operation of a sysfs based interface for query and control of the pvrusb2 driver. @@ -43,7 +43,7 @@ config VIDEO_PVRUSB2_DVB select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT - ---help--- + help This option enables a DVB interface for the pvrusb2 driver. If your device does not support digital television, this feature will have no affect on the driver's operation. @@ -53,7 +53,7 @@ config VIDEO_PVRUSB2_DVB config VIDEO_PVRUSB2_DEBUGIFC bool "pvrusb2 debug interface" depends on VIDEO_PVRUSB2_SYSFS - ---help--- + help This option enables the inclusion of a debug interface in the pvrusb2 driver, hosted through sysfs. diff --git a/drivers/media/usb/pwc/Kconfig b/drivers/media/usb/pwc/Kconfig index d63d0a850035..5f6d91edca41 100644 --- a/drivers/media/usb/pwc/Kconfig +++ b/drivers/media/usb/pwc/Kconfig @@ -2,7 +2,7 @@ config USB_PWC tristate "USB Philips Cameras" depends on VIDEO_V4L2 select VIDEOBUF2_VMALLOC - ---help--- + help Say Y or M here if you want to use one of these Philips & OEM webcams: * Philips PCA645, PCA646 @@ -41,7 +41,7 @@ config USB_PWC_INPUT_EVDEV bool "USB Philips Cameras input events device support" default y depends on USB_PWC && (USB_PWC=INPUT || INPUT=y) - ---help--- + help This option makes USB Philips cameras register the snapshot button as an input device to report button events. diff --git a/drivers/media/usb/rainshadow-cec/Kconfig b/drivers/media/usb/rainshadow-cec/Kconfig index 030ef01b1ff0..6b00be618db8 100644 --- a/drivers/media/usb/rainshadow-cec/Kconfig +++ b/drivers/media/usb/rainshadow-cec/Kconfig @@ -4,7 +4,7 @@ config USB_RAINSHADOW_CEC select CEC_CORE select SERIO select SERIO_SERPORT - ---help--- + help This is a cec driver for the RainShadow Tech HDMI CEC device. To compile this driver as a module, choose M here: the diff --git a/drivers/media/usb/siano/Kconfig b/drivers/media/usb/siano/Kconfig index d37b742d4f7a..cc5e5aa3c93a 100644 --- a/drivers/media/usb/siano/Kconfig +++ b/drivers/media/usb/siano/Kconfig @@ -8,6 +8,6 @@ config SMS_USB_DRV depends on !RC_CORE || RC_CORE select MEDIA_COMMON_OPTIONS select SMS_SIANO_MDTV - ---help--- + help Choose if you would like to have Siano's support for USB interface diff --git a/drivers/media/usb/stk1160/Kconfig b/drivers/media/usb/stk1160/Kconfig index 425ed00e2599..03426e4437ea 100644 --- a/drivers/media/usb/stk1160/Kconfig +++ b/drivers/media/usb/stk1160/Kconfig @@ -2,7 +2,7 @@ config VIDEO_STK1160_COMMON tristate "STK1160 USB video capture support" depends on VIDEO_DEV && I2C - ---help--- + help This is a video4linux driver for STK1160 based video capture devices. To compile this driver as a module, choose M here: the diff --git a/drivers/media/usb/stkwebcam/Kconfig b/drivers/media/usb/stkwebcam/Kconfig index a6a00aa4fce6..ea9e04b3caaf 100644 --- a/drivers/media/usb/stkwebcam/Kconfig +++ b/drivers/media/usb/stkwebcam/Kconfig @@ -1,7 +1,7 @@ config USB_STKWEBCAM tristate "USB Syntek DC1125 Camera support" depends on VIDEO_V4L2 - ---help--- + help Say Y here if you want to use this type of camera. Supported devices are typically found in some Asus laptops, with USB id 174f:a311 and 05e1:0501. Other Syntek cameras diff --git a/drivers/media/usb/tm6000/Kconfig b/drivers/media/usb/tm6000/Kconfig index a43b77abd931..321ae691f4d9 100644 --- a/drivers/media/usb/tm6000/Kconfig +++ b/drivers/media/usb/tm6000/Kconfig @@ -18,7 +18,7 @@ config VIDEO_TM6000_ALSA tristate "TV Master TM5600/6000/6010 audio support" depends on VIDEO_TM6000 && SND select SND_PCM - ---help--- + help This is a video4linux driver for direct (DMA) audio for TM5600/TM6000/TM6010 USB Devices. @@ -29,5 +29,5 @@ config VIDEO_TM6000_DVB tristate "DVB Support for tm6000 based TV cards" depends on VIDEO_TM6000 && DVB_CORE && USB select DVB_ZL10353 - ---help--- + help This adds support for DVB cards based on the tm5600/tm6000 chip. diff --git a/drivers/media/usb/usbtv/Kconfig b/drivers/media/usb/usbtv/Kconfig index 14a0941fa0d0..2b4ac0848469 100644 --- a/drivers/media/usb/usbtv/Kconfig +++ b/drivers/media/usb/usbtv/Kconfig @@ -4,7 +4,7 @@ config VIDEO_USBTV select SND_PCM select VIDEOBUF2_VMALLOC - ---help--- + help This is a video4linux2 driver for USBTV007 based video capture devices. To compile this driver as a module, choose M here: the diff --git a/drivers/media/usb/usbvision/Kconfig b/drivers/media/usb/usbvision/Kconfig index 6b6afc5d8f7e..7aa080cb9884 100644 --- a/drivers/media/usb/usbvision/Kconfig +++ b/drivers/media/usb/usbvision/Kconfig @@ -3,7 +3,7 @@ config VIDEO_USBVISION depends on I2C && VIDEO_V4L2 select VIDEO_TUNER select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT - ---help--- + help There are more than 50 different USB video devices based on NT1003/1004/1005 USB Bridges. This driver enables using those devices. diff --git a/drivers/media/usb/uvc/Kconfig b/drivers/media/usb/uvc/Kconfig index 6ed85efabcaa..94937d0cc2e3 100644 --- a/drivers/media/usb/uvc/Kconfig +++ b/drivers/media/usb/uvc/Kconfig @@ -2,7 +2,7 @@ config USB_VIDEO_CLASS tristate "USB Video Class (UVC)" depends on VIDEO_V4L2 select VIDEOBUF2_VMALLOC - ---help--- + help Support for the USB Video Class (UVC). Currently only video input devices, such as webcams, are supported. @@ -13,7 +13,7 @@ config USB_VIDEO_CLASS_INPUT_EVDEV default y depends on USB_VIDEO_CLASS depends on USB_VIDEO_CLASS=INPUT || INPUT=y - ---help--- + help This option makes USB Video Class devices register an input device to report button events. diff --git a/drivers/media/usb/zr364xx/Kconfig b/drivers/media/usb/zr364xx/Kconfig index ac429bca70e8..979b1d4f3f68 100644 --- a/drivers/media/usb/zr364xx/Kconfig +++ b/drivers/media/usb/zr364xx/Kconfig @@ -3,7 +3,7 @@ config USB_ZR364XX depends on VIDEO_V4L2 select VIDEOBUF_GEN select VIDEOBUF_VMALLOC - ---help--- + help Say Y here if you want to connect this type of camera to your computer's USB port. See for more info diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig index c0940f5c69b4..8402096f7796 100644 --- a/drivers/media/v4l2-core/Kconfig +++ b/drivers/media/v4l2-core/Kconfig @@ -13,7 +13,7 @@ config VIDEO_V4L2 config VIDEO_ADV_DEBUG bool "Enable advanced debug functionality on V4L2 drivers" default n - ---help--- + help Say Y here to enable advanced debugging functionality on some V4L devices. In doubt, say N. @@ -21,7 +21,7 @@ config VIDEO_ADV_DEBUG config VIDEO_FIXED_MINOR_RANGES bool "Enable old-style fixed minor ranges on drivers/video devices" default n - ---help--- + help Say Y here to enable the old-style fixed-range minor assignments. Only useful if you rely on the old behavior and use mknod instead of udev. @@ -33,7 +33,7 @@ config VIDEO_PCI_SKELETON depends on SAMPLES depends on VIDEO_V4L2 && VIDEOBUF2_CORE depends on VIDEOBUF2_MEMOPS && VIDEOBUF2_DMA_CONTIG - ---help--- + help Enable build of the skeleton PCI driver, used as a reference when developing new drivers. @@ -51,7 +51,7 @@ config V4L2_FLASH_LED_CLASS tristate "V4L2 flash API for LED flash class devices" depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on LEDS_CLASS_FLASH - ---help--- + help Say Y here to enable V4L2 flash API support for LED flash class drivers. diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index 1da5c20d65c0..277df2b39384 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -1,7 +1,7 @@ menuconfig STAGING_MEDIA bool "Media staging drivers" default n - ---help--- + help This option allows you to select a number of media drivers that don't have the "normal" Linux kernel quality level. Most of them don't follow properly the V4L, DVB and/or RC API's, diff --git a/drivers/staging/media/bcm2048/Kconfig b/drivers/staging/media/bcm2048/Kconfig index a9fc6e186494..a1526175eccb 100644 --- a/drivers/staging/media/bcm2048/Kconfig +++ b/drivers/staging/media/bcm2048/Kconfig @@ -5,7 +5,7 @@ config I2C_BCM2048 tristate "Broadcom BCM2048 FM Radio Receiver support" depends on I2C && VIDEO_V4L2 && RADIO_ADAPTERS - ---help--- + help Say Y here if you want support to BCM2048 FM Radio Receiver. This device driver supports only i2c bus. diff --git a/drivers/staging/media/imx/Kconfig b/drivers/staging/media/imx/Kconfig index 36b276ea2ecc..f6d220b649fb 100644 --- a/drivers/staging/media/imx/Kconfig +++ b/drivers/staging/media/imx/Kconfig @@ -6,7 +6,7 @@ config VIDEO_IMX_MEDIA depends on HAS_DMA select VIDEOBUF2_DMA_CONTIG select V4L2_FWNODE - ---help--- + help Say yes here to enable support for video4linux media controller driver for the i.MX5/6 SOC. @@ -17,7 +17,7 @@ config VIDEO_IMX_CSI tristate "i.MX5/6 Camera Sensor Interface driver" depends on VIDEO_IMX_MEDIA && VIDEO_DEV && I2C default y - ---help--- + help A video4linux camera sensor interface driver for i.MX5/6. config VIDEO_IMX7_CSI diff --git a/drivers/staging/media/ipu3/Kconfig b/drivers/staging/media/ipu3/Kconfig index 75cd889f18f7..d5e50f88684a 100644 --- a/drivers/staging/media/ipu3/Kconfig +++ b/drivers/staging/media/ipu3/Kconfig @@ -5,7 +5,7 @@ config VIDEO_IPU3_IMGU depends on X86 select IOMMU_IOVA select VIDEOBUF2_DMA_SG - ---help--- + help This is the Video4Linux2 driver for Intel IPU3 image processing unit, found in Intel Skylake and Kaby Lake SoCs and used for processing images and video. diff --git a/drivers/staging/media/omap4iss/Kconfig b/drivers/staging/media/omap4iss/Kconfig index 841cc0b3ce13..4dcbc5065821 100644 --- a/drivers/staging/media/omap4iss/Kconfig +++ b/drivers/staging/media/omap4iss/Kconfig @@ -6,5 +6,5 @@ config VIDEO_OMAP4 depends on ARCH_OMAP4 || COMPILE_TEST select MFD_SYSCON select VIDEOBUF2_DMA_CONTIG - ---help--- + help Driver for an OMAP 4 ISS controller. From 90675d391e9196e95a9e9e31eaa9693d4a995927 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 6 Mar 2019 16:13:21 -0500 Subject: [PATCH 082/218] media: vb2: add requires_requests bit for stateless codecs Stateless codecs require the use of the Request API as opposed of it being optional. So add a bit to indicate this and let vb2 check for this. If an attempt is made to queue a buffer without an associated request, then the EBADR error is returned to userspace. Doing this check in the vb2 core simplifies drivers, since they don't have to check for this, they can just set this flag. Signed-off-by: Hans Verkuil Reviewed-by: Paul Kocialkowski Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/uapi/v4l/vidioc-qbuf.rst | 4 ++++ drivers/media/common/videobuf2/videobuf2-core.c | 9 +++++++++ drivers/media/common/videobuf2/videobuf2-v4l2.c | 4 ++++ include/media/videobuf2-core.h | 3 +++ 4 files changed, 20 insertions(+) diff --git a/Documentation/media/uapi/v4l/vidioc-qbuf.rst b/Documentation/media/uapi/v4l/vidioc-qbuf.rst index c138d149faea..5739c3676062 100644 --- a/Documentation/media/uapi/v4l/vidioc-qbuf.rst +++ b/Documentation/media/uapi/v4l/vidioc-qbuf.rst @@ -189,6 +189,10 @@ EACCES The ``V4L2_BUF_FLAG_REQUEST_FD`` flag was set but the device does not support requests for the given buffer type. +EBADR + The ``V4L2_BUF_FLAG_REQUEST_FD`` flag was not set but the device requires + that the buffer is part of a request. + EBUSY The first buffer was queued via a request, but the application now tries to queue it directly, or vice versa (it is not permitted to mix the two diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index 678a31a2b549..b98ec6e1a222 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c +++ b/drivers/media/common/videobuf2/videobuf2-core.c @@ -1507,6 +1507,12 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb, vb = q->bufs[index]; + if (!req && vb->state != VB2_BUF_STATE_IN_REQUEST && + q->requires_requests) { + dprintk(1, "qbuf requires a request\n"); + return -EBADR; + } + if ((req && q->uses_qbuf) || (!req && vb->state != VB2_BUF_STATE_IN_REQUEST && q->uses_requests)) { @@ -2238,6 +2244,9 @@ int vb2_core_queue_init(struct vb2_queue *q) WARN_ON(!q->ops->buf_queue)) return -EINVAL; + if (WARN_ON(q->requires_requests && !q->supports_requests)) + return -EINVAL; + INIT_LIST_HEAD(&q->queued_list); INIT_LIST_HEAD(&q->done_list); spin_lock_init(&q->done_lock); diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c index 74d3abf33b50..84de18b30a95 100644 --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c @@ -381,6 +381,10 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md return 0; if (!(b->flags & V4L2_BUF_FLAG_REQUEST_FD)) { + if (q->requires_requests) { + dprintk(1, "%s: queue requires requests\n", opname); + return -EBADR; + } if (q->uses_requests) { dprintk(1, "%s: queue uses requests\n", opname); return -EBUSY; diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index c02af6370e9b..fe010ad62b90 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -482,6 +482,8 @@ struct vb2_buf_ops { * has not been called. This is a vb1 idiom that has been adopted * also by vb2. * @supports_requests: this queue supports the Request API. + * @requires_requests: this queue requires the Request API. If this is set to 1, + * then supports_requests must be set to 1 as well. * @uses_qbuf: qbuf was used directly for this queue. Set to 1 the first * time this is called. Set to 0 when the queue is canceled. * If this is 1, then you cannot queue buffers from a request. @@ -556,6 +558,7 @@ struct vb2_queue { unsigned allow_zero_bytesused:1; unsigned quirk_poll_must_check_waiting_for_buffers:1; unsigned supports_requests:1; + unsigned requires_requests:1; unsigned uses_qbuf:1; unsigned uses_requests:1; From ca0d1bd489a4e4cb0979a84d5b9ed037764d709f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 6 Mar 2019 16:13:23 -0500 Subject: [PATCH 083/218] media: cedrus: set requires_requests The cedrus stateless decoder requires the use of request, so indicate this by setting requires_requests to 1. Note that the cedrus driver never checked for this, and as far as I can tell would just crash if an attempt was made to queue a buffer without a request. Signed-off-by: Hans Verkuil Acked-by: Paul Kocialkowski Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/sunxi/cedrus/cedrus_video.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c index b47854b3bce4..9673874ece10 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c @@ -536,6 +536,7 @@ int cedrus_queue_init(void *priv, struct vb2_queue *src_vq, src_vq->lock = &ctx->dev->dev_mutex; src_vq->dev = ctx->dev->dev; src_vq->supports_requests = true; + src_vq->requires_requests = true; ret = vb2_queue_init(src_vq); if (ret) From e79c7159d471fa5e818bf9ec13e095e22033c792 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 20 Mar 2019 10:31:18 -0400 Subject: [PATCH 084/218] media: media requests: return EBADR instead of EACCES If requests are used when they shouldn't, or not used when they should, then return EBADR (Invalid request descriptor) instead of EACCES. The reason for this change is that EACCES has more to do with permissions (not being the owner of the resource), but in this case the request file descriptor is just wrong for the current mode of the device. Update the documentation accordingly. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/uapi/mediactl/request-api.rst | 2 +- Documentation/media/uapi/v4l/buffer.rst | 2 +- Documentation/media/uapi/v4l/vidioc-qbuf.rst | 12 +++++------- drivers/media/common/videobuf2/videobuf2-v4l2.c | 2 +- drivers/media/media-request.c | 4 ++-- include/media/media-request.h | 4 ++-- 6 files changed, 12 insertions(+), 14 deletions(-) diff --git a/Documentation/media/uapi/mediactl/request-api.rst b/Documentation/media/uapi/mediactl/request-api.rst index 1ad631e549fe..a74c82d95609 100644 --- a/Documentation/media/uapi/mediactl/request-api.rst +++ b/Documentation/media/uapi/mediactl/request-api.rst @@ -93,7 +93,7 @@ A queued request cannot be modified anymore. .. caution:: For :ref:`memory-to-memory devices ` you can use requests only for output buffers, not for capture buffers. Attempting to add a capture buffer - to a request will result in an ``EACCES`` error. + to a request will result in an ``EBADR`` error. If the request contains configurations for multiple entities, individual drivers may synchronize so the requested pipeline's topology is applied before the diff --git a/Documentation/media/uapi/v4l/buffer.rst b/Documentation/media/uapi/v4l/buffer.rst index 81ffdcb89057..b9a2e9dc707c 100644 --- a/Documentation/media/uapi/v4l/buffer.rst +++ b/Documentation/media/uapi/v4l/buffer.rst @@ -326,7 +326,7 @@ struct v4l2_buffer Applications should not set ``V4L2_BUF_FLAG_REQUEST_FD`` for any ioctls other than :ref:`VIDIOC_QBUF `. - If the device does not support requests, then ``EACCES`` will be returned. + If the device does not support requests, then ``EBADR`` will be returned. If requests are supported but an invalid request file descriptor is given, then ``EINVAL`` will be returned. diff --git a/Documentation/media/uapi/v4l/vidioc-qbuf.rst b/Documentation/media/uapi/v4l/vidioc-qbuf.rst index 5739c3676062..dbf7b445a27b 100644 --- a/Documentation/media/uapi/v4l/vidioc-qbuf.rst +++ b/Documentation/media/uapi/v4l/vidioc-qbuf.rst @@ -111,7 +111,7 @@ in use. Setting it means that the buffer will not be passed to the driver until the request itself is queued. Also, the driver will apply any settings associated with the request for this buffer. This field will be ignored unless the ``V4L2_BUF_FLAG_REQUEST_FD`` flag is set. -If the device does not support requests, then ``EACCES`` will be returned. +If the device does not support requests, then ``EBADR`` will be returned. If requests are supported but an invalid request file descriptor is given, then ``EINVAL`` will be returned. @@ -125,7 +125,7 @@ then ``EINVAL`` will be returned. For :ref:`memory-to-memory devices ` you can specify the ``request_fd`` only for output buffers, not for capture buffers. Attempting - to specify this for a capture buffer will result in an ``EACCES`` error. + to specify this for a capture buffer will result in an ``EBADR`` error. Applications call the ``VIDIOC_DQBUF`` ioctl to dequeue a filled (capturing) or displayed (output) buffer from the driver's outgoing @@ -185,12 +185,10 @@ EPIPE codecs if a buffer with the ``V4L2_BUF_FLAG_LAST`` was already dequeued and no new buffers are expected to become available. -EACCES - The ``V4L2_BUF_FLAG_REQUEST_FD`` flag was set but the device does not - support requests for the given buffer type. - EBADR - The ``V4L2_BUF_FLAG_REQUEST_FD`` flag was not set but the device requires + The ``V4L2_BUF_FLAG_REQUEST_FD`` flag was set but the device does not + support requests for the given buffer type, or + the ``V4L2_BUF_FLAG_REQUEST_FD`` flag was not set but the device requires that the buffer is part of a request. EBUSY diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c index 84de18b30a95..b11a779e97b0 100644 --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c @@ -392,7 +392,7 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md return 0; } else if (!q->supports_requests) { dprintk(1, "%s: queue does not support requests\n", opname); - return -EACCES; + return -EBADR; } else if (q->uses_qbuf) { dprintk(1, "%s: queue does not use requests\n", opname); return -EBUSY; diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c index eec2e2b2f6ec..ed87305b29f9 100644 --- a/drivers/media/media-request.c +++ b/drivers/media/media-request.c @@ -251,7 +251,7 @@ media_request_get_by_fd(struct media_device *mdev, int request_fd) if (!mdev || !mdev->ops || !mdev->ops->req_validate || !mdev->ops->req_queue) - return ERR_PTR(-EACCES); + return ERR_PTR(-EBADR); filp = fget(request_fd); if (!filp) @@ -407,7 +407,7 @@ int media_request_object_bind(struct media_request *req, int ret = -EBUSY; if (WARN_ON(!ops->release)) - return -EACCES; + return -EBADR; spin_lock_irqsave(&req->lock, flags); diff --git a/include/media/media-request.h b/include/media/media-request.h index bd36d7431698..3cd25a2717ce 100644 --- a/include/media/media-request.h +++ b/include/media/media-request.h @@ -198,7 +198,7 @@ void media_request_put(struct media_request *req); * Get the request represented by @request_fd that is owned * by the media device. * - * Return a -EACCES error pointer if requests are not supported + * Return a -EBADR error pointer if requests are not supported * by this driver. Return -EINVAL if the request was not found. * Return the pointer to the request if found: the caller will * have to call @media_request_put when it finished using the @@ -231,7 +231,7 @@ static inline void media_request_put(struct media_request *req) static inline struct media_request * media_request_get_by_fd(struct media_device *mdev, int request_fd) { - return ERR_PTR(-EACCES); + return ERR_PTR(-EBADR); } #endif From 7243e5a06e484746b4bead36dc7fc692781c738b Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 6 Mar 2019 16:13:24 -0500 Subject: [PATCH 085/218] media: vicodec: selection api should only check single buffer types The selection api should check only single buffer types because multiplanar types are converted to single in drivers/media/v4l2-core/v4l2-ioctl.c Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vicodec/vicodec-core.c | 20 +++---------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index 39433ffdf417..570d5d0a17ad 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -944,16 +944,6 @@ static int vidioc_g_selection(struct file *file, void *priv, { struct vicodec_ctx *ctx = file2ctx(file); struct vicodec_q_data *q_data; - enum v4l2_buf_type valid_cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - enum v4l2_buf_type valid_out_type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - - if (multiplanar) { - valid_cap_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - valid_out_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - } - - if (s->type != valid_cap_type && s->type != valid_out_type) - return -EINVAL; q_data = get_q_data(ctx, s->type); if (!q_data) @@ -962,8 +952,8 @@ static int vidioc_g_selection(struct file *file, void *priv, * encoder supports only cropping on the OUTPUT buffer * decoder supports only composing on the CAPTURE buffer */ - if ((ctx->is_enc && s->type == valid_out_type) || - (!ctx->is_enc && s->type == valid_cap_type)) { + if ((ctx->is_enc && s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) || + (!ctx->is_enc && s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)) { switch (s->target) { case V4L2_SEL_TGT_COMPOSE: case V4L2_SEL_TGT_CROP: @@ -991,12 +981,8 @@ static int vidioc_s_selection(struct file *file, void *priv, { struct vicodec_ctx *ctx = file2ctx(file); struct vicodec_q_data *q_data; - enum v4l2_buf_type out_type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - if (multiplanar) - out_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - - if (s->type != out_type) + if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) return -EINVAL; q_data = get_q_data(ctx, s->type); From fb56f4be05adb64674a8a4ec230090960a61732e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 12 Mar 2019 07:53:55 -0400 Subject: [PATCH 086/218] media: vicodec: fix g_selection: either handle crop or compose The logic of g_selection was wrong: encoders support crop, decoders support compose, but the code allowed both. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vicodec/vicodec-core.c | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index 570d5d0a17ad..c34a1ac15243 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -952,11 +952,25 @@ static int vidioc_g_selection(struct file *file, void *priv, * encoder supports only cropping on the OUTPUT buffer * decoder supports only composing on the CAPTURE buffer */ - if ((ctx->is_enc && s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) || - (!ctx->is_enc && s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)) { + if (ctx->is_enc && s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { + switch (s->target) { + case V4L2_SEL_TGT_CROP: + s->r.left = 0; + s->r.top = 0; + s->r.width = q_data->visible_width; + s->r.height = q_data->visible_height; + return 0; + case V4L2_SEL_TGT_CROP_DEFAULT: + case V4L2_SEL_TGT_CROP_BOUNDS: + s->r.left = 0; + s->r.top = 0; + s->r.width = q_data->coded_width; + s->r.height = q_data->coded_height; + return 0; + } + } else if (!ctx->is_enc && s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { switch (s->target) { case V4L2_SEL_TGT_COMPOSE: - case V4L2_SEL_TGT_CROP: s->r.left = 0; s->r.top = 0; s->r.width = q_data->visible_width; @@ -964,8 +978,6 @@ static int vidioc_g_selection(struct file *file, void *priv, return 0; case V4L2_SEL_TGT_COMPOSE_DEFAULT: case V4L2_SEL_TGT_COMPOSE_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: - case V4L2_SEL_TGT_CROP_BOUNDS: s->r.left = 0; s->r.top = 0; s->r.width = q_data->coded_width; From 4d10452cd1ed619d95fde81cef837069f4c754cd Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 6 Mar 2019 16:13:25 -0500 Subject: [PATCH 087/218] media: vicodec: upon release, call m2m release before freeing ctrl handler 'v4l2_m2m_ctx_release' calls request complete so it should be called before 'v4l2_ctrl_handler_free'. Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vicodec/vicodec-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index c34a1ac15243..027daa51ced5 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -1620,12 +1620,12 @@ static int vicodec_release(struct file *file) struct video_device *vfd = video_devdata(file); struct vicodec_ctx *ctx = file2ctx(file); - v4l2_fh_del(&ctx->fh); - v4l2_fh_exit(&ctx->fh); - v4l2_ctrl_handler_free(&ctx->hdl); mutex_lock(vfd->lock); v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); mutex_unlock(vfd->lock); + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + v4l2_ctrl_handler_free(&ctx->hdl); kfree(ctx); return 0; From 09ca38a50795a263d2b16dc95794dc5bc17c1d5c Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 6 Mar 2019 16:13:26 -0500 Subject: [PATCH 088/218] media: v4l2-ctrl: v4l2_ctrl_request_setup returns with error upon failure If one of the controls fails to set, then 'v4l2_ctrl_request_setup' immediately returns with the error code. Signed-off-by: Dafna Hirschfeld Reviewed-by: Paul Kocialkowski Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ctrls.c | 18 +++++++++++------- include/media/v4l2-ctrls.h | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index b79d3bbd8350..54d66dbc2a31 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -3899,18 +3899,19 @@ void v4l2_ctrl_request_complete(struct media_request *req, } EXPORT_SYMBOL(v4l2_ctrl_request_complete); -void v4l2_ctrl_request_setup(struct media_request *req, +int v4l2_ctrl_request_setup(struct media_request *req, struct v4l2_ctrl_handler *main_hdl) { struct media_request_object *obj; struct v4l2_ctrl_handler *hdl; struct v4l2_ctrl_ref *ref; + int ret = 0; if (!req || !main_hdl) - return; + return 0; if (WARN_ON(req->state != MEDIA_REQUEST_STATE_QUEUED)) - return; + return -EBUSY; /* * Note that it is valid if nothing was found. It means @@ -3919,10 +3920,10 @@ void v4l2_ctrl_request_setup(struct media_request *req, */ obj = media_request_object_find(req, &req_ops, main_hdl); if (!obj) - return; + return 0; if (obj->completed) { media_request_object_put(obj); - return; + return -EBUSY; } hdl = container_of(obj, struct v4l2_ctrl_handler, req_obj); @@ -3990,12 +3991,15 @@ void v4l2_ctrl_request_setup(struct media_request *req, update_from_auto_cluster(master); } - try_or_set_cluster(NULL, master, true, 0); - + ret = try_or_set_cluster(NULL, master, true, 0); v4l2_ctrl_unlock(master); + + if (ret) + break; } media_request_object_put(obj); + return ret; } EXPORT_SYMBOL(v4l2_ctrl_request_setup); diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index e5cae37ced2d..200f8a66ecaa 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -1127,7 +1127,7 @@ __poll_t v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait); * applying control values in a request is only applicable to memory-to-memory * devices. */ -void v4l2_ctrl_request_setup(struct media_request *req, +int v4l2_ctrl_request_setup(struct media_request *req, struct v4l2_ctrl_handler *parent); /** From f902796a51a849ad2fc6671817d7b60156dc7559 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 6 Mar 2019 16:13:27 -0500 Subject: [PATCH 089/218] media: vicodec: change variable name for the return value of v4l2_fwht_encode v4l2_fwht_encode returns either an error code on failure or the size of the compressed frame on success. So change the var assigned to it from 'ret' to 'comp_sz_or_errcode' to clarify that. Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vicodec/vicodec-core.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index 027daa51ced5..47765751eed7 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -177,13 +177,14 @@ static int device_process(struct vicodec_ctx *ctx, if (ctx->is_enc) { struct vicodec_q_data *q_src; + int comp_sz_or_errcode; q_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); state->info = q_src->info; - ret = v4l2_fwht_encode(state, p_src, p_dst); - if (ret < 0) - return ret; - vb2_set_plane_payload(&dst_vb->vb2_buf, 0, ret); + comp_sz_or_errcode = v4l2_fwht_encode(state, p_src, p_dst); + if (comp_sz_or_errcode < 0) + return comp_sz_or_errcode; + vb2_set_plane_payload(&dst_vb->vb2_buf, 0, comp_sz_or_errcode); } else { unsigned int comp_frame_size = ntohl(ctx->state.header.size); From 8eead25cbdf911e17cff321903bd3397bc6ea22c Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 6 Mar 2019 16:13:28 -0500 Subject: [PATCH 090/218] media: vicodec: bugfix - call v4l2_m2m_buf_copy_metadata also if decoding fails The function 'v4l2_m2m_buf_copy_metadata' should be called even if decoding/encoding ends with status VB2_BUF_STATE_ERROR, so that the metadata is copied from the source buffer to the dest buffer. Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vicodec/vicodec-core.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index 47765751eed7..11fbc44973b2 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -158,12 +158,10 @@ static int device_process(struct vicodec_ctx *ctx, struct vb2_v4l2_buffer *dst_vb) { struct vicodec_dev *dev = ctx->dev; - struct vicodec_q_data *q_dst; struct v4l2_fwht_state *state = &ctx->state; u8 *p_src, *p_dst; int ret; - q_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); if (ctx->is_enc) p_src = vb2_plane_vaddr(&src_vb->vb2_buf, 0); else @@ -186,8 +184,10 @@ static int device_process(struct vicodec_ctx *ctx, return comp_sz_or_errcode; vb2_set_plane_payload(&dst_vb->vb2_buf, 0, comp_sz_or_errcode); } else { + struct vicodec_q_data *q_dst; unsigned int comp_frame_size = ntohl(ctx->state.header.size); + q_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); if (comp_frame_size > ctx->comp_max_size) return -EINVAL; state->info = q_dst->info; @@ -196,11 +196,6 @@ static int device_process(struct vicodec_ctx *ctx, return ret; vb2_set_plane_payload(&dst_vb->vb2_buf, 0, q_dst->sizeimage); } - - dst_vb->sequence = q_dst->sequence++; - dst_vb->flags &= ~V4L2_BUF_FLAG_LAST; - v4l2_m2m_buf_copy_metadata(src_vb, dst_vb, !ctx->is_enc); - return 0; } @@ -274,16 +269,22 @@ static void device_run(void *priv) struct vicodec_ctx *ctx = priv; struct vicodec_dev *dev = ctx->dev; struct vb2_v4l2_buffer *src_buf, *dst_buf; - struct vicodec_q_data *q_src; + struct vicodec_q_data *q_src, *q_dst; u32 state; src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); q_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); + q_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); state = VB2_BUF_STATE_DONE; if (device_process(ctx, src_buf, dst_buf)) state = VB2_BUF_STATE_ERROR; + else + dst_buf->sequence = q_dst->sequence++; + dst_buf->flags &= ~V4L2_BUF_FLAG_LAST; + v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, !ctx->is_enc); + ctx->last_dst_buf = dst_buf; spin_lock(ctx->lock); From a04a7a2108a1f13addbbcedbeb2cbf7b89dcf970 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 6 Mar 2019 16:13:29 -0500 Subject: [PATCH 091/218] media: vicodec: bugfix: free compressed_frame upon device release Free compressed_frame buffer upon device release. Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vicodec/vicodec-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index 11fbc44973b2..41e09b558a88 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -1628,6 +1628,7 @@ static int vicodec_release(struct file *file) v4l2_fh_del(&ctx->fh); v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->hdl); + kvfree(ctx->state.compressed_frame); kfree(ctx); return 0; From 30364c41bd27ff28bc600a5080558b3b11c008ba Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 6 Mar 2019 16:13:30 -0500 Subject: [PATCH 092/218] media: vicodec: Move raw frame preparation code to a function Introduce 'prepare_raw_frame' function that fills the values of a raw frame struct according to the format. Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/vicodec/codec-v4l2-fwht.c | 205 ++++++++++-------- 1 file changed, 109 insertions(+), 96 deletions(-) diff --git a/drivers/media/platform/vicodec/codec-v4l2-fwht.c b/drivers/media/platform/vicodec/codec-v4l2-fwht.c index 6573a471c5ca..515b3115b3c6 100644 --- a/drivers/media/platform/vicodec/codec-v4l2-fwht.c +++ b/drivers/media/platform/vicodec/codec-v4l2-fwht.c @@ -75,6 +75,107 @@ const struct v4l2_fwht_pixfmt_info *v4l2_fwht_get_pixfmt(u32 idx) return v4l2_fwht_pixfmts + idx; } +static int prepare_raw_frame(struct fwht_raw_frame *rf, + const struct v4l2_fwht_pixfmt_info *info, u8 *buf, + unsigned int size) +{ + rf->luma = buf; + rf->width_div = info->width_div; + rf->height_div = info->height_div; + rf->luma_alpha_step = info->luma_alpha_step; + rf->chroma_step = info->chroma_step; + rf->alpha = NULL; + rf->components_num = info->components_num; + + switch (info->id) { + case V4L2_PIX_FMT_GREY: + rf->cb = NULL; + rf->cr = NULL; + break; + case V4L2_PIX_FMT_YUV420: + rf->cb = rf->luma + size; + rf->cr = rf->cb + size / 4; + break; + case V4L2_PIX_FMT_YVU420: + rf->cr = rf->luma + size; + rf->cb = rf->cr + size / 4; + break; + case V4L2_PIX_FMT_YUV422P: + rf->cb = rf->luma + size; + rf->cr = rf->cb + size / 2; + break; + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV24: + rf->cb = rf->luma + size; + rf->cr = rf->cb + 1; + break; + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV61: + case V4L2_PIX_FMT_NV42: + rf->cr = rf->luma + size; + rf->cb = rf->cr + 1; + break; + case V4L2_PIX_FMT_YUYV: + rf->cb = rf->luma + 1; + rf->cr = rf->cb + 2; + break; + case V4L2_PIX_FMT_YVYU: + rf->cr = rf->luma + 1; + rf->cb = rf->cr + 2; + break; + case V4L2_PIX_FMT_UYVY: + rf->cb = rf->luma; + rf->cr = rf->cb + 2; + rf->luma++; + break; + case V4L2_PIX_FMT_VYUY: + rf->cr = rf->luma; + rf->cb = rf->cr + 2; + rf->luma++; + break; + case V4L2_PIX_FMT_RGB24: + case V4L2_PIX_FMT_HSV24: + rf->cr = rf->luma; + rf->cb = rf->cr + 2; + rf->luma++; + break; + case V4L2_PIX_FMT_BGR24: + rf->cb = rf->luma; + rf->cr = rf->cb + 2; + rf->luma++; + break; + case V4L2_PIX_FMT_RGB32: + case V4L2_PIX_FMT_XRGB32: + case V4L2_PIX_FMT_HSV32: + rf->cr = rf->luma + 1; + rf->cb = rf->cr + 2; + rf->luma += 2; + break; + case V4L2_PIX_FMT_BGR32: + case V4L2_PIX_FMT_XBGR32: + rf->cb = rf->luma; + rf->cr = rf->cb + 2; + rf->luma++; + break; + case V4L2_PIX_FMT_ARGB32: + rf->alpha = rf->luma; + rf->cr = rf->luma + 1; + rf->cb = rf->cr + 2; + rf->luma += 2; + break; + case V4L2_PIX_FMT_ABGR32: + rf->cb = rf->luma; + rf->cr = rf->cb + 2; + rf->luma++; + rf->alpha = rf->cr + 1; + break; + default: + return -EINVAL; + } + return 0; +} + int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out) { unsigned int size = state->stride * state->coded_height; @@ -89,103 +190,15 @@ int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out) if (!info) return -EINVAL; - rf.luma = p_in; - rf.width_div = info->width_div; - rf.height_div = info->height_div; - rf.luma_alpha_step = info->luma_alpha_step; - rf.chroma_step = info->chroma_step; - rf.alpha = NULL; - rf.components_num = info->components_num; - - switch (info->id) { - case V4L2_PIX_FMT_GREY: - rf.cb = NULL; - rf.cr = NULL; - break; - case V4L2_PIX_FMT_YUV420: - rf.cb = rf.luma + size; - rf.cr = rf.cb + size / 4; - chroma_stride /= 2; - break; - case V4L2_PIX_FMT_YVU420: - rf.cr = rf.luma + size; - rf.cb = rf.cr + size / 4; - chroma_stride /= 2; - break; - case V4L2_PIX_FMT_YUV422P: - rf.cb = rf.luma + size; - rf.cr = rf.cb + size / 2; - chroma_stride /= 2; - break; - case V4L2_PIX_FMT_NV12: - case V4L2_PIX_FMT_NV16: - case V4L2_PIX_FMT_NV24: - rf.cb = rf.luma + size; - rf.cr = rf.cb + 1; - break; - case V4L2_PIX_FMT_NV21: - case V4L2_PIX_FMT_NV61: - case V4L2_PIX_FMT_NV42: - rf.cr = rf.luma + size; - rf.cb = rf.cr + 1; - break; - case V4L2_PIX_FMT_YUYV: - rf.cb = rf.luma + 1; - rf.cr = rf.cb + 2; - break; - case V4L2_PIX_FMT_YVYU: - rf.cr = rf.luma + 1; - rf.cb = rf.cr + 2; - break; - case V4L2_PIX_FMT_UYVY: - rf.cb = rf.luma; - rf.cr = rf.cb + 2; - rf.luma++; - break; - case V4L2_PIX_FMT_VYUY: - rf.cr = rf.luma; - rf.cb = rf.cr + 2; - rf.luma++; - break; - case V4L2_PIX_FMT_RGB24: - case V4L2_PIX_FMT_HSV24: - rf.cr = rf.luma; - rf.cb = rf.cr + 2; - rf.luma++; - break; - case V4L2_PIX_FMT_BGR24: - rf.cb = rf.luma; - rf.cr = rf.cb + 2; - rf.luma++; - break; - case V4L2_PIX_FMT_RGB32: - case V4L2_PIX_FMT_XRGB32: - case V4L2_PIX_FMT_HSV32: - rf.cr = rf.luma + 1; - rf.cb = rf.cr + 2; - rf.luma += 2; - break; - case V4L2_PIX_FMT_BGR32: - case V4L2_PIX_FMT_XBGR32: - rf.cb = rf.luma; - rf.cr = rf.cb + 2; - rf.luma++; - break; - case V4L2_PIX_FMT_ARGB32: - rf.alpha = rf.luma; - rf.cr = rf.luma + 1; - rf.cb = rf.cr + 2; - rf.luma += 2; - break; - case V4L2_PIX_FMT_ABGR32: - rf.cb = rf.luma; - rf.cr = rf.cb + 2; - rf.luma++; - rf.alpha = rf.cr + 1; - break; - default: + if (prepare_raw_frame(&rf, info, p_in, size)) return -EINVAL; - } + + if (info->planes_num == 3) + chroma_stride /= 2; + + if (info->id == V4L2_PIX_FMT_NV24 || + info->id == V4L2_PIX_FMT_NV42) + chroma_stride *= 2; cf.i_frame_qp = state->i_frame_qp; cf.p_frame_qp = state->p_frame_qp; From bdbfd992bb9f19817911205cb7173cc6328de2a3 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 6 Mar 2019 16:13:31 -0500 Subject: [PATCH 093/218] media: vicodec: add field 'buf' to fwht_raw_frame Add the field 'buf' to fwht_raw_frame to indicate the start of the raw frame buffer. This field will be used to copy the capture buffer to the reference buffer in the next patch. Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vicodec/codec-fwht.h | 1 + drivers/media/platform/vicodec/vicodec-core.c | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/vicodec/codec-fwht.h b/drivers/media/platform/vicodec/codec-fwht.h index c410512d47c5..8f0b790839f8 100644 --- a/drivers/media/platform/vicodec/codec-fwht.h +++ b/drivers/media/platform/vicodec/codec-fwht.h @@ -124,6 +124,7 @@ struct fwht_raw_frame { unsigned int luma_alpha_step; unsigned int chroma_step; unsigned int components_num; + u8 *buf; u8 *luma, *cb, *cr, *alpha; }; diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index 41e09b558a88..467352d71674 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -1366,7 +1366,8 @@ static int vicodec_start_streaming(struct vb2_queue *q, state->stride = q_data->coded_width * info->bytesperline_mult; - state->ref_frame.luma = kvmalloc(total_planes_size, GFP_KERNEL); + state->ref_frame.buf = kvmalloc(total_planes_size, GFP_KERNEL); + state->ref_frame.luma = state->ref_frame.buf; ctx->comp_max_size = total_planes_size; new_comp_frame = kvmalloc(ctx->comp_max_size, GFP_KERNEL); @@ -1415,7 +1416,9 @@ static void vicodec_stop_streaming(struct vb2_queue *q) if ((!V4L2_TYPE_IS_OUTPUT(q->type) && !ctx->is_enc) || (V4L2_TYPE_IS_OUTPUT(q->type) && ctx->is_enc)) { - kvfree(ctx->state.ref_frame.luma); + kvfree(ctx->state.ref_frame.buf); + ctx->state.ref_frame.buf = NULL; + ctx->state.ref_frame.luma = NULL; ctx->comp_max_size = 0; ctx->source_changed = false; } From 86764b88c447f9690765db59189ecbeb72325e4c Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 6 Mar 2019 16:13:32 -0500 Subject: [PATCH 094/218] media: vicodec: keep the ref frame according to the format in decoder In the decoder, save the inner reference frame in the same format as the capture buffer. The decoder writes directly to the capture buffer and then the capture buffer is copied to the reference buffer. This will simplify the stateless decoder. Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vicodec/codec-fwht.c | 83 +++--- drivers/media/platform/vicodec/codec-fwht.h | 11 +- .../media/platform/vicodec/codec-v4l2-fwht.c | 263 ++---------------- .../media/platform/vicodec/codec-v4l2-fwht.h | 1 + drivers/media/platform/vicodec/vicodec-core.c | 40 +++ 5 files changed, 126 insertions(+), 272 deletions(-) diff --git a/drivers/media/platform/vicodec/codec-fwht.c b/drivers/media/platform/vicodec/codec-fwht.c index cf469a1191aa..5d3e844d2802 100644 --- a/drivers/media/platform/vicodec/codec-fwht.c +++ b/drivers/media/platform/vicodec/codec-fwht.c @@ -639,12 +639,13 @@ decide_blocktype(const u8 *cur, const u8 *reference, s16 *deltablock, return vari <= vard ? IBLOCK : PBLOCK; } -static void fill_decoder_block(u8 *dst, const s16 *input, int stride) +static void fill_decoder_block(u8 *dst, const s16 *input, int stride, + unsigned int dst_step) { int i, j; for (i = 0; i < 8; i++) { - for (j = 0; j < 8; j++, input++, dst++) { + for (j = 0; j < 8; j++, input++, dst += dst_step) { if (*input < 0) *dst = 0; else if (*input > 255) @@ -652,17 +653,19 @@ static void fill_decoder_block(u8 *dst, const s16 *input, int stride) else *dst = *input; } - dst += stride - 8; + dst += stride - (8 * dst_step); } } -static void add_deltas(s16 *deltas, const u8 *ref, int stride) +static void add_deltas(s16 *deltas, const u8 *ref, int stride, + unsigned int ref_step) { int k, l; for (k = 0; k < 8; k++) { for (l = 0; l < 8; l++) { - *deltas += *ref++; + *deltas += *ref; + ref += ref_step; /* * Due to quantizing, it might possible that the * decoded coefficients are slightly out of range @@ -673,7 +676,7 @@ static void add_deltas(s16 *deltas, const u8 *ref, int stride) *deltas = 255; deltas++; } - ref += stride - 8; + ref += stride - (8 * ref_step); } } @@ -718,8 +721,8 @@ static u32 encode_plane(u8 *input, u8 *refp, __be16 **rlco, __be16 *rlco_max, ifwht(cf->de_coeffs, cf->de_fwht, blocktype); if (blocktype == PBLOCK) - add_deltas(cf->de_fwht, refp, 8); - fill_decoder_block(refp, cf->de_fwht, 8); + add_deltas(cf->de_fwht, refp, 8, 1); + fill_decoder_block(refp, cf->de_fwht, 8, 1); } input += 8 * input_step; @@ -828,8 +831,10 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm, return encoding; } -static bool decode_plane(struct fwht_cframe *cf, const __be16 **rlco, u8 *ref, - u32 height, u32 width, u32 coded_width, +static bool decode_plane(struct fwht_cframe *cf, const __be16 **rlco, + u32 height, u32 width, const u8 *ref, u32 ref_stride, + unsigned int ref_step, u8 *dst, + unsigned int dst_stride, unsigned int dst_step, bool uncompressed, const __be16 *end_of_rlco_buf) { unsigned int copies = 0; @@ -841,10 +846,15 @@ static bool decode_plane(struct fwht_cframe *cf, const __be16 **rlco, u8 *ref, height = round_up(height, 8); if (uncompressed) { + int i; + if (end_of_rlco_buf + 1 < *rlco + width * height / 2) return false; - memcpy(ref, *rlco, width * height); - *rlco += width * height / 2; + for (i = 0; i < height; i++) { + memcpy(dst, *rlco, width); + dst += dst_stride; + *rlco += width / 2; + } return true; } @@ -856,15 +866,17 @@ static bool decode_plane(struct fwht_cframe *cf, const __be16 **rlco, u8 *ref, */ for (j = 0; j < height / 8; j++) { for (i = 0; i < width / 8; i++) { - u8 *refp = ref + j * 8 * coded_width + i * 8; + const u8 *refp = ref + j * 8 * ref_stride + + i * 8 * ref_step; + u8 *dstp = dst + j * 8 * dst_stride + i * 8 * dst_step; if (copies) { memcpy(cf->de_fwht, copy, sizeof(copy)); if (stat & PFRAME_BIT) add_deltas(cf->de_fwht, refp, - coded_width); - fill_decoder_block(refp, cf->de_fwht, - coded_width); + ref_stride, ref_step); + fill_decoder_block(dstp, cf->de_fwht, + dst_stride, dst_step); copies--; continue; } @@ -884,23 +896,29 @@ static bool decode_plane(struct fwht_cframe *cf, const __be16 **rlco, u8 *ref, if (copies) memcpy(copy, cf->de_fwht, sizeof(copy)); if (stat & PFRAME_BIT) - add_deltas(cf->de_fwht, refp, coded_width); - fill_decoder_block(refp, cf->de_fwht, coded_width); + add_deltas(cf->de_fwht, refp, + ref_stride, ref_step); + fill_decoder_block(dstp, cf->de_fwht, dst_stride, + dst_step); } } return true; } -bool fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref, - u32 hdr_flags, unsigned int components_num, - unsigned int width, unsigned int height, - unsigned int coded_width) +bool fwht_decode_frame(struct fwht_cframe *cf, u32 hdr_flags, + unsigned int components_num, unsigned int width, + unsigned int height, const struct fwht_raw_frame *ref, + unsigned int ref_stride, unsigned int ref_chroma_stride, + struct fwht_raw_frame *dst, unsigned int dst_stride, + unsigned int dst_chroma_stride) { const __be16 *rlco = cf->rlc_data; const __be16 *end_of_rlco_buf = cf->rlc_data + (cf->size / sizeof(*rlco)) - 1; - if (!decode_plane(cf, &rlco, ref->luma, height, width, coded_width, + if (!decode_plane(cf, &rlco, height, width, ref->luma, ref_stride, + ref->luma_alpha_step, dst->luma, dst_stride, + dst->luma_alpha_step, hdr_flags & FWHT_FL_LUMA_IS_UNCOMPRESSED, end_of_rlco_buf)) return false; @@ -908,27 +926,30 @@ bool fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref, if (components_num >= 3) { u32 h = height; u32 w = width; - u32 c = coded_width; if (!(hdr_flags & FWHT_FL_CHROMA_FULL_HEIGHT)) h /= 2; - if (!(hdr_flags & FWHT_FL_CHROMA_FULL_WIDTH)) { + if (!(hdr_flags & FWHT_FL_CHROMA_FULL_WIDTH)) w /= 2; - c /= 2; - } - if (!decode_plane(cf, &rlco, ref->cb, h, w, c, + + if (!decode_plane(cf, &rlco, h, w, ref->cb, ref_chroma_stride, + ref->chroma_step, dst->cb, dst_chroma_stride, + dst->chroma_step, hdr_flags & FWHT_FL_CB_IS_UNCOMPRESSED, end_of_rlco_buf)) return false; - if (!decode_plane(cf, &rlco, ref->cr, h, w, c, + if (!decode_plane(cf, &rlco, h, w, ref->cr, ref_chroma_stride, + ref->chroma_step, dst->cr, dst_chroma_stride, + dst->chroma_step, hdr_flags & FWHT_FL_CR_IS_UNCOMPRESSED, end_of_rlco_buf)) return false; } if (components_num == 4) - if (!decode_plane(cf, &rlco, ref->alpha, height, width, - coded_width, + if (!decode_plane(cf, &rlco, height, width, ref->alpha, ref_stride, + ref->luma_alpha_step, dst->alpha, dst_stride, + dst->luma_alpha_step, hdr_flags & FWHT_FL_ALPHA_IS_UNCOMPRESSED, end_of_rlco_buf)) return false; diff --git a/drivers/media/platform/vicodec/codec-fwht.h b/drivers/media/platform/vicodec/codec-fwht.h index 8f0b790839f8..b6fec2b1cbca 100644 --- a/drivers/media/platform/vicodec/codec-fwht.h +++ b/drivers/media/platform/vicodec/codec-fwht.h @@ -141,9 +141,10 @@ u32 fwht_encode_frame(struct fwht_raw_frame *frm, bool is_intra, bool next_is_intra, unsigned int width, unsigned int height, unsigned int stride, unsigned int chroma_stride); -bool fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref, - u32 hdr_flags, unsigned int components_num, - unsigned int width, unsigned int height, - unsigned int coded_width); - +bool fwht_decode_frame(struct fwht_cframe *cf, u32 hdr_flags, + unsigned int components_num, unsigned int width, + unsigned int height, const struct fwht_raw_frame *ref, + unsigned int ref_stride, unsigned int ref_chroma_stride, + struct fwht_raw_frame *dst, unsigned int dst_stride, + unsigned int dst_chroma_stride); #endif diff --git a/drivers/media/platform/vicodec/codec-v4l2-fwht.c b/drivers/media/platform/vicodec/codec-v4l2-fwht.c index 515b3115b3c6..f15d76fae45c 100644 --- a/drivers/media/platform/vicodec/codec-v4l2-fwht.c +++ b/drivers/media/platform/vicodec/codec-v4l2-fwht.c @@ -248,14 +248,17 @@ int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out) int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out) { - unsigned int i, j, k; u32 flags; struct fwht_cframe cf; - u8 *p, *ref_p; unsigned int components_num = 3; unsigned int version; const struct v4l2_fwht_pixfmt_info *info; unsigned int hdr_width_div, hdr_height_div; + struct fwht_raw_frame dst_rf; + unsigned int dst_chroma_stride = state->stride; + unsigned int ref_chroma_stride = state->ref_stride; + unsigned int dst_size = state->stride * state->coded_height; + unsigned int ref_size; if (!state->info) return -EINVAL; @@ -303,241 +306,29 @@ int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out) hdr_height_div != info->height_div) return -EINVAL; - if (!fwht_decode_frame(&cf, &state->ref_frame, flags, components_num, - state->visible_width, state->visible_height, - state->coded_width)) - return -EINVAL; - - /* - * TODO - handle the case where the compressed stream encodes a - * different format than the requested decoded format. - */ - switch (state->info->id) { - case V4L2_PIX_FMT_GREY: - ref_p = state->ref_frame.luma; - for (i = 0; i < state->coded_height; i++) { - memcpy(p_out, ref_p, state->visible_width); - p_out += state->stride; - ref_p += state->coded_width; - } - break; - case V4L2_PIX_FMT_YUV420: - case V4L2_PIX_FMT_YUV422P: - ref_p = state->ref_frame.luma; - for (i = 0; i < state->coded_height; i++) { - memcpy(p_out, ref_p, state->visible_width); - p_out += state->stride; - ref_p += state->coded_width; - } - - ref_p = state->ref_frame.cb; - for (i = 0; i < state->coded_height / 2; i++) { - memcpy(p_out, ref_p, state->visible_width / 2); - p_out += state->stride / 2; - ref_p += state->coded_width / 2; - } - ref_p = state->ref_frame.cr; - for (i = 0; i < state->coded_height / 2; i++) { - memcpy(p_out, ref_p, state->visible_width / 2); - p_out += state->stride / 2; - ref_p += state->coded_width / 2; - } - break; - case V4L2_PIX_FMT_YVU420: - ref_p = state->ref_frame.luma; - for (i = 0; i < state->coded_height; i++) { - memcpy(p_out, ref_p, state->visible_width); - p_out += state->stride; - ref_p += state->coded_width; - } - - ref_p = state->ref_frame.cr; - for (i = 0; i < state->coded_height / 2; i++) { - memcpy(p_out, ref_p, state->visible_width / 2); - p_out += state->stride / 2; - ref_p += state->coded_width / 2; - } - ref_p = state->ref_frame.cb; - for (i = 0; i < state->coded_height / 2; i++) { - memcpy(p_out, ref_p, state->visible_width / 2); - p_out += state->stride / 2; - ref_p += state->coded_width / 2; - } - break; - case V4L2_PIX_FMT_NV12: - case V4L2_PIX_FMT_NV16: - case V4L2_PIX_FMT_NV24: - ref_p = state->ref_frame.luma; - for (i = 0; i < state->coded_height; i++) { - memcpy(p_out, ref_p, state->visible_width); - p_out += state->stride; - ref_p += state->coded_width; - } - - k = 0; - for (i = 0; i < state->coded_height / 2; i++) { - for (j = 0, p = p_out; j < state->coded_width / 2; j++) { - *p++ = state->ref_frame.cb[k]; - *p++ = state->ref_frame.cr[k]; - k++; - } - p_out += state->stride; - } - break; - case V4L2_PIX_FMT_NV21: - case V4L2_PIX_FMT_NV61: - case V4L2_PIX_FMT_NV42: - ref_p = state->ref_frame.luma; - for (i = 0; i < state->coded_height; i++) { - memcpy(p_out, ref_p, state->visible_width); - p_out += state->stride; - ref_p += state->coded_width; - } - - k = 0; - for (i = 0; i < state->coded_height / 2; i++) { - for (j = 0, p = p_out; j < state->coded_width / 2; j++) { - *p++ = state->ref_frame.cr[k]; - *p++ = state->ref_frame.cb[k]; - k++; - } - p_out += state->stride; - } - break; - case V4L2_PIX_FMT_YUYV: - k = 0; - for (i = 0; i < state->coded_height; i++) { - for (j = 0, p = p_out; j < state->coded_width / 2; j++) { - *p++ = state->ref_frame.luma[k]; - *p++ = state->ref_frame.cb[k / 2]; - *p++ = state->ref_frame.luma[k + 1]; - *p++ = state->ref_frame.cr[k / 2]; - k += 2; - } - p_out += state->stride; - } - break; - case V4L2_PIX_FMT_YVYU: - k = 0; - for (i = 0; i < state->coded_height; i++) { - for (j = 0, p = p_out; j < state->coded_width / 2; j++) { - *p++ = state->ref_frame.luma[k]; - *p++ = state->ref_frame.cr[k / 2]; - *p++ = state->ref_frame.luma[k + 1]; - *p++ = state->ref_frame.cb[k / 2]; - k += 2; - } - p_out += state->stride; - } - break; - case V4L2_PIX_FMT_UYVY: - k = 0; - for (i = 0; i < state->coded_height; i++) { - for (j = 0, p = p_out; j < state->coded_width / 2; j++) { - *p++ = state->ref_frame.cb[k / 2]; - *p++ = state->ref_frame.luma[k]; - *p++ = state->ref_frame.cr[k / 2]; - *p++ = state->ref_frame.luma[k + 1]; - k += 2; - } - p_out += state->stride; - } - break; - case V4L2_PIX_FMT_VYUY: - k = 0; - for (i = 0; i < state->coded_height; i++) { - for (j = 0, p = p_out; j < state->coded_width / 2; j++) { - *p++ = state->ref_frame.cr[k / 2]; - *p++ = state->ref_frame.luma[k]; - *p++ = state->ref_frame.cb[k / 2]; - *p++ = state->ref_frame.luma[k + 1]; - k += 2; - } - p_out += state->stride; - } - break; - case V4L2_PIX_FMT_RGB24: - case V4L2_PIX_FMT_HSV24: - k = 0; - for (i = 0; i < state->coded_height; i++) { - for (j = 0, p = p_out; j < state->coded_width; j++) { - *p++ = state->ref_frame.cr[k]; - *p++ = state->ref_frame.luma[k]; - *p++ = state->ref_frame.cb[k]; - k++; - } - p_out += state->stride; - } - break; - case V4L2_PIX_FMT_BGR24: - k = 0; - for (i = 0; i < state->coded_height; i++) { - for (j = 0, p = p_out; j < state->coded_width; j++) { - *p++ = state->ref_frame.cb[k]; - *p++ = state->ref_frame.luma[k]; - *p++ = state->ref_frame.cr[k]; - k++; - } - p_out += state->stride; - } - break; - case V4L2_PIX_FMT_RGB32: - case V4L2_PIX_FMT_XRGB32: - case V4L2_PIX_FMT_HSV32: - k = 0; - for (i = 0; i < state->coded_height; i++) { - for (j = 0, p = p_out; j < state->coded_width; j++) { - *p++ = 0; - *p++ = state->ref_frame.cr[k]; - *p++ = state->ref_frame.luma[k]; - *p++ = state->ref_frame.cb[k]; - k++; - } - p_out += state->stride; - } - break; - case V4L2_PIX_FMT_BGR32: - case V4L2_PIX_FMT_XBGR32: - k = 0; - for (i = 0; i < state->coded_height; i++) { - for (j = 0, p = p_out; j < state->coded_width; j++) { - *p++ = state->ref_frame.cb[k]; - *p++ = state->ref_frame.luma[k]; - *p++ = state->ref_frame.cr[k]; - *p++ = 0; - k++; - } - p_out += state->stride; - } - break; - case V4L2_PIX_FMT_ARGB32: - k = 0; - for (i = 0; i < state->coded_height; i++) { - for (j = 0, p = p_out; j < state->coded_width; j++) { - *p++ = state->ref_frame.alpha[k]; - *p++ = state->ref_frame.cr[k]; - *p++ = state->ref_frame.luma[k]; - *p++ = state->ref_frame.cb[k]; - k++; - } - p_out += state->stride; - } - break; - case V4L2_PIX_FMT_ABGR32: - k = 0; - for (i = 0; i < state->coded_height; i++) { - for (j = 0, p = p_out; j < state->coded_width; j++) { - *p++ = state->ref_frame.cb[k]; - *p++ = state->ref_frame.luma[k]; - *p++ = state->ref_frame.cr[k]; - *p++ = state->ref_frame.alpha[k]; - k++; - } - p_out += state->stride; - } - break; - default: + if (prepare_raw_frame(&dst_rf, info, p_out, dst_size)) return -EINVAL; + if (info->planes_num == 3) { + dst_chroma_stride /= 2; + ref_chroma_stride /= 2; } + if (info->id == V4L2_PIX_FMT_NV24 || + info->id == V4L2_PIX_FMT_NV42) { + dst_chroma_stride *= 2; + ref_chroma_stride *= 2; + } + + + ref_size = state->ref_stride * state->coded_height; + + if (prepare_raw_frame(&state->ref_frame, info, state->ref_frame.buf, + ref_size)) + return -EINVAL; + + if (!fwht_decode_frame(&cf, flags, components_num, + state->visible_width, state->visible_height, + &state->ref_frame, state->ref_stride, ref_chroma_stride, + &dst_rf, state->stride, dst_chroma_stride)) + return -EINVAL; return 0; } diff --git a/drivers/media/platform/vicodec/codec-v4l2-fwht.h b/drivers/media/platform/vicodec/codec-v4l2-fwht.h index aa6fa90a48be..53eba97ebc83 100644 --- a/drivers/media/platform/vicodec/codec-v4l2-fwht.h +++ b/drivers/media/platform/vicodec/codec-v4l2-fwht.h @@ -30,6 +30,7 @@ struct v4l2_fwht_state { unsigned int coded_width; unsigned int coded_height; unsigned int stride; + unsigned int ref_stride; unsigned int gop_size; unsigned int gop_cnt; u16 i_frame_qp; diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index 467352d71674..970b307b6ffa 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -153,6 +153,43 @@ static struct vicodec_q_data *get_q_data(struct vicodec_ctx *ctx, return NULL; } +static void copy_cap_to_ref(const u8 *cap, const struct v4l2_fwht_pixfmt_info *info, + struct v4l2_fwht_state *state) +{ + int plane_idx; + u8 *p_ref = state->ref_frame.buf; + unsigned int cap_stride = state->stride; + unsigned int ref_stride = state->ref_stride; + + for (plane_idx = 0; plane_idx < info->planes_num; plane_idx++) { + int i; + unsigned int h_div = (plane_idx == 1 || plane_idx == 2) ? + info->height_div : 1; + const u8 *row_cap = cap; + u8 *row_ref = p_ref; + + if (info->planes_num == 3 && plane_idx == 1) { + cap_stride /= 2; + ref_stride /= 2; + } + + if (plane_idx == 1 && + (info->id == V4L2_PIX_FMT_NV24 || + info->id == V4L2_PIX_FMT_NV42)) { + cap_stride *= 2; + ref_stride *= 2; + } + + for (i = 0; i < state->visible_height / h_div; i++) { + memcpy(row_ref, row_cap, ref_stride); + row_ref += ref_stride; + row_cap += cap_stride; + } + cap += cap_stride * (state->coded_height / h_div); + p_ref += ref_stride * (state->coded_height / h_div); + } +} + static int device_process(struct vicodec_ctx *ctx, struct vb2_v4l2_buffer *src_vb, struct vb2_v4l2_buffer *dst_vb) @@ -194,6 +231,8 @@ static int device_process(struct vicodec_ctx *ctx, ret = v4l2_fwht_decode(state, p_src, p_dst); if (ret < 0) return ret; + copy_cap_to_ref(p_dst, ctx->state.info, &ctx->state); + vb2_set_plane_payload(&dst_vb->vb2_buf, 0, q_dst->sizeimage); } return 0; @@ -1366,6 +1405,7 @@ static int vicodec_start_streaming(struct vb2_queue *q, state->stride = q_data->coded_width * info->bytesperline_mult; + state->ref_stride = q_data->coded_width * info->luma_alpha_step; state->ref_frame.buf = kvmalloc(total_planes_size, GFP_KERNEL); state->ref_frame.luma = state->ref_frame.buf; ctx->comp_max_size = total_planes_size; From 92dc64d41276c34343dcd542c2b7a1ed2bea42ad Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 6 Mar 2019 16:13:33 -0500 Subject: [PATCH 095/218] media: vicodec: Validate version dependent header values in a separate function Move the code that validates version dependent header values to a separate function 'validate_by_version' Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vicodec/vicodec-core.c | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index 970b307b6ffa..ab837d5cb2d8 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -190,6 +190,23 @@ static void copy_cap_to_ref(const u8 *cap, const struct v4l2_fwht_pixfmt_info *i } } +static bool validate_by_version(unsigned int flags, unsigned int version) +{ + if (!version || version > FWHT_VERSION) + return false; + + if (version >= 2) { + unsigned int components_num = 1 + + ((flags & FWHT_FL_COMPONENTS_NUM_MSK) >> + FWHT_FL_COMPONENTS_NUM_OFFSET); + unsigned int pixenc = flags & FWHT_FL_PIXENC_MSK; + + if (components_num == 0 || components_num > 4 || !pixenc) + return false; + } + return true; +} + static int device_process(struct vicodec_ctx *ctx, struct vb2_v4l2_buffer *src_vb, struct vb2_v4l2_buffer *dst_vb) @@ -396,21 +413,11 @@ static bool is_header_valid(const struct fwht_cframe_hdr *p_hdr) unsigned int version = ntohl(p_hdr->version); unsigned int flags = ntohl(p_hdr->flags); - if (!version || version > FWHT_VERSION) - return false; - if (w < MIN_WIDTH || w > MAX_WIDTH || h < MIN_HEIGHT || h > MAX_HEIGHT) return false; - if (version >= 2) { - unsigned int components_num = 1 + - ((flags & FWHT_FL_COMPONENTS_NUM_MSK) >> - FWHT_FL_COMPONENTS_NUM_OFFSET); - unsigned int pixenc = flags & FWHT_FL_PIXENC_MSK; - - if (components_num == 0 || components_num > 4 || !pixenc) - return false; - } + if (!validate_by_version(flags, version)) + return false; info = info_from_header(p_hdr); if (!info) From 50e4c5e1b6e4ff583a0335d97a6386a00da56446 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 6 Mar 2019 16:13:34 -0500 Subject: [PATCH 096/218] media: vicodec: rename v4l2_fwht_default_fmt to v4l2_fwht_find_nth_fmt Rename 'v4l2_fwht_default_fmt' to 'v4l2_fwht_find_nth_fmt' and add a function 'v4l2_fwht_validate_fmt' to check if a format info matches the parameters. This function will also be used to validate the stateless params when adding support for stateless codecs. Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/vicodec/codec-v4l2-fwht.c | 22 ++++++++++++++----- .../media/platform/vicodec/codec-v4l2-fwht.h | 5 ++++- drivers/media/platform/vicodec/vicodec-core.c | 4 ++-- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/vicodec/codec-v4l2-fwht.c b/drivers/media/platform/vicodec/codec-v4l2-fwht.c index f15d76fae45c..372ed95e1a1f 100644 --- a/drivers/media/platform/vicodec/codec-v4l2-fwht.c +++ b/drivers/media/platform/vicodec/codec-v4l2-fwht.c @@ -37,7 +37,19 @@ static const struct v4l2_fwht_pixfmt_info v4l2_fwht_pixfmts[] = { { V4L2_PIX_FMT_GREY, 1, 1, 1, 1, 0, 1, 1, 1, 1, FWHT_FL_PIXENC_RGB}, }; -const struct v4l2_fwht_pixfmt_info *v4l2_fwht_default_fmt(u32 width_div, +bool v4l2_fwht_validate_fmt(const struct v4l2_fwht_pixfmt_info *info, + u32 width_div, u32 height_div, u32 components_num, + u32 pixenc) +{ + if (info->width_div == width_div && + info->height_div == height_div && + (!pixenc || info->pixenc == pixenc) && + info->components_num == components_num) + return true; + return false; +} + +const struct v4l2_fwht_pixfmt_info *v4l2_fwht_find_nth_fmt(u32 width_div, u32 height_div, u32 components_num, u32 pixenc, @@ -46,10 +58,10 @@ const struct v4l2_fwht_pixfmt_info *v4l2_fwht_default_fmt(u32 width_div, unsigned int i; for (i = 0; i < ARRAY_SIZE(v4l2_fwht_pixfmts); i++) { - if (v4l2_fwht_pixfmts[i].width_div == width_div && - v4l2_fwht_pixfmts[i].height_div == height_div && - (!pixenc || v4l2_fwht_pixfmts[i].pixenc == pixenc) && - v4l2_fwht_pixfmts[i].components_num == components_num) { + bool is_valid = v4l2_fwht_validate_fmt(&v4l2_fwht_pixfmts[i], + width_div, height_div, + components_num, pixenc); + if (is_valid) { if (start_idx == 0) return v4l2_fwht_pixfmts + i; start_idx--; diff --git a/drivers/media/platform/vicodec/codec-v4l2-fwht.h b/drivers/media/platform/vicodec/codec-v4l2-fwht.h index 53eba97ebc83..b59503d4049a 100644 --- a/drivers/media/platform/vicodec/codec-v4l2-fwht.h +++ b/drivers/media/platform/vicodec/codec-v4l2-fwht.h @@ -48,7 +48,10 @@ struct v4l2_fwht_state { const struct v4l2_fwht_pixfmt_info *v4l2_fwht_find_pixfmt(u32 pixelformat); const struct v4l2_fwht_pixfmt_info *v4l2_fwht_get_pixfmt(u32 idx); -const struct v4l2_fwht_pixfmt_info *v4l2_fwht_default_fmt(u32 width_div, +bool v4l2_fwht_validate_fmt(const struct v4l2_fwht_pixfmt_info *info, + u32 width_div, u32 height_div, u32 components_num, + u32 pixenc); +const struct v4l2_fwht_pixfmt_info *v4l2_fwht_find_nth_fmt(u32 width_div, u32 height_div, u32 components_num, u32 pixenc, diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index ab837d5cb2d8..f68c90f995b9 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -401,7 +401,7 @@ info_from_header(const struct fwht_cframe_hdr *p_hdr) FWHT_FL_COMPONENTS_NUM_OFFSET); pixenc = (flags & FWHT_FL_PIXENC_MSK); } - return v4l2_fwht_default_fmt(width_div, height_div, + return v4l2_fwht_find_nth_fmt(width_div, height_div, components_num, pixenc, 0); } @@ -622,7 +622,7 @@ static int enum_fmt(struct v4l2_fmtdesc *f, struct vicodec_ctx *ctx, if (!info || ctx->is_enc) info = v4l2_fwht_get_pixfmt(f->index); else - info = v4l2_fwht_default_fmt(info->width_div, + info = v4l2_fwht_find_nth_fmt(info->width_div, info->height_div, info->components_num, info->pixenc, From 747993722d20ff6586c1c2237f3fd779036f1c56 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 6 Mar 2019 16:13:35 -0500 Subject: [PATCH 097/218] media: vicodec: Handle the case that the reference buffer is NULL In the stateless decoder the reference buffer is null if the frame is an I-frame (flagged with FWHT_FL_I_FRAME). Make sure not to dereference it in that case. Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vicodec/codec-fwht.c | 9 +++++---- drivers/media/platform/vicodec/codec-v4l2-fwht.c | 11 +++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/vicodec/codec-fwht.c b/drivers/media/platform/vicodec/codec-fwht.c index 5d3e844d2802..31faf319e508 100644 --- a/drivers/media/platform/vicodec/codec-fwht.c +++ b/drivers/media/platform/vicodec/codec-fwht.c @@ -841,6 +841,7 @@ static bool decode_plane(struct fwht_cframe *cf, const __be16 **rlco, s16 copy[8 * 8]; u16 stat; unsigned int i, j; + bool is_intra = !ref; width = round_up(width, 8); height = round_up(height, 8); @@ -872,7 +873,7 @@ static bool decode_plane(struct fwht_cframe *cf, const __be16 **rlco, if (copies) { memcpy(cf->de_fwht, copy, sizeof(copy)); - if (stat & PFRAME_BIT) + if ((stat & PFRAME_BIT) && !is_intra) add_deltas(cf->de_fwht, refp, ref_stride, ref_step); fill_decoder_block(dstp, cf->de_fwht, @@ -884,18 +885,18 @@ static bool decode_plane(struct fwht_cframe *cf, const __be16 **rlco, stat = derlc(rlco, cf->coeffs, end_of_rlco_buf); if (stat & OVERFLOW_BIT) return false; - if (stat & PFRAME_BIT) + if ((stat & PFRAME_BIT) && !is_intra) dequantize_inter(cf->coeffs); else dequantize_intra(cf->coeffs); ifwht(cf->coeffs, cf->de_fwht, - (stat & PFRAME_BIT) ? 0 : 1); + ((stat & PFRAME_BIT) && !is_intra) ? 0 : 1); copies = (stat & DUPS_MASK) >> 1; if (copies) memcpy(copy, cf->de_fwht, sizeof(copy)); - if (stat & PFRAME_BIT) + if ((stat & PFRAME_BIT) && !is_intra) add_deltas(cf->de_fwht, refp, ref_stride, ref_step); fill_decoder_block(dstp, cf->de_fwht, dst_stride, diff --git a/drivers/media/platform/vicodec/codec-v4l2-fwht.c b/drivers/media/platform/vicodec/codec-v4l2-fwht.c index 372ed95e1a1f..01e7f09efc4e 100644 --- a/drivers/media/platform/vicodec/codec-v4l2-fwht.c +++ b/drivers/media/platform/vicodec/codec-v4l2-fwht.c @@ -99,6 +99,17 @@ static int prepare_raw_frame(struct fwht_raw_frame *rf, rf->alpha = NULL; rf->components_num = info->components_num; + /* + * The buffer is NULL if it is the reference + * frame of an I-frame in the stateless decoder + */ + if (!buf) { + rf->luma = NULL; + rf->cb = NULL; + rf->cr = NULL; + rf->alpha = NULL; + return 0; + } switch (info->id) { case V4L2_PIX_FMT_GREY: rf->cb = NULL; From c022a4a9572265fbc81e245e1322211c8ab0f4f4 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 6 Mar 2019 16:13:36 -0500 Subject: [PATCH 098/218] media: vicodec: add struct for encoder/decoder instance Add struct 'vicodec_dev_instance' for the fields in vicodec_dev that have have both decoder and encoder versions. Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vicodec/vicodec-core.c | 194 +++++++++--------- 1 file changed, 92 insertions(+), 102 deletions(-) diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index f68c90f995b9..b86985babdb1 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -89,21 +89,21 @@ enum { V4L2_M2M_DST = 1, }; +struct vicodec_dev_instance { + struct video_device vfd; + struct mutex mutex; + spinlock_t lock; + struct v4l2_m2m_dev *m2m_dev; +}; + struct vicodec_dev { struct v4l2_device v4l2_dev; - struct video_device enc_vfd; - struct video_device dec_vfd; + struct vicodec_dev_instance stateful_enc; + struct vicodec_dev_instance stateful_dec; #ifdef CONFIG_MEDIA_CONTROLLER struct media_device mdev; #endif - struct mutex enc_mutex; - struct mutex dec_mutex; - spinlock_t enc_lock; - spinlock_t dec_lock; - - struct v4l2_m2m_dev *enc_dev; - struct v4l2_m2m_dev *dec_dev; }; struct vicodec_ctx { @@ -367,9 +367,9 @@ static void device_run(void *priv) spin_unlock(ctx->lock); if (ctx->is_enc) - v4l2_m2m_job_finish(dev->enc_dev, ctx->fh.m2m_ctx); + v4l2_m2m_job_finish(dev->stateful_enc.m2m_dev, ctx->fh.m2m_ctx); else - v4l2_m2m_job_finish(dev->dec_dev, ctx->fh.m2m_ctx); + v4l2_m2m_job_finish(dev->stateful_dec.m2m_dev, ctx->fh.m2m_ctx); } static void job_remove_src_buf(struct vicodec_ctx *ctx, u32 state) @@ -1504,9 +1504,8 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, src_vq->ops = &vicodec_qops; src_vq->mem_ops = &vb2_vmalloc_memops; src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; - src_vq->lock = ctx->is_enc ? &ctx->dev->enc_mutex : - &ctx->dev->dec_mutex; - + src_vq->lock = ctx->is_enc ? &ctx->dev->stateful_enc.mutex : + &ctx->dev->stateful_dec.mutex; ret = vb2_queue_init(src_vq); if (ret) return ret; @@ -1594,7 +1593,7 @@ static int vicodec_open(struct file *file) goto open_unlock; } - if (vfd == &dev->enc_vfd) + if (vfd == &dev->stateful_enc.vfd) ctx->is_enc = true; v4l2_fh_init(&ctx->fh, video_devdata(file)); @@ -1642,13 +1641,13 @@ static int vicodec_open(struct file *file) ctx->state.colorspace = V4L2_COLORSPACE_REC709; if (ctx->is_enc) { - ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->enc_dev, ctx, - &queue_init); - ctx->lock = &dev->enc_lock; + ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->stateful_enc.m2m_dev, + ctx, &queue_init); + ctx->lock = &dev->stateful_enc.lock; } else { - ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->dec_dev, ctx, - &queue_init); - ctx->lock = &dev->dec_lock; + ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->stateful_dec.m2m_dev, + ctx, &queue_init); + ctx->lock = &dev->stateful_dec.lock; } if (IS_ERR(ctx->fh.m2m_ctx)) { @@ -1707,19 +1706,57 @@ static const struct v4l2_m2m_ops m2m_ops = { .job_ready = job_ready, }; +static int register_instance(struct vicodec_dev *dev, + struct vicodec_dev_instance *dev_instance, + const char *name, bool is_enc) +{ + struct video_device *vfd; + int ret; + + spin_lock_init(&dev_instance->lock); + mutex_init(&dev_instance->mutex); + dev_instance->m2m_dev = v4l2_m2m_init(&m2m_ops); + if (IS_ERR(dev_instance->m2m_dev)) { + v4l2_err(&dev->v4l2_dev, "Failed to init vicodec enc device\n"); + return PTR_ERR(dev_instance->m2m_dev); + } + + dev_instance->vfd = vicodec_videodev; + vfd = &dev_instance->vfd; + vfd->lock = &dev_instance->mutex; + vfd->v4l2_dev = &dev->v4l2_dev; + strscpy(vfd->name, name, sizeof(vfd->name)); + vfd->device_caps = V4L2_CAP_STREAMING | + (multiplanar ? V4L2_CAP_VIDEO_M2M_MPLANE : V4L2_CAP_VIDEO_M2M); + if (is_enc) { + v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD); + v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD); + } else { + v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD); + v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD); + } + video_set_drvdata(vfd, dev); + + ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); + if (ret) { + v4l2_err(&dev->v4l2_dev, "Failed to register video device '%s'\n", name); + v4l2_m2m_release(dev_instance->m2m_dev); + return ret; + } + v4l2_info(&dev->v4l2_dev, "Device '%s' registered as /dev/video%d\n", + name, vfd->num); + return 0; +} + static int vicodec_probe(struct platform_device *pdev) { struct vicodec_dev *dev; - struct video_device *vfd; int ret; dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); if (!dev) return -ENOMEM; - spin_lock_init(&dev->enc_lock); - spin_lock_init(&dev->dec_lock); - ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); if (ret) return ret; @@ -1733,100 +1770,53 @@ static int vicodec_probe(struct platform_device *pdev) dev->v4l2_dev.mdev = &dev->mdev; #endif - mutex_init(&dev->enc_mutex); - mutex_init(&dev->dec_mutex); - platform_set_drvdata(pdev, dev); - dev->enc_dev = v4l2_m2m_init(&m2m_ops); - if (IS_ERR(dev->enc_dev)) { - v4l2_err(&dev->v4l2_dev, "Failed to init vicodec device\n"); - ret = PTR_ERR(dev->enc_dev); + if (register_instance(dev, &dev->stateful_enc, + "stateful-encoder", true)) goto unreg_dev; - } - dev->dec_dev = v4l2_m2m_init(&m2m_ops); - if (IS_ERR(dev->dec_dev)) { - v4l2_err(&dev->v4l2_dev, "Failed to init vicodec device\n"); - ret = PTR_ERR(dev->dec_dev); - goto err_enc_m2m; - } - - dev->enc_vfd = vicodec_videodev; - vfd = &dev->enc_vfd; - vfd->lock = &dev->enc_mutex; - vfd->v4l2_dev = &dev->v4l2_dev; - strscpy(vfd->name, "vicodec-enc", sizeof(vfd->name)); - vfd->device_caps = V4L2_CAP_STREAMING | - (multiplanar ? V4L2_CAP_VIDEO_M2M_MPLANE : V4L2_CAP_VIDEO_M2M); - v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD); - v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD); - video_set_drvdata(vfd, dev); - - ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); - if (ret) { - v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); - goto err_dec_m2m; - } - v4l2_info(&dev->v4l2_dev, - "Device registered as /dev/video%d\n", vfd->num); - - dev->dec_vfd = vicodec_videodev; - vfd = &dev->dec_vfd; - vfd->lock = &dev->dec_mutex; - vfd->v4l2_dev = &dev->v4l2_dev; - vfd->device_caps = V4L2_CAP_STREAMING | - (multiplanar ? V4L2_CAP_VIDEO_M2M_MPLANE : V4L2_CAP_VIDEO_M2M); - strscpy(vfd->name, "vicodec-dec", sizeof(vfd->name)); - v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD); - v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD); - video_set_drvdata(vfd, dev); - - ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); - if (ret) { - v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); - goto unreg_enc; - } - v4l2_info(&dev->v4l2_dev, - "Device registered as /dev/video%d\n", vfd->num); + if (register_instance(dev, &dev->stateful_dec, + "stateful-decoder", false)) + goto unreg_sf_enc; #ifdef CONFIG_MEDIA_CONTROLLER - ret = v4l2_m2m_register_media_controller(dev->enc_dev, - &dev->enc_vfd, MEDIA_ENT_F_PROC_VIDEO_ENCODER); + ret = v4l2_m2m_register_media_controller(dev->stateful_enc.m2m_dev, + &dev->stateful_enc.vfd, + MEDIA_ENT_F_PROC_VIDEO_ENCODER); if (ret) { - v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller\n"); + v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller for enc\n"); goto unreg_m2m; } - ret = v4l2_m2m_register_media_controller(dev->dec_dev, - &dev->dec_vfd, MEDIA_ENT_F_PROC_VIDEO_DECODER); + ret = v4l2_m2m_register_media_controller(dev->stateful_dec.m2m_dev, + &dev->stateful_dec.vfd, + MEDIA_ENT_F_PROC_VIDEO_DECODER); if (ret) { - v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller\n"); - goto unreg_m2m_enc_mc; + v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller for dec\n"); + goto unreg_m2m_sf_enc_mc; } ret = media_device_register(&dev->mdev); if (ret) { v4l2_err(&dev->v4l2_dev, "Failed to register mem2mem media device\n"); - goto unreg_m2m_dec_mc; + goto unreg_m2m_sf_dec_mc; } #endif return 0; #ifdef CONFIG_MEDIA_CONTROLLER -unreg_m2m_dec_mc: - v4l2_m2m_unregister_media_controller(dev->dec_dev); -unreg_m2m_enc_mc: - v4l2_m2m_unregister_media_controller(dev->enc_dev); +unreg_m2m_sf_dec_mc: + v4l2_m2m_unregister_media_controller(dev->stateful_dec.m2m_dev); +unreg_m2m_sf_enc_mc: + v4l2_m2m_unregister_media_controller(dev->stateful_enc.m2m_dev); unreg_m2m: - video_unregister_device(&dev->dec_vfd); + video_unregister_device(&dev->stateful_dec.vfd); + v4l2_m2m_release(dev->stateful_dec.m2m_dev); #endif -unreg_enc: - video_unregister_device(&dev->enc_vfd); -err_dec_m2m: - v4l2_m2m_release(dev->dec_dev); -err_enc_m2m: - v4l2_m2m_release(dev->enc_dev); +unreg_sf_enc: + video_unregister_device(&dev->stateful_enc.vfd); + v4l2_m2m_release(dev->stateful_enc.m2m_dev); unreg_dev: v4l2_device_unregister(&dev->v4l2_dev); @@ -1841,15 +1831,15 @@ static int vicodec_remove(struct platform_device *pdev) #ifdef CONFIG_MEDIA_CONTROLLER media_device_unregister(&dev->mdev); - v4l2_m2m_unregister_media_controller(dev->enc_dev); - v4l2_m2m_unregister_media_controller(dev->dec_dev); + v4l2_m2m_unregister_media_controller(dev->stateful_enc.m2m_dev); + v4l2_m2m_unregister_media_controller(dev->stateful_dec.m2m_dev); media_device_cleanup(&dev->mdev); #endif - v4l2_m2m_release(dev->enc_dev); - v4l2_m2m_release(dev->dec_dev); - video_unregister_device(&dev->enc_vfd); - video_unregister_device(&dev->dec_vfd); + v4l2_m2m_release(dev->stateful_enc.m2m_dev); + v4l2_m2m_release(dev->stateful_dec.m2m_dev); + video_unregister_device(&dev->stateful_enc.vfd); + video_unregister_device(&dev->stateful_dec.vfd); v4l2_device_unregister(&dev->v4l2_dev); return 0; From b663e57cb490cb7a712057e4a4e5159f174cf9e8 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 6 Mar 2019 16:13:37 -0500 Subject: [PATCH 099/218] media: vicodec: add documentation to V4L2_CID_FWHT_I/P_FRAME_QP add documentation to V4L2_CID_FWHT_I/P_FRAME_QP controls in ext-ctrls-codec.rst [mchehab+samsung@kernel.org: remove extra blank lines] Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/uapi/v4l/ext-ctrls-codec.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst index c97fb7923be5..3a0fe41549f7 100644 --- a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst +++ b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst @@ -1537,6 +1537,14 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - non-intra-coded frames, in zigzag scanning order. Only relevant for non-4:2:0 YUV formats. +``V4L2_CID_FWHT_I_FRAME_QP (integer)`` + Quantization parameter for an I frame for FWHT. Valid range: from 1 + to 31. + +``V4L2_CID_FWHT_P_FRAME_QP (integer)`` + Quantization parameter for a P frame for FWHT. Valid range: from 1 + to 31. + MFC 5.1 MPEG Controls ===================== From f94368e3b04aca0d204d56a076bfca572e2c6c5f Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 6 Mar 2019 16:13:38 -0500 Subject: [PATCH 100/218] media: vicodec: add documentation to V4L2_CID_MPEG_VIDEO_FWHT_PARAMS add documentation to V4L2_CID_MPEG_VIDEO_FWHT_PARAMS control and its related 'v4l2_ctrl_fwht_params' struct [mchehab+samsung@kernel.org: remove extra blank lines] Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/uapi/v4l/ext-ctrls-codec.rst | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst index 3a0fe41549f7..0aaee04f81dd 100644 --- a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst +++ b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst @@ -1704,6 +1704,122 @@ enum v4l2_mpeg_mfc51_video_force_frame_type - - Force a non-coded frame. +.. _v4l2-mpeg-fwht: + +``V4L2_CID_MPEG_VIDEO_FWHT_PARAMS (struct)`` + Specifies the fwht parameters (as extracted from the bitstream) for the + associated FWHT data. This includes the necessary parameters for + configuring a stateless hardware decoding pipeline for FWHT. + + .. note:: + + This compound control is not yet part of the public kernel API and + it is expected to change. + +.. c:type:: v4l2_ctrl_fwht_params + +.. cssclass:: longtable + +.. flat-table:: struct v4l2_ctrl_fwht_params + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u64 + - ``backward_ref_ts`` + - Timestamp of the V4L2 capture buffer to use as backward reference, used + with P-coded frames. The timestamp refers to the + ``timestamp`` field in struct :c:type:`v4l2_buffer`. Use the + :c:func:`v4l2_timeval_to_ns()` function to convert the struct + :c:type:`timeval` in struct :c:type:`v4l2_buffer` to a __u64. + * - __u32 + - ``version`` + - The version of the codec + * - __u32 + - ``width`` + - The width of the frame + * - __u32 + - ``height`` + - The height of the frame + * - __u32 + - ``flags`` + - The flags of the frame, see :ref:`fwht-flags`. + * - __u32 + - ``colorspace`` + - The colorspace of the frame, from enum :c:type:`v4l2_colorspace`. + * - __u32 + - ``xfer_func`` + - The transfer function, from enum :c:type:`v4l2_xfer_func`. + * - __u32 + - ``ycbcr_enc`` + - The Y'CbCr encoding, from enum :c:type:`v4l2_ycbcr_encoding`. + * - __u32 + - ``quantization`` + - The quantization range, from enum :c:type:`v4l2_quantization`. + + + +.. _fwht-flags: + +FWHT Flags +============ +.. tabularcolumns:: |p{7.0cm}|p{2.2cm}|p{8.3cm}| + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 3 1 4 + + * - ``FWHT_FL_IS_INTERLACED`` + - 0x00000001 + - Set if this is an interlaced format + * - ``FWHT_FL_IS_BOTTOM_FIRST`` + - 0x00000002 + - Set if this is a bottom-first (NTSC) interlaced format + * - ``FWHT_FL_IS_ALTERNATE`` + - 0x00000004 + - Set if each 'frame' contains just one field + * - ``FWHT_FL_IS_BOTTOM_FIELD`` + - 0x00000008 + - If FWHT_FL_IS_ALTERNATE was set, then this is set if this 'frame' is the + bottom field, else it is the top field. + * - ``FWHT_FL_LUMA_IS_UNCOMPRESSED`` + - 0x00000010 + - Set if the luma plane is uncompressed + * - ``FWHT_FL_CB_IS_UNCOMPRESSED`` + - 0x00000020 + - Set if the cb plane is uncompressed + * - ``FWHT_FL_CR_IS_UNCOMPRESSED`` + - 0x00000040 + - Set if the cr plane is uncompressed + * - ``FWHT_FL_CHROMA_FULL_HEIGHT`` + - 0x00000080 + - Set if the chroma plane has the same height as the luma plane, + else the chroma plane is half the height of the luma plane + * - ``FWHT_FL_CHROMA_FULL_WIDTH`` + - 0x00000100 + - Set if the chroma plane has the same width as the luma plane, + else the chroma plane is half the width of the luma plane + * - ``FWHT_FL_ALPHA_IS_UNCOMPRESSED`` + - 0x00000200 + - Set if the alpha plane is uncompressed + * - ``FWHT_FL_I_FRAME`` + - 0x00000400 + - Set if this is an I-frame + * - ``FWHT_FL_COMPONENTS_NUM_MSK`` + - 0x00070000 + - A 4-values flag - the number of components - 1 + * - ``FWHT_FL_PIXENC_YUV`` + - 0x00080000 + - Set if the pixel encoding is YUV + * - ``FWHT_FL_PIXENC_RGB`` + - 0x00100000 + - Set if the pixel encoding is RGB + * - ``FWHT_FL_PIXENC_HSV`` + - 0x00180000 + - Set if the pixel encoding is HSV CX2341x MPEG Controls From ee3963c492ccdb2aa32a45481dea62865bce603d Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 6 Mar 2019 16:13:39 -0500 Subject: [PATCH 101/218] media: vicodec: add documentation to V4L2_PIX_FMT_FWHT_STATELESS add documentation to V4L2_PIX_FMT_FWHT_STATELESS in pixfmt-compressed.rst Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/uapi/v4l/pixfmt-compressed.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/media/uapi/v4l/pixfmt-compressed.rst b/Documentation/media/uapi/v4l/pixfmt-compressed.rst index 2675bef3eefe..6c961cfb74da 100644 --- a/Documentation/media/uapi/v4l/pixfmt-compressed.rst +++ b/Documentation/media/uapi/v4l/pixfmt-compressed.rst @@ -125,3 +125,9 @@ Compressed Formats - Video elementary stream using a codec based on the Fast Walsh Hadamard Transform. This codec is implemented by the vicodec ('Virtual Codec') driver. See the codec-fwht.h header for more details. + * .. _V4L2-PIX-FMT-FWHT-STATELESS: + + - ``V4L2_PIX_FMT_FWHT_STATELESS`` + - 'SFWH' + - Same format as V4L2_PIX_FMT_FWHT but requires stateless codec implementation. + See the :ref:`associated Codec Control IDs `. From 2495f39ce1fa027aab0c3161c14f074295f81c71 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 6 Mar 2019 16:13:40 -0500 Subject: [PATCH 102/218] media: vicodec: Introducing stateless fwht defs and structs Add structs and definitions needed to implement stateless decoder for fwht and add I/P-frames QP controls to the public api. Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vicodec/vicodec-core.c | 41 ++++++------------- drivers/media/v4l2-core/v4l2-ctrls.c | 12 ++++++ include/media/fwht-ctrls.h | 31 ++++++++++++++ include/media/v4l2-ctrls.h | 5 ++- include/uapi/linux/v4l2-controls.h | 4 ++ include/uapi/linux/videodev2.h | 1 + 6 files changed, 65 insertions(+), 29 deletions(-) create mode 100644 include/media/fwht-ctrls.h diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index b86985babdb1..a3a9d8ac4a33 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -64,6 +64,10 @@ static const struct v4l2_fwht_pixfmt_info pixfmt_fwht = { V4L2_PIX_FMT_FWHT, 0, 3, 1, 1, 1, 1, 1, 0, 1 }; +static const struct v4l2_fwht_pixfmt_info pixfmt_stateless_fwht = { + V4L2_PIX_FMT_FWHT_STATELESS, 0, 3, 1, 1, 1, 1, 1, 0, 1 +}; + static void vicodec_dev_release(struct device *dev) { } @@ -1524,10 +1528,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, return vb2_queue_init(dst_vq); } -#define VICODEC_CID_CUSTOM_BASE (V4L2_CID_MPEG_BASE | 0xf000) -#define VICODEC_CID_I_FRAME_QP (VICODEC_CID_CUSTOM_BASE + 0) -#define VICODEC_CID_P_FRAME_QP (VICODEC_CID_CUSTOM_BASE + 1) - static int vicodec_s_ctrl(struct v4l2_ctrl *ctrl) { struct vicodec_ctx *ctx = container_of(ctrl->handler, @@ -1537,10 +1537,10 @@ static int vicodec_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_MPEG_VIDEO_GOP_SIZE: ctx->state.gop_size = ctrl->val; return 0; - case VICODEC_CID_I_FRAME_QP: + case V4L2_CID_FWHT_I_FRAME_QP: ctx->state.i_frame_qp = ctrl->val; return 0; - case VICODEC_CID_P_FRAME_QP: + case V4L2_CID_FWHT_P_FRAME_QP: ctx->state.p_frame_qp = ctrl->val; return 0; } @@ -1551,26 +1551,9 @@ static const struct v4l2_ctrl_ops vicodec_ctrl_ops = { .s_ctrl = vicodec_s_ctrl, }; -static const struct v4l2_ctrl_config vicodec_ctrl_i_frame = { - .ops = &vicodec_ctrl_ops, - .id = VICODEC_CID_I_FRAME_QP, - .name = "FWHT I-Frame QP Value", - .type = V4L2_CTRL_TYPE_INTEGER, - .min = 1, - .max = 31, - .def = 20, - .step = 1, -}; - -static const struct v4l2_ctrl_config vicodec_ctrl_p_frame = { - .ops = &vicodec_ctrl_ops, - .id = VICODEC_CID_P_FRAME_QP, - .name = "FWHT P-Frame QP Value", - .type = V4L2_CTRL_TYPE_INTEGER, - .min = 1, - .max = 31, - .def = 20, - .step = 1, +static const struct v4l2_ctrl_config vicodec_ctrl_stateless_state = { + .id = V4L2_CID_MPEG_VIDEO_FWHT_PARAMS, + .elem_size = sizeof(struct v4l2_ctrl_fwht_params), }; /* @@ -1603,8 +1586,10 @@ static int vicodec_open(struct file *file) v4l2_ctrl_handler_init(hdl, 4); v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 16, 1, 10); - v4l2_ctrl_new_custom(hdl, &vicodec_ctrl_i_frame, NULL); - v4l2_ctrl_new_custom(hdl, &vicodec_ctrl_p_frame, NULL); + v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_FWHT_I_FRAME_QP, + 1, 31, 1, 20); + v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_FWHT_P_FRAME_QP, + 1, 31, 1, 20); if (hdl->error) { rc = hdl->error; v4l2_ctrl_handler_free(hdl); diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 54d66dbc2a31..aed1c3a06500 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -849,6 +849,9 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: return "Force Key Frame"; case V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS: return "MPEG-2 Slice Parameters"; case V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION: return "MPEG-2 Quantization Matrices"; + case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS: return "FWHT Stateless Parameters"; + case V4L2_CID_FWHT_I_FRAME_QP: return "FWHT I-Frame QP Value"; + case V4L2_CID_FWHT_P_FRAME_QP: return "FWHT P-Frame QP Value"; /* VPX controls */ case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS: return "VPX Number of Partitions"; @@ -1303,6 +1306,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION: *type = V4L2_CTRL_TYPE_MPEG2_QUANTIZATION; break; + case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS: + *type = V4L2_CTRL_TYPE_FWHT_PARAMS; + break; default: *type = V4L2_CTRL_TYPE_INTEGER; break; @@ -1669,6 +1675,9 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx, case V4L2_CTRL_TYPE_MPEG2_QUANTIZATION: return 0; + case V4L2_CTRL_TYPE_FWHT_PARAMS: + return 0; + default: return -EINVAL; } @@ -2249,6 +2258,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, case V4L2_CTRL_TYPE_MPEG2_QUANTIZATION: elem_size = sizeof(struct v4l2_ctrl_mpeg2_quantization); break; + case V4L2_CTRL_TYPE_FWHT_PARAMS: + elem_size = sizeof(struct v4l2_ctrl_fwht_params); + break; default: if (type < V4L2_CTRL_COMPOUND_TYPES) elem_size = sizeof(s32); diff --git a/include/media/fwht-ctrls.h b/include/media/fwht-ctrls.h new file mode 100644 index 000000000000..615027410e47 --- /dev/null +++ b/include/media/fwht-ctrls.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * These are the FWHT state controls for use with stateless FWHT + * codec drivers. + * + * It turns out that these structs are not stable yet and will undergo + * more changes. So keep them private until they are stable and ready to + * become part of the official public API. + */ + +#ifndef _FWHT_CTRLS_H_ +#define _FWHT_CTRLS_H_ + +#define V4L2_CTRL_TYPE_FWHT_PARAMS 0x0105 + +#define V4L2_CID_MPEG_VIDEO_FWHT_PARAMS (V4L2_CID_MPEG_BASE + 292) + +struct v4l2_ctrl_fwht_params { + __u64 backward_ref_ts; + __u32 version; + __u32 width; + __u32 height; + __u32 flags; + __u32 colorspace; + __u32 xfer_func; + __u32 ycbcr_enc; + __u32 quantization; +}; + + +#endif diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index 200f8a66ecaa..bd621cec65a5 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -23,10 +23,11 @@ #include /* - * Include the mpeg2 stateless codec compound control definitions. + * Include the mpeg2 and fwht stateless codec compound control definitions. * This will move to the public headers once this API is fully stable. */ #include +#include /* forward references */ struct file; @@ -49,6 +50,7 @@ struct poll_table_struct; * @p_char: Pointer to a string. * @p_mpeg2_slice_params: Pointer to a MPEG2 slice parameters structure. * @p_mpeg2_quantization: Pointer to a MPEG2 quantization data structure. + * @p_fwht_params: Pointer to a FWHT stateless parameters structure. * @p: Pointer to a compound value. */ union v4l2_ctrl_ptr { @@ -60,6 +62,7 @@ union v4l2_ctrl_ptr { char *p_char; struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params; struct v4l2_ctrl_mpeg2_quantization *p_mpeg2_quantization; + struct v4l2_ctrl_fwht_params *p_fwht_params; void *p; }; diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 06479f2fb3ae..78816ec88751 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -404,6 +404,10 @@ enum v4l2_mpeg_video_multi_slice_mode { #define V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE (V4L2_CID_MPEG_BASE+228) #define V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME (V4L2_CID_MPEG_BASE+229) +/* CIDs for the FWHT codec as used by the vicodec driver. */ +#define V4L2_CID_FWHT_I_FRAME_QP (V4L2_CID_MPEG_BASE + 290) +#define V4L2_CID_FWHT_P_FRAME_QP (V4L2_CID_MPEG_BASE + 291) + #define V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP (V4L2_CID_MPEG_BASE+300) #define V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP (V4L2_CID_MPEG_BASE+301) #define V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP (V4L2_CID_MPEG_BASE+302) diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 1db220da3bcc..496e6453450c 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -669,6 +669,7 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_VP9 v4l2_fourcc('V', 'P', '9', '0') /* VP9 */ #define V4L2_PIX_FMT_HEVC v4l2_fourcc('H', 'E', 'V', 'C') /* HEVC aka H.265 */ #define V4L2_PIX_FMT_FWHT v4l2_fourcc('F', 'W', 'H', 'T') /* Fast Walsh Hadamard Transform (vicodec) */ +#define V4L2_PIX_FMT_FWHT_STATELESS v4l2_fourcc('S', 'F', 'W', 'H') /* Stateless FWHT (vicodec) */ /* Vendor-specific formats */ #define V4L2_PIX_FMT_CPIA1 v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */ From f05a51b98eaf4f4bf798169ba7793f90cc256e69 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 13 Mar 2019 10:44:20 -0400 Subject: [PATCH 103/218] media: v4l2-ioctl.c: add V4L2_PIX_FMT_FWHT_STATELESS to v4l_fill_fmtdesc Add V4L2_PIX_FMT_FWHT_STATELESS to the list of pixelformats that v4l_fill_fmtdesc() understands. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 038739584a84..ac87c3e37280 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1337,6 +1337,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_VP9: descr = "VP9"; break; case V4L2_PIX_FMT_HEVC: descr = "HEVC"; break; /* aka H.265 */ case V4L2_PIX_FMT_FWHT: descr = "FWHT"; break; /* used in vicodec */ + case V4L2_PIX_FMT_FWHT_STATELESS: descr = "FWHT Stateless"; break; /* used in vicodec */ case V4L2_PIX_FMT_CPIA1: descr = "GSPCA CPiA YUV"; break; case V4L2_PIX_FMT_WNVA: descr = "WNVA"; break; case V4L2_PIX_FMT_SN9C10X: descr = "GSPCA SN9C10X"; break; From fde649b418d15867a1ce0805cc984e4ccc221766 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 6 Mar 2019 16:13:41 -0500 Subject: [PATCH 104/218] media: vicodec: Register another node for stateless decoder Add stateless decoder instance field to the dev struct and register another node for the statelsess decoder. The stateless API for the node will be implemented in further patches. Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil [hverkuil-cisco@xs4all.nl: fix typo: videdev-stateless-dec -> stateless-decoder] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vicodec/vicodec-core.c | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index a3a9d8ac4a33..a8e8db85b684 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -104,6 +104,7 @@ struct vicodec_dev { struct v4l2_device v4l2_dev; struct vicodec_dev_instance stateful_enc; struct vicodec_dev_instance stateful_dec; + struct vicodec_dev_instance stateless_dec; #ifdef CONFIG_MEDIA_CONTROLLER struct media_device mdev; #endif @@ -114,6 +115,7 @@ struct vicodec_ctx { struct v4l2_fh fh; struct vicodec_dev *dev; bool is_enc; + bool is_stateless; spinlock_t *lock; struct v4l2_ctrl_handler hdl; @@ -372,6 +374,9 @@ static void device_run(void *priv) if (ctx->is_enc) v4l2_m2m_job_finish(dev->stateful_enc.m2m_dev, ctx->fh.m2m_ctx); + else if (ctx->is_stateless) + v4l2_m2m_job_finish(dev->stateless_dec.m2m_dev, + ctx->fh.m2m_ctx); else v4l2_m2m_job_finish(dev->stateful_dec.m2m_dev, ctx->fh.m2m_ctx); } @@ -1508,8 +1513,14 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, src_vq->ops = &vicodec_qops; src_vq->mem_ops = &vb2_vmalloc_memops; src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; - src_vq->lock = ctx->is_enc ? &ctx->dev->stateful_enc.mutex : - &ctx->dev->stateful_dec.mutex; + if (ctx->is_enc) + src_vq->lock = &ctx->dev->stateful_enc.mutex; + else if (ctx->is_stateless) + src_vq->lock = &ctx->dev->stateless_dec.mutex; + else + src_vq->lock = &ctx->dev->stateful_dec.mutex; + src_vq->supports_requests = ctx->is_stateless; + src_vq->requires_requests = ctx->is_stateless; ret = vb2_queue_init(src_vq); if (ret) return ret; @@ -1578,6 +1589,8 @@ static int vicodec_open(struct file *file) if (vfd == &dev->stateful_enc.vfd) ctx->is_enc = true; + else if (vfd == &dev->stateless_dec.vfd) + ctx->is_stateless = true; v4l2_fh_init(&ctx->fh, video_devdata(file)); file->private_data = &ctx->fh; @@ -1590,6 +1603,8 @@ static int vicodec_open(struct file *file) 1, 31, 1, 20); v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_FWHT_P_FRAME_QP, 1, 31, 1, 20); + if (ctx->is_stateless) + v4l2_ctrl_new_custom(hdl, &vicodec_ctrl_stateless_state, NULL); if (hdl->error) { rc = hdl->error; v4l2_ctrl_handler_free(hdl); @@ -1629,6 +1644,10 @@ static int vicodec_open(struct file *file) ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->stateful_enc.m2m_dev, ctx, &queue_init); ctx->lock = &dev->stateful_enc.lock; + } else if (ctx->is_stateless) { + ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->stateless_dec.m2m_dev, + ctx, &queue_init); + ctx->lock = &dev->stateless_dec.lock; } else { ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->stateful_dec.m2m_dev, ctx, &queue_init); @@ -1765,6 +1784,10 @@ static int vicodec_probe(struct platform_device *pdev) "stateful-decoder", false)) goto unreg_sf_enc; + if (register_instance(dev, &dev->stateless_dec, + "stateless-decoder", false)) + goto unreg_sf_dec; + #ifdef CONFIG_MEDIA_CONTROLLER ret = v4l2_m2m_register_media_controller(dev->stateful_enc.m2m_dev, &dev->stateful_enc.vfd, @@ -1782,23 +1805,36 @@ static int vicodec_probe(struct platform_device *pdev) goto unreg_m2m_sf_enc_mc; } + ret = v4l2_m2m_register_media_controller(dev->stateless_dec.m2m_dev, + &dev->stateless_dec.vfd, + MEDIA_ENT_F_PROC_VIDEO_DECODER); + if (ret) { + v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller for stateless dec\n"); + goto unreg_m2m_sf_dec_mc; + } + ret = media_device_register(&dev->mdev); if (ret) { v4l2_err(&dev->v4l2_dev, "Failed to register mem2mem media device\n"); - goto unreg_m2m_sf_dec_mc; + goto unreg_m2m_sl_dec_mc; } #endif return 0; #ifdef CONFIG_MEDIA_CONTROLLER +unreg_m2m_sl_dec_mc: + v4l2_m2m_unregister_media_controller(dev->stateless_dec.m2m_dev); unreg_m2m_sf_dec_mc: v4l2_m2m_unregister_media_controller(dev->stateful_dec.m2m_dev); unreg_m2m_sf_enc_mc: v4l2_m2m_unregister_media_controller(dev->stateful_enc.m2m_dev); unreg_m2m: + video_unregister_device(&dev->stateless_dec.vfd); + v4l2_m2m_release(dev->stateless_dec.m2m_dev); +#endif +unreg_sf_dec: video_unregister_device(&dev->stateful_dec.vfd); v4l2_m2m_release(dev->stateful_dec.m2m_dev); -#endif unreg_sf_enc: video_unregister_device(&dev->stateful_enc.vfd); v4l2_m2m_release(dev->stateful_enc.m2m_dev); @@ -1818,6 +1854,7 @@ static int vicodec_remove(struct platform_device *pdev) media_device_unregister(&dev->mdev); v4l2_m2m_unregister_media_controller(dev->stateful_enc.m2m_dev); v4l2_m2m_unregister_media_controller(dev->stateful_dec.m2m_dev); + v4l2_m2m_unregister_media_controller(dev->stateless_dec.m2m_dev); media_device_cleanup(&dev->mdev); #endif @@ -1825,6 +1862,7 @@ static int vicodec_remove(struct platform_device *pdev) v4l2_m2m_release(dev->stateful_dec.m2m_dev); video_unregister_device(&dev->stateful_enc.vfd); video_unregister_device(&dev->stateful_dec.vfd); + video_unregister_device(&dev->stateless_dec.vfd); v4l2_device_unregister(&dev->v4l2_dev); return 0; From 997deb811bf55731a7c0bd972d8d0a266ef8d7e5 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 6 Mar 2019 16:13:42 -0500 Subject: [PATCH 105/218] media: vicodec: Add support for stateless decoder. Implement a stateless decoder for the new node. Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil [hverkuil-cisco@xs4all.nl: add 'return 0;' before default case in vicodec_try_ctrl()] Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/vicodec/codec-v4l2-fwht.h | 1 + drivers/media/platform/vicodec/vicodec-core.c | 287 ++++++++++++++++-- 2 files changed, 264 insertions(+), 24 deletions(-) diff --git a/drivers/media/platform/vicodec/codec-v4l2-fwht.h b/drivers/media/platform/vicodec/codec-v4l2-fwht.h index b59503d4049a..1a0d2a9f931a 100644 --- a/drivers/media/platform/vicodec/codec-v4l2-fwht.h +++ b/drivers/media/platform/vicodec/codec-v4l2-fwht.h @@ -44,6 +44,7 @@ struct v4l2_fwht_state { struct fwht_raw_frame ref_frame; struct fwht_cframe_hdr header; u8 *compressed_frame; + u64 ref_frame_ts; }; const struct v4l2_fwht_pixfmt_info *v4l2_fwht_find_pixfmt(u32 pixelformat); diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index a8e8db85b684..617fc53246e4 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -213,6 +213,41 @@ static bool validate_by_version(unsigned int flags, unsigned int version) return true; } +static bool validate_stateless_params_flags(const struct v4l2_ctrl_fwht_params *params, + const struct v4l2_fwht_pixfmt_info *cur_info) +{ + unsigned int width_div = + (params->flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2; + unsigned int height_div = + (params->flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2; + unsigned int components_num = 3; + unsigned int pixenc = 0; + + if (params->version < 3) + return false; + + components_num = 1 + ((params->flags & FWHT_FL_COMPONENTS_NUM_MSK) >> + FWHT_FL_COMPONENTS_NUM_OFFSET); + pixenc = (params->flags & FWHT_FL_PIXENC_MSK); + if (v4l2_fwht_validate_fmt(cur_info, width_div, height_div, + components_num, pixenc)) + return true; + return false; +} + + +static void update_state_from_header(struct vicodec_ctx *ctx) +{ + const struct fwht_cframe_hdr *p_hdr = &ctx->state.header; + + ctx->state.visible_width = ntohl(p_hdr->width); + ctx->state.visible_height = ntohl(p_hdr->height); + ctx->state.colorspace = ntohl(p_hdr->colorspace); + ctx->state.xfer_func = ntohl(p_hdr->xfer_func); + ctx->state.ycbcr_enc = ntohl(p_hdr->ycbcr_enc); + ctx->state.quantization = ntohl(p_hdr->quantization); +} + static int device_process(struct vicodec_ctx *ctx, struct vb2_v4l2_buffer *src_vb, struct vb2_v4l2_buffer *dst_vb) @@ -220,12 +255,48 @@ static int device_process(struct vicodec_ctx *ctx, struct vicodec_dev *dev = ctx->dev; struct v4l2_fwht_state *state = &ctx->state; u8 *p_src, *p_dst; - int ret; + int ret = 0; - if (ctx->is_enc) + if (ctx->is_enc || ctx->is_stateless) p_src = vb2_plane_vaddr(&src_vb->vb2_buf, 0); else p_src = state->compressed_frame; + + if (ctx->is_stateless) { + struct media_request *src_req = src_vb->vb2_buf.req_obj.req; + + ret = v4l2_ctrl_request_setup(src_req, &ctx->hdl); + if (ret) + return ret; + update_state_from_header(ctx); + + ctx->state.header.size = + htonl(vb2_get_plane_payload(&src_vb->vb2_buf, 0)); + /* + * set the reference buffer from the reference timestamp + * only if this is a P-frame + */ + if (!(ntohl(ctx->state.header.flags) & FWHT_FL_I_FRAME)) { + struct vb2_buffer *ref_vb2_buf; + int ref_buf_idx; + struct vb2_queue *vq_cap = + v4l2_m2m_get_vq(ctx->fh.m2m_ctx, + V4L2_BUF_TYPE_VIDEO_CAPTURE); + + ref_buf_idx = vb2_find_timestamp(vq_cap, + ctx->state.ref_frame_ts, 0); + if (ref_buf_idx < 0) + return -EINVAL; + + ref_vb2_buf = vq_cap->bufs[ref_buf_idx]; + if (ref_vb2_buf->state == VB2_BUF_STATE_ERROR) + ret = -EINVAL; + ctx->state.ref_frame.buf = + vb2_plane_vaddr(ref_vb2_buf, 0); + } else { + ctx->state.ref_frame.buf = NULL; + } + } p_dst = vb2_plane_vaddr(&dst_vb->vb2_buf, 0); if (!p_src || !p_dst) { v4l2_err(&dev->v4l2_dev, @@ -254,11 +325,12 @@ static int device_process(struct vicodec_ctx *ctx, ret = v4l2_fwht_decode(state, p_src, p_dst); if (ret < 0) return ret; - copy_cap_to_ref(p_dst, ctx->state.info, &ctx->state); + if (!ctx->is_stateless) + copy_cap_to_ref(p_dst, ctx->state.info, &ctx->state); vb2_set_plane_payload(&dst_vb->vb2_buf, 0, q_dst->sizeimage); } - return 0; + return ret; } /* @@ -333,9 +405,13 @@ static void device_run(void *priv) struct vb2_v4l2_buffer *src_buf, *dst_buf; struct vicodec_q_data *q_src, *q_dst; u32 state; + struct media_request *src_req; + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + src_req = src_buf->vb2_buf.req_obj.req; + q_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); q_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); @@ -354,7 +430,7 @@ static void device_run(void *priv) dst_buf->flags |= V4L2_BUF_FLAG_LAST; v4l2_event_queue_fh(&ctx->fh, &eos_event); } - if (ctx->is_enc) { + if (ctx->is_enc || ctx->is_stateless) { src_buf->sequence = q_src->sequence++; src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); v4l2_m2m_buf_done(src_buf, state); @@ -366,6 +442,9 @@ static void device_run(void *priv) ctx->comp_has_next_frame = false; } v4l2_m2m_buf_done(dst_buf, state); + if (ctx->is_stateless && src_req) + v4l2_ctrl_request_complete(src_req, &ctx->hdl); + ctx->comp_size = 0; ctx->header_size = 0; ctx->comp_magic_cnt = 0; @@ -444,6 +523,12 @@ static void update_capture_data_from_header(struct vicodec_ctx *ctx) unsigned int hdr_width_div = (flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2; unsigned int hdr_height_div = (flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2; + /* + * This function should not be used by a stateless codec since + * it changes values in q_data that are not request specific + */ + WARN_ON(ctx->is_stateless); + q_dst->info = info; q_dst->visible_width = ntohl(p_hdr->width); q_dst->visible_height = ntohl(p_hdr->height); @@ -496,7 +581,7 @@ static int job_ready(void *priv) if (ctx->source_changed) return 0; - if (ctx->is_enc || ctx->comp_has_frame) + if (ctx->is_stateless || ctx->is_enc || ctx->comp_has_frame) return 1; restart: @@ -1254,6 +1339,14 @@ static int vicodec_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, return 0; } +static int vicodec_buf_out_validate(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + + vbuf->field = V4L2_FIELD_NONE; + return 0; +} + static int vicodec_buf_prepare(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); @@ -1317,10 +1410,11 @@ static void vicodec_buf_queue(struct vb2_buffer *vb) } /* - * source change event is relevant only for the decoder + * source change event is relevant only for the stateful decoder * in the compressed stream */ - if (ctx->is_enc || !V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { + if (ctx->is_stateless || ctx->is_enc || + !V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); return; } @@ -1368,12 +1462,33 @@ static void vicodec_return_bufs(struct vb2_queue *q, u32 state) vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); if (vbuf == NULL) return; + v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req, + &ctx->hdl); spin_lock(ctx->lock); v4l2_m2m_buf_done(vbuf, state); spin_unlock(ctx->lock); } } +static unsigned int total_frame_size(struct vicodec_q_data *q_data) +{ + unsigned int size; + unsigned int chroma_div; + + if (!q_data->info) { + WARN_ON(1); + return 0; + } + size = q_data->coded_width * q_data->coded_height; + chroma_div = q_data->info->width_div * q_data->info->height_div; + + if (q_data->info->components_num == 4) + return 2 * size + 2 * (size / chroma_div); + else if (q_data->info->components_num == 3) + return size + 2 * (size / chroma_div); + return size; +} + static int vicodec_start_streaming(struct vb2_queue *q, unsigned int count) { @@ -1384,7 +1499,7 @@ static int vicodec_start_streaming(struct vb2_queue *q, unsigned int size = q_data->coded_width * q_data->coded_height; unsigned int chroma_div; unsigned int total_planes_size; - u8 *new_comp_frame; + u8 *new_comp_frame = NULL; if (!info) return -EINVAL; @@ -1407,12 +1522,8 @@ static int vicodec_start_streaming(struct vb2_queue *q, vicodec_return_bufs(q, VB2_BUF_STATE_QUEUED); return -EINVAL; } - if (info->components_num == 4) - total_planes_size = 2 * size + 2 * (size / chroma_div); - else if (info->components_num == 3) - total_planes_size = size + 2 * (size / chroma_div); - else - total_planes_size = size; + total_planes_size = total_frame_size(q_data); + ctx->comp_max_size = total_planes_size; state->visible_width = q_data->visible_width; state->visible_height = q_data->visible_height; @@ -1421,10 +1532,14 @@ static int vicodec_start_streaming(struct vb2_queue *q, state->stride = q_data->coded_width * info->bytesperline_mult; + if (ctx->is_stateless) { + state->ref_stride = state->stride; + return 0; + } state->ref_stride = q_data->coded_width * info->luma_alpha_step; + state->ref_frame.buf = kvmalloc(total_planes_size, GFP_KERNEL); state->ref_frame.luma = state->ref_frame.buf; - ctx->comp_max_size = total_planes_size; new_comp_frame = kvmalloc(ctx->comp_max_size, GFP_KERNEL); if (!state->ref_frame.luma || !new_comp_frame) { @@ -1472,7 +1587,8 @@ static void vicodec_stop_streaming(struct vb2_queue *q) if ((!V4L2_TYPE_IS_OUTPUT(q->type) && !ctx->is_enc) || (V4L2_TYPE_IS_OUTPUT(q->type) && ctx->is_enc)) { - kvfree(ctx->state.ref_frame.buf); + if (!ctx->is_stateless) + kvfree(ctx->state.ref_frame.buf); ctx->state.ref_frame.buf = NULL; ctx->state.ref_frame.luma = NULL; ctx->comp_max_size = 0; @@ -1488,14 +1604,24 @@ static void vicodec_stop_streaming(struct vb2_queue *q) } } +static void vicodec_buf_request_complete(struct vb2_buffer *vb) +{ + struct vicodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + + v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl); +} + + static const struct vb2_ops vicodec_qops = { - .queue_setup = vicodec_queue_setup, - .buf_prepare = vicodec_buf_prepare, - .buf_queue = vicodec_buf_queue, - .start_streaming = vicodec_start_streaming, - .stop_streaming = vicodec_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, + .queue_setup = vicodec_queue_setup, + .buf_out_validate = vicodec_buf_out_validate, + .buf_prepare = vicodec_buf_prepare, + .buf_queue = vicodec_buf_queue, + .buf_request_complete = vicodec_buf_request_complete, + .start_streaming = vicodec_start_streaming, + .stop_streaming = vicodec_stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, }; static int queue_init(void *priv, struct vb2_queue *src_vq, @@ -1539,10 +1665,57 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, return vb2_queue_init(dst_vq); } +static int vicodec_try_ctrl(struct v4l2_ctrl *ctrl) +{ + struct vicodec_ctx *ctx = container_of(ctrl->handler, + struct vicodec_ctx, hdl); + const struct v4l2_ctrl_fwht_params *params; + struct vicodec_q_data *q_dst = get_q_data(ctx, + V4L2_BUF_TYPE_VIDEO_CAPTURE); + + switch (ctrl->id) { + case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS: + if (!q_dst->info) + return -EINVAL; + params = ctrl->p_new.p_fwht_params; + if (params->width > q_dst->coded_width || + params->width < MIN_WIDTH || + params->height > q_dst->coded_height || + params->height < MIN_HEIGHT) + return -EINVAL; + if (!validate_by_version(params->flags, params->version)) + return -EINVAL; + if (!validate_stateless_params_flags(params, q_dst->info)) + return -EINVAL; + return 0; + default: + return 0; + } + return 0; +} + +static void update_header_from_stateless_params(struct vicodec_ctx *ctx, + const struct v4l2_ctrl_fwht_params *params) +{ + struct fwht_cframe_hdr *p_hdr = &ctx->state.header; + + p_hdr->magic1 = FWHT_MAGIC1; + p_hdr->magic2 = FWHT_MAGIC2; + p_hdr->version = htonl(params->version); + p_hdr->width = htonl(params->width); + p_hdr->height = htonl(params->height); + p_hdr->flags = htonl(params->flags); + p_hdr->colorspace = htonl(params->colorspace); + p_hdr->xfer_func = htonl(params->xfer_func); + p_hdr->ycbcr_enc = htonl(params->ycbcr_enc); + p_hdr->quantization = htonl(params->quantization); +} + static int vicodec_s_ctrl(struct v4l2_ctrl *ctrl) { struct vicodec_ctx *ctx = container_of(ctrl->handler, struct vicodec_ctx, hdl); + const struct v4l2_ctrl_fwht_params *params; switch (ctrl->id) { case V4L2_CID_MPEG_VIDEO_GOP_SIZE: @@ -1554,15 +1727,22 @@ static int vicodec_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_FWHT_P_FRAME_QP: ctx->state.p_frame_qp = ctrl->val; return 0; + case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS: + params = ctrl->p_new.p_fwht_params; + update_header_from_stateless_params(ctx, params); + ctx->state.ref_frame_ts = params->backward_ref_ts; + return 0; } return -EINVAL; } static const struct v4l2_ctrl_ops vicodec_ctrl_ops = { .s_ctrl = vicodec_s_ctrl, + .try_ctrl = vicodec_try_ctrl, }; static const struct v4l2_ctrl_config vicodec_ctrl_stateless_state = { + .ops = &vicodec_ctrl_ops, .id = V4L2_CID_MPEG_VIDEO_FWHT_PARAMS, .elem_size = sizeof(struct v4l2_ctrl_fwht_params), }; @@ -1687,6 +1867,59 @@ static int vicodec_release(struct file *file) return 0; } +static int vicodec_request_validate(struct media_request *req) +{ + struct media_request_object *obj; + struct v4l2_ctrl_handler *parent_hdl, *hdl; + struct vicodec_ctx *ctx = NULL; + struct v4l2_ctrl *ctrl; + unsigned int count; + + list_for_each_entry(obj, &req->objects, list) { + struct vb2_buffer *vb; + + if (vb2_request_object_is_buffer(obj)) { + vb = container_of(obj, struct vb2_buffer, req_obj); + ctx = vb2_get_drv_priv(vb->vb2_queue); + + break; + } + } + + if (!ctx) { + pr_err("No buffer was provided with the request\n"); + return -ENOENT; + } + + count = vb2_request_buffer_cnt(req); + if (!count) { + v4l2_info(&ctx->dev->v4l2_dev, + "No buffer was provided with the request\n"); + return -ENOENT; + } else if (count > 1) { + v4l2_info(&ctx->dev->v4l2_dev, + "More than one buffer was provided with the request\n"); + return -EINVAL; + } + + parent_hdl = &ctx->hdl; + + hdl = v4l2_ctrl_request_hdl_find(req, parent_hdl); + if (!hdl) { + v4l2_info(&ctx->dev->v4l2_dev, "Missing codec control\n"); + return -ENOENT; + } + ctrl = v4l2_ctrl_request_hdl_ctrl_find(hdl, + vicodec_ctrl_stateless_state.id); + if (!ctrl) { + v4l2_info(&ctx->dev->v4l2_dev, + "Missing required codec control\n"); + return -ENOENT; + } + + return vb2_request_validate(req); +} + static const struct v4l2_file_operations vicodec_fops = { .owner = THIS_MODULE, .open = vicodec_open, @@ -1705,6 +1938,11 @@ static const struct video_device vicodec_videodev = { .release = video_device_release_empty, }; +static const struct media_device_ops vicodec_m2m_media_ops = { + .req_validate = vicodec_request_validate, + .req_queue = v4l2_m2m_request_queue, +}; + static const struct v4l2_m2m_ops m2m_ops = { .device_run = device_run, .job_ready = job_ready, @@ -1771,6 +2009,7 @@ static int vicodec_probe(struct platform_device *pdev) strscpy(dev->mdev.bus_info, "platform:vicodec", sizeof(dev->mdev.bus_info)); media_device_init(&dev->mdev); + dev->mdev.ops = &vicodec_m2m_media_ops; dev->v4l2_dev.mdev = &dev->mdev; #endif From 35e2e8b5fb0799206efb9005564334ef80e49e34 Mon Sep 17 00:00:00 2001 From: Dafna Hirschfeld Date: Wed, 6 Mar 2019 16:13:43 -0500 Subject: [PATCH 106/218] media: vicodec: set pixelformat to V4L2_PIX_FMT_FWHT_STATELESS for stateless decoder for stateless decoder, set the output pixelformat to V4L2_PIX_FMT_FWHT_STATELESS and the pix info to pixfmt_stateless_fwht Signed-off-by: Dafna Hirschfeld Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vicodec/vicodec-core.c | 47 ++++++++++++++----- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index 617fc53246e4..a5f8f74ea3bf 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -727,7 +727,8 @@ static int enum_fmt(struct v4l2_fmtdesc *f, struct vicodec_ctx *ctx, } else { if (f->index) return -EINVAL; - f->pixelformat = V4L2_PIX_FMT_FWHT; + f->pixelformat = ctx->is_stateless ? + V4L2_PIX_FMT_FWHT_STATELESS : V4L2_PIX_FMT_FWHT; } return 0; } @@ -829,13 +830,15 @@ static int vidioc_try_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f) struct v4l2_pix_format_mplane *pix_mp; struct v4l2_pix_format *pix; struct v4l2_plane_pix_format *plane; - const struct v4l2_fwht_pixfmt_info *info = &pixfmt_fwht; + const struct v4l2_fwht_pixfmt_info *info = ctx->is_stateless ? + &pixfmt_stateless_fwht : &pixfmt_fwht; switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OUTPUT: pix = &f->fmt.pix; - if (pix->pixelformat != V4L2_PIX_FMT_FWHT) + if (pix->pixelformat != V4L2_PIX_FMT_FWHT && + pix->pixelformat != V4L2_PIX_FMT_FWHT_STATELESS) info = find_fmt(pix->pixelformat); pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH); @@ -856,7 +859,8 @@ static int vidioc_try_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f) case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: pix_mp = &f->fmt.pix_mp; plane = pix_mp->plane_fmt; - if (pix_mp->pixelformat != V4L2_PIX_FMT_FWHT) + if (pix_mp->pixelformat != V4L2_PIX_FMT_FWHT && + pix_mp->pixelformat != V4L2_PIX_FMT_FWHT_STATELESS) info = find_fmt(pix_mp->pixelformat); pix_mp->num_planes = 1; @@ -933,8 +937,12 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv, if (multiplanar) return -EINVAL; pix = &f->fmt.pix; - pix->pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT : - find_fmt(pix->pixelformat)->id; + if (ctx->is_enc) + pix->pixelformat = find_fmt(pix->pixelformat)->id; + else if (ctx->is_stateless) + pix->pixelformat = V4L2_PIX_FMT_FWHT_STATELESS; + else + pix->pixelformat = V4L2_PIX_FMT_FWHT; if (!pix->colorspace) pix->colorspace = V4L2_COLORSPACE_REC709; break; @@ -942,8 +950,12 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv, if (!multiplanar) return -EINVAL; pix_mp = &f->fmt.pix_mp; - pix_mp->pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT : - find_fmt(pix_mp->pixelformat)->id; + if (ctx->is_enc) + pix_mp->pixelformat = find_fmt(pix_mp->pixelformat)->id; + else if (ctx->is_stateless) + pix_mp->pixelformat = V4L2_PIX_FMT_FWHT_STATELESS; + else + pix_mp->pixelformat = V4L2_PIX_FMT_FWHT; if (!pix_mp->colorspace) pix_mp->colorspace = V4L2_COLORSPACE_REC709; break; @@ -986,6 +998,8 @@ static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f) if (pix->pixelformat == V4L2_PIX_FMT_FWHT) q_data->info = &pixfmt_fwht; + else if (pix->pixelformat == V4L2_PIX_FMT_FWHT_STATELESS) + q_data->info = &pixfmt_stateless_fwht; else q_data->info = find_fmt(pix->pixelformat); q_data->coded_width = pix->width; @@ -1007,6 +1021,8 @@ static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f) if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT) q_data->info = &pixfmt_fwht; + else if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT_STATELESS) + q_data->info = &pixfmt_stateless_fwht; else q_data->info = find_fmt(pix_mp->pixelformat); q_data->coded_width = pix_mp->width; @@ -1231,6 +1247,8 @@ static int vicodec_enum_framesizes(struct file *file, void *fh, struct v4l2_frmsizeenum *fsize) { switch (fsize->pixel_format) { + case V4L2_PIX_FMT_FWHT_STATELESS: + break; case V4L2_PIX_FMT_FWHT: break; default: @@ -1518,7 +1536,8 @@ static int vicodec_start_streaming(struct vb2_queue *q, (!V4L2_TYPE_IS_OUTPUT(q->type) && ctx->is_enc)) return 0; - if (info->id == V4L2_PIX_FMT_FWHT) { + if (info->id == V4L2_PIX_FMT_FWHT || + info->id == V4L2_PIX_FMT_FWHT_STATELESS) { vicodec_return_bufs(q, VB2_BUF_STATE_QUEUED); return -EINVAL; } @@ -1794,15 +1813,19 @@ static int vicodec_open(struct file *file) ctx->fh.ctrl_handler = hdl; v4l2_ctrl_handler_setup(hdl); - ctx->q_data[V4L2_M2M_SRC].info = - ctx->is_enc ? v4l2_fwht_get_pixfmt(0) : &pixfmt_fwht; + if (ctx->is_enc) + ctx->q_data[V4L2_M2M_SRC].info = v4l2_fwht_get_pixfmt(0); + else if (ctx->is_stateless) + ctx->q_data[V4L2_M2M_SRC].info = &pixfmt_stateless_fwht; + else + ctx->q_data[V4L2_M2M_SRC].info = &pixfmt_fwht; ctx->q_data[V4L2_M2M_SRC].coded_width = 1280; ctx->q_data[V4L2_M2M_SRC].coded_height = 720; ctx->q_data[V4L2_M2M_SRC].visible_width = 1280; ctx->q_data[V4L2_M2M_SRC].visible_height = 720; size = 1280 * 720 * ctx->q_data[V4L2_M2M_SRC].info->sizeimage_mult / ctx->q_data[V4L2_M2M_SRC].info->sizeimage_div; - if (ctx->is_enc) + if (ctx->is_enc || ctx->is_stateless) ctx->q_data[V4L2_M2M_SRC].sizeimage = size; else ctx->q_data[V4L2_M2M_SRC].sizeimage = From 149e31e90b505ae0cc909bd0d92b2ba4826574d6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 22 Apr 2018 04:00:08 -0400 Subject: [PATCH 107/218] media: v4l: rcar_fdp1: Fix indentation oddities Indentation is odd in several places, especially when printing messages to the kernel log. Fix it to match the usual coding style. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar_fdp1.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/media/platform/rcar_fdp1.c b/drivers/media/platform/rcar_fdp1.c index 6bda1eee9170..6a90bc4c476e 100644 --- a/drivers/media/platform/rcar_fdp1.c +++ b/drivers/media/platform/rcar_fdp1.c @@ -945,7 +945,7 @@ static void fdp1_configure_wpf(struct fdp1_ctx *ctx, u32 rndctl; pstride = q_data->format.plane_fmt[0].bytesperline - << FD1_WPF_PSTRIDE_Y_SHIFT; + << FD1_WPF_PSTRIDE_Y_SHIFT; if (q_data->format.num_planes > 1) pstride |= q_data->format.plane_fmt[1].bytesperline @@ -1139,8 +1139,8 @@ static int fdp1_m2m_job_ready(void *priv) int dstbufs = 1; dprintk(ctx->fdp1, "+ Src: %d : Dst: %d\n", - v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx), - v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx)); + v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx), + v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx)); /* One output buffer is required for each field */ if (V4L2_FIELD_HAS_BOTH(src_q_data->format.field)) @@ -1278,7 +1278,7 @@ static void fdp1_m2m_device_run(void *priv) fdp1_queue_field(ctx, fbuf); dprintk(fdp1, "Queued Buffer [%d] last_field:%d\n", - i, fbuf->last_field); + i, fbuf->last_field); } /* Queue as many jobs as our data provides for */ @@ -1337,7 +1337,7 @@ static void device_frame_end(struct fdp1_dev *fdp1, fdp1_job_free(fdp1, job); dprintk(fdp1, "curr_ctx->num_processed %d curr_ctx->translen %d\n", - ctx->num_processed, ctx->translen); + ctx->num_processed, ctx->translen); if (ctx->num_processed == ctx->translen || ctx->aborting) { @@ -1362,7 +1362,7 @@ static int fdp1_vidioc_querycap(struct file *file, void *priv, strscpy(cap->driver, DRIVER_NAME, sizeof(cap->driver)); strscpy(cap->card, DRIVER_NAME, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), - "platform:%s", DRIVER_NAME); + "platform:%s", DRIVER_NAME); return 0; } @@ -1993,13 +1993,13 @@ static void fdp1_stop_streaming(struct vb2_queue *q) /* Free smsk_data */ if (ctx->smsk_cpu) { dma_free_coherent(ctx->fdp1->dev, ctx->smsk_size, - ctx->smsk_cpu, ctx->smsk_addr[0]); + ctx->smsk_cpu, ctx->smsk_addr[0]); ctx->smsk_addr[0] = ctx->smsk_addr[1] = 0; ctx->smsk_cpu = NULL; } WARN(!list_empty(&ctx->fields_queue), - "Buffer queue not empty"); + "Buffer queue not empty"); } else { /* Empty Capture queues (Jobs) */ struct fdp1_job *job; @@ -2021,10 +2021,10 @@ static void fdp1_stop_streaming(struct vb2_queue *q) fdp1_field_complete(ctx, ctx->previous); WARN(!list_empty(&ctx->fdp1->queued_job_list), - "Queued Job List not empty"); + "Queued Job List not empty"); WARN(!list_empty(&ctx->fdp1->hw_job_list), - "HW Job list not empty"); + "HW Job list not empty"); } } @@ -2110,7 +2110,7 @@ static int fdp1_open(struct file *file) fdp1_ctrl_deint_menu); ctrl = v4l2_ctrl_new_std(&ctx->hdl, &fdp1_ctrl_ops, - V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 2, 1, 1); + V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 2, 1, 1); if (ctrl) ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; @@ -2347,8 +2347,8 @@ static int fdp1_probe(struct platform_device *pdev) goto release_m2m; } - v4l2_info(&fdp1->v4l2_dev, - "Device registered as /dev/video%d\n", vfd->num); + v4l2_info(&fdp1->v4l2_dev, "Device registered as /dev/video%d\n", + vfd->num); /* Power up the cells to read HW */ pm_runtime_enable(&pdev->dev); @@ -2367,7 +2367,7 @@ static int fdp1_probe(struct platform_device *pdev) break; default: dev_err(fdp1->dev, "FDP1 Unidentifiable (0x%08x)\n", - hw_version); + hw_version); } /* Allow the hw to sleep until an open call puts it to use */ From 153d11cc530cb2a3045167253582d3d2849ad519 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 7 Dec 2018 06:43:03 -0500 Subject: [PATCH 108/218] media: imx214: don't de-reference a NULL pointer As warned by smatch: drivers/media/i2c/imx214.c:591 imx214_set_format() warn: variable dereferenced before check 'format' (see line 589) It turns that the code at imx214_set_format() has support for being called with the format being NULL. I've no idea why, as it is only called internally with the pointer set, and via subdev API (with should also set it). Also, the entire logic there depends on having format != NULL, so just remove the bogus broken support for a null format. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans Verkuil Reviewed-by: Ricardo Ribalda Delgado Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/imx214.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c index 9857e151db46..83e9961b0505 100644 --- a/drivers/media/i2c/imx214.c +++ b/drivers/media/i2c/imx214.c @@ -588,12 +588,10 @@ static int imx214_set_format(struct v4l2_subdev *sd, __crop = __imx214_get_pad_crop(imx214, cfg, format->pad, format->which); - if (format) - mode = v4l2_find_nearest_size(imx214_modes, - ARRAY_SIZE(imx214_modes), width, height, - format->format.width, format->format.height); - else - mode = &imx214_modes[0]; + mode = v4l2_find_nearest_size(imx214_modes, + ARRAY_SIZE(imx214_modes), width, height, + format->format.width, + format->format.height); __crop->width = mode->width; __crop->height = mode->height; From 3d19cde7be76d4471426edc348bcf3b45c64f097 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Mar 2019 15:09:30 -0400 Subject: [PATCH 109/218] media: cx2341x: replace badly designed macros There are some macros at cx2341x_update() with seemed to be introduced in order to ensure that lines would be less than 80 columns. Well, the thing is that they make the code harder to be analized, not only by humans, but also for static code analyzers: drivers/media/common/cx2341x.c:1116 cx2341x_update() error: we previously assumed 'old' could be null (see line 1047) So, remove the "force" var, and replace the NEQ macro to a better designed one that makes clearer about what it is doing. While here, also remove the "temporal" var, as it is just another way of doing the same type of check as the new CMP_FIELD() macro already does. Finally, fix coding style at the block code. remove such macros. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/cx2341x.c | 151 ++++++++++++++++++++------------- 1 file changed, 93 insertions(+), 58 deletions(-) diff --git a/drivers/media/common/cx2341x.c b/drivers/media/common/cx2341x.c index 1dcc39b87bb7..121cda73ff88 100644 --- a/drivers/media/common/cx2341x.c +++ b/drivers/media/common/cx2341x.c @@ -1028,7 +1028,7 @@ static int cx2341x_api(void *priv, cx2341x_mbox_func func, return func(priv, cmd, args, 0, data); } -#define NEQ(field) (old->field != new->field) +#define CMP_FIELD(__old, __new, __field) (__old->__field != __new->__field) int cx2341x_update(void *priv, cx2341x_mbox_func func, const struct cx2341x_mpeg_params *old, @@ -1042,20 +1042,22 @@ int cx2341x_update(void *priv, cx2341x_mbox_func func, 11, /* VCD */ 12, /* SVCD */ }; - - int err = 0; - int force = (old == NULL); - u16 temporal = new->video_temporal_filter; + int err; cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0); - if (force || NEQ(is_50hz)) { + if (!old || + CMP_FIELD(old, new, is_50hz)) { err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1, new->is_50hz); - if (err) return err; + if (err) + return err; } - if (force || NEQ(width) || NEQ(height) || NEQ(video_encoding)) { + if (!old || + CMP_FIELD(old, new, width) || + CMP_FIELD(old, new, height) || + CMP_FIELD(old, new, video_encoding)) { u16 w = new->width; u16 h = new->height; @@ -1065,94 +1067,127 @@ int cx2341x_update(void *priv, cx2341x_mbox_func func, } err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w); - if (err) return err; + if (err) + return err; } - if (force || NEQ(stream_type)) { + if (!old || + CMP_FIELD(old, new, stream_type)) { err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[new->stream_type]); - if (err) return err; + if (err) + return err; } - if (force || NEQ(video_aspect)) { + if (!old || + CMP_FIELD(old, new, video_aspect)) { err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1, 1 + new->video_aspect); - if (err) return err; + if (err) + return err; } - if (force || NEQ(video_b_frames) || NEQ(video_gop_size)) { + if (!old || + CMP_FIELD(old, new, video_b_frames) || + CMP_FIELD(old, new, video_gop_size)) { err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2, - new->video_gop_size, new->video_b_frames + 1); - if (err) return err; + new->video_gop_size, new->video_b_frames + 1); + if (err) + return err; } - if (force || NEQ(video_gop_closure)) { + if (!old || + CMP_FIELD(old, new, video_gop_closure)) { err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, new->video_gop_closure); - if (err) return err; + if (err) + return err; } - if (force || NEQ(audio_properties)) { + if (!old || + CMP_FIELD(old, new, audio_properties)) { err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new->audio_properties); - if (err) return err; + if (err) + return err; } - if (force || NEQ(audio_mute)) { + if (!old || + CMP_FIELD(old, new, audio_mute)) { err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1, new->audio_mute); - if (err) return err; + if (err) + return err; } - if (force || NEQ(video_bitrate_mode) || NEQ(video_bitrate) || - NEQ(video_bitrate_peak)) { + if (!old || + CMP_FIELD(old, new, video_bitrate_mode) || + CMP_FIELD(old, new, video_bitrate) || + CMP_FIELD(old, new, video_bitrate_peak)) { err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5, - new->video_bitrate_mode, new->video_bitrate, - new->video_bitrate_peak / 400, 0, 0); - if (err) return err; + new->video_bitrate_mode, new->video_bitrate, + new->video_bitrate_peak / 400, 0, 0); + if (err) + return err; } - if (force || NEQ(video_spatial_filter_mode) || - NEQ(video_temporal_filter_mode) || - NEQ(video_median_filter_type)) { + if (!old || + CMP_FIELD(old, new, video_spatial_filter_mode) || + CMP_FIELD(old, new, video_temporal_filter_mode) || + CMP_FIELD(old, new, video_median_filter_type)) { err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE, - 2, new->video_spatial_filter_mode | + 2, + new->video_spatial_filter_mode | (new->video_temporal_filter_mode << 1), - new->video_median_filter_type); - if (err) return err; + new->video_median_filter_type); + if (err) + return err; } - if (force || NEQ(video_luma_median_filter_bottom) || - NEQ(video_luma_median_filter_top) || - NEQ(video_chroma_median_filter_bottom) || - NEQ(video_chroma_median_filter_top)) { + if (!old || + CMP_FIELD(old, new, video_luma_median_filter_bottom) || + CMP_FIELD(old, new, video_luma_median_filter_top) || + CMP_FIELD(old, new, video_chroma_median_filter_bottom) || + CMP_FIELD(old, new, video_chroma_median_filter_top)) { err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4, - new->video_luma_median_filter_bottom, - new->video_luma_median_filter_top, - new->video_chroma_median_filter_bottom, - new->video_chroma_median_filter_top); - if (err) return err; + new->video_luma_median_filter_bottom, + new->video_luma_median_filter_top, + new->video_chroma_median_filter_bottom, + new->video_chroma_median_filter_top); + if (err) + return err; } - if (force || NEQ(video_luma_spatial_filter_type) || - NEQ(video_chroma_spatial_filter_type)) { + if (!old || + CMP_FIELD(old, new, video_luma_spatial_filter_type) || + CMP_FIELD(old, new, video_chroma_spatial_filter_type)) { err = cx2341x_api(priv, func, CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2, new->video_luma_spatial_filter_type, new->video_chroma_spatial_filter_type); - if (err) return err; + if (err) + return err; } - if (force || NEQ(video_spatial_filter) || - old->video_temporal_filter != temporal) { + if (!old || + CMP_FIELD(old, new, video_spatial_filter) || + CMP_FIELD(old, new, video_temporal_filter)) { err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS, - 2, new->video_spatial_filter, temporal); - if (err) return err; + 2, new->video_spatial_filter, + new->video_temporal_filter); + if (err) + return err; } - if (force || NEQ(video_temporal_decimation)) { + if (!old || + CMP_FIELD(old, new, video_temporal_decimation)) { err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE, 1, new->video_temporal_decimation); - if (err) return err; + if (err) + return err; } - if (force || NEQ(video_mute) || - (new->video_mute && NEQ(video_mute_yuv))) { + if (!old || + CMP_FIELD(old, new, video_mute) || + (new->video_mute && CMP_FIELD(old, new, video_mute_yuv))) { err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1, - new->video_mute | (new->video_mute_yuv << 8)); - if (err) return err; + new->video_mute | (new->video_mute_yuv << 8)); + if (err) + return err; } - if (force || NEQ(stream_insert_nav_packets)) { + if (!old || + CMP_FIELD(old, new, stream_insert_nav_packets)) { err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2, - 7, new->stream_insert_nav_packets); - if (err) return err; + 7, new->stream_insert_nav_packets); + if (err) + return err; } return 0; } From 4f777d011bdd9e78fcf02701e89c8be457504a6c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Mar 2019 16:20:47 -0400 Subject: [PATCH 110/218] media: pwc-ctl: pChoose can't be NULL The way the code works, compression will be a valid value (less or equal to 3) on both set_video_mode_foo() calls at the beginning of the while() loop. So, the value for pChoose can't be NULL. Solves those smatch warnings: drivers/media/usb/pwc/pwc-ctrl.c: drivers/media/usb/pwc/pwc-ctrl.c:252 set_video_mode_Timon() warn: variable dereferenced before check 'pChoose' (see line 248) drivers/media/usb/pwc/pwc-ctrl.c: drivers/media/usb/pwc/pwc-ctrl.c:302 set_video_mode_Kiara() warn: variable dereferenced before check 'pChoose' (see line 298) and simplifies the code a little bit. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/pwc/pwc-ctrl.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/media/usb/pwc/pwc-ctrl.c b/drivers/media/usb/pwc/pwc-ctrl.c index 655cef39eb3d..b681a184ef87 100644 --- a/drivers/media/usb/pwc/pwc-ctrl.c +++ b/drivers/media/usb/pwc/pwc-ctrl.c @@ -242,14 +242,14 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int pixfmt, fps = (frames / 5) - 1; /* Find a supported framerate with progressively higher compression */ - pChoose = NULL; - while (*compression <= 3) { + do { pChoose = &Timon_table[size][fps][*compression]; if (pChoose->alternate != 0) break; (*compression)++; - } - if (pChoose == NULL || pChoose->alternate == 0) + } while (*compression <= 3); + + if (pChoose->alternate == 0) return -ENOENT; /* Not supported. */ if (send_to_cam) @@ -279,7 +279,7 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int pixfmt, static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int pixfmt, int frames, int *compression, int send_to_cam) { - const struct Kiara_table_entry *pChoose = NULL; + const struct Kiara_table_entry *pChoose; int fps, ret = 0; if (size >= PSZ_MAX || *compression < 0 || *compression > 3) @@ -293,13 +293,14 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int pixfmt, fps = (frames / 5) - 1; /* Find a supported framerate with progressively higher compression */ - while (*compression <= 3) { + do { pChoose = &Kiara_table[size][fps][*compression]; if (pChoose->alternate != 0) break; (*compression)++; - } - if (pChoose == NULL || pChoose->alternate == 0) + } while (*compression <= 3); + + if (pChoose->alternate == 0) return -ENOENT; /* Not supported. */ /* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */ From 1021cd56772b636ebccc3941c44094ef6b0fac4e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Mar 2019 16:32:19 -0400 Subject: [PATCH 111/218] media: sti/delta: remove uneeded check At the error logic, ipc_buf was already asigned to &ctx->ipc_buf_struct, with can't be null, as warned by smatch: drivers/media/platform/sti/delta/delta-ipc.c:223 delta_ipc_open() warn: variable dereferenced before check 'ctx->ipc_buf' (see line 183) So, remove the uneeded check. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/sti/delta/delta-ipc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/sti/delta/delta-ipc.c b/drivers/media/platform/sti/delta/delta-ipc.c index a4603d573c34..186d88f02ecd 100644 --- a/drivers/media/platform/sti/delta/delta-ipc.c +++ b/drivers/media/platform/sti/delta/delta-ipc.c @@ -220,10 +220,8 @@ int delta_ipc_open(struct delta_ctx *pctx, const char *name, err: pctx->sys_errors++; - if (ctx->ipc_buf) { - hw_free(pctx, ctx->ipc_buf); - ctx->ipc_buf = NULL; - } + hw_free(pctx, ctx->ipc_buf); + ctx->ipc_buf = NULL; return ret; }; From bf78f23acf023d5bc9d31bab2918a3092dc821f0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Mar 2019 16:47:13 -0400 Subject: [PATCH 112/218] media: rcar-dma: p_set can't be NULL The only way for p_set to be NULL would be if vin_coef_set would be an empty array. On such case, the driver will OOPS, as it would try to de-reference a NULL value. So, the check if p_set is not NULL doesn't make any sense. Solves those two smatch warnings: drivers/media/platform/rcar-vin/rcar-dma.c:489 rvin_set_coeff() warn: variable dereferenced before check 'p_set' (see line 484) drivers/media/platform/rcar-vin/rcar-dma.c:494 rvin_set_coeff() error: we previously assumed 'p_set' could be null (see line 489) Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c b/drivers/media/platform/rcar-vin/rcar-dma.c index 2207a31d355e..91ab064404a1 100644 --- a/drivers/media/platform/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/rcar-vin/rcar-dma.c @@ -486,7 +486,7 @@ static void rvin_set_coeff(struct rvin_dev *vin, unsigned short xs) } /* Use previous value if its XS value is closer */ - if (p_prev_set && p_set && + if (p_prev_set && xs - p_prev_set->xs_value < p_set->xs_value - xs) p_set = p_prev_set; From ded716267196862809e5926072adc962a611a1e3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Mar 2019 17:09:05 -0400 Subject: [PATCH 113/218] media: hfi_parser: don't trick gcc with a wrong expected size Smatch warns about small size on two structs: drivers/media/platform/qcom/venus/hfi_parser.c:103 parse_profile_level() error: memcpy() 'proflevel' too small (8 vs 128) drivers/media/platform/qcom/venus/hfi_parser.c: drivers/media/platform/qcom/venus/hfi_parser.c:129 parse_caps() error: memcpy() 'cap' too small (16 vs 512) The reason is that the hfi_parser actually expects: - multiple data entries on hfi_capabilities - multiple profile_level on hfi_profile_level_supported However, the structs trick gcc, making it to believe that there's just one value for each. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/hfi_helper.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi_helper.h b/drivers/media/platform/qcom/venus/hfi_helper.h index 15804ad7e65d..34ea503a9842 100644 --- a/drivers/media/platform/qcom/venus/hfi_helper.h +++ b/drivers/media/platform/qcom/venus/hfi_helper.h @@ -569,7 +569,7 @@ struct hfi_capability { struct hfi_capabilities { u32 num_capabilities; - struct hfi_capability data[1]; + struct hfi_capability *data; }; #define HFI_DEBUG_MSG_LOW 0x01 @@ -726,7 +726,7 @@ struct hfi_profile_level { struct hfi_profile_level_supported { u32 profile_count; - struct hfi_profile_level profile_level[1]; + struct hfi_profile_level *profile_level; }; struct hfi_quality_vs_speed { From 122d0e8dd050cc5dc3fb9e9b5f2dee3c5276ce35 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 28 Mar 2019 14:36:14 -0400 Subject: [PATCH 114/218] media: dvbdev: remove double-unlock As warned by smatch: drivers/media/dvb-core/dvbdev.c: drivers/media/dvb-core/dvbdev.c:529 dvb_register_device() error: double unlock 'sem:&minor_rwsem' Reported-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvbdev.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index 4a5834a1c3b7..a3393cd4e584 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -526,7 +526,6 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, dvb_media_device_free(dvbdev); kfree(dvbdevfops); kfree(dvbdev); - up_write(&minor_rwsem); mutex_unlock(&dvbdev_register_lock); return ret; } From 9b9ea7c2b57a0c9c3341fc6db039d1f7971a432e Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Thu, 28 Feb 2019 10:28:34 -0500 Subject: [PATCH 115/218] media: gspca: Kill URBs on USB device disconnect In order to prevent ISOC URBs from being infinitely resubmitted, the driver's USB disconnect handler must kill all the in-flight URBs. While here, change the URB packet status message to a debug level, to avoid spamming the console too much. This commit fixes a lockup caused by an interrupt storm coming from the URB completion handler. Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/gspca/gspca.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index 9448ac0b8bc9..4d7517411cc2 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -294,7 +294,7 @@ static void fill_frame(struct gspca_dev *gspca_dev, /* check the packet status and length */ st = urb->iso_frame_desc[i].status; if (st) { - pr_err("ISOC data error: [%d] len=%d, status=%d\n", + gspca_dbg(gspca_dev, D_PACK, "ISOC data error: [%d] len=%d, status=%d\n", i, len, st); gspca_dev->last_packet_type = DISCARD_PACKET; continue; @@ -1642,6 +1642,8 @@ void gspca_disconnect(struct usb_interface *intf) mutex_lock(&gspca_dev->usb_lock); gspca_dev->present = false; + destroy_urbs(gspca_dev); + gspca_input_destroy_urb(gspca_dev); vb2_queue_error(&gspca_dev->queue); From bcfc16eb1650f14053eb70725574f98648bb7c0a Mon Sep 17 00:00:00 2001 From: Lucas Leonardo Ciancaglini Date: Mon, 11 Mar 2019 01:34:38 -0400 Subject: [PATCH 116/218] media: staging/imx: Fix inconsistent long line breaks Small readability changes to make the breaking of some lines cleaner. Signed-off-by: Lucas Leonardo Ciancaglini Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx-media-dev.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c index 10a63a4fa90b..0a7d1d183141 100644 --- a/drivers/staging/media/imx/imx-media-dev.c +++ b/drivers/staging/media/imx/imx-media-dev.c @@ -50,12 +50,14 @@ int imx_media_add_async_subdev(struct imx_media_dev *imxmd, int ret; if (fwnode) { - asd = v4l2_async_notifier_add_fwnode_subdev( - &imxmd->notifier, fwnode, sizeof(*imxasd)); + asd = v4l2_async_notifier_add_fwnode_subdev(&imxmd->notifier, + fwnode, + sizeof(*imxasd)); } else { devname = dev_name(&pdev->dev); - asd = v4l2_async_notifier_add_devname_subdev( - &imxmd->notifier, devname, sizeof(*imxasd)); + asd = v4l2_async_notifier_add_devname_subdev(&imxmd->notifier, + devname, + sizeof(*imxasd)); } if (IS_ERR(asd)) { @@ -266,10 +268,9 @@ static int imx_media_alloc_pad_vdev_lists(struct imx_media_dev *imxmd) list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) { entity = &sd->entity; - vdev_lists = devm_kcalloc( - imxmd->md.dev, - entity->num_pads, sizeof(*vdev_lists), - GFP_KERNEL); + vdev_lists = devm_kcalloc(imxmd->md.dev, + entity->num_pads, sizeof(*vdev_lists), + GFP_KERNEL); if (!vdev_lists) return -ENOMEM; From 2980c03e1f09a4ba36cb0d818a6a203213e98868 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 13 Mar 2019 17:10:29 -0400 Subject: [PATCH 117/218] media: staging: media: davinci_vpfe: fix large stack usage with clang clang is unable to optimize the isif_ioctl() in the same way that gcc does, as it fails to prove that the local copy of the 'struct vpfe_isif_raw_config' argument is unnecessary: drivers/staging/media/davinci_vpfe/dm365_isif.c:622:13: error: stack frame size of 1344 bytes in function 'isif_ioctl' [-Werror,-Wframe-larger-than=] Marking it as 'const' while passing the data down clearly shows us that the copy is never modified, and we can skip copying it entirely, which reduces the stack usage to just eight bytes. Signed-off-by: Arnd Bergmann Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/davinci_vpfe/dm365_isif.c | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c index 0a6d038fcec9..46fd8184fc77 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_isif.c +++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c @@ -433,9 +433,9 @@ static int isif_get_params(struct v4l2_subdev *sd, void *params) return 0; } -static int isif_validate_df_csc_params(struct vpfe_isif_df_csc *df_csc) +static int isif_validate_df_csc_params(const struct vpfe_isif_df_csc *df_csc) { - struct vpfe_isif_color_space_conv *csc; + const struct vpfe_isif_color_space_conv *csc; int err = -EINVAL; int i; @@ -481,7 +481,7 @@ static int isif_validate_df_csc_params(struct vpfe_isif_df_csc *df_csc) #define DM365_ISIF_MAX_DFCMEM0 0x1fff #define DM365_ISIF_MAX_DFCMEM1 0x1fff -static int isif_validate_dfc_params(struct vpfe_isif_dfc *dfc) +static int isif_validate_dfc_params(const struct vpfe_isif_dfc *dfc) { int err = -EINVAL; int i; @@ -532,7 +532,7 @@ static int isif_validate_dfc_params(struct vpfe_isif_dfc *dfc) #define DM365_ISIF_MAX_CLVSV 0x1fff #define DM365_ISIF_MAX_HEIGHT_BLACK_REGION 0x1fff -static int isif_validate_bclamp_params(struct vpfe_isif_black_clamp *bclamp) +static int isif_validate_bclamp_params(const struct vpfe_isif_black_clamp *bclamp) { int err = -EINVAL; @@ -580,7 +580,7 @@ static int isif_validate_bclamp_params(struct vpfe_isif_black_clamp *bclamp) } static int -isif_validate_raw_params(struct vpfe_isif_raw_config *params) +isif_validate_raw_params(const struct vpfe_isif_raw_config *params) { int ret; @@ -593,20 +593,18 @@ isif_validate_raw_params(struct vpfe_isif_raw_config *params) return isif_validate_bclamp_params(¶ms->bclamp); } -static int isif_set_params(struct v4l2_subdev *sd, void *params) +static int isif_set_params(struct v4l2_subdev *sd, const struct vpfe_isif_raw_config *params) { struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd); - struct vpfe_isif_raw_config isif_raw_params; int ret = -EINVAL; /* only raw module parameters can be set through the IOCTL */ if (isif->formats[ISIF_PAD_SINK].code != MEDIA_BUS_FMT_SGRBG12_1X12) return ret; - memcpy(&isif_raw_params, params, sizeof(isif_raw_params)); - if (!isif_validate_raw_params(&isif_raw_params)) { - memcpy(&isif->isif_cfg.bayer.config_params, &isif_raw_params, - sizeof(isif_raw_params)); + if (!isif_validate_raw_params(params)) { + memcpy(&isif->isif_cfg.bayer.config_params, params, + sizeof(*params)); ret = 0; } return ret; From fc1209602959ffc022432b527fae54b48bf0623a Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 13 Mar 2019 17:17:32 -0400 Subject: [PATCH 118/218] media: staging: media: imx7-mipi-csis: fix debugfs compilation When CONFIG_DEBUGFS is enabled, we get a warning about an incorrect section annotation that can lead to undefined behavior: WARNING: vmlinux.o(.text+0xd3c7c4): Section mismatch in reference from the function mipi_csis_probe() to the function .init.text:mipi_csis_debugfs_init() The function mipi_csis_probe() references the function __init mipi_csis_debugfs_init(). This is often because mipi_csis_probe lacks a __init annotation or the annotation of mipi_csis_debugfs_init is wrong. The same function for an unknown reason has a different version for !CONFIG_DEBUGFS, which does not have this problem, but behaves the same way otherwise (it does nothing when debugfs is disabled). Consolidate the two versions, using the correct section from one version, and the implementation from the other. Signed-off-by: Arnd Bergmann Reviewed-by: Rui Miguel Silva Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx7-mipi-csis.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c index a1f36be2e844..6cae2960eea1 100644 --- a/drivers/staging/media/imx/imx7-mipi-csis.c +++ b/drivers/staging/media/imx/imx7-mipi-csis.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -889,8 +890,6 @@ static int mipi_csis_subdev_init(struct v4l2_subdev *mipi_sd, return ret; } -#ifdef CONFIG_DEBUG_FS -#include static int mipi_csis_dump_regs_show(struct seq_file *m, void *private) { @@ -900,7 +899,7 @@ static int mipi_csis_dump_regs_show(struct seq_file *m, void *private) } DEFINE_SHOW_ATTRIBUTE(mipi_csis_dump_regs); -static int __init_or_module mipi_csis_debugfs_init(struct csi_state *state) +static int mipi_csis_debugfs_init(struct csi_state *state) { struct dentry *d; @@ -934,17 +933,6 @@ static void mipi_csis_debugfs_exit(struct csi_state *state) debugfs_remove_recursive(state->debugfs_root); } -#else -static int mipi_csis_debugfs_init(struct csi_state *state __maybe_unused) -{ - return 0; -} - -static void mipi_csis_debugfs_exit(struct csi_state *state __maybe_unused) -{ -} -#endif - static int mipi_csis_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; From 5f2efda71c09b12012053f457fac7692f268b72c Mon Sep 17 00:00:00 2001 From: Koen Vandeputte Date: Mon, 18 Mar 2019 12:40:05 -0400 Subject: [PATCH 119/218] media: i2c: tda1997x: select V4L2_FWNODE Building tda1997x fails now unless V4L2_FWNODE is selected: drivers/media/i2c/tda1997x.o: in function `tda1997x_parse_dt' undefined reference to `v4l2_fwnode_endpoint_parse' While at it, also sort the selections alphabetically Fixes: 9ac0038db9a7 ("media: i2c: Add TDA1997x HDMI receiver driver") Signed-off-by: Koen Vandeputte Cc: stable@vger.kernel.org # v4.17+ Acked-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 1a1746b3db91..5f5c36442710 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -60,8 +60,9 @@ config VIDEO_TDA1997X tristate "NXP TDA1997x HDMI receiver" depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API depends on SND_SOC - select SND_PCM select HDMI + select SND_PCM + select V4L2_FWNODE help V4L2 subdevice driver for the NXP TDA1997x HDMI receivers. From 0e633f97162c1c74c68e2eb20bbd9259dce87cd9 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 22 Mar 2019 10:34:22 -0400 Subject: [PATCH 120/218] media: davinci-isif: avoid uninitialized variable use clang warns about a possible variable use that gcc never complained about: drivers/media/platform/davinci/isif.c:982:32: error: variable 'frame_size' is uninitialized when used here [-Werror,-Wuninitialized] dm365_vpss_set_pg_frame_size(frame_size); ^~~~~~~~~~ drivers/media/platform/davinci/isif.c:887:2: note: variable 'frame_size' is declared here struct vpss_pg_frame_size frame_size; ^ 1 error generated. There is no initialization for this variable at all, and there has never been one in the mainline kernel, so we really should not put that stack data into an mmio register. On the other hand, I suspect that gcc checks the condition more closely and notices that the global isif_cfg.bayer.config_params.test_pat_gen flag is initialized to zero and never written to from any code path, so anything depending on it can be eliminated. To shut up the clang warning, just remove the dead code manually, it has probably never been used because any attempt to do so would have resulted in undefined behavior. Fixes: 63e3ab142fa3 ("V4L/DVB: V4L - vpfe capture - source for ISIF driver on DM365") Signed-off-by: Arnd Bergmann Reviewed-by: Nathan Chancellor Acked-by: Lad, Prabhakar Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/isif.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/media/platform/davinci/isif.c b/drivers/media/platform/davinci/isif.c index 47cecd10eb9f..2dee9af6d413 100644 --- a/drivers/media/platform/davinci/isif.c +++ b/drivers/media/platform/davinci/isif.c @@ -884,9 +884,7 @@ static int isif_set_hw_if_params(struct vpfe_hw_if_param *params) static int isif_config_ycbcr(void) { struct isif_ycbcr_config *params = &isif_cfg.ycbcr; - struct vpss_pg_frame_size frame_size; u32 modeset = 0, ccdcfg = 0; - struct vpss_sync_pol sync; dev_dbg(isif_cfg.dev, "\nStarting isif_config_ycbcr..."); @@ -974,13 +972,6 @@ static int isif_config_ycbcr(void) /* two fields are interleaved in memory */ regw(0x00000249, SDOFST); - /* Setup test pattern if enabled */ - if (isif_cfg.bayer.config_params.test_pat_gen) { - sync.ccdpg_hdpol = params->hd_pol; - sync.ccdpg_vdpol = params->vd_pol; - dm365_vpss_set_sync_pol(sync); - dm365_vpss_set_pg_frame_size(frame_size); - } return 0; } From d7a955c8ef7cd8fecfd9e900c47f72e67dfcc49a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 25 Mar 2019 05:06:26 -0400 Subject: [PATCH 121/218] media: v4l2-ctrl: potential shift wrapping bugs This code generates a static checker warning: drivers/media/v4l2-core/v4l2-ctrls.c:2921 v4l2_querymenu() warn: should '(1 << i)' be a 64 bit type? The problem is that "ctrl->menu_skip_mask" is a u64 and we're only testing the lower 32 bits. Signed-off-by: Dan Carpenter Reviewed-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ctrls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index aed1c3a06500..b1ae2e555c68 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -1605,7 +1605,7 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx, case V4L2_CTRL_TYPE_INTEGER_MENU: if (ptr.p_s32[idx] < ctrl->minimum || ptr.p_s32[idx] > ctrl->maximum) return -ERANGE; - if (ctrl->menu_skip_mask & (1 << ptr.p_s32[idx])) + if (ctrl->menu_skip_mask & (1ULL << ptr.p_s32[idx])) return -EINVAL; if (ctrl->type == V4L2_CTRL_TYPE_MENU && ctrl->qmenu[ptr.p_s32[idx]][0] == '\0') @@ -2930,7 +2930,7 @@ int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm) return -EINVAL; /* Use mask to see if this menu item should be skipped */ - if (ctrl->menu_skip_mask & (1 << i)) + if (ctrl->menu_skip_mask & (1ULL << i)) return -EINVAL; /* Empty menu items should also be skipped */ if (ctrl->type == V4L2_CTRL_TYPE_MENU) { From 52fafc58c3535c9f4f53864686dbaee3bcbadcb4 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Tue, 26 Mar 2019 03:44:23 -0400 Subject: [PATCH 122/218] media: mtk-vcodec: fix access to incorrect planes member Commit 0650a91499e0 ("media: mtk-vcodec: Correct return type for mem2mem buffer helpers") fixed the return types for mem2mem buffer helper functions by changing a few local variables from vb2_buffer to vb2_v4l2_buffer. However, it left a few accesses to vb2_buffer::planes as-is, accidentally turning them into accesses to vb2_v4l2_buffer::planes and resulting in values being read from/written to the wrong place. Fix this by inserting vb2_buf into these accesses so they mimic their original behavior. Fixes: 0650a91499e0 ("media: mtk-vcodec: Correct return type for mem2mem buffer helpers") Signed-off-by: Alexandre Courbot Reviewed-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 4 ++-- drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c index a85c7cc8328e..e20b340855e7 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c @@ -388,7 +388,7 @@ static void mtk_vdec_worker(struct work_struct *work) } buf.va = vb2_plane_vaddr(&src_buf->vb2_buf, 0); buf.dma_addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); - buf.size = (size_t)src_buf->planes[0].bytesused; + buf.size = (size_t)src_buf->vb2_buf.planes[0].bytesused; if (!buf.va) { v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); mtk_v4l2_err("[%d] id=%d src_addr is NULL!!", @@ -1155,7 +1155,7 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) src_mem.va = vb2_plane_vaddr(&src_buf->vb2_buf, 0); src_mem.dma_addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); - src_mem.size = (size_t)src_buf->planes[0].bytesused; + src_mem.size = (size_t)src_buf->vb2_buf.planes[0].bytesused; mtk_v4l2_debug(2, "[%d] buf id=%d va=%p dma=%pad size=%zx", ctx->id, src_buf->vb2_buf.index, diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c index c6b48b5925fb..50351adafc47 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c @@ -894,7 +894,7 @@ static void vb2ops_venc_stop_streaming(struct vb2_queue *q) if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { while ((dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx))) { - dst_buf->planes[0].bytesused = 0; + dst_buf->vb2_buf.planes[0].bytesused = 0; v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR); } } else { @@ -947,7 +947,7 @@ static int mtk_venc_encode_header(void *priv) bs_buf.va = vb2_plane_vaddr(&dst_buf->vb2_buf, 0); bs_buf.dma_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); - bs_buf.size = (size_t)dst_buf->planes[0].length; + bs_buf.size = (size_t)dst_buf->vb2_buf.planes[0].length; mtk_v4l2_debug(1, "[%d] buf id=%d va=0x%p dma_addr=0x%llx size=%zu", @@ -976,7 +976,7 @@ static int mtk_venc_encode_header(void *priv) } ctx->state = MTK_STATE_HEADER; - dst_buf->planes[0].bytesused = enc_result.bs_size; + dst_buf->vb2_buf.planes[0].bytesused = enc_result.bs_size; v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); return 0; @@ -1107,12 +1107,12 @@ static void mtk_venc_worker(struct work_struct *work) if (ret) { v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); - dst_buf->planes[0].bytesused = 0; + dst_buf->vb2_buf.planes[0].bytesused = 0; v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR); mtk_v4l2_err("venc_if_encode failed=%d", ret); } else { v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); - dst_buf->planes[0].bytesused = enc_result.bs_size; + dst_buf->vb2_buf.planes[0].bytesused = enc_result.bs_size; v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); mtk_v4l2_debug(2, "venc_if_encode bs size=%d", enc_result.bs_size); From 99df48ec7c5b10d00a394cc260726c5316640c81 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Tue, 26 Mar 2019 03:44:46 -0400 Subject: [PATCH 123/218] media: mtk-vcodec: remove ready_to_display This member is never read throughout the code, so remove it. Signed-off-by: Alexandre Courbot Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 5 ----- drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h | 2 -- 2 files changed, 7 deletions(-) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c index e20b340855e7..710dcebb42b3 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c @@ -133,8 +133,6 @@ static struct vb2_buffer *get_display_buffer(struct mtk_vcodec_ctx *ctx) vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1, ctx->picinfo.c_bs_sz); - dstbuf->ready_to_display = true; - mtk_v4l2_debug(2, "[%d]status=%x queue id=%d to done_list %d", ctx->id, disp_frame_buffer->status, @@ -1122,11 +1120,9 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) v4l2_m2m_buf_queue(ctx->m2m_ctx, vb2_v4l2); buf->queued_in_vb2 = true; buf->queued_in_v4l2 = true; - buf->ready_to_display = false; } else { buf->queued_in_vb2 = false; buf->queued_in_v4l2 = true; - buf->ready_to_display = false; } mutex_unlock(&ctx->lock); return; @@ -1253,7 +1249,6 @@ static int vb2ops_vdec_buf_init(struct vb2_buffer *vb) if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { buf->used = false; - buf->ready_to_display = false; buf->queued_in_v4l2 = false; } else { buf->lastframe = false; diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h index dc4fc1df63c5..e4984edec4f8 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h @@ -45,7 +45,6 @@ struct vdec_fb { * @list: link list * @used: Capture buffer contain decoded frame data and keep in * codec data structure - * @ready_to_display: Capture buffer not display yet * @queued_in_vb2: Capture buffer is queue in vb2 * @queued_in_v4l2: Capture buffer is in v4l2 driver, but not in vb2 * queue yet @@ -60,7 +59,6 @@ struct mtk_video_dec_buf { struct list_head list; bool used; - bool ready_to_display; bool queued_in_vb2; bool queued_in_v4l2; bool lastframe; From aeb0d0f581e2079868e64a2e5ee346d340376eae Mon Sep 17 00:00:00 2001 From: Kangjie Lu Date: Sat, 9 Mar 2019 02:20:56 -0500 Subject: [PATCH 124/218] media: video-mux: fix null pointer dereferences devm_kcalloc may fail and return a null pointer. The fix returns -ENOMEM upon failures to avoid null pointer dereferences. Signed-off-by: Kangjie Lu Reviewed-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/video-mux.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c index 0ba30756e1e4..d8cd5f5cb10d 100644 --- a/drivers/media/platform/video-mux.c +++ b/drivers/media/platform/video-mux.c @@ -419,9 +419,14 @@ static int video_mux_probe(struct platform_device *pdev) vmux->active = -1; vmux->pads = devm_kcalloc(dev, num_pads, sizeof(*vmux->pads), GFP_KERNEL); + if (!vmux->pads) + return -ENOMEM; + vmux->format_mbus = devm_kcalloc(dev, num_pads, sizeof(*vmux->format_mbus), GFP_KERNEL); + if (!vmux->format_mbus) + return -ENOMEM; for (i = 0; i < num_pads; i++) { vmux->pads[i].flags = (i < num_pads - 1) ? MEDIA_PAD_FL_SINK From f8ee34c3e77afd8cfc13f98e326325f17494f1e5 Mon Sep 17 00:00:00 2001 From: Kangjie Lu Date: Sat, 9 Mar 2019 02:42:26 -0500 Subject: [PATCH 125/218] media: usbvision: fix a potential NULL pointer dereference In case usb_alloc_coherent fails, the fix returns -ENOMEM to avoid a potential NULL pointer dereference. Signed-off-by: Kangjie Lu Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/usbvision/usbvision-core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/usb/usbvision/usbvision-core.c b/drivers/media/usb/usbvision/usbvision-core.c index 92d166bf8c12..abc4eed832a3 100644 --- a/drivers/media/usb/usbvision/usbvision-core.c +++ b/drivers/media/usb/usbvision/usbvision-core.c @@ -2302,6 +2302,9 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) sb_size, GFP_KERNEL, &urb->transfer_dma); + if (!usbvision->sbuf[buf_idx].data) + return -ENOMEM; + urb->dev = dev; urb->context = usbvision; urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp); From 2e7682ebfc750177a4944eeb56e97a3f05734528 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 14 Mar 2019 22:01:24 -0400 Subject: [PATCH 126/218] media: tw5864: Fix possible NULL pointer dereference in tw5864_handle_frame 'vb' null check should be done before dereferencing it in tw5864_handle_frame, otherwise a NULL pointer dereference may occur. Fixes: 34d1324edd31 ("[media] pci: Add tw5864 driver") Signed-off-by: YueHaibing Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/tw5864/tw5864-video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/tw5864/tw5864-video.c b/drivers/media/pci/tw5864/tw5864-video.c index 5a1f3aa4101a..434d313a3c15 100644 --- a/drivers/media/pci/tw5864/tw5864-video.c +++ b/drivers/media/pci/tw5864/tw5864-video.c @@ -1395,13 +1395,13 @@ static void tw5864_handle_frame(struct tw5864_h264_frame *frame) input->vb = NULL; spin_unlock_irqrestore(&input->slock, flags); - v4l2_buf = to_vb2_v4l2_buffer(&vb->vb.vb2_buf); - if (!vb) { /* Gone because of disabling */ dev_dbg(&dev->pci->dev, "vb is empty, dropping frame\n"); return; } + v4l2_buf = to_vb2_v4l2_buffer(&vb->vb.vb2_buf); + /* * Check for space. * Mind the overhead of startcode emulation prevention. From 9c2ccc324b3a6cbc865ab8b3e1a09e93d3c8ade9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 26 Mar 2019 01:12:07 -0400 Subject: [PATCH 127/218] media: wl128x: prevent two potential buffer overflows Smatch marks skb->data as untrusted so it warns that "evt_hdr->dlen" can copy up to 255 bytes and we only have room for two bytes. Even if this comes from the firmware and we trust it, the new policy generally is just to fix it as kernel hardenning. I can't test this code so I tried to be very conservative. I considered not allowing "evt_hdr->dlen == 1" because it doesn't initialize the whole variable but in the end I decided to allow it and manually initialized "asic_id" and "asic_ver" to zero. Fixes: e8454ff7b9a4 ("[media] drivers:media:radio: wl128x: FM Driver Common sources") Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/wl128x/fmdrv_common.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c index 1614809f7d35..a1fcb80a2191 100644 --- a/drivers/media/radio/wl128x/fmdrv_common.c +++ b/drivers/media/radio/wl128x/fmdrv_common.c @@ -489,7 +489,8 @@ int fmc_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload, return -EIO; } /* Send response data to caller */ - if (response != NULL && response_len != NULL && evt_hdr->dlen) { + if (response != NULL && response_len != NULL && evt_hdr->dlen && + evt_hdr->dlen <= payload_len) { /* Skip header info and copy only response data */ skb_pull(skb, sizeof(struct fm_event_msg_hdr)); memcpy(response, skb->data, evt_hdr->dlen); @@ -583,6 +584,8 @@ static void fm_irq_handle_flag_getcmd_resp(struct fmdev *fmdev) return; fm_evt_hdr = (void *)skb->data; + if (fm_evt_hdr->dlen > sizeof(fmdev->irq_info.flag)) + return; /* Skip header info and copy only response data */ skb_pull(skb, sizeof(struct fm_event_msg_hdr)); @@ -1309,7 +1312,7 @@ static int load_default_rx_configuration(struct fmdev *fmdev) static int fm_power_up(struct fmdev *fmdev, u8 mode) { u16 payload; - __be16 asic_id, asic_ver; + __be16 asic_id = 0, asic_ver = 0; int resp_len, ret; u8 fw_name[50]; From b4a7113f84128ed0acbc5ff886bd5cf4d87ab733 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 28 Mar 2019 10:41:38 -0400 Subject: [PATCH 128/218] media: wl128x: Fix some error handling in fmc_prepare() The st_register() returns have changed over time, but these days it never returns -1. We should just be checking for any negative error codes. Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/wl128x/fmdrv_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c index a1fcb80a2191..053d51a5890a 100644 --- a/drivers/media/radio/wl128x/fmdrv_common.c +++ b/drivers/media/radio/wl128x/fmdrv_common.c @@ -1524,7 +1524,7 @@ int fmc_prepare(struct fmdev *fmdev) } ret = 0; - } else if (ret == -1) { + } else if (ret < 0) { fmerr("st_register failed %d\n", ret); return -EAGAIN; } From 060162c1af5cd807384247cc95a0d5cb016e316a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 28 Mar 2019 15:02:23 -0400 Subject: [PATCH 129/218] media: vim2m: Fix RGB 565 BE/LE support The support for those two formats are archtecture-dependent. Use the endianness to CPU macros to do it right. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vim2m.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c index dd47821fc661..d8763a8a7be6 100644 --- a/drivers/media/platform/vim2m.c +++ b/drivers/media/platform/vim2m.c @@ -302,7 +302,7 @@ static void copy_two_pixels(struct vim2m_q_data *q_data_in, switch (in->fourcc) { case V4L2_PIX_FMT_RGB565: /* rrrrrggg gggbbbbb */ for (i = 0; i < 2; i++) { - u16 pix = *(u16 *)(src[i]); + u16 pix = le16_to_cpu(*(__le16 *)(src[i])); *r++ = (u8)(((pix & 0xf800) >> 11) << 3) | 0x07; *g++ = (u8)((((pix & 0x07e0) >> 5)) << 2) | 0x03; @@ -311,12 +311,11 @@ static void copy_two_pixels(struct vim2m_q_data *q_data_in, break; case V4L2_PIX_FMT_RGB565X: /* gggbbbbb rrrrrggg */ for (i = 0; i < 2; i++) { - u16 pix = *(u16 *)(src[i]); + u16 pix = be16_to_cpu(*(__be16 *)(src[i])); - *r++ = (u8)(((0x00f8 & pix) >> 3) << 3) | 0x07; - *g++ = (u8)(((pix & 0x7) << 2) | - ((pix & 0xe000) >> 5)) | 0x03; - *b++ = (u8)(((pix & 0x1f00) >> 8) << 3) | 0x07; + *r++ = (u8)(((pix & 0xf800) >> 11) << 3) | 0x07; + *g++ = (u8)((((pix & 0x07e0) >> 5)) << 2) | 0x03; + *b++ = (u8)((pix & 0x1f) << 3) | 0x07; } break; default: @@ -345,21 +344,26 @@ static void copy_two_pixels(struct vim2m_q_data *q_data_in, switch (out->fourcc) { case V4L2_PIX_FMT_RGB565: /* rrrrrggg gggbbbbb */ for (i = 0; i < 2; i++) { - u16 *pix = (u16 *)*dst; + u16 pix; + __le16 *dst_pix = (__le16 *)*dst; - *pix = ((*r << 8) & 0xf800) | ((*g << 3) & 0x07e0) | - (*b >> 3); + pix = ((*r << 8) & 0xf800) | ((*g << 3) & 0x07e0) | + (*b >> 3); + + *dst_pix = cpu_to_le16(pix); *dst += 2; } return; case V4L2_PIX_FMT_RGB565X: /* gggbbbbb rrrrrggg */ for (i = 0; i < 2; i++) { - u16 *pix = (u16 *)*dst; - u8 green = *g++ >> 2; + u16 pix; + __be16 *dst_pix = (__be16 *)*dst; - *pix = ((green << 8) & 0xe000) | (green & 0x07) | - ((*b++ << 5) & 0x1f00) | ((*r++ & 0xf8)); + pix = ((*r << 8) & 0xf800) | ((*g << 3) & 0x07e0) | + (*b >> 3); + + *dst_pix = cpu_to_be16(pix); *dst += 2; } From 85709cbf152465c77a9c2de48a6f4ef23c8c3d83 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 10 Sep 2018 08:19:16 -0400 Subject: [PATCH 130/218] media: replace strncpy() by strscpy() The strncpy() function is being deprecated upstream. Replace it by the safer strscpy(). While here, replace a few occurences of strlcpy() that were recently added to also use strscpy(). Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/as102_fe.c | 2 +- drivers/media/dvb-frontends/dib7000p.c | 3 ++- drivers/media/dvb-frontends/dib8000.c | 4 ++-- drivers/media/dvb-frontends/dib9000.c | 6 ++++-- drivers/media/dvb-frontends/dvb-pll.c | 2 +- drivers/media/dvb-frontends/m88ds3103.c | 2 +- drivers/media/pci/bt8xx/dst.c | 3 ++- drivers/media/pci/mantis/mantis_i2c.c | 2 +- drivers/media/pci/saa7134/saa7134-go7007.c | 2 +- drivers/media/platform/am437x/am437x-vpfe.c | 2 +- drivers/media/platform/davinci/vpfe_capture.c | 2 +- drivers/media/platform/davinci/vpif_capture.c | 3 ++- drivers/media/platform/davinci/vpif_display.c | 4 ++-- drivers/media/platform/exynos4-is/fimc-capture.c | 2 +- drivers/media/platform/exynos4-is/fimc-m2m.c | 2 +- drivers/media/platform/imx-pxp.c | 4 ++-- drivers/media/platform/mtk-vpu/mtk_vpu.c | 2 +- drivers/media/platform/mx2_emmaprp.c | 4 ++-- drivers/media/platform/s5p-g2d/g2d.c | 6 +++--- .../media/platform/sunxi/sun6i-csi/sun6i_video.c | 4 ++-- drivers/media/platform/ti-vpe/vpe.c | 6 +++--- drivers/media/platform/vicodec/vicodec-core.c | 4 ++-- drivers/media/platform/vim2m.c | 4 ++-- drivers/media/platform/vivid/vivid-core.c | 2 +- drivers/media/radio/si4713/si4713.c | 2 +- drivers/media/usb/go7007/go7007-usb.c | 16 ++++++++-------- drivers/media/usb/go7007/go7007-v4l2.c | 2 +- drivers/media/usb/hdpvr/hdpvr-video.c | 10 ++++------ drivers/media/usb/pulse8-cec/pulse8-cec.c | 4 ++-- drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 5 ++--- drivers/media/usb/pvrusb2/pvrusb2-v4l2.c | 4 ++-- drivers/staging/media/bcm2048/radio-bcm2048.c | 4 ++-- drivers/staging/media/imx/imx-ic-common.c | 2 +- drivers/staging/media/imx/imx-media-vdic.c | 2 +- drivers/staging/media/zoran/zoran_driver.c | 10 +++++----- 35 files changed, 70 insertions(+), 68 deletions(-) diff --git a/drivers/media/dvb-frontends/as102_fe.c b/drivers/media/dvb-frontends/as102_fe.c index f59a102b0a64..9ba8f39fe310 100644 --- a/drivers/media/dvb-frontends/as102_fe.c +++ b/drivers/media/dvb-frontends/as102_fe.c @@ -467,7 +467,7 @@ struct dvb_frontend *as102_attach(const char *name, /* init frontend callback ops */ memcpy(&fe->ops, &as102_fe_ops, sizeof(struct dvb_frontend_ops)); - strncpy(fe->ops.info.name, name, sizeof(fe->ops.info.name)); + strscpy(fe->ops.info.name, name, sizeof(fe->ops.info.name)); return fe; diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c index f8040f6def62..d869029ca87d 100644 --- a/drivers/media/dvb-frontends/dib7000p.c +++ b/drivers/media/dvb-frontends/dib7000p.c @@ -2774,7 +2774,8 @@ static struct dvb_frontend *dib7000p_init(struct i2c_adapter *i2c_adap, u8 i2c_a dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr); /* init 7090 tuner adapter */ - strncpy(st->dib7090_tuner_adap.name, "DiB7090 tuner interface", sizeof(st->dib7090_tuner_adap.name)); + strscpy(st->dib7090_tuner_adap.name, "DiB7090 tuner interface", + sizeof(st->dib7090_tuner_adap.name)); st->dib7090_tuner_adap.algo = &dib7090_tuner_xfer_algo; st->dib7090_tuner_adap.algo_data = NULL; st->dib7090_tuner_adap.dev.parent = st->i2c_adap->dev.parent; diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index 85c429cce23e..564669338dc6 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c @@ -4458,8 +4458,8 @@ static struct dvb_frontend *dib8000_init(struct i2c_adapter *i2c_adap, u8 i2c_ad dibx000_init_i2c_master(&state->i2c_master, DIB8000, state->i2c.adap, state->i2c.addr); /* init 8096p tuner adapter */ - strncpy(state->dib8096p_tuner_adap.name, "DiB8096P tuner interface", - sizeof(state->dib8096p_tuner_adap.name)); + strscpy(state->dib8096p_tuner_adap.name, "DiB8096P tuner interface", + sizeof(state->dib8096p_tuner_adap.name)); state->dib8096p_tuner_adap.algo = &dib8096p_tuner_xfer_algo; state->dib8096p_tuner_adap.algo_data = NULL; state->dib8096p_tuner_adap.dev.parent = state->i2c.adap->dev.parent; diff --git a/drivers/media/dvb-frontends/dib9000.c b/drivers/media/dvb-frontends/dib9000.c index 1875da07c150..e7838926e6bc 100644 --- a/drivers/media/dvb-frontends/dib9000.c +++ b/drivers/media/dvb-frontends/dib9000.c @@ -2521,7 +2521,8 @@ struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, c dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c.i2c_adap, st->i2c.i2c_addr); st->tuner_adap.dev.parent = i2c_adap->dev.parent; - strncpy(st->tuner_adap.name, "DIB9000_FW TUNER ACCESS", sizeof(st->tuner_adap.name)); + strscpy(st->tuner_adap.name, "DIB9000_FW TUNER ACCESS", + sizeof(st->tuner_adap.name)); st->tuner_adap.algo = &dib9000_tuner_algo; st->tuner_adap.algo_data = NULL; i2c_set_adapdata(&st->tuner_adap, st); @@ -2529,7 +2530,8 @@ struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, c goto error; st->component_bus.dev.parent = i2c_adap->dev.parent; - strncpy(st->component_bus.name, "DIB9000_FW COMPONENT BUS ACCESS", sizeof(st->component_bus.name)); + strscpy(st->component_bus.name, "DIB9000_FW COMPONENT BUS ACCESS", + sizeof(st->component_bus.name)); st->component_bus.algo = &dib9000_component_bus_algo; st->component_bus.algo_data = NULL; st->component_bus_speed = 340; diff --git a/drivers/media/dvb-frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c index 29836c1a40e9..da1b48a18515 100644 --- a/drivers/media/dvb-frontends/dvb-pll.c +++ b/drivers/media/dvb-frontends/dvb-pll.c @@ -839,7 +839,7 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, sizeof(struct dvb_tuner_ops)); - strncpy(fe->ops.tuner_ops.info.name, desc->name, + strscpy(fe->ops.tuner_ops.info.name, desc->name, sizeof(fe->ops.tuner_ops.info.name)); fe->ops.tuner_ops.info.frequency_min_hz = desc->min; diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c index 403f42806455..b543e1c4c4f9 100644 --- a/drivers/media/dvb-frontends/m88ds3103.c +++ b/drivers/media/dvb-frontends/m88ds3103.c @@ -1469,7 +1469,7 @@ static int m88ds3103_probe(struct i2c_client *client, /* create dvb_frontend */ memcpy(&dev->fe.ops, &m88ds3103_ops, sizeof(struct dvb_frontend_ops)); if (dev->chip_id == M88RS6000_CHIP_ID) - strncpy(dev->fe.ops.info.name, "Montage Technology M88RS6000", + strscpy(dev->fe.ops.info.name, "Montage Technology M88RS6000", sizeof(dev->fe.ops.info.name)); if (!pdata->attach_in_use) dev->fe.ops.release = NULL; diff --git a/drivers/media/pci/bt8xx/dst.c b/drivers/media/pci/bt8xx/dst.c index c94318c71a0c..3315a6d67edf 100644 --- a/drivers/media/pci/bt8xx/dst.c +++ b/drivers/media/pci/bt8xx/dst.c @@ -1100,7 +1100,8 @@ static int dst_get_device_id(struct dst_state *state) /* Card capabilities */ state->dst_hw_cap = p_dst_type->dst_feature; pr_err("Recognise [%s]\n", p_dst_type->device_id); - strncpy(&state->fw_name[0], p_dst_type->device_id, 6); + strscpy((char *)state->fw_name, p_dst_type->device_id, + sizeof(state->fw_name)); /* Multiple tuners */ if (p_dst_type->tuner_type & TUNER_TYPE_MULTI) { switch (use_dst_type) { diff --git a/drivers/media/pci/mantis/mantis_i2c.c b/drivers/media/pci/mantis/mantis_i2c.c index 6528a2180119..f8b503ef42bc 100644 --- a/drivers/media/pci/mantis/mantis_i2c.c +++ b/drivers/media/pci/mantis/mantis_i2c.c @@ -225,7 +225,7 @@ int mantis_i2c_init(struct mantis_pci *mantis) init_waitqueue_head(&mantis->i2c_wq); mutex_init(&mantis->i2c_lock); - strncpy(i2c_adapter->name, "Mantis I2C", sizeof(i2c_adapter->name)); + strscpy(i2c_adapter->name, "Mantis I2C", sizeof(i2c_adapter->name)); i2c_set_adapdata(i2c_adapter, mantis); i2c_adapter->owner = THIS_MODULE; diff --git a/drivers/media/pci/saa7134/saa7134-go7007.c b/drivers/media/pci/saa7134/saa7134-go7007.c index 275c5e151818..626e130a9770 100644 --- a/drivers/media/pci/saa7134/saa7134-go7007.c +++ b/drivers/media/pci/saa7134/saa7134-go7007.c @@ -444,7 +444,7 @@ static int saa7134_go7007_init(struct saa7134_dev *dev) sd = &saa->sd; v4l2_subdev_init(sd, &saa7134_go7007_sd_ops); v4l2_set_subdevdata(sd, saa); - strncpy(sd->name, "saa7134-go7007", sizeof(sd->name)); + strscpy(sd->name, "saa7134-go7007", sizeof(sd->name)); /* Allocate a couple pages for receiving the compressed stream */ saa->top = (u8 *)get_zeroed_page(GFP_KERNEL); diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c index 5c17624aaade..fe7b937eb5f2 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.c +++ b/drivers/media/platform/am437x/am437x-vpfe.c @@ -1540,7 +1540,7 @@ static int vpfe_enum_fmt(struct file *file, void *priv, if (!fmt) return -EINVAL; - strncpy(f->description, fmt->name, sizeof(f->description) - 1); + strscpy(f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->fourcc; f->type = vpfe->fmt.type; diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c index 26dadbba930f..1e3a13830544 100644 --- a/drivers/media/platform/davinci/vpfe_capture.c +++ b/drivers/media/platform/davinci/vpfe_capture.c @@ -1759,7 +1759,7 @@ static int vpfe_probe(struct platform_device *pdev) mutex_lock(&ccdc_lock); - strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32); + strscpy(ccdc_cfg->name, vpfe_cfg->ccdc, sizeof(ccdc_cfg->name)); /* Get VINT0 irq resource */ res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res1) { diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index 6216b7ac6875..b5aacb0fb96b 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -1254,7 +1254,8 @@ static int vpif_s_dv_timings(struct file *file, void *priv, } else { std_info->l5 = std_info->vsize - (bt->vfrontporch - 1); } - strncpy(std_info->name, "Custom timings BT656/1120", VPIF_MAX_NAME); + strscpy(std_info->name, "Custom timings BT656/1120", + sizeof(std_info->name)); std_info->width = bt->width; std_info->height = bt->height; std_info->frm_fmt = bt->interlaced ? 0 : 1; diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index f4b4f2a1dfc0..a69897c68a50 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -987,8 +987,8 @@ static int vpif_s_dv_timings(struct file *file, void *priv, } else { std_info->l5 = std_info->vsize - (bt->vfrontporch - 1); } - strncpy(std_info->name, "Custom timings BT656/1120", - VPIF_MAX_NAME); + strscpy(std_info->name, "Custom timings BT656/1120", + sizeof(std_info->name)); std_info->width = bt->width; std_info->height = bt->height; std_info->frm_fmt = bt->interlaced ? 0 : 1; diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index 3e9fcf4f8a13..de4af0357a3c 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c @@ -742,7 +742,7 @@ static int fimc_cap_enum_fmt_mplane(struct file *file, void *priv, f->index); if (!fmt) return -EINVAL; - strncpy(f->description, fmt->name, sizeof(f->description) - 1); + strscpy(f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->fourcc; if (fmt->fourcc == MEDIA_BUS_FMT_JPEG_1X8) f->flags |= V4L2_FMT_FLAG_COMPRESSED; diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c index 61c8177409cf..1bea1ce4091e 100644 --- a/drivers/media/platform/exynos4-is/fimc-m2m.c +++ b/drivers/media/platform/exynos4-is/fimc-m2m.c @@ -252,7 +252,7 @@ static int fimc_m2m_enum_fmt_mplane(struct file *file, void *priv, if (!fmt) return -EINVAL; - strncpy(f->description, fmt->name, sizeof(f->description) - 1); + strscpy(f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->fourcc; return 0; } diff --git a/drivers/media/platform/imx-pxp.c b/drivers/media/platform/imx-pxp.c index 0bcfc5aa8f3d..8e7ef23b9a7e 100644 --- a/drivers/media/platform/imx-pxp.c +++ b/drivers/media/platform/imx-pxp.c @@ -1025,8 +1025,8 @@ static irqreturn_t pxp_irq_handler(int irq, void *dev_id) static int pxp_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - strlcpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver)); - strlcpy(cap->card, MEM2MEM_NAME, sizeof(cap->card)); + strscpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver)); + strscpy(cap->card, MEM2MEM_NAME, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", MEM2MEM_NAME); return 0; diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.c b/drivers/media/platform/mtk-vpu/mtk_vpu.c index b6602490a247..46c45f93c977 100644 --- a/drivers/media/platform/mtk-vpu/mtk_vpu.c +++ b/drivers/media/platform/mtk-vpu/mtk_vpu.c @@ -614,7 +614,7 @@ static void vpu_init_ipi_handler(void *data, unsigned int len, void *priv) struct vpu_run *run = (struct vpu_run *)data; vpu->run.signaled = run->signaled; - strncpy(vpu->run.fw_ver, run->fw_ver, VPU_FW_VER_LEN); + strscpy(vpu->run.fw_ver, run->fw_ver, sizeof(vpu->run.fw_ver)); vpu->run.dec_capability = run->dec_capability; vpu->run.enc_capability = run->enc_capability; wake_up_interruptible(&vpu->run.wq); diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c index f60f499c596b..e100b30bb6f5 100644 --- a/drivers/media/platform/mx2_emmaprp.c +++ b/drivers/media/platform/mx2_emmaprp.c @@ -385,8 +385,8 @@ static irqreturn_t emmaprp_irq(int irq_emma, void *data) static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1); - strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1); + strscpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver)); + strscpy(cap->card, MEM2MEM_NAME, sizeof(cap->card)); cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c index 971c47165010..c8f394e1aff4 100644 --- a/drivers/media/platform/s5p-g2d/g2d.c +++ b/drivers/media/platform/s5p-g2d/g2d.c @@ -297,8 +297,8 @@ static int g2d_release(struct file *file) static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - strncpy(cap->driver, G2D_NAME, sizeof(cap->driver) - 1); - strncpy(cap->card, G2D_NAME, sizeof(cap->card) - 1); + strscpy(cap->driver, G2D_NAME, sizeof(cap->driver)); + strscpy(cap->card, G2D_NAME, sizeof(cap->card)); cap->bus_info[0] = 0; cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; @@ -312,7 +312,7 @@ static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f) return -EINVAL; fmt = &formats[f->index]; f->pixelformat = fmt->fourcc; - strncpy(f->description, fmt->name, sizeof(f->description) - 1); + strscpy(f->description, fmt->name, sizeof(f->description)); return 0; } diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c index 1fd16861f111..f0dfe68486d1 100644 --- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c +++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c @@ -412,7 +412,7 @@ static int vidioc_enum_input(struct file *file, void *fh, if (inp->index != 0) return -EINVAL; - strlcpy(inp->name, "camera", sizeof(inp->name)); + strscpy(inp->name, "camera", sizeof(inp->name)); inp->type = V4L2_INPUT_TYPE_CAMERA; return 0; @@ -644,7 +644,7 @@ int sun6i_video_init(struct sun6i_video *video, struct sun6i_csi *csi, } /* Register video device */ - strlcpy(vdev->name, name, sizeof(vdev->name)); + strscpy(vdev->name, name, sizeof(vdev->name)); vdev->release = video_device_release_empty; vdev->fops = &sun6i_video_fops; vdev->ioctl_ops = &sun6i_video_ioctl_ops; diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c index 207e7e76c048..1e40eafec284 100644 --- a/drivers/media/platform/ti-vpe/vpe.c +++ b/drivers/media/platform/ti-vpe/vpe.c @@ -1491,8 +1491,8 @@ handled: static int vpe_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - strncpy(cap->driver, VPE_MODULE_NAME, sizeof(cap->driver) - 1); - strncpy(cap->card, VPE_MODULE_NAME, sizeof(cap->card) - 1); + strscpy(cap->driver, VPE_MODULE_NAME, sizeof(cap->driver)); + strscpy(cap->card, VPE_MODULE_NAME, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", VPE_MODULE_NAME); cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; @@ -1519,7 +1519,7 @@ static int __enum_fmt(struct v4l2_fmtdesc *f, u32 type) if (!fmt) return -EINVAL; - strncpy(f->description, fmt->name, sizeof(f->description) - 1); + strscpy(f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->fourcc; return 0; } diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index a5f8f74ea3bf..bd01a9206aa6 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -692,8 +692,8 @@ static const struct v4l2_fwht_pixfmt_info *find_fmt(u32 fmt) static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - strncpy(cap->driver, VICODEC_NAME, sizeof(cap->driver) - 1); - strncpy(cap->card, VICODEC_NAME, sizeof(cap->card) - 1); + strscpy(cap->driver, VICODEC_NAME, sizeof(cap->driver)); + strscpy(cap->card, VICODEC_NAME, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", VICODEC_NAME); return 0; diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c index d8763a8a7be6..243c82b5d537 100644 --- a/drivers/media/platform/vim2m.c +++ b/drivers/media/platform/vim2m.c @@ -659,8 +659,8 @@ static void device_work(struct work_struct *w) static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1); - strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1); + strscpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver)); + strscpy(cap->card, MEM2MEM_NAME, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", MEM2MEM_NAME); return 0; diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c index 342e0e6c103b..7047df6f0e0e 100644 --- a/drivers/media/platform/vivid/vivid-core.c +++ b/drivers/media/platform/vivid/vivid-core.c @@ -681,7 +681,7 @@ static int vivid_create_instance(struct platform_device *pdev, int inst) dev->v4l2_dev.mdev = &dev->mdev; /* Initialize media device */ - strlcpy(dev->mdev.model, VIVID_MODULE_NAME, sizeof(dev->mdev.model)); + strscpy(dev->mdev.model, VIVID_MODULE_NAME, sizeof(dev->mdev.model)); snprintf(dev->mdev.bus_info, sizeof(dev->mdev.bus_info), "platform:%s-%03d", VIVID_MODULE_NAME, inst); dev->mdev.dev = &pdev->dev; diff --git a/drivers/media/radio/si4713/si4713.c b/drivers/media/radio/si4713/si4713.c index f4a53f1e856e..a8584371a32d 100644 --- a/drivers/media/radio/si4713/si4713.c +++ b/drivers/media/radio/si4713/si4713.c @@ -1272,7 +1272,7 @@ static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) if (vm->index > 0) return -EINVAL; - strncpy(vm->name, "FM Modulator", 32); + strscpy(vm->name, "FM Modulator", sizeof(vm->name)); vm->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_CONTROLS; diff --git a/drivers/media/usb/go7007/go7007-usb.c b/drivers/media/usb/go7007/go7007-usb.c index 19c6a0354ce0..abe98488be23 100644 --- a/drivers/media/usb/go7007/go7007-usb.c +++ b/drivers/media/usb/go7007/go7007-usb.c @@ -1132,7 +1132,7 @@ static int go7007_usb_probe(struct usb_interface *intf, usb->usbdev = usbdev; usb_make_path(usbdev, go->bus_info, sizeof(go->bus_info)); go->board_id = id->driver_info; - strncpy(go->name, name, sizeof(go->name)); + strscpy(go->name, name, sizeof(go->name)); if (board->flags & GO7007_USB_EZUSB) go->hpi_ops = &go7007_usb_ezusb_hpi_ops; else @@ -1198,7 +1198,7 @@ static int go7007_usb_probe(struct usb_interface *intf, go->board_id = GO7007_BOARDID_ENDURA; usb->board = board = &board_endura; go->board_info = &board->main_info; - strncpy(go->name, "Pelco Endura", + strscpy(go->name, "Pelco Endura", sizeof(go->name)); } else { u16 channel; @@ -1232,21 +1232,21 @@ static int go7007_usb_probe(struct usb_interface *intf, case 1: go->tuner_type = TUNER_SONY_BTF_PG472Z; go->std = V4L2_STD_PAL; - strncpy(go->name, "Plextor PX-TV402U-EU", - sizeof(go->name)); + strscpy(go->name, "Plextor PX-TV402U-EU", + sizeof(go->name)); break; case 2: go->tuner_type = TUNER_SONY_BTF_PK467Z; go->std = V4L2_STD_NTSC_M_JP; num_i2c_devs -= 2; - strncpy(go->name, "Plextor PX-TV402U-JP", - sizeof(go->name)); + strscpy(go->name, "Plextor PX-TV402U-JP", + sizeof(go->name)); break; case 3: go->tuner_type = TUNER_SONY_BTF_PB463Z; num_i2c_devs -= 2; - strncpy(go->name, "Plextor PX-TV402U-NA", - sizeof(go->name)); + strscpy(go->name, "Plextor PX-TV402U-NA", + sizeof(go->name)); break; default: pr_debug("unable to detect tuner type!\n"); diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c index 7a2781fa83e7..bebdfcecf600 100644 --- a/drivers/media/usb/go7007/go7007-v4l2.c +++ b/drivers/media/usb/go7007/go7007-v4l2.c @@ -327,7 +327,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt->flags = V4L2_FMT_FLAG_COMPRESSED; - strncpy(fmt->description, desc, sizeof(fmt->description)); + strscpy(fmt->description, desc, sizeof(fmt->description)); return 0; } diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index e082086428a4..3804aa3fb50f 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c @@ -769,8 +769,7 @@ static int vidioc_enum_input(struct file *file, void *_fh, struct v4l2_input *i) i->type = V4L2_INPUT_TYPE_CAMERA; - strncpy(i->name, iname[n], sizeof(i->name) - 1); - i->name[sizeof(i->name) - 1] = '\0'; + strscpy(i->name, iname[n], sizeof(i->name)); i->audioset = 1<capability = V4L2_AUDCAP_STEREO; - strncpy(audio->name, audio_iname[n], sizeof(audio->name) - 1); - audio->name[sizeof(audio->name) - 1] = '\0'; + strscpy(audio->name, audio_iname[n], sizeof(audio->name)); return 0; } @@ -874,7 +872,6 @@ static int vidioc_g_audio(struct file *file, void *private_data, audio->index = dev->options.audio_input; audio->capability = V4L2_AUDCAP_STEREO; strscpy(audio->name, audio_iname[audio->index], sizeof(audio->name)); - audio->name[sizeof(audio->name) - 1] = '\0'; return 0; } @@ -991,7 +988,8 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *private_data, return -EINVAL; f->flags = V4L2_FMT_FLAG_COMPRESSED; - strncpy(f->description, "MPEG2-TS with AVC/AAC streams", 32); + strscpy(f->description, "MPEG2-TS with AVC/AAC streams", + sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_MPEG; return 0; diff --git a/drivers/media/usb/pulse8-cec/pulse8-cec.c b/drivers/media/usb/pulse8-cec/pulse8-cec.c index b085b14f3f87..ea9ee74fa336 100644 --- a/drivers/media/usb/pulse8-cec/pulse8-cec.c +++ b/drivers/media/usb/pulse8-cec/pulse8-cec.c @@ -435,7 +435,7 @@ static int pulse8_setup(struct pulse8 *pulse8, struct serio *serio, err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 0); if (err) return err; - strncpy(log_addrs->osd_name, data, 13); + strscpy(log_addrs->osd_name, data, sizeof(log_addrs->osd_name)); dev_dbg(pulse8->dev, "OSD name: %s\n", log_addrs->osd_name); return 0; @@ -566,7 +566,7 @@ static int pulse8_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) char *osd_str = cmd + 1; cmd[0] = MSGCODE_SET_OSD_NAME; - strncpy(cmd + 1, adap->log_addrs.osd_name, 13); + strscpy(cmd + 1, adap->log_addrs.osd_name, sizeof(cmd) - 1); if (osd_len < 4) { memset(osd_str + osd_len, ' ', 4 - osd_len); osd_len = 4; diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index 446a999dd2ce..51112b7988e4 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -2459,9 +2459,8 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, if (!(qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY)) { ciptr->set_value = ctrl_cx2341x_set; } - strncpy(hdw->mpeg_ctrl_info[idx].desc,qctrl.name, - PVR2_CTLD_INFO_DESC_SIZE); - hdw->mpeg_ctrl_info[idx].desc[PVR2_CTLD_INFO_DESC_SIZE-1] = 0; + strscpy(hdw->mpeg_ctrl_info[idx].desc, qctrl.name, + sizeof(hdw->mpeg_ctrl_info[idx].desc)); ciptr->default_value = qctrl.default_value; switch (qctrl.type) { default: diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c index 08d5b7aa3537..cb6668580d77 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c @@ -284,7 +284,7 @@ static int pvr2_enumaudio(struct file *file, void *priv, struct v4l2_audio *vin) if (vin->index > 0) return -EINVAL; - strncpy(vin->name, "PVRUSB2 Audio", 14); + strscpy(vin->name, "PVRUSB2 Audio", sizeof(vin->name)); vin->capability = V4L2_AUDCAP_STEREO; return 0; } @@ -293,7 +293,7 @@ static int pvr2_g_audio(struct file *file, void *priv, struct v4l2_audio *vin) { /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */ vin->index = 0; - strncpy(vin->name, "PVRUSB2 Audio", 14); + strscpy(vin->name, "PVRUSB2 Audio", sizeof(vin->name)); vin->capability = V4L2_AUDCAP_STEREO; return 0; } diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c index d9b02ff66259..09903ffb13ba 100644 --- a/drivers/staging/media/bcm2048/radio-bcm2048.c +++ b/drivers/staging/media/bcm2048/radio-bcm2048.c @@ -2404,7 +2404,7 @@ static int bcm2048_vidioc_g_audio(struct file *file, void *priv, if (audio->index > 1) return -EINVAL; - strncpy(audio->name, "Radio", 32); + strscpy(audio->name, "Radio", sizeof(audio->name)); audio->capability = V4L2_AUDCAP_STEREO; return 0; @@ -2432,7 +2432,7 @@ static int bcm2048_vidioc_g_tuner(struct file *file, void *priv, if (tuner->index > 0) return -EINVAL; - strncpy(tuner->name, "FM Receiver", 32); + strscpy(tuner->name, "FM Receiver", sizeof(tuner->name)); tuner->type = V4L2_TUNER_RADIO; tuner->rangelow = dev_to_v4l2(bcm2048_get_region_bottom_frequency(bdev)); diff --git a/drivers/staging/media/imx/imx-ic-common.c b/drivers/staging/media/imx/imx-ic-common.c index 90a926891eb9..1addb0893c57 100644 --- a/drivers/staging/media/imx/imx-ic-common.c +++ b/drivers/staging/media/imx/imx-ic-common.c @@ -63,7 +63,7 @@ static int imx_ic_probe(struct platform_device *pdev) priv->sd.owner = THIS_MODULE; priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; priv->sd.grp_id = pdata->grp_id; - strncpy(priv->sd.name, pdata->sd_name, sizeof(priv->sd.name)); + strscpy(priv->sd.name, pdata->sd_name, sizeof(priv->sd.name)); ret = ic_ops[priv->task_id]->init(priv); if (ret) diff --git a/drivers/staging/media/imx/imx-media-vdic.c b/drivers/staging/media/imx/imx-media-vdic.c index f8c84a07dad9..5439b88dba20 100644 --- a/drivers/staging/media/imx/imx-media-vdic.c +++ b/drivers/staging/media/imx/imx-media-vdic.c @@ -964,7 +964,7 @@ static int imx_vdic_probe(struct platform_device *pdev) priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; /* get our group id */ priv->sd.grp_id = pdata->grp_id; - strncpy(priv->sd.name, pdata->sd_name, sizeof(priv->sd.name)); + strscpy(priv->sd.name, pdata->sd_name, sizeof(priv->sd.name)); mutex_init(&priv->lock); diff --git a/drivers/staging/media/zoran/zoran_driver.c b/drivers/staging/media/zoran/zoran_driver.c index 04f88f9d6bb4..c998aa4dc73b 100644 --- a/drivers/staging/media/zoran/zoran_driver.c +++ b/drivers/staging/media/zoran/zoran_driver.c @@ -1526,8 +1526,8 @@ static int zoran_enum_fmt(struct zoran *zr, struct v4l2_fmtdesc *fmt, int flag) for (num = i = 0; i < NUM_FORMATS; i++) { if (zoran_formats[i].flags & flag && num++ == fmt->index) { - strncpy(fmt->description, zoran_formats[i].name, - sizeof(fmt->description) - 1); + strscpy(fmt->description, zoran_formats[i].name, + sizeof(fmt->description)); /* fmt struct pre-zeroed, so adding '\0' not needed */ fmt->pixelformat = zoran_formats[i].fourcc; if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED) @@ -2301,8 +2301,8 @@ static int zoran_enum_input(struct file *file, void *__fh, if (inp->index >= zr->card.inputs) return -EINVAL; - strncpy(inp->name, zr->card.input[inp->index].name, - sizeof(inp->name) - 1); + strscpy(inp->name, zr->card.input[inp->index].name, + sizeof(inp->name)); inp->type = V4L2_INPUT_TYPE_CAMERA; inp->std = V4L2_STD_ALL; @@ -2344,7 +2344,7 @@ static int zoran_enum_output(struct file *file, void *__fh, outp->index = 0; outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY; - strncpy(outp->name, "Autodetect", sizeof(outp->name)-1); + strscpy(outp->name, "Autodetect", sizeof(outp->name)); return 0; } From 05fa38fd63e557d2681b063f053c5b94d9c442e3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Mar 2019 10:29:40 -0400 Subject: [PATCH 131/218] media: bt8xx: avoid a needless u8 to char conversion Instead of doing the cast, just change the type to char. Suggested-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/dst.c | 4 ++-- drivers/media/pci/bt8xx/dst_common.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/pci/bt8xx/dst.c b/drivers/media/pci/bt8xx/dst.c index 3315a6d67edf..e929797206f6 100644 --- a/drivers/media/pci/bt8xx/dst.c +++ b/drivers/media/pci/bt8xx/dst.c @@ -1100,8 +1100,8 @@ static int dst_get_device_id(struct dst_state *state) /* Card capabilities */ state->dst_hw_cap = p_dst_type->dst_feature; pr_err("Recognise [%s]\n", p_dst_type->device_id); - strscpy((char *)state->fw_name, p_dst_type->device_id, - sizeof(state->fw_name)); + strscpy(state->fw_name, p_dst_type->device_id, + sizeof(state->fw_name)); /* Multiple tuners */ if (p_dst_type->tuner_type & TUNER_TYPE_MULTI) { switch (use_dst_type) { diff --git a/drivers/media/pci/bt8xx/dst_common.h b/drivers/media/pci/bt8xx/dst_common.h index 6a2cfdd44e3e..79dec1b1722c 100644 --- a/drivers/media/pci/bt8xx/dst_common.h +++ b/drivers/media/pci/bt8xx/dst_common.h @@ -138,7 +138,7 @@ struct dst_state { u32 tuner_type; char *tuner_name; struct mutex dst_mutex; - u8 fw_name[8]; + char fw_name[8]; struct dvb_device *dst_ca; }; From c4b50cabd6a2c018c5b388392cce4d842d15ad86 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 18 Mar 2019 11:25:43 -0400 Subject: [PATCH 132/218] media: ov7740: enable to get exposure control in autoexposure mode The exposure control is clustered with the autoexposure control and flagged as volatile, but the g_volatile_ctrl() doesn't handle V4L2_CID_EXPOSURE_AUTO. So, the value of the exposure control can't be read in autoexposure mode. This enables to get the exposure control in autoexposure mode by making ov7740_get_volatile_ctrl() deal with V4L2_CID_EXPOSURE_AUTO. This also sets the exposure control as volatile by specifying the argument to v4l2_ctrl_auto_cluster() instead of manually flagging it. Cc: Wenyou Yang Cc: Eugen Hristev Signed-off-by: Akinobu Mita Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov7740.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c index dfece91ce96b..54e80a60aa57 100644 --- a/drivers/media/i2c/ov7740.c +++ b/drivers/media/i2c/ov7740.c @@ -448,6 +448,27 @@ static int ov7740_get_gain(struct ov7740 *ov7740, struct v4l2_ctrl *ctrl) return 0; } +static int ov7740_get_exp(struct ov7740 *ov7740, struct v4l2_ctrl *ctrl) +{ + struct regmap *regmap = ov7740->regmap; + unsigned int value0, value1; + int ret; + + if (ctrl->val == V4L2_EXPOSURE_MANUAL) + return 0; + + ret = regmap_read(regmap, REG_AEC, &value0); + if (ret) + return ret; + ret = regmap_read(regmap, REG_HAEC, &value1); + if (ret) + return ret; + + ov7740->exposure->val = (value1 << 8) | (value0 & 0xff); + + return 0; +} + static int ov7740_set_exp(struct regmap *regmap, int value) { int ret; @@ -494,6 +515,9 @@ static int ov7740_get_volatile_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_AUTOGAIN: ret = ov7740_get_gain(ov7740, ctrl); break; + case V4L2_CID_EXPOSURE_AUTO: + ret = ov7740_get_exp(ov7740, ctrl); + break; default: ret = -EINVAL; break; @@ -991,8 +1015,6 @@ static int ov7740_init_controls(struct ov7740 *ov7740) ov7740->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops, V4L2_CID_EXPOSURE, 0, 65535, 1, 500); - if (ov7740->exposure) - ov7740->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE; ov7740->auto_exposure = v4l2_ctrl_new_std_menu(ctrl_hdlr, &ov7740_ctrl_ops, @@ -1003,7 +1025,7 @@ static int ov7740_init_controls(struct ov7740 *ov7740) v4l2_ctrl_auto_cluster(3, &ov7740->auto_wb, 0, false); v4l2_ctrl_auto_cluster(2, &ov7740->auto_gain, 0, true); v4l2_ctrl_auto_cluster(2, &ov7740->auto_exposure, - V4L2_EXPOSURE_MANUAL, false); + V4L2_EXPOSURE_MANUAL, true); v4l2_ctrl_cluster(2, &ov7740->hflip); if (ctrl_hdlr->error) { From 95db3cc936f5340ebbb6acc44579a2084f2866aa Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 26 Mar 2019 05:19:28 -0400 Subject: [PATCH 133/218] media: MAINTAINERS: Fix files for obsolete SoC camera framework The SoC camera was moved to the staging tree but we missed updating MAINTAINERS. Do that now. Fixes: 280de94a6519 ("media: soc_camera: Move to the staging tree") Reported-by: Joe Perches Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index e17ebf70b548..c6c15de0583f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14325,9 +14325,8 @@ SOC-CAMERA V4L2 SUBSYSTEM L: linux-media@vger.kernel.org T: git git://linuxtv.org/media_tree.git S: Orphan -F: include/media/soc* -F: drivers/media/i2c/soc_camera/ -F: drivers/media/platform/soc_camera/ +F: include/media/soc_camera.h +F: drivers/staging/media/soc_camera/ SOCIONEXT SYNQUACER I2C DRIVER M: Ard Biesheuvel From dfe571ca8daaf0655d36ef1a86900b77fe752fb7 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 26 Mar 2019 05:24:11 -0400 Subject: [PATCH 134/218] media: soc_camera: Remove leftover files, add TODO Remove a few files left over from the mt9t031 driver. While at it, add a TODO file for the SoC camera framework as a whole. Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/mt9t031/Kconfig | 5 ----- drivers/staging/media/mt9t031/Makefile | 1 - drivers/staging/media/mt9t031/TODO | 5 ----- drivers/staging/media/soc_camera/TODO | 4 ++++ 4 files changed, 4 insertions(+), 11 deletions(-) delete mode 100644 drivers/staging/media/mt9t031/Kconfig delete mode 100644 drivers/staging/media/mt9t031/Makefile delete mode 100644 drivers/staging/media/mt9t031/TODO create mode 100644 drivers/staging/media/soc_camera/TODO diff --git a/drivers/staging/media/mt9t031/Kconfig b/drivers/staging/media/mt9t031/Kconfig deleted file mode 100644 index 9a58aaf72edd..000000000000 --- a/drivers/staging/media/mt9t031/Kconfig +++ /dev/null @@ -1,5 +0,0 @@ -config SOC_CAMERA_MT9T031 - tristate "mt9t031 support (DEPRECATED)" - depends on SOC_CAMERA && I2C - help - This driver supports MT9T031 cameras from Micron. diff --git a/drivers/staging/media/mt9t031/Makefile b/drivers/staging/media/mt9t031/Makefile deleted file mode 100644 index bfd24c442b33..000000000000 --- a/drivers/staging/media/mt9t031/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o diff --git a/drivers/staging/media/mt9t031/TODO b/drivers/staging/media/mt9t031/TODO deleted file mode 100644 index 15580a4f950c..000000000000 --- a/drivers/staging/media/mt9t031/TODO +++ /dev/null @@ -1,5 +0,0 @@ -This sensor driver needs to be converted to a regular -v4l2 subdev driver. The soc_camera framework is deprecated and -will be removed in the future. Unless someone does this work this -sensor driver will be deleted when the soc_camera framework is -deleted. diff --git a/drivers/staging/media/soc_camera/TODO b/drivers/staging/media/soc_camera/TODO new file mode 100644 index 000000000000..932af6443b67 --- /dev/null +++ b/drivers/staging/media/soc_camera/TODO @@ -0,0 +1,4 @@ +The SoC camera framework is obsolete and scheduled for removal in the near +future. Developers are encouraged to convert the drivers to use the +regular V4L2 API if these drivers are still needed (and if someone has the +hardware). From 12d5290e63a88ae8b93fe51e7554e66415f3986c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Mar 2019 11:28:45 -0400 Subject: [PATCH 135/218] media: staging: use strscpy() instead of strlcpy() There are a few left overs at staging which were still using the deprecated strlcpy() function. Reviewed-by: Hans Verkuil Reviewed-by: Mukesh Ojha Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx-media-dev-common.c | 4 ++-- drivers/staging/media/rockchip/vpu/rockchip_vpu_drv.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/media/imx/imx-media-dev-common.c b/drivers/staging/media/imx/imx-media-dev-common.c index 910594125889..6cd93419b81d 100644 --- a/drivers/staging/media/imx/imx-media-dev-common.c +++ b/drivers/staging/media/imx/imx-media-dev-common.c @@ -30,7 +30,7 @@ struct imx_media_dev *imx_media_dev_init(struct device *dev) dev_set_drvdata(dev, imxmd); - strlcpy(imxmd->md.model, "imx-media", sizeof(imxmd->md.model)); + strscpy(imxmd->md.model, "imx-media", sizeof(imxmd->md.model)); imxmd->md.ops = &imx_media_md_ops; imxmd->md.dev = dev; @@ -38,7 +38,7 @@ struct imx_media_dev *imx_media_dev_init(struct device *dev) imxmd->v4l2_dev.mdev = &imxmd->md; imxmd->v4l2_dev.notify = imx_media_notify; - strlcpy(imxmd->v4l2_dev.name, "imx-media", + strscpy(imxmd->v4l2_dev.name, "imx-media", sizeof(imxmd->v4l2_dev.name)); media_device_init(&imxmd->md); diff --git a/drivers/staging/media/rockchip/vpu/rockchip_vpu_drv.c b/drivers/staging/media/rockchip/vpu/rockchip_vpu_drv.c index 57611464ad07..58721c46fba4 100644 --- a/drivers/staging/media/rockchip/vpu/rockchip_vpu_drv.c +++ b/drivers/staging/media/rockchip/vpu/rockchip_vpu_drv.c @@ -462,7 +462,7 @@ static int rockchip_vpu_probe(struct platform_device *pdev) } vpu->mdev.dev = vpu->dev; - strlcpy(vpu->mdev.model, DRIVER_NAME, sizeof(vpu->mdev.model)); + strscpy(vpu->mdev.model, DRIVER_NAME, sizeof(vpu->mdev.model)); media_device_init(&vpu->mdev); vpu->v4l2_dev.mdev = &vpu->mdev; From 8b0a61d1f72e75e43aaebd52d7bc89e9899cdb5f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Mar 2019 11:58:14 -0400 Subject: [PATCH 136/218] media: pixfmt-packed-yuv.rst: fix PDF output Some lines inside this table has more than 34 columns, which isn't what is expected, according to the .. tabularcolumns:: definition. That causes the PDF output to fail. This patch ensures that all columns will have exactly the same size, merging the unused ones using :cpan: Signed-off-by: Mauro Carvalho Chehab --- .../media/uapi/v4l/pixfmt-packed-yuv.rst | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/Documentation/media/uapi/v4l/pixfmt-packed-yuv.rst b/Documentation/media/uapi/v4l/pixfmt-packed-yuv.rst index 7fcee1c11ac4..9d2b281f06a2 100644 --- a/Documentation/media/uapi/v4l/pixfmt-packed-yuv.rst +++ b/Documentation/media/uapi/v4l/pixfmt-packed-yuv.rst @@ -44,6 +44,7 @@ component of each pixel in one 16 or 32 bit word. - :cspan:`7` Byte 2 - :cspan:`7` Byte 3 + * - - - 7 @@ -81,6 +82,7 @@ component of each pixel in one 16 or 32 bit word. - 2 - 1 - 0 + * .. _V4L2-PIX-FMT-YUV444: - ``V4L2_PIX_FMT_YUV444`` @@ -103,7 +105,9 @@ component of each pixel in one 16 or 32 bit word. - Y'\ :sub:`2` - Y'\ :sub:`1` - Y'\ :sub:`0` - - + + - :cspan:`15` + * .. _V4L2-PIX-FMT-YUV555: - ``V4L2_PIX_FMT_YUV555`` @@ -126,7 +130,8 @@ component of each pixel in one 16 or 32 bit word. - Y'\ :sub:`0` - Cb\ :sub:`4` - Cb\ :sub:`3` - - + + - :cspan:`15` * .. _V4L2-PIX-FMT-YUV565: - ``V4L2_PIX_FMT_YUV565`` @@ -149,7 +154,9 @@ component of each pixel in one 16 or 32 bit word. - Cb\ :sub:`5` - Cb\ :sub:`4` - Cb\ :sub:`3` - - + + - :cspan:`15` + * .. _V4L2-PIX-FMT-YUV32: - ``V4L2_PIX_FMT_YUV32`` @@ -190,7 +197,7 @@ component of each pixel in one 16 or 32 bit word. - Cr\ :sub:`2` - Cr\ :sub:`1` - Cr\ :sub:`0` - - + * .. _V4L2-PIX-FMT-AYUV32: - ``V4L2_PIX_FMT_AYUV32`` @@ -231,7 +238,7 @@ component of each pixel in one 16 or 32 bit word. - Cr\ :sub:`2` - Cr\ :sub:`1` - Cr\ :sub:`0` - - + * .. _V4L2-PIX-FMT-XYUV32: - ``V4L2_PIX_FMT_XYUV32`` @@ -272,7 +279,7 @@ component of each pixel in one 16 or 32 bit word. - Cr\ :sub:`2` - Cr\ :sub:`1` - Cr\ :sub:`0` - - + * .. _V4L2-PIX-FMT-VUYA32: - ``V4L2_PIX_FMT_VUYA32`` @@ -313,7 +320,7 @@ component of each pixel in one 16 or 32 bit word. - a\ :sub:`2` - a\ :sub:`1` - a\ :sub:`0` - - + * .. _V4L2-PIX-FMT-VUYX32: - ``V4L2_PIX_FMT_VUYX32`` From 94fa831e3b359f24c01b9936de33b84c38caacbb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Mar 2019 12:13:50 -0400 Subject: [PATCH 137/218] media: pdf docs: adjust several tables for better display Avoid cell overlapping by changing some sizes, and changing the font sizes when needed. Tested with Sphinx 1.7.8. Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/uapi/v4l/buffer.rst | 19 ++-- .../media/uapi/v4l/colorspaces-defs.rst | 4 +- Documentation/media/uapi/v4l/colorspaces.rst | 4 +- Documentation/media/uapi/v4l/dev-raw-vbi.rst | 4 +- Documentation/media/uapi/v4l/dev-rds.rst | 2 +- .../media/uapi/v4l/dev-sliced-vbi.rst | 22 ++--- Documentation/media/uapi/v4l/dev-subdev.rst | 82 ++++++++++++----- .../media/uapi/v4l/ext-ctrls-camera.rst | 17 +++- .../media/uapi/v4l/ext-ctrls-codec.rst | 91 ++++++++++++++++--- .../media/uapi/v4l/ext-ctrls-detect.rst | 2 +- Documentation/media/uapi/v4l/ext-ctrls-dv.rst | 2 +- .../media/uapi/v4l/ext-ctrls-flash.rst | 4 +- .../media/uapi/v4l/ext-ctrls-jpeg.rst | 2 +- Documentation/media/uapi/v4l/field-order.rst | 4 +- .../media/uapi/v4l/pixfmt-meta-d4xx.rst | 9 +- .../media/uapi/v4l/pixfmt-meta-vsp1-hgt.rst | 9 ++ .../media/uapi/v4l/pixfmt-packed-hsv.rst | 2 +- .../media/uapi/v4l/pixfmt-packed-rgb.rst | 4 +- .../media/uapi/v4l/pixfmt-packed-yuv.rst | 2 +- .../media/uapi/v4l/pixfmt-srggb10p.rst | 2 +- .../media/uapi/v4l/pixfmt-srggb12p.rst | 3 +- .../media/uapi/v4l/pixfmt-srggb14p.rst | 24 ++++- .../media/uapi/v4l/pixfmt-v4l2-mplane.rst | 17 ++-- Documentation/media/uapi/v4l/pixfmt-y10p.rst | 10 ++ .../media/uapi/v4l/subdev-formats.rst | 6 +- 25 files changed, 259 insertions(+), 88 deletions(-) diff --git a/Documentation/media/uapi/v4l/buffer.rst b/Documentation/media/uapi/v4l/buffer.rst index b9a2e9dc707c..1cbd9cde57f3 100644 --- a/Documentation/media/uapi/v4l/buffer.rst +++ b/Documentation/media/uapi/v4l/buffer.rst @@ -165,7 +165,7 @@ of appropriately sized buffers for each use case). struct v4l2_buffer ================== -.. tabularcolumns:: |p{2.8cm}|p{2.5cm}|p{1.3cm}|p{10.5cm}| +.. tabularcolumns:: |p{2.8cm}|p{2.5cm}|p{1.6cm}|p{10.2cm}| .. cssclass:: longtable @@ -420,7 +420,7 @@ enum v4l2_buf_type .. cssclass:: longtable -.. tabularcolumns:: |p{7.2cm}|p{0.6cm}|p{9.7cm}| +.. tabularcolumns:: |p{7.8cm}|p{0.6cm}|p{9.1cm}| .. flat-table:: :header-rows: 0 @@ -482,7 +482,11 @@ enum v4l2_buf_type Buffer Flags ============ -.. tabularcolumns:: |p{7.0cm}|p{2.2cm}|p{8.3cm}| +.. raw:: latex + + \small + +.. tabularcolumns:: |p{7.0cm}|p{2.1cm}|p{8.4cm}| .. cssclass:: longtable @@ -681,6 +685,9 @@ Buffer Flags exposure of the frame has begun. This is only valid for the ``V4L2_BUF_TYPE_VIDEO_CAPTURE`` buffer type. +.. raw:: latex + + \normalsize .. c:type:: v4l2_memory @@ -688,7 +695,7 @@ Buffer Flags enum v4l2_memory ================ -.. tabularcolumns:: |p{6.6cm}|p{2.2cm}|p{8.7cm}| +.. tabularcolumns:: |p{5.0cm}|p{0.8cm}|p{11.7cm}| .. flat-table:: :header-rows: 0 @@ -724,7 +731,7 @@ The :c:type:`v4l2_buffer_timecode` structure is designed to hold a struct v4l2_timecode -------------------- -.. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.7cm}| +.. tabularcolumns:: |p{1.4cm}|p{2.8cm}|p{12.3cm}| .. flat-table:: :header-rows: 0 @@ -761,7 +768,7 @@ struct v4l2_timecode Timecode Types -------------- -.. tabularcolumns:: |p{6.6cm}|p{2.2cm}|p{8.7cm}| +.. tabularcolumns:: |p{5.6cm}|p{0.8cm}|p{11.1cm}| .. flat-table:: :header-rows: 0 diff --git a/Documentation/media/uapi/v4l/colorspaces-defs.rst b/Documentation/media/uapi/v4l/colorspaces-defs.rst index c4e8fc620379..e122bbe3d799 100644 --- a/Documentation/media/uapi/v4l/colorspaces-defs.rst +++ b/Documentation/media/uapi/v4l/colorspaces-defs.rst @@ -39,7 +39,7 @@ whole range, 0-255, dividing the angular value by 1.41. The enum colorspaces except for BT.2020 which uses limited range R'G'B' quantization. -.. tabularcolumns:: |p{6.0cm}|p{11.5cm}| +.. tabularcolumns:: |p{6.7cm}|p{10.8cm}| .. c:type:: v4l2_colorspace @@ -112,7 +112,7 @@ whole range, 0-255, dividing the angular value by 1.41. The enum .. c:type:: v4l2_ycbcr_encoding -.. tabularcolumns:: |p{6.5cm}|p{11.0cm}| +.. tabularcolumns:: |p{7.2cm}|p{10.3cm}| .. flat-table:: V4L2 Y'CbCr Encodings :header-rows: 1 diff --git a/Documentation/media/uapi/v4l/colorspaces.rst b/Documentation/media/uapi/v4l/colorspaces.rst index c5a560f0c13d..4f6c82fa057f 100644 --- a/Documentation/media/uapi/v4l/colorspaces.rst +++ b/Documentation/media/uapi/v4l/colorspaces.rst @@ -56,9 +56,9 @@ The Y value in the CIE XYZ colorspace corresponds to luminance. Often the CIE XYZ colorspace is transformed to the normalized CIE xyY colorspace: -x = X / (X + Y + Z) + x = X / (X + Y + Z) -y = Y / (X + Y + Z) + y = Y / (X + Y + Z) The x and y values are the chromaticity coordinates and can be used to define a color without the luminance component Y. It is very confusing diff --git a/Documentation/media/uapi/v4l/dev-raw-vbi.rst b/Documentation/media/uapi/v4l/dev-raw-vbi.rst index d6a707f0b24f..e06b03ca2ab2 100644 --- a/Documentation/media/uapi/v4l/dev-raw-vbi.rst +++ b/Documentation/media/uapi/v4l/dev-raw-vbi.rst @@ -106,7 +106,7 @@ VBI devices must implement both the :ref:`VIDIOC_G_FMT ` and and always returns default parameters as :ref:`VIDIOC_G_FMT ` does. :ref:`VIDIOC_TRY_FMT ` is optional. -.. tabularcolumns:: |p{2.4cm}|p{4.4cm}|p{10.7cm}| +.. tabularcolumns:: |p{1.6cm}|p{4.2cm}|p{11.7cm}| .. c:type:: v4l2_vbi_format @@ -190,7 +190,7 @@ and always returns default parameters as :ref:`VIDIOC_G_FMT ` does applications must set it to zero. -.. tabularcolumns:: |p{4.0cm}|p{1.5cm}|p{12.0cm}| +.. tabularcolumns:: |p{4.4cm}|p{1.5cm}|p{11.6cm}| .. _vbifmt-flags: diff --git a/Documentation/media/uapi/v4l/dev-rds.rst b/Documentation/media/uapi/v4l/dev-rds.rst index 624d6f95b842..64a724ef58f5 100644 --- a/Documentation/media/uapi/v4l/dev-rds.rst +++ b/Documentation/media/uapi/v4l/dev-rds.rst @@ -146,7 +146,7 @@ RDS datastructures .. _v4l2-rds-block-codes: -.. tabularcolumns:: |p{5.6cm}|p{2.0cm}|p{1.5cm}|p{7.0cm}| +.. tabularcolumns:: |p{6.4cm}|p{2.0cm}|p{1.2cm}|p{7.9cm}| .. flat-table:: Block defines :header-rows: 0 diff --git a/Documentation/media/uapi/v4l/dev-sliced-vbi.rst b/Documentation/media/uapi/v4l/dev-sliced-vbi.rst index 0aa6cb8a272b..e86346f66017 100644 --- a/Documentation/media/uapi/v4l/dev-sliced-vbi.rst +++ b/Documentation/media/uapi/v4l/dev-sliced-vbi.rst @@ -118,7 +118,7 @@ struct v4l2_sliced_vbi_format \scriptsize \setlength{\tabcolsep}{2pt} -.. tabularcolumns:: |p{.75cm}|p{3.3cm}|p{3.4cm}|p{3.4cm}|p{3.4cm}| +.. tabularcolumns:: |p{.85cm}|p{3.3cm}|p{4.4cm}|p{4.4cm}|p{4.4cm}| .. cssclass:: longtable @@ -223,7 +223,7 @@ Sliced VBI services .. raw:: latex - \footnotesize + \scriptsize .. tabularcolumns:: |p{4.1cm}|p{1.1cm}|p{2.4cm}|p{2.0cm}|p{7.3cm}| @@ -541,7 +541,7 @@ Magic Constants for struct v4l2_mpeg_vbi_fmt_ivtv magic field structs v4l2_mpeg_vbi_itv0 and v4l2_mpeg_vbi_ITV0 ------------------------------------------------- -.. tabularcolumns:: |p{4.9cm}|p{2.4cm}|p{10.2cm}| +.. tabularcolumns:: |p{5.2cm}|p{2.4cm}|p{9.9cm}| .. flat-table:: :header-rows: 0 @@ -561,12 +561,12 @@ structs v4l2_mpeg_vbi_itv0 and v4l2_mpeg_vbi_ITV0 :: - linemask[0] b0: line 6 first field - linemask[0] b17: line 23 first field - linemask[0] b18: line 6 second field - linemask[0] b31: line 19 second field - linemask[1] b0: line 20 second field - linemask[1] b3: line 23 second field + linemask[0] b0: line 6 first field + linemask[0] b17: line 23 first field + linemask[0] b18: line 6 second field + linemask[0] b31: line 19 second field + linemask[1] b0: line 20 second field + linemask[1] b3: line 23 second field linemask[1] b4-b31: unused and set to 0 * - struct :c:type:`v4l2_mpeg_vbi_itv0_line` @@ -590,7 +590,7 @@ structs v4l2_mpeg_vbi_itv0 and v4l2_mpeg_vbi_ITV0 struct v4l2_mpeg_vbi_ITV0 ------------------------- -.. tabularcolumns:: |p{4.9cm}|p{4.4cm}|p{8.2cm}| +.. tabularcolumns:: |p{5.2cm}|p{2.4cm}|p{9.9cm}| .. flat-table:: :header-rows: 0 @@ -635,7 +635,7 @@ struct v4l2_mpeg_vbi_itv0_line Line Identifiers for struct v4l2_mpeg_vbi_itv0_line id field ------------------------------------------------------------ -.. tabularcolumns:: |p{6.6cm}|p{2.2cm}|p{8.7cm}| +.. tabularcolumns:: |p{7.0cm}|p{1.8cm}|p{8.7cm}| .. flat-table:: :header-rows: 1 diff --git a/Documentation/media/uapi/v4l/dev-subdev.rst b/Documentation/media/uapi/v4l/dev-subdev.rst index 2c2768c7343b..029bb2d9928a 100644 --- a/Documentation/media/uapi/v4l/dev-subdev.rst +++ b/Documentation/media/uapi/v4l/dev-subdev.rst @@ -211,7 +211,7 @@ list entity names and pad numbers). .. raw:: latex - \tiny + \scriptsize .. tabularcolumns:: |p{2.0cm}|p{2.3cm}|p{2.3cm}|p{2.3cm}|p{2.3cm}|p{2.3cm}|p{2.3cm}| @@ -223,40 +223,80 @@ list entity names and pad numbers). :widths: 5 5 5 5 5 5 5 * - - - Sensor/0 format - - Frontend/0 format - - Frontend/1 format - - Scaler/0 format - - Scaler/0 compose selection rectangle - - Scaler/1 format + - Sensor/0 + + format + - Frontend/0 + + format + - Frontend/1 + + format + - Scaler/0 + + format + - Scaler/0 + + compose selection rectangle + - Scaler/1 + + format * - Initial state - - 2048x1536/SGRBG8_1X8 + - 2048x1536 + + SGRBG8_1X8 - (default) - (default) - (default) - (default) - (default) * - Configure frontend sink format - - 2048x1536/SGRBG8_1X8 - - *2048x1536/SGRBG8_1X8* - - *2046x1534/SGRBG8_1X8* + - 2048x1536 + + SGRBG8_1X8 + - *2048x1536* + + *SGRBG8_1X8* + - *2046x1534* + + *SGRBG8_1X8* - (default) - (default) - (default) * - Configure scaler sink format - - 2048x1536/SGRBG8_1X8 - - 2048x1536/SGRBG8_1X8 - - 2046x1534/SGRBG8_1X8 - - *2046x1534/SGRBG8_1X8* + - 2048x1536 + + SGRBG8_1X8 + - 2048x1536 + + SGRBG8_1X8 + - 2046x1534 + + SGRBG8_1X8 + - *2046x1534* + + *SGRBG8_1X8* - *0,0/2046x1534* - - *2046x1534/SGRBG8_1X8* + - *2046x1534* + + *SGRBG8_1X8* * - Configure scaler sink compose selection - - 2048x1536/SGRBG8_1X8 - - 2048x1536/SGRBG8_1X8 - - 2046x1534/SGRBG8_1X8 - - 2046x1534/SGRBG8_1X8 + - 2048x1536 + + SGRBG8_1X8 + - 2048x1536 + + SGRBG8_1X8 + - 2046x1534 + + SGRBG8_1X8 + - 2046x1534 + + SGRBG8_1X8 - *0,0/1280x960* - - *1280x960/SGRBG8_1X8* + - *1280x960* + + *SGRBG8_1X8* .. raw:: latex diff --git a/Documentation/media/uapi/v4l/ext-ctrls-camera.rst b/Documentation/media/uapi/v4l/ext-ctrls-camera.rst index d3a553cd86c9..51c1d5c9eb00 100644 --- a/Documentation/media/uapi/v4l/ext-ctrls-camera.rst +++ b/Documentation/media/uapi/v4l/ext-ctrls-camera.rst @@ -88,7 +88,7 @@ enum v4l2_exposure_metering - Determines how the camera measures the amount of light available for the frame exposure. Possible values are: -.. tabularcolumns:: |p{8.5cm}|p{9.0cm}| +.. tabularcolumns:: |p{8.7cm}|p{8.8cm}| .. flat-table:: :header-rows: 0 @@ -180,7 +180,7 @@ enum v4l2_exposure_metering - control may stop updates of the ``V4L2_CID_AUTO_FOCUS_STATUS`` control value. -.. tabularcolumns:: |p{6.5cm}|p{11.0cm}| +.. tabularcolumns:: |p{6.7cm}|p{10.8cm}| .. flat-table:: :header-rows: 0 @@ -206,7 +206,7 @@ enum v4l2_exposure_metering - enum v4l2_auto_focus_range - Determines auto focus distance range for which lens may be adjusted. -.. tabularcolumns:: |p{6.5cm}|p{11.0cm}| +.. tabularcolumns:: |p{6.8cm}|p{10.7cm}| .. flat-table:: :header-rows: 0 @@ -281,7 +281,7 @@ enum v4l2_auto_n_preset_white_balance - representation. The following white balance presets are listed in order of increasing color temperature. -.. tabularcolumns:: |p{7.0 cm}|p{10.5cm}| +.. tabularcolumns:: |p{7.2 cm}|p{10.3cm}| .. flat-table:: :header-rows: 0 @@ -387,7 +387,11 @@ enum v4l2_scene_mode - to ``V4L2_SCENE_MODE_NONE`` to make sure the other possibly related controls are accessible. The following scene programs are defined: -.. tabularcolumns:: |p{6.0cm}|p{11.5cm}| +.. raw:: latex + + \small + +.. tabularcolumns:: |p{5.9cm}|p{11.5cm}| .. flat-table:: :header-rows: 0 @@ -459,6 +463,9 @@ enum v4l2_scene_mode - may be switched to close-up mode and this setting may also involve some lens-distortion correction. +.. raw:: latex + + \normalsize ``V4L2_CID_3A_LOCK (bitmask)`` diff --git a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst index 0aaee04f81dd..67a122339c0e 100644 --- a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst +++ b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst @@ -105,7 +105,7 @@ enum v4l2_mpeg_stream_vbi_fmt - -.. tabularcolumns:: |p{6 cm}|p{11.5cm}| +.. tabularcolumns:: |p{6.6 cm}|p{10.9cm}| .. flat-table:: :header-rows: 0 @@ -477,7 +477,7 @@ enum v4l2_mpeg_audio_dec_playback - -.. tabularcolumns:: |p{9.0cm}|p{8.5cm}| +.. tabularcolumns:: |p{9.8cm}|p{7.7cm}| .. flat-table:: :header-rows: 0 @@ -888,7 +888,7 @@ enum v4l2_mpeg_video_multi_slice_mode - -.. tabularcolumns:: |p{8.7cm}|p{8.8cm}| +.. tabularcolumns:: |p{9.6cm}|p{7.9cm}| .. flat-table:: :header-rows: 0 @@ -923,9 +923,11 @@ enum v4l2_mpeg_video_multi_slice_mode - enum v4l2_mpeg_video_h264_loop_filter_mode - Loop filter mode for H264 encoder. Possible values are: +.. raw:: latex + \small -.. tabularcolumns:: |p{14.0cm}|p{3.5cm}| +.. tabularcolumns:: |p{13.6cm}|p{3.9cm}| .. flat-table:: :header-rows: 0 @@ -938,6 +940,9 @@ enum v4l2_mpeg_video_h264_loop_filter_mode - * - ``V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY`` - Loop filter is disabled at the slice boundary. +.. raw:: latex + + \normalsize ``V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA (integer)`` @@ -964,6 +969,8 @@ enum v4l2_mpeg_video_h264_entropy_mode - encoder. Possible values are: +.. tabularcolumns:: |p{9.0cm}|p{8.5cm}| + .. flat-table:: :header-rows: 0 @@ -1129,7 +1136,9 @@ enum v4l2_mpeg_video_header_mode - it returned together with the first frame. Applicable to encoders. Possible values are: +.. raw:: latex + \small .. tabularcolumns:: |p{10.3cm}|p{7.2cm}| @@ -1143,6 +1152,9 @@ enum v4l2_mpeg_video_header_mode - - The stream header is returned together with the first encoded frame. +.. raw:: latex + + \normalsize ``V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER (boolean)`` @@ -1181,6 +1193,10 @@ enum v4l2_mpeg_video_h264_sei_fp_arrangement_type - Frame packing arrangement type for H264 SEI. Applicable to the H264 encoder. Possible values are: +.. raw:: latex + + \small + .. tabularcolumns:: |p{12cm}|p{5.5cm}| .. flat-table:: @@ -1200,6 +1216,10 @@ enum v4l2_mpeg_video_h264_sei_fp_arrangement_type - * - ``V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TEMPORAL`` - One view per frame. +.. raw:: latex + + \normalsize + ``V4L2_CID_MPEG_VIDEO_H264_FMO (boolean)`` @@ -1217,6 +1237,10 @@ enum v4l2_mpeg_video_h264_fmo_map_type - patterns of macroblocks. Applicable to the H264 encoder. Possible values are: +.. raw:: latex + + \small + .. tabularcolumns:: |p{12.5cm}|p{5.0cm}| .. flat-table:: @@ -1240,6 +1264,10 @@ enum v4l2_mpeg_video_h264_fmo_map_type - * - ``V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_EXPLICIT`` - User defined map type. +.. raw:: latex + + \normalsize + ``V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP (integer)`` @@ -1361,6 +1389,8 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - .. cssclass:: longtable +.. tabularcolumns:: |p{5.8cm}|p{4.8cm}|p{6.6cm}| + .. flat-table:: struct v4l2_ctrl_mpeg2_slice_params :header-rows: 0 :stub-columns: 0 @@ -1402,6 +1432,8 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - .. cssclass:: longtable +.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| + .. flat-table:: struct v4l2_mpeg2_sequence :header-rows: 0 :stub-columns: 0 @@ -1433,6 +1465,8 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - .. cssclass:: longtable +.. tabularcolumns:: |p{1.5cm}|p{6.3cm}|p{9.4cm}| + .. flat-table:: struct v4l2_mpeg2_picture :header-rows: 0 :stub-columns: 0 @@ -1492,6 +1526,12 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - .. cssclass:: longtable +.. tabularcolumns:: |p{1.2cm}|p{8.0cm}|p{7.4cm}| + +.. raw:: latex + + \small + .. flat-table:: struct v4l2_ctrl_mpeg2_quantization :header-rows: 0 :stub-columns: 0 @@ -1545,6 +1585,11 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type - Quantization parameter for a P frame for FWHT. Valid range: from 1 to 31. +.. raw:: latex + + \normalsize + + MFC 5.1 MPEG Controls ===================== @@ -1652,7 +1697,11 @@ enum v4l2_mpeg_mfc51_video_frame_skip_mode - are: -.. tabularcolumns:: |p{9.0cm}|p{8.5cm}| +.. tabularcolumns:: |p{9.2cm}|p{8.3cm}| + +.. raw:: latex + + \small .. flat-table:: :header-rows: 0 @@ -1667,7 +1716,9 @@ enum v4l2_mpeg_mfc51_video_frame_skip_mode - - Frame skip mode enabled and buffer limit is set by the VBV (MPEG1/2/4) or CPB (H264) buffer size control. +.. raw:: latex + \normalsize ``V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT (integer)`` Enable rate-control with fixed target bit. If this setting is @@ -1690,7 +1741,7 @@ enum v4l2_mpeg_mfc51_video_force_frame_type - Force a frame type for the next queued buffer. Applicable to encoders. Possible values are: - +.. tabularcolumns:: |p{9.5cm}|p{8.0cm}| .. flat-table:: :header-rows: 0 @@ -1720,6 +1771,8 @@ enum v4l2_mpeg_mfc51_video_force_frame_type - .. cssclass:: longtable +.. tabularcolumns:: |p{1.4cm}|p{4.3cm}|p{11.8cm}| + .. flat-table:: struct v4l2_ctrl_fwht_params :header-rows: 0 :stub-columns: 0 @@ -1763,10 +1816,11 @@ enum v4l2_mpeg_mfc51_video_force_frame_type - FWHT Flags ============ -.. tabularcolumns:: |p{7.0cm}|p{2.2cm}|p{8.3cm}| .. cssclass:: longtable +.. tabularcolumns:: |p{6.8cm}|p{2.4cm}|p{8.3cm}| + .. flat-table:: :header-rows: 0 :stub-columns: 0 @@ -1869,10 +1923,12 @@ enum v4l2_mpeg_cx2341x_video_luma_spatial_filter_type - Select the algorithm to use for the Luma Spatial Filter (default ``1D_HOR``). Possible values: - - .. tabularcolumns:: |p{14.5cm}|p{3.0cm}| +.. raw:: latex + + \small + .. flat-table:: :header-rows: 0 :stub-columns: 0 @@ -1888,6 +1944,10 @@ enum v4l2_mpeg_cx2341x_video_luma_spatial_filter_type - * - ``V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE`` - Two-dimensional symmetrical non-separable +.. raw:: latex + + \normalsize + .. _chroma-spatial-filter-type: @@ -1900,6 +1960,7 @@ enum v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type - ``1D_HOR``). Possible values are: +.. tabularcolumns:: |p{14.0cm}|p{3.5cm}| .. flat-table:: :header-rows: 0 @@ -2042,6 +2103,10 @@ enum v4l2_vp8_num_ref_frames - .. tabularcolumns:: |p{7.9cm}|p{9.6cm}| +.. raw:: latex + + \small + .. flat-table:: :header-rows: 0 :stub-columns: 0 @@ -2056,6 +2121,10 @@ enum v4l2_vp8_num_ref_frames - - The last encoded frame, the golden frame and the altref frame will be searched. +.. raw:: latex + + \normalsize + ``V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL (integer)`` @@ -2085,7 +2154,7 @@ enum v4l2_vp8_golden_frame_sel - .. raw:: latex - \footnotesize + \scriptsize .. tabularcolumns:: |p{9.0cm}|p{8.0cm}| @@ -2407,7 +2476,7 @@ enum v4l2_mpeg_video_hevc_loop_filter_mode - \footnotesize -.. tabularcolumns:: |p{10.7cm}|p{6.3cm}| +.. tabularcolumns:: |p{12.1cm}|p{5.4cm}| .. flat-table:: :header-rows: 0 diff --git a/Documentation/media/uapi/v4l/ext-ctrls-detect.rst b/Documentation/media/uapi/v4l/ext-ctrls-detect.rst index 8a45ce642829..80981d0cff42 100644 --- a/Documentation/media/uapi/v4l/ext-ctrls-detect.rst +++ b/Documentation/media/uapi/v4l/ext-ctrls-detect.rst @@ -30,7 +30,7 @@ Detect Control IDs ``V4L2_CID_DETECT_MD_MODE (menu)`` Sets the motion detection mode. -.. tabularcolumns:: |p{7.5cm}|p{10.0cm}| +.. tabularcolumns:: |p{7.7cm}|p{9.8cm}| .. flat-table:: :header-rows: 0 diff --git a/Documentation/media/uapi/v4l/ext-ctrls-dv.rst b/Documentation/media/uapi/v4l/ext-ctrls-dv.rst index 57edf211875c..5c70ac98f710 100644 --- a/Documentation/media/uapi/v4l/ext-ctrls-dv.rst +++ b/Documentation/media/uapi/v4l/ext-ctrls-dv.rst @@ -106,7 +106,7 @@ enum v4l2_dv_it_content_type - or an analog source. The enum v4l2_dv_it_content_type defines the possible content types: -.. tabularcolumns:: |p{7.0cm}|p{10.5cm}| +.. tabularcolumns:: |p{7.3cm}|p{10.4cm}| .. flat-table:: :header-rows: 0 diff --git a/Documentation/media/uapi/v4l/ext-ctrls-flash.rst b/Documentation/media/uapi/v4l/ext-ctrls-flash.rst index 5f30791c35b5..eff056b17167 100644 --- a/Documentation/media/uapi/v4l/ext-ctrls-flash.rst +++ b/Documentation/media/uapi/v4l/ext-ctrls-flash.rst @@ -87,7 +87,7 @@ Flash Control IDs ``V4L2_CID_FLASH_STROBE_SOURCE (menu)`` Defines the source of the flash LED strobe. -.. tabularcolumns:: |p{7.0cm}|p{10.5cm}| +.. tabularcolumns:: |p{7.5cm}|p{10.0cm}| .. flat-table:: :header-rows: 0 @@ -146,7 +146,7 @@ Flash Control IDs an effect is chip dependent. Reading the faults resets the control and returns the chip to a usable state if possible. -.. tabularcolumns:: |p{8.0cm}|p{9.5cm}| +.. tabularcolumns:: |p{8.4cm}|p{9.1cm}| .. flat-table:: :header-rows: 0 diff --git a/Documentation/media/uapi/v4l/ext-ctrls-jpeg.rst b/Documentation/media/uapi/v4l/ext-ctrls-jpeg.rst index cf9cd8a9f9b4..60ce3f949319 100644 --- a/Documentation/media/uapi/v4l/ext-ctrls-jpeg.rst +++ b/Documentation/media/uapi/v4l/ext-ctrls-jpeg.rst @@ -37,7 +37,7 @@ JPEG Control IDs how Cb and Cr components are downsampled after converting an input image from RGB to Y'CbCr color space. -.. tabularcolumns:: |p{7.0cm}|p{10.5cm}| +.. tabularcolumns:: |p{7.5cm}|p{10.0cm}| .. flat-table:: :header-rows: 0 diff --git a/Documentation/media/uapi/v4l/field-order.rst b/Documentation/media/uapi/v4l/field-order.rst index 8415268d439c..3fb473e3b8e2 100644 --- a/Documentation/media/uapi/v4l/field-order.rst +++ b/Documentation/media/uapi/v4l/field-order.rst @@ -64,7 +64,9 @@ enum v4l2_field .. c:type:: v4l2_field -.. tabularcolumns:: |p{6.6cm}|p{2.2cm}|p{8.7cm}| +.. tabularcolumns:: |p{5.8cm}|p{0.6cm}|p{11.1cm}| + +.. cssclass:: longtable .. flat-table:: :header-rows: 0 diff --git a/Documentation/media/uapi/v4l/pixfmt-meta-d4xx.rst b/Documentation/media/uapi/v4l/pixfmt-meta-d4xx.rst index 862e1f327150..87e8fd7d5d02 100644 --- a/Documentation/media/uapi/v4l/pixfmt-meta-d4xx.rst +++ b/Documentation/media/uapi/v4l/pixfmt-meta-d4xx.rst @@ -36,13 +36,16 @@ per frame, therefore their headers cannot be larger than 255 bytes. Below are proprietary Microsoft style metadata types, used by D4xx cameras, where all fields are in little endian order: +.. tabularcolumns:: |p{5.0cm}|p{12.5cm}| + + .. flat-table:: D4xx metadata - :widths: 1 4 + :widths: 1 2 :header-rows: 1 :stub-columns: 0 - * - Field - - Description + * - **Field** + - **Description** * - :cspan:`1` *Depth Control* * - __u32 ID - 0x80000000 diff --git a/Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgt.rst b/Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgt.rst index 2ebccdcca95d..d1a341af9c48 100644 --- a/Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgt.rst +++ b/Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgt.rst @@ -41,6 +41,10 @@ The Hue position **m** (0 - 5) of the bucket in the matrix depends on how the HGT Hue areas are configured. There are 6 user configurable Hue Areas which can be configured to cover overlapping Hue values: +.. raw:: latex + + \small + :: Area 0 Area 1 Area 2 Area 3 Area 4 Area 5 @@ -53,6 +57,11 @@ Areas which can be configured to cover overlapping Hue values: 5U 0L 0U 1L 1U 2L 2U 3L 3U 4L 4U 5L 5U 0L <0..............................Hue Value............................255> + +.. raw:: latex + + \normalsize + When two consecutive areas don't overlap (n+1L is equal to nU) the boundary value is considered as part of the lower area. diff --git a/Documentation/media/uapi/v4l/pixfmt-packed-hsv.rst b/Documentation/media/uapi/v4l/pixfmt-packed-hsv.rst index 38b1895a509f..dfc4a8367b3d 100644 --- a/Documentation/media/uapi/v4l/pixfmt-packed-hsv.rst +++ b/Documentation/media/uapi/v4l/pixfmt-packed-hsv.rst @@ -31,7 +31,7 @@ The values are packed in 24 or 32 bit formats. \tiny \setlength{\tabcolsep}{2pt} -.. tabularcolumns:: |p{2.0cm}|p{0.54cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}| +.. tabularcolumns:: |p{2.6cm}|p{0.8cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}| .. _packed-hsv-formats: diff --git a/Documentation/media/uapi/v4l/pixfmt-packed-rgb.rst b/Documentation/media/uapi/v4l/pixfmt-packed-rgb.rst index 6b3781c04dd5..4766a6f47222 100644 --- a/Documentation/media/uapi/v4l/pixfmt-packed-rgb.rst +++ b/Documentation/media/uapi/v4l/pixfmt-packed-rgb.rst @@ -27,7 +27,7 @@ next to each other in memory. \tiny \setlength{\tabcolsep}{2pt} -.. tabularcolumns:: |p{2.3cm}|p{1.6cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}| +.. tabularcolumns:: |p{2.8cm}|p{2.0cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}| .. _rgb-formats: @@ -656,7 +656,7 @@ either the corresponding ARGB or XRGB format, depending on the driver. \tiny \setlength{\tabcolsep}{2pt} -.. tabularcolumns:: |p{2.2cm}|p{0.60cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}| +.. tabularcolumns:: |p{2.6cm}|p{0.70cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}| .. _rgb-formats-deprecated: diff --git a/Documentation/media/uapi/v4l/pixfmt-packed-yuv.rst b/Documentation/media/uapi/v4l/pixfmt-packed-yuv.rst index 9d2b281f06a2..41b60fae703a 100644 --- a/Documentation/media/uapi/v4l/pixfmt-packed-yuv.rst +++ b/Documentation/media/uapi/v4l/pixfmt-packed-yuv.rst @@ -28,7 +28,7 @@ component of each pixel in one 16 or 32 bit word. .. _packed-yuv-formats: -.. tabularcolumns:: |p{2.0cm}|p{0.67cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}|p{0.29cm}| +.. tabularcolumns:: |p{2.5cm}|p{0.69cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}|p{0.31cm}| .. flat-table:: Packed YUV Image Formats :header-rows: 2 diff --git a/Documentation/media/uapi/v4l/pixfmt-srggb10p.rst b/Documentation/media/uapi/v4l/pixfmt-srggb10p.rst index cdb70ac26126..fd32660a3766 100644 --- a/Documentation/media/uapi/v4l/pixfmt-srggb10p.rst +++ b/Documentation/media/uapi/v4l/pixfmt-srggb10p.rst @@ -40,7 +40,7 @@ of a small V4L2_PIX_FMT_SBGGR10P image: **Byte Order.** Each cell is one byte. -.. tabularcolumns:: |p{2.0cm}|p{1.0cm}|p{1.0cm}|p{1.0cm}|p{1.0cm}|p{5.4cm}| +.. tabularcolumns:: |p{2.4cm}|p{1.4cm}|p{1.2cm}|p{1.2cm}|p{1.2cm}|p{6.4cm}| .. flat-table:: :header-rows: 0 diff --git a/Documentation/media/uapi/v4l/pixfmt-srggb12p.rst b/Documentation/media/uapi/v4l/pixfmt-srggb12p.rst index 01413be12916..960851275f23 100644 --- a/Documentation/media/uapi/v4l/pixfmt-srggb12p.rst +++ b/Documentation/media/uapi/v4l/pixfmt-srggb12p.rst @@ -18,6 +18,7 @@ V4L2_PIX_FMT_SRGGB12P ('pRAA'), V4L2_PIX_FMT_SGRBG12P ('pgAA'), V4L2_PIX_FMT_SGB 12-bit packed Bayer formats +--------------------------- Description @@ -37,7 +38,7 @@ Below is an example of a small V4L2_PIX_FMT_SBGGR12P image: **Byte Order.** Each cell is one byte. -.. tabularcolumns:: |p{2.0cm}|p{1.0cm}|p{1.0cm}|p{2.7cm}|p{1.0cm}|p{1.0cm}|p{2.7cm}| +.. tabularcolumns:: |p{2.2cm}|p{1.2cm}|p{1.2cm}|p{3.1cm}|p{1.2cm}|p{1.2cm}|p{3.1cm}| .. flat-table:: diff --git a/Documentation/media/uapi/v4l/pixfmt-srggb14p.rst b/Documentation/media/uapi/v4l/pixfmt-srggb14p.rst index b583531c2853..1a988d7e7ff8 100644 --- a/Documentation/media/uapi/v4l/pixfmt-srggb14p.rst +++ b/Documentation/media/uapi/v4l/pixfmt-srggb14p.rst @@ -41,17 +41,21 @@ of one of these formats: **Byte Order.** Each cell is one byte. +.. raw:: latex + \footnotesize + +.. tabularcolumns:: |p{1.8cm}|p{1.0cm}|p{1.0cm}|p{1.0cm}|p{1.1cm}|p{3.3cm}|p{3.3cm}|p{3.3cm}| .. flat-table:: :header-rows: 0 :stub-columns: 0 - :widths: 2 1 1 1 1 1 1 1 + :widths: 2 1 1 1 1 3 3 3 - .. row 1 - - start + 0: + - start + 0 - B\ :sub:`00high` @@ -62,17 +66,20 @@ Each cell is one byte. - G\ :sub:`03high` - G\ :sub:`01low bits 1--0`\ (bits 7--6) + B\ :sub:`00low bits 5--0`\ (bits 5--0) - R\ :sub:`02low bits 3--0`\ (bits 7--4) + G\ :sub:`01low bits 5--2`\ (bits 3--0) - G\ :sub:`03low bits 5--0`\ (bits 7--2) + R\ :sub:`02low bits 5--4`\ (bits 1--0) - .. row 2 - - start + 7: + - start + 7 - G\ :sub:`00high` @@ -83,12 +90,15 @@ Each cell is one byte. - R\ :sub:`03high` - R\ :sub:`01low bits 1--0`\ (bits 7--6) + G\ :sub:`00low bits 5--0`\ (bits 5--0) - G\ :sub:`02low bits 3--0`\ (bits 7--4) + R\ :sub:`01low bits 5--2`\ (bits 3--0) - R\ :sub:`03low bits 5--0`\ (bits 7--2) + G\ :sub:`02low bits 5--4`\ (bits 1--0) - .. row 3 @@ -104,12 +114,15 @@ Each cell is one byte. - G\ :sub:`23high` - G\ :sub:`21low bits 1--0`\ (bits 7--6) + B\ :sub:`20low bits 5--0`\ (bits 5--0) - R\ :sub:`22low bits 3--0`\ (bits 7--4) + G\ :sub:`21low bits 5--2`\ (bits 3--0) - G\ :sub:`23low bits 5--0`\ (bits 7--2) + R\ :sub:`22low bits 5--4`\ (bits 1--0) - .. row 4 @@ -132,3 +145,8 @@ Each cell is one byte. - R\ :sub:`33low bits 5--0`\ (bits 7--2) G\ :sub:`32low bits 5--4`\ (bits 1--0) + +.. raw:: latex + + \normalsize + diff --git a/Documentation/media/uapi/v4l/pixfmt-v4l2-mplane.rst b/Documentation/media/uapi/v4l/pixfmt-v4l2-mplane.rst index 7f82dad9013a..5688c816e334 100644 --- a/Documentation/media/uapi/v4l/pixfmt-v4l2-mplane.rst +++ b/Documentation/media/uapi/v4l/pixfmt-v4l2-mplane.rst @@ -19,6 +19,7 @@ array of struct :c:type:`v4l2_plane_pix_format` structures, describing all planes of that format. + .. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.7cm}| .. c:type:: v4l2_plane_pix_format @@ -41,6 +42,10 @@ describing all planes of that format. applications. +.. raw:: latex + + \small + .. tabularcolumns:: |p{4.4cm}|p{5.6cm}|p{7.5cm}| .. c:type:: v4l2_pix_format_mplane @@ -82,9 +87,7 @@ describing all planes of that format. * - __u8 - ``flags`` - Flags set by the application or driver, see :ref:`format-flags`. - * - union { - - (anonymous) - - + * - :cspan:`2` union { (anonymous) * - __u8 - ``ycbcr_enc`` - Y'CbCr encoding, from enum :c:type:`v4l2_ycbcr_encoding`. @@ -97,9 +100,7 @@ describing all planes of that format. This information supplements the ``colorspace`` and must be set by the driver for capture streams and by the application for output streams, see :ref:`colorspaces`. - * - } - - - - + * - :cspan:`2` } * - __u8 - ``quantization`` - Quantization range, from enum :c:type:`v4l2_quantization`. @@ -116,3 +117,7 @@ describing all planes of that format. - ``reserved[7]`` - Reserved for future extensions. Should be zeroed by drivers and applications. + +.. raw:: latex + + \normalsize diff --git a/Documentation/media/uapi/v4l/pixfmt-y10p.rst b/Documentation/media/uapi/v4l/pixfmt-y10p.rst index 7893642faee3..39cd789dcb59 100644 --- a/Documentation/media/uapi/v4l/pixfmt-y10p.rst +++ b/Documentation/media/uapi/v4l/pixfmt-y10p.rst @@ -27,6 +27,12 @@ in the same order. **Bit-packed representation.** +.. raw:: latex + + \small + +.. tabularcolumns:: |p{1.2cm}||p{1.2cm}||p{1.2cm}||p{1.2cm}|p{3.2cm}|p{3.2cm}| + .. flat-table:: :header-rows: 0 :stub-columns: 0 @@ -38,3 +44,7 @@ in the same order. - Y'\ :sub:`03[9:2]` - Y'\ :sub:`03[1:0]`\ (bits 7--6) Y'\ :sub:`02[1:0]`\ (bits 5--4) Y'\ :sub:`01[1:0]`\ (bits 3--2) Y'\ :sub:`00[1:0]`\ (bits 1--0) + +.. raw:: latex + + \normalsize diff --git a/Documentation/media/uapi/v4l/subdev-formats.rst b/Documentation/media/uapi/v4l/subdev-formats.rst index f5440d55d510..bf1dbb68eebc 100644 --- a/Documentation/media/uapi/v4l/subdev-formats.rst +++ b/Documentation/media/uapi/v4l/subdev-formats.rst @@ -7414,7 +7414,7 @@ The following table lists existing HSV/HSL formats. \tiny \setlength{\tabcolsep}{2pt} -.. tabularcolumns:: |p{3.0cm}|p{0.60cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}| +.. tabularcolumns:: |p{3.9cm}|p{0.73cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}| .. _v4l2-mbus-pixelcode-hsv: @@ -7524,7 +7524,7 @@ The following table lists existing JPEG compressed formats. .. _v4l2-mbus-pixelcode-jpeg: -.. tabularcolumns:: |p{5.4cm}|p{1.4cm}|p{10.7cm}| +.. tabularcolumns:: |p{6.0cm}|p{1.4cm}|p{10.1cm}| .. flat-table:: JPEG Formats :header-rows: 1 @@ -7557,7 +7557,7 @@ formats. .. _v4l2-mbus-pixelcode-vendor-specific: -.. tabularcolumns:: |p{6.8cm}|p{1.4cm}|p{9.3cm}| +.. tabularcolumns:: |p{8.0cm}|p{1.4cm}|p{7.7cm}| .. flat-table:: Vendor and device specific formats :header-rows: 1 From 1c3ec30bb23023d738b538e64ac3028902d53692 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 30 Mar 2019 09:33:54 -0400 Subject: [PATCH 138/218] media: index.rst: exclude Indexes section from latex/pdf output With LaTex, the Index at the end will always be present. Having an extra chapter for it there will just add extra noise to the document. Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/media/index.rst b/Documentation/media/index.rst index 0a222fc1d7ca..0301c25ff887 100644 --- a/Documentation/media/index.rst +++ b/Documentation/media/index.rst @@ -18,7 +18,7 @@ Linux Media Subsystem Documentation v4l-drivers/index cec-drivers/index -.. only:: subproject +.. only:: html and subproject Indices ======= From 87effaae9e90474546d441b9123bca824e670a0b Mon Sep 17 00:00:00 2001 From: Fish Lin Date: Thu, 28 Mar 2019 23:20:46 -0400 Subject: [PATCH 139/218] media: v4l: add I / P frame min max QP definitions Add following V4L2 QP parameters for H.264: * V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP * V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP * V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP * V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP These controls will limit QP range for intra and inter frame, provide more manual control to improve video encode quality. Signed-off-by: Fish Lin Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/uapi/v4l/ext-ctrls-codec.rst | 24 +++++++++++++++++++ drivers/media/v4l2-core/v4l2-ctrls.c | 4 ++++ include/uapi/linux/v4l2-controls.h | 4 ++++ 3 files changed, 32 insertions(+) diff --git a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst index 67a122339c0e..4a8446203085 100644 --- a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst +++ b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst @@ -1055,6 +1055,30 @@ enum v4l2_mpeg_video_h264_entropy_mode - Quantization parameter for an B frame for H264. Valid range: from 0 to 51. +``V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP (integer)`` + Minimum quantization parameter for the H264 I frame to limit I frame + quality to a range. Valid range: from 0 to 51. If + V4L2_CID_MPEG_VIDEO_H264_MIN_QP is also set, the quantization parameter + should be chosen to meet both requirements. + +``V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP (integer)`` + Maximum quantization parameter for the H264 I frame to limit I frame + quality to a range. Valid range: from 0 to 51. If + V4L2_CID_MPEG_VIDEO_H264_MAX_QP is also set, the quantization parameter + should be chosen to meet both requirements. + +``V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP (integer)`` + Minimum quantization parameter for the H264 P frame to limit P frame + quality to a range. Valid range: from 0 to 51. If + V4L2_CID_MPEG_VIDEO_H264_MIN_QP is also set, the quantization parameter + should be chosen to meet both requirements. + +``V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP (integer)`` + Maximum quantization parameter for the H264 P frame to limit P frame + quality to a range. Valid range: from 0 to 51. If + V4L2_CID_MPEG_VIDEO_H264_MAX_QP is also set, the quantization parameter + should be chosen to meet both requirements. + ``V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP (integer)`` Quantization parameter for an I frame for MPEG4. Valid range: from 1 to 31. diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index b1ae2e555c68..89a1fe564675 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -828,6 +828,10 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION: return "H264 Constrained Intra Pred"; case V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET: return "H264 Chroma QP Index Offset"; + case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP: return "H264 I-Frame Minimum QP Value"; + case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP: return "H264 I-Frame Maximum QP Value"; + case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP: return "H264 P-Frame Minimum QP Value"; + case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP: return "H264 P-Frame Maximum QP Value"; case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: return "MPEG4 I-Frame QP Value"; case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP: return "MPEG4 P-Frame QP Value"; case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP: return "MPEG4 B-Frame QP Value"; diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 78816ec88751..37807f23231e 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -539,6 +539,10 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type { #define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP (V4L2_CID_MPEG_BASE+382) #define V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION (V4L2_CID_MPEG_BASE+383) #define V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET (V4L2_CID_MPEG_BASE+384) +#define V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP (V4L2_CID_MPEG_BASE+385) +#define V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP (V4L2_CID_MPEG_BASE+386) +#define V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP (V4L2_CID_MPEG_BASE+387) +#define V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP (V4L2_CID_MPEG_BASE+388) #define V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP (V4L2_CID_MPEG_BASE+400) #define V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP (V4L2_CID_MPEG_BASE+401) #define V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP (V4L2_CID_MPEG_BASE+402) From 1e8f401474d6b7c2138521d38a73d829eba0138e Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Fri, 29 Mar 2019 03:38:28 -0400 Subject: [PATCH 140/218] media: atmel: atmel-isc: reworked driver and formats This change is a redesign in the formats and the way the ISC is configured w.r.t. sensor format and the output format from the ISC. I have changed the splitting between sensor output (which is also ISC input) and ISC output. The sensor format represents the way the sensor is configured, and what ISC is receiving. The format configuration represents the way ISC is interpreting the data and formatting the output to the subsystem. Now it's much easier to figure out what is the ISC configuration for input, and what is the configuration for output. The non-raw format can be obtained directly from sensor or it can be done inside the ISC. The controller format list will include a configuration for each format. The old supported formats are still in place, if we want to dump the sensor format directly to the output, the try format routine will detect and configure the pipeline accordingly. This also fixes the previous issues when the raw format was NULL which resulted in many crashes for sensors which did not have the expected/tested formats. Signed-off-by: Eugen Hristev Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/atmel/atmel-isc.c | 953 ++++++++++++----------- 1 file changed, 508 insertions(+), 445 deletions(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 9a399aa7ca92..61d927684183 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -89,35 +89,25 @@ struct isc_subdev_entity { struct list_head list; }; -/* Indicate the format is generated by the sensor */ -#define FMT_FLAG_FROM_SENSOR BIT(0) -/* Indicate the format is produced by ISC itself */ -#define FMT_FLAG_FROM_CONTROLLER BIT(1) -/* Indicate a Raw Bayer format */ -#define FMT_FLAG_RAW_FORMAT BIT(2) - -#define FMT_FLAG_RAW_FROM_SENSOR (FMT_FLAG_FROM_SENSOR | \ - FMT_FLAG_RAW_FORMAT) - /* * struct isc_format - ISC media bus format information + This structure represents the interface between the ISC + and the sensor. It's the input format received by + the ISC. * @fourcc: Fourcc code for this format * @mbus_code: V4L2 media bus format code. - * flags: Indicate format from sensor or converted by controller - * @bpp: Bits per pixel (when stored in memory) - * (when transferred over a bus) - * @sd_support: Subdev supports this format - * @isc_support: ISC can convert raw format to this format + * @cfa_baycfg: If this format is RAW BAYER, indicate the type of bayer. + this is either BGBG, RGRG, etc. + * @pfe_cfg0_bps: Number of hardware data lines connected to the ISC */ struct isc_format { u32 fourcc; u32 mbus_code; - u32 flags; - u8 bpp; + u32 cfa_baycfg; bool sd_support; - bool isc_support; + u32 pfe_cfg0_bps; }; /* Pipeline bitmap */ @@ -135,16 +125,31 @@ struct isc_format { #define GAM_ENABLES (GAM_RENABLE | GAM_GENABLE | GAM_BENABLE | GAM_ENABLE) +/* + * struct fmt_config - ISC format configuration and internal pipeline + This structure represents the internal configuration + of the ISC. + It also holds the format that ISC will present to v4l2. + * @sd_format: Pointer to an isc_format struct that holds the sensor + configuration. + * @fourcc: Fourcc code for this format. + * @bpp: Bytes per pixel in the current format. + * @rlp_cfg_mode: Configuration of the RLP (rounding, limiting packaging) + * @dcfg_imode: Configuration of the input of the DMA module + * @dctrl_dview: Configuration of the output of the DMA module + * @bits_pipeline: Configuration of the pipeline, which modules are enabled + */ struct fmt_config { - u32 fourcc; + struct isc_format *sd_format; - u32 pfe_cfg0_bps; - u32 cfa_baycfg; - u32 rlp_cfg_mode; - u32 dcfg_imode; - u32 dctrl_dview; + u32 fourcc; + u8 bpp; - u32 bits_pipeline; + u32 rlp_cfg_mode; + u32 dcfg_imode; + u32 dctrl_dview; + + u32 bits_pipeline; }; #define HIST_ENTRIES 512 @@ -196,8 +201,9 @@ struct isc_device { struct v4l2_format fmt; struct isc_format **user_formats; unsigned int num_user_formats; - const struct isc_format *current_fmt; - const struct isc_format *raw_fmt; + + struct fmt_config config; + struct fmt_config try_config; struct isc_ctrls ctrls; struct work_struct awb_work; @@ -210,319 +216,122 @@ struct isc_device { struct list_head subdev_entities; }; +/* This is a list of the formats that the ISC can *output* */ +static struct isc_format controller_formats[] = { + { + .fourcc = V4L2_PIX_FMT_ARGB444, + }, + { + .fourcc = V4L2_PIX_FMT_ARGB555, + }, + { + .fourcc = V4L2_PIX_FMT_RGB565, + }, + { + .fourcc = V4L2_PIX_FMT_ARGB32, + }, + { + .fourcc = V4L2_PIX_FMT_YUV420, + }, + { + .fourcc = V4L2_PIX_FMT_YUYV, + }, + { + .fourcc = V4L2_PIX_FMT_YUV422P, + }, + { + .fourcc = V4L2_PIX_FMT_GREY, + }, +}; + +/* This is a list of formats that the ISC can receive as *input* */ static struct isc_format formats_list[] = { { .fourcc = V4L2_PIX_FMT_SBGGR8, .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8, - .flags = FMT_FLAG_RAW_FROM_SENSOR, - .bpp = 8, + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, + .cfa_baycfg = ISC_BAY_CFG_BGBG, }, { .fourcc = V4L2_PIX_FMT_SGBRG8, .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8, - .flags = FMT_FLAG_RAW_FROM_SENSOR, - .bpp = 8, + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, + .cfa_baycfg = ISC_BAY_CFG_GBGB, }, { .fourcc = V4L2_PIX_FMT_SGRBG8, .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8, - .flags = FMT_FLAG_RAW_FROM_SENSOR, - .bpp = 8, + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, + .cfa_baycfg = ISC_BAY_CFG_GRGR, }, { .fourcc = V4L2_PIX_FMT_SRGGB8, .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8, - .flags = FMT_FLAG_RAW_FROM_SENSOR, - .bpp = 8, + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, + .cfa_baycfg = ISC_BAY_CFG_RGRG, }, { .fourcc = V4L2_PIX_FMT_SBGGR10, .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10, - .flags = FMT_FLAG_RAW_FROM_SENSOR, - .bpp = 16, + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN, + .cfa_baycfg = ISC_BAY_CFG_RGRG, }, { .fourcc = V4L2_PIX_FMT_SGBRG10, .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10, - .flags = FMT_FLAG_RAW_FROM_SENSOR, - .bpp = 16, + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN, + .cfa_baycfg = ISC_BAY_CFG_GBGB, }, { .fourcc = V4L2_PIX_FMT_SGRBG10, .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, - .flags = FMT_FLAG_RAW_FROM_SENSOR, - .bpp = 16, + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN, + .cfa_baycfg = ISC_BAY_CFG_GRGR, }, { .fourcc = V4L2_PIX_FMT_SRGGB10, .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10, - .flags = FMT_FLAG_RAW_FROM_SENSOR, - .bpp = 16, + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN, + .cfa_baycfg = ISC_BAY_CFG_RGRG, }, { .fourcc = V4L2_PIX_FMT_SBGGR12, .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12, - .flags = FMT_FLAG_RAW_FROM_SENSOR, - .bpp = 16, + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TWELVE, + .cfa_baycfg = ISC_BAY_CFG_BGBG, }, { .fourcc = V4L2_PIX_FMT_SGBRG12, .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12, - .flags = FMT_FLAG_RAW_FROM_SENSOR, - .bpp = 16, + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TWELVE, + .cfa_baycfg = ISC_BAY_CFG_GBGB, }, { .fourcc = V4L2_PIX_FMT_SGRBG12, .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12, - .flags = FMT_FLAG_RAW_FROM_SENSOR, - .bpp = 16, + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TWELVE, + .cfa_baycfg = ISC_BAY_CFG_GRGR, }, { .fourcc = V4L2_PIX_FMT_SRGGB12, .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12, - .flags = FMT_FLAG_RAW_FROM_SENSOR, - .bpp = 16, - }, - { - .fourcc = V4L2_PIX_FMT_YUV420, - .mbus_code = 0x0, - .flags = FMT_FLAG_FROM_CONTROLLER, - .bpp = 12, - }, - { - .fourcc = V4L2_PIX_FMT_YUV422P, - .mbus_code = 0x0, - .flags = FMT_FLAG_FROM_CONTROLLER, - .bpp = 16, + .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TWELVE, + .cfa_baycfg = ISC_BAY_CFG_RGRG, }, { .fourcc = V4L2_PIX_FMT_GREY, .mbus_code = MEDIA_BUS_FMT_Y8_1X8, - .flags = FMT_FLAG_FROM_CONTROLLER | - FMT_FLAG_FROM_SENSOR, - .bpp = 8, - }, - { - .fourcc = V4L2_PIX_FMT_ARGB444, - .mbus_code = MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE, - .flags = FMT_FLAG_FROM_CONTROLLER, - .bpp = 16, - }, - { - .fourcc = V4L2_PIX_FMT_ARGB555, - .mbus_code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, - .flags = FMT_FLAG_FROM_CONTROLLER, - .bpp = 16, - }, - { - .fourcc = V4L2_PIX_FMT_RGB565, - .mbus_code = MEDIA_BUS_FMT_RGB565_2X8_LE, - .flags = FMT_FLAG_FROM_CONTROLLER, - .bpp = 16, - }, - { - .fourcc = V4L2_PIX_FMT_ARGB32, - .mbus_code = MEDIA_BUS_FMT_ARGB8888_1X32, - .flags = FMT_FLAG_FROM_CONTROLLER, - .bpp = 32, + .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, }, { .fourcc = V4L2_PIX_FMT_YUYV, .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8, - .flags = FMT_FLAG_FROM_CONTROLLER | - FMT_FLAG_FROM_SENSOR, - .bpp = 16, - }, -}; - -static struct fmt_config fmt_configs_list[] = { - { - .fourcc = V4L2_PIX_FMT_SBGGR8, .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, - .cfa_baycfg = ISC_BAY_CFG_BGBG, - .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT8, - .dcfg_imode = ISC_DCFG_IMODE_PACKED8, - .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, - .bits_pipeline = 0x0, - }, - { - .fourcc = V4L2_PIX_FMT_SGBRG8, - .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, - .cfa_baycfg = ISC_BAY_CFG_GBGB, - .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT8, - .dcfg_imode = ISC_DCFG_IMODE_PACKED8, - .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, - .bits_pipeline = 0x0, - }, - { - .fourcc = V4L2_PIX_FMT_SGRBG8, - .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, - .cfa_baycfg = ISC_BAY_CFG_GRGR, - .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT8, - .dcfg_imode = ISC_DCFG_IMODE_PACKED8, - .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, - .bits_pipeline = 0x0, - }, - { - .fourcc = V4L2_PIX_FMT_SRGGB8, - .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, - .cfa_baycfg = ISC_BAY_CFG_RGRG, - .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT8, - .dcfg_imode = ISC_DCFG_IMODE_PACKED8, - .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, - .bits_pipeline = 0x0, - }, - { - .fourcc = V4L2_PIX_FMT_SBGGR10, - .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN, - .cfa_baycfg = ISC_BAY_CFG_BGBG, - .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT10, - .dcfg_imode = ISC_DCFG_IMODE_PACKED16, - .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, - .bits_pipeline = 0x0, - }, - { - .fourcc = V4L2_PIX_FMT_SGBRG10, - .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN, - .cfa_baycfg = ISC_BAY_CFG_GBGB, - .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT10, - .dcfg_imode = ISC_DCFG_IMODE_PACKED16, - .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, - .bits_pipeline = 0x0, - }, - { - .fourcc = V4L2_PIX_FMT_SGRBG10, - .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN, - .cfa_baycfg = ISC_BAY_CFG_GRGR, - .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT10, - .dcfg_imode = ISC_DCFG_IMODE_PACKED16, - .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, - .bits_pipeline = 0x0, - }, - { - .fourcc = V4L2_PIX_FMT_SRGGB10, - .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TEN, - .cfa_baycfg = ISC_BAY_CFG_RGRG, - .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT10, - .dcfg_imode = ISC_DCFG_IMODE_PACKED16, - .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, - .bits_pipeline = 0x0, - }, - { - .fourcc = V4L2_PIX_FMT_SBGGR12, - .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TWELVE, - .cfa_baycfg = ISC_BAY_CFG_BGBG, - .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT12, - .dcfg_imode = ISC_DCFG_IMODE_PACKED16, - .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, - .bits_pipeline = 0x0, - }, - { - .fourcc = V4L2_PIX_FMT_SGBRG12, - .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TWELVE, - .cfa_baycfg = ISC_BAY_CFG_GBGB, - .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT12, - .dcfg_imode = ISC_DCFG_IMODE_PACKED16, - .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, - .bits_pipeline = 0x0 - }, - { - .fourcc = V4L2_PIX_FMT_SGRBG12, - .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TWELVE, - .cfa_baycfg = ISC_BAY_CFG_GRGR, - .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT12, - .dcfg_imode = ISC_DCFG_IMODE_PACKED16, - .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, - .bits_pipeline = 0x0, - }, - { - .fourcc = V4L2_PIX_FMT_SRGGB12, - .pfe_cfg0_bps = ISC_PFG_CFG0_BPS_TWELVE, - .cfa_baycfg = ISC_BAY_CFG_RGRG, - .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT12, - .dcfg_imode = ISC_DCFG_IMODE_PACKED16, - .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, - .bits_pipeline = 0x0, - }, - { - .fourcc = V4L2_PIX_FMT_YUV420, - .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, - .cfa_baycfg = ISC_BAY_CFG_BGBG, - .rlp_cfg_mode = ISC_RLP_CFG_MODE_YYCC, - .dcfg_imode = ISC_DCFG_IMODE_YC420P, - .dctrl_dview = ISC_DCTRL_DVIEW_PLANAR, - .bits_pipeline = SUB420_ENABLE | SUB422_ENABLE | - CBC_ENABLE | CSC_ENABLE | - GAM_ENABLES | - CFA_ENABLE | WB_ENABLE, - }, - { - .fourcc = V4L2_PIX_FMT_YUV422P, - .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, - .cfa_baycfg = ISC_BAY_CFG_BGBG, - .rlp_cfg_mode = ISC_RLP_CFG_MODE_YYCC, - .dcfg_imode = ISC_DCFG_IMODE_YC422P, - .dctrl_dview = ISC_DCTRL_DVIEW_PLANAR, - .bits_pipeline = SUB422_ENABLE | - CBC_ENABLE | CSC_ENABLE | - GAM_ENABLES | - CFA_ENABLE | WB_ENABLE, - }, - { - .fourcc = V4L2_PIX_FMT_GREY, - .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, - .cfa_baycfg = ISC_BAY_CFG_BGBG, - .rlp_cfg_mode = ISC_RLP_CFG_MODE_DATY8, - .dcfg_imode = ISC_DCFG_IMODE_PACKED8, - .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, - .bits_pipeline = CBC_ENABLE | CSC_ENABLE | - GAM_ENABLES | - CFA_ENABLE | WB_ENABLE, - }, - { - .fourcc = V4L2_PIX_FMT_ARGB444, - .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, - .cfa_baycfg = ISC_BAY_CFG_BGBG, - .rlp_cfg_mode = ISC_RLP_CFG_MODE_ARGB444, - .dcfg_imode = ISC_DCFG_IMODE_PACKED16, - .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, - .bits_pipeline = GAM_ENABLES | CFA_ENABLE | WB_ENABLE, - }, - { - .fourcc = V4L2_PIX_FMT_ARGB555, - .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, - .cfa_baycfg = ISC_BAY_CFG_BGBG, - .rlp_cfg_mode = ISC_RLP_CFG_MODE_ARGB555, - .dcfg_imode = ISC_DCFG_IMODE_PACKED16, - .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, - .bits_pipeline = GAM_ENABLES | CFA_ENABLE | WB_ENABLE, }, { .fourcc = V4L2_PIX_FMT_RGB565, + .mbus_code = MEDIA_BUS_FMT_RGB565_2X8_LE, .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, - .cfa_baycfg = ISC_BAY_CFG_BGBG, - .rlp_cfg_mode = ISC_RLP_CFG_MODE_RGB565, - .dcfg_imode = ISC_DCFG_IMODE_PACKED16, - .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, - .bits_pipeline = GAM_ENABLES | CFA_ENABLE | WB_ENABLE, - }, - { - .fourcc = V4L2_PIX_FMT_ARGB32, - .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, - .cfa_baycfg = ISC_BAY_CFG_BGBG, - .rlp_cfg_mode = ISC_RLP_CFG_MODE_ARGB32, - .dcfg_imode = ISC_DCFG_IMODE_PACKED32, - .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, - .bits_pipeline = GAM_ENABLES | CFA_ENABLE | WB_ENABLE, - }, - { - .fourcc = V4L2_PIX_FMT_YUYV, - .pfe_cfg0_bps = ISC_PFE_CFG0_BPS_EIGHT, - .cfa_baycfg = ISC_BAY_CFG_BGBG, - .rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT8, - .dcfg_imode = ISC_DCFG_IMODE_PACKED8, - .dctrl_dview = ISC_DCTRL_DVIEW_PACKED, - .bits_pipeline = 0x0 }, }; @@ -571,6 +380,13 @@ static const u32 isc_gamma_table[GAMMA_MAX + 1][GAMMA_ENTRIES] = { 0x3E20007, 0x3E90007, 0x3F00008, 0x3F80007 }, }; +#define ISC_IS_FORMAT_RAW(mbus_code) \ + (((mbus_code) & 0xf000) == 0x3000) + +static unsigned int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "debug level (0-2)"); + static unsigned int sensor_preferred = 1; module_param(sensor_preferred, uint, 0644); MODULE_PARM_DESC(sensor_preferred, @@ -896,40 +712,17 @@ static int isc_buffer_prepare(struct vb2_buffer *vb) return 0; } -static inline bool sensor_is_preferred(const struct isc_format *isc_fmt) -{ - return (sensor_preferred && isc_fmt->sd_support) || - !isc_fmt->isc_support; -} - -static struct fmt_config *get_fmt_config(u32 fourcc) -{ - struct fmt_config *config; - int i; - - config = &fmt_configs_list[0]; - for (i = 0; i < ARRAY_SIZE(fmt_configs_list); i++) { - if (config->fourcc == fourcc) - return config; - - config++; - } - return NULL; -} - static void isc_start_dma(struct isc_device *isc) { struct regmap *regmap = isc->regmap; - struct v4l2_pix_format *pixfmt = &isc->fmt.fmt.pix; - u32 sizeimage = pixfmt->sizeimage; - struct fmt_config *config = get_fmt_config(isc->current_fmt->fourcc); + u32 sizeimage = isc->fmt.fmt.pix.sizeimage; u32 dctrl_dview; dma_addr_t addr0; addr0 = vb2_dma_contig_plane_dma_addr(&isc->cur_frm->vb.vb2_buf, 0); regmap_write(regmap, ISC_DAD0, addr0); - switch (pixfmt->pixelformat) { + switch (isc->config.fourcc) { case V4L2_PIX_FMT_YUV420: regmap_write(regmap, ISC_DAD1, addr0 + (sizeimage * 2) / 3); regmap_write(regmap, ISC_DAD2, addr0 + (sizeimage * 5) / 6); @@ -942,10 +735,7 @@ static void isc_start_dma(struct isc_device *isc) break; } - if (sensor_is_preferred(isc->current_fmt)) - dctrl_dview = ISC_DCTRL_DVIEW_PACKED; - else - dctrl_dview = config->dctrl_dview; + dctrl_dview = isc->config.dctrl_dview; regmap_write(regmap, ISC_DCTRL, dctrl_dview | ISC_DCTRL_IE_IS); regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_CAPTURE); @@ -955,7 +745,6 @@ static void isc_set_pipeline(struct isc_device *isc, u32 pipeline) { struct regmap *regmap = isc->regmap; struct isc_ctrls *ctrls = &isc->ctrls; - struct fmt_config *config = get_fmt_config(isc->raw_fmt->fourcc); u32 val, bay_cfg; const u32 *gamma; unsigned int i; @@ -969,7 +758,7 @@ static void isc_set_pipeline(struct isc_device *isc, u32 pipeline) if (!pipeline) return; - bay_cfg = config->cfa_baycfg; + bay_cfg = isc->config.sd_format->cfa_baycfg; regmap_write(regmap, ISC_WB_CFG, bay_cfg); regmap_write(regmap, ISC_WB_O_RGR, 0x0); @@ -1011,24 +800,24 @@ static int isc_update_profile(struct isc_device *isc) } if (counter < 0) { - v4l2_warn(&isc->v4l2_dev, "Time out to update profie\n"); + v4l2_warn(&isc->v4l2_dev, "Time out to update profile\n"); return -ETIMEDOUT; } return 0; } -static void isc_set_histogram(struct isc_device *isc) +static void isc_set_histogram(struct isc_device *isc, bool enable) { struct regmap *regmap = isc->regmap; struct isc_ctrls *ctrls = &isc->ctrls; - struct fmt_config *config = get_fmt_config(isc->raw_fmt->fourcc); - if (ctrls->awb && (ctrls->hist_stat != HIST_ENABLED)) { + if (enable) { regmap_write(regmap, ISC_HIS_CFG, ISC_HIS_CFG_MODE_R | - (config->cfa_baycfg << ISC_HIS_CFG_BAYSEL_SHIFT) | - ISC_HIS_CFG_RAR); + (isc->config.sd_format->cfa_baycfg + << ISC_HIS_CFG_BAYSEL_SHIFT) | + ISC_HIS_CFG_RAR); regmap_write(regmap, ISC_HIS_CTRL, ISC_HIS_CTRL_EN); regmap_write(regmap, ISC_INTEN, ISC_INT_HISDONE); ctrls->hist_id = ISC_HIS_CFG_MODE_R; @@ -1036,7 +825,7 @@ static void isc_set_histogram(struct isc_device *isc) regmap_write(regmap, ISC_CTRLEN, ISC_CTRL_HISREQ); ctrls->hist_stat = HIST_ENABLED; - } else if (!ctrls->awb && (ctrls->hist_stat != HIST_DISABLED)) { + } else { regmap_write(regmap, ISC_INTDIS, ISC_INT_HISDONE); regmap_write(regmap, ISC_HIS_CTRL, ISC_HIS_CTRL_DIS); @@ -1044,53 +833,18 @@ static void isc_set_histogram(struct isc_device *isc) } } -static inline void isc_get_param(const struct isc_format *fmt, - u32 *rlp_mode, u32 *dcfg) -{ - struct fmt_config *config = get_fmt_config(fmt->fourcc); - - *dcfg = ISC_DCFG_YMBSIZE_BEATS8; - - switch (fmt->fourcc) { - case V4L2_PIX_FMT_SBGGR10: - case V4L2_PIX_FMT_SGBRG10: - case V4L2_PIX_FMT_SGRBG10: - case V4L2_PIX_FMT_SRGGB10: - case V4L2_PIX_FMT_SBGGR12: - case V4L2_PIX_FMT_SGBRG12: - case V4L2_PIX_FMT_SGRBG12: - case V4L2_PIX_FMT_SRGGB12: - *rlp_mode = config->rlp_cfg_mode; - *dcfg |= config->dcfg_imode; - break; - default: - *rlp_mode = ISC_RLP_CFG_MODE_DAT8; - *dcfg |= ISC_DCFG_IMODE_PACKED8; - break; - } -} - static int isc_configure(struct isc_device *isc) { struct regmap *regmap = isc->regmap; - const struct isc_format *current_fmt = isc->current_fmt; - struct fmt_config *curfmt_config = get_fmt_config(current_fmt->fourcc); - struct fmt_config *rawfmt_config = get_fmt_config(isc->raw_fmt->fourcc); - struct isc_subdev_entity *subdev = isc->current_subdev; u32 pfe_cfg0, rlp_mode, dcfg, mask, pipeline; + struct isc_subdev_entity *subdev = isc->current_subdev; - if (sensor_is_preferred(current_fmt)) { - pfe_cfg0 = curfmt_config->pfe_cfg0_bps; - pipeline = 0x0; - isc_get_param(current_fmt, &rlp_mode, &dcfg); - isc->ctrls.hist_stat = HIST_INIT; - } else { - pfe_cfg0 = rawfmt_config->pfe_cfg0_bps; - pipeline = curfmt_config->bits_pipeline; - rlp_mode = curfmt_config->rlp_cfg_mode; - dcfg = curfmt_config->dcfg_imode | + pfe_cfg0 = isc->config.sd_format->pfe_cfg0_bps; + rlp_mode = isc->config.rlp_cfg_mode; + pipeline = isc->config.bits_pipeline; + + dcfg = isc->config.dcfg_imode | ISC_DCFG_YMBSIZE_BEATS8 | ISC_DCFG_CMBSIZE_BEATS8; - } pfe_cfg0 |= subdev->pfe_cfg0 | ISC_PFE_CFG0_MODE_PROGRESSIVE; mask = ISC_PFE_CFG0_BPS_MASK | ISC_PFE_CFG0_HPOL_LOW | @@ -1108,8 +862,15 @@ static int isc_configure(struct isc_device *isc) /* Set the pipeline */ isc_set_pipeline(isc, pipeline); - if (pipeline) - isc_set_histogram(isc); + /* + * The current implemented histogram is available for RAW R, B, GB + * channels. We need to check if sensor is outputting RAW BAYER + */ + if (isc->ctrls.awb && + ISC_IS_FORMAT_RAW(isc->config.sd_format->mbus_code)) + isc_set_histogram(isc, true); + else + isc_set_histogram(isc, false); /* Update profile */ return isc_update_profile(isc); @@ -1126,7 +887,8 @@ static int isc_start_streaming(struct vb2_queue *vq, unsigned int count) /* Enable stream on the sub device */ ret = v4l2_subdev_call(isc->current_subdev->sd, video, s_stream, 1); if (ret && ret != -ENOIOCTLCMD) { - v4l2_err(&isc->v4l2_dev, "stream on failed in subdev\n"); + v4l2_err(&isc->v4l2_dev, "stream on failed in subdev %d\n", + ret); goto err_start_stream; } @@ -1224,6 +986,22 @@ static void isc_buffer_queue(struct vb2_buffer *vb) spin_unlock_irqrestore(&isc->dma_queue_lock, flags); } +static struct isc_format *find_format_by_fourcc(struct isc_device *isc, + unsigned int fourcc) +{ + unsigned int num_formats = isc->num_user_formats; + struct isc_format *fmt; + unsigned int i; + + for (i = 0; i < num_formats; i++) { + fmt = isc->user_formats[i]; + if (fmt->fourcc == fourcc) + return fmt; + } + + return NULL; +} + static const struct vb2_ops isc_vb2_ops = { .queue_setup = isc_queue_setup, .wait_prepare = vb2_ops_wait_prepare, @@ -1250,15 +1028,31 @@ static int isc_querycap(struct file *file, void *priv, static int isc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - struct isc_device *isc = video_drvdata(file); u32 index = f->index; + u32 i, supported_index; - if (index >= isc->num_user_formats) - return -EINVAL; + if (index < ARRAY_SIZE(controller_formats)) { + f->pixelformat = controller_formats[index].fourcc; + return 0; + } - f->pixelformat = isc->user_formats[index]->fourcc; + index -= ARRAY_SIZE(controller_formats); - return 0; + i = 0; + supported_index = 0; + + for (i = 0; i < ARRAY_SIZE(formats_list); i++) { + if (!ISC_IS_FORMAT_RAW(formats_list[i].mbus_code) || + !formats_list[i].sd_support) + continue; + if (supported_index == index) { + f->pixelformat = formats_list[i].fourcc; + return 0; + } + supported_index++; + } + + return -EINVAL; } static int isc_g_fmt_vid_cap(struct file *file, void *priv, @@ -1271,26 +1065,235 @@ static int isc_g_fmt_vid_cap(struct file *file, void *priv, return 0; } -static struct isc_format *find_format_by_fourcc(struct isc_device *isc, - unsigned int fourcc) +/* + * Checks the current configured format, if ISC can output it, + * considering which type of format the ISC receives from the sensor + */ +static int isc_try_validate_formats(struct isc_device *isc) { - unsigned int num_formats = isc->num_user_formats; - struct isc_format *fmt; - unsigned int i; + int ret; + bool bayer = false, yuv = false, rgb = false, grey = false; - for (i = 0; i < num_formats; i++) { - fmt = isc->user_formats[i]; - if (fmt->fourcc == fourcc) - return fmt; + /* all formats supported by the RLP module are OK */ + switch (isc->try_config.fourcc) { + case V4L2_PIX_FMT_SBGGR8: + case V4L2_PIX_FMT_SGBRG8: + case V4L2_PIX_FMT_SGRBG8: + case V4L2_PIX_FMT_SRGGB8: + case V4L2_PIX_FMT_SBGGR10: + case V4L2_PIX_FMT_SGBRG10: + case V4L2_PIX_FMT_SGRBG10: + case V4L2_PIX_FMT_SRGGB10: + case V4L2_PIX_FMT_SBGGR12: + case V4L2_PIX_FMT_SGBRG12: + case V4L2_PIX_FMT_SGRBG12: + case V4L2_PIX_FMT_SRGGB12: + ret = 0; + bayer = true; + break; + + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YUV422P: + case V4L2_PIX_FMT_YUYV: + ret = 0; + yuv = true; + break; + + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_ARGB32: + case V4L2_PIX_FMT_ARGB444: + case V4L2_PIX_FMT_ARGB555: + ret = 0; + rgb = true; + break; + case V4L2_PIX_FMT_GREY: + ret = 0; + grey = true; + break; + default: + /* any other different formats are not supported */ + ret = -EINVAL; } - return NULL; + /* we cannot output RAW/Grey if we do not receive RAW */ + if ((bayer || grey) && + !ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) + return -EINVAL; + + v4l2_dbg(1, debug, &isc->v4l2_dev, + "Format validation, requested rgb=%u, yuv=%u, grey=%u, bayer=%u\n", + rgb, yuv, grey, bayer); + + return ret; +} + +/* + * Configures the RLP and DMA modules, depending on the output format + * configured for the ISC. + * If direct_dump == true, just dump raw data 8 bits. + */ +static int isc_try_configure_rlp_dma(struct isc_device *isc, bool direct_dump) +{ + if (direct_dump) { + isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT8; + isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED8; + isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; + isc->try_config.bpp = 16; + return 0; + } + + switch (isc->try_config.fourcc) { + case V4L2_PIX_FMT_SBGGR8: + case V4L2_PIX_FMT_SGBRG8: + case V4L2_PIX_FMT_SGRBG8: + case V4L2_PIX_FMT_SRGGB8: + isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT8; + isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED8; + isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; + isc->try_config.bpp = 8; + break; + case V4L2_PIX_FMT_SBGGR10: + case V4L2_PIX_FMT_SGBRG10: + case V4L2_PIX_FMT_SGRBG10: + case V4L2_PIX_FMT_SRGGB10: + isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT10; + isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16; + isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; + isc->try_config.bpp = 16; + break; + case V4L2_PIX_FMT_SBGGR12: + case V4L2_PIX_FMT_SGBRG12: + case V4L2_PIX_FMT_SGRBG12: + case V4L2_PIX_FMT_SRGGB12: + isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DAT12; + isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16; + isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; + isc->try_config.bpp = 16; + break; + case V4L2_PIX_FMT_RGB565: + isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_RGB565; + isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16; + isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; + isc->try_config.bpp = 16; + break; + case V4L2_PIX_FMT_ARGB444: + isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_ARGB444; + isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16; + isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; + isc->try_config.bpp = 16; + break; + case V4L2_PIX_FMT_ARGB555: + isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_ARGB555; + isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED16; + isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; + isc->try_config.bpp = 16; + break; + case V4L2_PIX_FMT_ARGB32: + isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_ARGB32; + isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED32; + isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; + isc->try_config.bpp = 32; + break; + case V4L2_PIX_FMT_YUV420: + isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_YYCC; + isc->try_config.dcfg_imode = ISC_DCFG_IMODE_YC420P; + isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PLANAR; + isc->try_config.bpp = 12; + break; + case V4L2_PIX_FMT_YUV422P: + isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_YYCC; + isc->try_config.dcfg_imode = ISC_DCFG_IMODE_YC422P; + isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PLANAR; + isc->try_config.bpp = 16; + break; + case V4L2_PIX_FMT_YUYV: + isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_YYCC; + isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED32; + isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; + isc->try_config.bpp = 16; + break; + case V4L2_PIX_FMT_GREY: + isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_DATY8; + isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED8; + isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; + isc->try_config.bpp = 8; + break; + default: + return -EINVAL; + } + return 0; +} + +/* + * Configuring pipeline modules, depending on which format the ISC outputs + * and considering which format it has as input from the sensor. + */ +static int isc_try_configure_pipeline(struct isc_device *isc) +{ + switch (isc->try_config.fourcc) { + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_ARGB555: + case V4L2_PIX_FMT_ARGB444: + case V4L2_PIX_FMT_ARGB32: + /* if sensor format is RAW, we convert inside ISC */ + if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) { + isc->try_config.bits_pipeline = CFA_ENABLE | + WB_ENABLE | GAM_ENABLES; + } else { + isc->try_config.bits_pipeline = 0x0; + } + break; + case V4L2_PIX_FMT_YUV420: + /* if sensor format is RAW, we convert inside ISC */ + if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) { + isc->try_config.bits_pipeline = CFA_ENABLE | + CSC_ENABLE | WB_ENABLE | GAM_ENABLES | + SUB420_ENABLE | SUB422_ENABLE | CBC_ENABLE; + } else { + isc->try_config.bits_pipeline = 0x0; + } + break; + case V4L2_PIX_FMT_YUV422P: + /* if sensor format is RAW, we convert inside ISC */ + if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) { + isc->try_config.bits_pipeline = CFA_ENABLE | + CSC_ENABLE | WB_ENABLE | GAM_ENABLES | + SUB422_ENABLE | CBC_ENABLE; + } else { + isc->try_config.bits_pipeline = 0x0; + } + break; + case V4L2_PIX_FMT_YUYV: + /* if sensor format is RAW, we convert inside ISC */ + if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) { + isc->try_config.bits_pipeline = CFA_ENABLE | + CSC_ENABLE | WB_ENABLE | GAM_ENABLES | + SUB422_ENABLE | CBC_ENABLE; + } else { + isc->try_config.bits_pipeline = 0x0; + } + break; + case V4L2_PIX_FMT_GREY: + if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) { + /* if sensor format is RAW, we convert inside ISC */ + isc->try_config.bits_pipeline = CFA_ENABLE | + CSC_ENABLE | WB_ENABLE | GAM_ENABLES | + CBC_ENABLE; + } else { + isc->try_config.bits_pipeline = 0x0; + } + break; + default: + isc->try_config.bits_pipeline = 0x0; + } + return 0; } static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f, - struct isc_format **current_fmt, u32 *code) + u32 *code) { - struct isc_format *isc_fmt; + int i; + struct isc_format *sd_fmt = NULL, *direct_fmt = NULL; struct v4l2_pix_format *pixfmt = &f->fmt.pix; struct v4l2_subdev_pad_config pad_cfg; struct v4l2_subdev_format format = { @@ -1298,17 +1301,62 @@ static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f, }; u32 mbus_code; int ret; + bool rlp_dma_direct_dump = false; if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - isc_fmt = find_format_by_fourcc(isc, pixfmt->pixelformat); - if (!isc_fmt) { - v4l2_warn(&isc->v4l2_dev, "Format 0x%x not found\n", - pixfmt->pixelformat); - isc_fmt = isc->user_formats[isc->num_user_formats - 1]; - pixfmt->pixelformat = isc_fmt->fourcc; + /* Step 1: find a RAW format that is supported */ + for (i = 0; i < isc->num_user_formats; i++) { + if (ISC_IS_FORMAT_RAW(isc->user_formats[i]->mbus_code)) { + sd_fmt = isc->user_formats[i]; + break; + } } + /* Step 2: We can continue with this RAW format, or we can look + * for better: maybe sensor supports directly what we need. + */ + direct_fmt = find_format_by_fourcc(isc, pixfmt->pixelformat); + + /* Step 3: We have both. We decide given the module parameter which + * one to use. + */ + if (direct_fmt && sd_fmt && sensor_preferred) + sd_fmt = direct_fmt; + + /* Step 4: we do not have RAW but we have a direct format. Use it. */ + if (direct_fmt && !sd_fmt) + sd_fmt = direct_fmt; + + /* Step 5: if we are using a direct format, we need to package + * everything as 8 bit data and just dump it + */ + if (sd_fmt == direct_fmt) + rlp_dma_direct_dump = true; + + /* Step 6: We have no format. This can happen if the userspace + * requests some weird/invalid format. + * In this case, default to whatever we have + */ + if (!sd_fmt && !direct_fmt) { + sd_fmt = isc->user_formats[isc->num_user_formats - 1]; + v4l2_dbg(1, debug, &isc->v4l2_dev, + "Sensor not supporting %.4s, using %.4s\n", + (char *)&pixfmt->pixelformat, (char *)&sd_fmt->fourcc); + } + + if (!sd_fmt) { + ret = -EINVAL; + goto isc_try_fmt_err; + } + + /* Step 7: Print out what we decided for debugging */ + v4l2_dbg(1, debug, &isc->v4l2_dev, + "Preferring to have sensor using format %.4s\n", + (char *)&sd_fmt->fourcc); + + /* Step 8: at this moment we decided which format the subdev will use */ + isc->try_config.sd_format = sd_fmt; /* Limit to Atmel ISC hardware capabilities */ if (pixfmt->width > ISC_MAX_SUPPORT_WIDTH) @@ -1316,30 +1364,56 @@ static int isc_try_fmt(struct isc_device *isc, struct v4l2_format *f, if (pixfmt->height > ISC_MAX_SUPPORT_HEIGHT) pixfmt->height = ISC_MAX_SUPPORT_HEIGHT; - if (sensor_is_preferred(isc_fmt)) - mbus_code = isc_fmt->mbus_code; - else - mbus_code = isc->raw_fmt->mbus_code; + /* + * The mbus format is the one the subdev outputs. + * The pixels will be transferred in this format Sensor -> ISC + */ + mbus_code = sd_fmt->mbus_code; + + /* + * Validate formats. If the required format is not OK, default to raw. + */ + + isc->try_config.fourcc = pixfmt->pixelformat; + + if (isc_try_validate_formats(isc)) { + pixfmt->pixelformat = isc->try_config.fourcc = sd_fmt->fourcc; + /* Re-try to validate the new format */ + ret = isc_try_validate_formats(isc); + if (ret) + goto isc_try_fmt_err; + } + + ret = isc_try_configure_rlp_dma(isc, rlp_dma_direct_dump); + if (ret) + goto isc_try_fmt_err; + + ret = isc_try_configure_pipeline(isc); + if (ret) + goto isc_try_fmt_err; v4l2_fill_mbus_format(&format.format, pixfmt, mbus_code); ret = v4l2_subdev_call(isc->current_subdev->sd, pad, set_fmt, &pad_cfg, &format); if (ret < 0) - return ret; + goto isc_try_fmt_err; v4l2_fill_pix_format(pixfmt, &format.format); pixfmt->field = V4L2_FIELD_NONE; - pixfmt->bytesperline = (pixfmt->width * isc_fmt->bpp) >> 3; + pixfmt->bytesperline = (pixfmt->width * isc->try_config.bpp) >> 3; pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; - if (current_fmt) - *current_fmt = isc_fmt; - if (code) *code = mbus_code; return 0; + +isc_try_fmt_err: + v4l2_err(&isc->v4l2_dev, "Could not find any possible format for a working pipeline\n"); + memset(&isc->try_config, 0, sizeof(isc->try_config)); + + return ret; } static int isc_set_fmt(struct isc_device *isc, struct v4l2_format *f) @@ -1347,11 +1421,10 @@ static int isc_set_fmt(struct isc_device *isc, struct v4l2_format *f) struct v4l2_subdev_format format = { .which = V4L2_SUBDEV_FORMAT_ACTIVE, }; - struct isc_format *current_fmt; - u32 mbus_code; + u32 mbus_code = 0; int ret; - ret = isc_try_fmt(isc, f, ¤t_fmt, &mbus_code); + ret = isc_try_fmt(isc, f, &mbus_code); if (ret) return ret; @@ -1362,7 +1435,10 @@ static int isc_set_fmt(struct isc_device *isc, struct v4l2_format *f) return ret; isc->fmt = *f; - isc->current_fmt = current_fmt; + /* make the try configuration active */ + isc->config = isc->try_config; + + v4l2_dbg(1, debug, &isc->v4l2_dev, "New ISC configuration in place\n"); return 0; } @@ -1383,7 +1459,7 @@ static int isc_try_fmt_vid_cap(struct file *file, void *priv, { struct isc_device *isc = video_drvdata(file); - return isc_try_fmt(isc, f, NULL, NULL); + return isc_try_fmt(isc, f, NULL); } static int isc_enum_input(struct file *file, void *priv, @@ -1432,27 +1508,31 @@ static int isc_enum_framesizes(struct file *file, void *fh, struct v4l2_frmsizeenum *fsize) { struct isc_device *isc = video_drvdata(file); - const struct isc_format *isc_fmt; struct v4l2_subdev_frame_size_enum fse = { .index = fsize->index, .which = V4L2_SUBDEV_FORMAT_ACTIVE, }; - int ret; + int ret = -EINVAL; + int i; - isc_fmt = find_format_by_fourcc(isc, fsize->pixel_format); - if (!isc_fmt) - return -EINVAL; + for (i = 0; i < isc->num_user_formats; i++) + if (isc->user_formats[i]->fourcc == fsize->pixel_format) + ret = 0; - if (sensor_is_preferred(isc_fmt)) - fse.code = isc_fmt->mbus_code; - else - fse.code = isc->raw_fmt->mbus_code; + for (i = 0; i < ARRAY_SIZE(controller_formats); i++) + if (controller_formats[i].fourcc == fsize->pixel_format) + ret = 0; + + if (ret) + return ret; ret = v4l2_subdev_call(isc->current_subdev->sd, pad, enum_frame_size, NULL, &fse); if (ret) return ret; + fse.code = isc->config.sd_format->mbus_code; + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; fsize->discrete.width = fse.max_width; fsize->discrete.height = fse.max_height; @@ -1464,29 +1544,32 @@ static int isc_enum_frameintervals(struct file *file, void *fh, struct v4l2_frmivalenum *fival) { struct isc_device *isc = video_drvdata(file); - const struct isc_format *isc_fmt; struct v4l2_subdev_frame_interval_enum fie = { .index = fival->index, .width = fival->width, .height = fival->height, .which = V4L2_SUBDEV_FORMAT_ACTIVE, }; - int ret; + int ret = -EINVAL; + int i; - isc_fmt = find_format_by_fourcc(isc, fival->pixel_format); - if (!isc_fmt) - return -EINVAL; + for (i = 0; i < isc->num_user_formats; i++) + if (isc->user_formats[i]->fourcc == fival->pixel_format) + ret = 0; - if (sensor_is_preferred(isc_fmt)) - fie.code = isc_fmt->mbus_code; - else - fie.code = isc->raw_fmt->mbus_code; + for (i = 0; i < ARRAY_SIZE(controller_formats); i++) + if (controller_formats[i].fourcc == fival->pixel_format) + ret = 0; + + if (ret) + return ret; ret = v4l2_subdev_call(isc->current_subdev->sd, pad, enum_frame_interval, NULL, &fie); if (ret) return ret; + fie.code = isc->config.sd_format->mbus_code; fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; fival->discrete = fie.interval; @@ -1669,7 +1752,6 @@ static void isc_awb_work(struct work_struct *w) struct isc_device *isc = container_of(w, struct isc_device, awb_work); struct regmap *regmap = isc->regmap; - struct fmt_config *config = get_fmt_config(isc->raw_fmt->fourcc); struct isc_ctrls *ctrls = &isc->ctrls; u32 hist_id = ctrls->hist_id; u32 baysel; @@ -1687,7 +1769,7 @@ static void isc_awb_work(struct work_struct *w) } ctrls->hist_id = hist_id; - baysel = config->cfa_baycfg << ISC_HIS_CFG_BAYSEL_SHIFT; + baysel = isc->config.sd_format->cfa_baycfg << ISC_HIS_CFG_BAYSEL_SHIFT; pm_runtime_get_sync(isc->dev); @@ -1755,7 +1837,6 @@ static int isc_ctrl_init(struct isc_device *isc) return 0; } - static int isc_async_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, struct v4l2_async_subdev *asd) @@ -1813,35 +1894,20 @@ static int isc_formats_init(struct isc_device *isc) .which = V4L2_SUBDEV_FORMAT_ACTIVE, }; + num_fmts = 0; while (!v4l2_subdev_call(subdev, pad, enum_mbus_code, NULL, &mbus_code)) { mbus_code.index++; fmt = find_format_by_code(mbus_code.code, &i); - if ((!fmt) || (!(fmt->flags & FMT_FLAG_FROM_SENSOR))) + if (!fmt) { + v4l2_warn(&isc->v4l2_dev, "Mbus code %x not supported\n", + mbus_code.code); continue; + } fmt->sd_support = true; - - if (fmt->flags & FMT_FLAG_RAW_FORMAT) - isc->raw_fmt = fmt; - } - - fmt = &formats_list[0]; - for (i = 0; i < list_size; i++) { - if (fmt->flags & FMT_FLAG_FROM_CONTROLLER) - fmt->isc_support = true; - - fmt++; - } - - fmt = &formats_list[0]; - num_fmts = 0; - for (i = 0; i < list_size; i++) { - if (fmt->isc_support || fmt->sd_support) - num_fmts++; - - fmt++; + num_fmts++; } if (!num_fmts) @@ -1856,9 +1922,8 @@ static int isc_formats_init(struct isc_device *isc) fmt = &formats_list[0]; for (i = 0, j = 0; i < list_size; i++) { - if (fmt->isc_support || fmt->sd_support) + if (fmt->sd_support) isc->user_formats[j++] = fmt; - fmt++; } @@ -1878,13 +1943,11 @@ static int isc_set_default_fmt(struct isc_device *isc) }; int ret; - ret = isc_try_fmt(isc, &f, NULL, NULL); + ret = isc_try_fmt(isc, &f, NULL); if (ret) return ret; - isc->current_fmt = isc->user_formats[0]; isc->fmt = f; - return 0; } From b063474e2130b6bab48ac20acd9b821dfc16c171 Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Fri, 29 Mar 2019 03:38:31 -0400 Subject: [PATCH 141/218] media: atmel: atmel-isc: removed ARGB32 added ABGR32 and XBGR32 ISC will output the "ARGB32" configuration in byte order: B, G, R, Alpha. This is in fact the format BGRA, aka ABGR32. If alpha is missing, the same format is equivalent to XBGR32. Added both formats and removed ARGB32 which is wrong. Signed-off-by: Eugen Hristev Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/atmel/atmel-isc.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index 61d927684183..4bba9da206e4 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -228,7 +228,10 @@ static struct isc_format controller_formats[] = { .fourcc = V4L2_PIX_FMT_RGB565, }, { - .fourcc = V4L2_PIX_FMT_ARGB32, + .fourcc = V4L2_PIX_FMT_ABGR32, + }, + { + .fourcc = V4L2_PIX_FMT_XBGR32, }, { .fourcc = V4L2_PIX_FMT_YUV420, @@ -1100,7 +1103,8 @@ static int isc_try_validate_formats(struct isc_device *isc) break; case V4L2_PIX_FMT_RGB565: - case V4L2_PIX_FMT_ARGB32: + case V4L2_PIX_FMT_ABGR32: + case V4L2_PIX_FMT_XBGR32: case V4L2_PIX_FMT_ARGB444: case V4L2_PIX_FMT_ARGB555: ret = 0; @@ -1188,7 +1192,8 @@ static int isc_try_configure_rlp_dma(struct isc_device *isc, bool direct_dump) isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; isc->try_config.bpp = 16; break; - case V4L2_PIX_FMT_ARGB32: + case V4L2_PIX_FMT_ABGR32: + case V4L2_PIX_FMT_XBGR32: isc->try_config.rlp_cfg_mode = ISC_RLP_CFG_MODE_ARGB32; isc->try_config.dcfg_imode = ISC_DCFG_IMODE_PACKED32; isc->try_config.dctrl_dview = ISC_DCTRL_DVIEW_PACKED; @@ -1234,7 +1239,8 @@ static int isc_try_configure_pipeline(struct isc_device *isc) case V4L2_PIX_FMT_RGB565: case V4L2_PIX_FMT_ARGB555: case V4L2_PIX_FMT_ARGB444: - case V4L2_PIX_FMT_ARGB32: + case V4L2_PIX_FMT_ABGR32: + case V4L2_PIX_FMT_XBGR32: /* if sensor format is RAW, we convert inside ISC */ if (ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) { isc->try_config.bits_pipeline = CFA_ENABLE | From 1a726df6078c2fa1ce07f1e086576977d99f7fcf Mon Sep 17 00:00:00 2001 From: Yannick Fertre Date: Fri, 29 Mar 2019 08:39:42 -0400 Subject: [PATCH 142/218] media: platform: stm32: wait end of transmission MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is mandatory to write CEC_CFGR only when CECEN=0. To protect transmission, a check have been added to delayed logical address modification. This patch is necessary tp pass all tests of compliance. Signed-off-by: Yannick Fertré Reviewed-by: Benjamin Gaignard Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/stm32/stm32-cec.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/media/platform/stm32/stm32-cec.c b/drivers/media/platform/stm32/stm32-cec.c index 7c496bc1cf38..8a86b2cc22fa 100644 --- a/drivers/media/platform/stm32/stm32-cec.c +++ b/drivers/media/platform/stm32/stm32-cec.c @@ -56,6 +56,13 @@ #define ALL_TX_IT (TXEND | TXBR | TXACKE | TXERR | TXUDR | ARBLST) #define ALL_RX_IT (RXEND | RXBR | RXACKE | RXOVR) +/* + * 400 ms is the time it takes for one 16 byte message to be + * transferred and 5 is the maximum number of retries. Add + * another 100 ms as a margin. + */ +#define CEC_XFER_TIMEOUT_MS (5 * 400 + 100) + struct stm32_cec { struct cec_adapter *adap; struct device *dev; @@ -188,7 +195,11 @@ static int stm32_cec_adap_log_addr(struct cec_adapter *adap, u8 logical_addr) { struct stm32_cec *cec = adap->priv; u32 oar = (1 << logical_addr) << 16; + u32 val; + /* Poll every 100µs the register CEC_CR to wait end of transmission */ + regmap_read_poll_timeout(cec->regmap, CEC_CR, val, !(val & TXSOM), + 100, CEC_XFER_TIMEOUT_MS * 1000); regmap_update_bits(cec->regmap, CEC_CR, CECEN, 0); if (logical_addr == CEC_LOG_ADDR_INVALID) From c4d1de702575728c6fa15ee15990d39a24e1f638 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 1 Apr 2019 03:42:05 -0400 Subject: [PATCH 143/218] media: v4l2-ctrls.h: remove spurious text Somehow the string "Controls name" got pasted in two places where it doesn't belong. Remove that text. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-ctrls.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index bd621cec65a5..ee026387f513 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -937,7 +937,7 @@ s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl); * __v4l2_ctrl_s_ctrl() - Unlocked variant of v4l2_ctrl_s_ctrl(). * * @ctrl: The control. - * @val: TheControls name new value. + * @val: The new value. * * This sets the control's new value safely by going through the control * framework. This function assumes the control's handler is already locked, @@ -1042,7 +1042,7 @@ int __v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s); * * @ctrl: The control. * @s: The new string. - *Controls name + * * This sets the control's new string safely by going through the control * framework. This function will lock the control's handler, so it cannot be * used from within the &v4l2_ctrl_ops functions. From e6c237ad93a08da61d2ccb3c0425ebdb494555b1 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Thu, 28 Mar 2019 12:16:30 -0400 Subject: [PATCH 144/218] media: vb2: Minor function naming fix Minor fix for helper function and comment, s/v4l2_vb2_buffer/vb2_v4l2_buffer. Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/videobuf2/videobuf2-v4l2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c index b11a779e97b0..1c3147275785 100644 --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c @@ -122,9 +122,9 @@ static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b) } /* - * __init_v4l2_vb2_buffer() - initialize the v4l2_vb2_buffer struct + * __init_vb2_v4l2_buffer() - initialize the vb2_v4l2_buffer struct */ -static void __init_v4l2_vb2_buffer(struct vb2_buffer *vb) +static void __init_vb2_v4l2_buffer(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); @@ -595,7 +595,7 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb, struct vb2_plane *planes) static const struct vb2_buf_ops v4l2_buf_ops = { .verify_planes_array = __verify_planes_array_core, - .init_buffer = __init_v4l2_vb2_buffer, + .init_buffer = __init_vb2_v4l2_buffer, .fill_user_buffer = __fill_v4l2_buffer, .fill_vb2_buffer = __fill_vb2_buffer, .copy_timestamp = __copy_timestamp, From 9fb10beb8a57f6fa9fdb592652f213df6b98600a Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Thu, 28 Mar 2019 14:07:03 -0400 Subject: [PATCH 145/218] media: rockchip/vpu: Rename pixel format helpers The rockchip VPU driver uses generic names for its pixel format helpers. We want to use the same names for generic versions of these helpers, so rename the rockchip ones. The driver will be switched to the generic helpers later. Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/rockchip/vpu/rockchip_vpu_enc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/media/rockchip/vpu/rockchip_vpu_enc.c b/drivers/staging/media/rockchip/vpu/rockchip_vpu_enc.c index ab0fb2053620..fb5e36aedd8c 100644 --- a/drivers/staging/media/rockchip/vpu/rockchip_vpu_enc.c +++ b/drivers/staging/media/rockchip/vpu/rockchip_vpu_enc.c @@ -41,7 +41,7 @@ * @is_compressed: Is it a compressed format? * @multiplanar: Is it a multiplanar variant format? (e.g. NV12M) */ -struct v4l2_format_info { +struct rockchip_vpu_v4l2_format_info { u32 format; u32 header_size; u8 num_planes; @@ -52,10 +52,10 @@ struct v4l2_format_info { u8 multiplanar; }; -static const struct v4l2_format_info * -v4l2_format_info(u32 format) +static const struct rockchip_vpu_v4l2_format_info * +rockchip_vpu_v4l2_format_info(u32 format) { - static const struct v4l2_format_info formats[] = { + static const struct rockchip_vpu_v4l2_format_info formats[] = { { .format = V4L2_PIX_FMT_YUV420M, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2, .multiplanar = 1 }, { .format = V4L2_PIX_FMT_NV12M, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2, .multiplanar = 1 }, { .format = V4L2_PIX_FMT_YUYV, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 }, @@ -76,11 +76,11 @@ static void fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, int pixelformat, int width, int height) { - const struct v4l2_format_info *info; + const struct rockchip_vpu_v4l2_format_info *info; struct v4l2_plane_pix_format *plane; int i; - info = v4l2_format_info(pixelformat); + info = rockchip_vpu_v4l2_format_info(pixelformat); if (!info) return; From f44b969aa3cddabe86e9aff411889643298e8d59 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Thu, 28 Mar 2019 14:07:04 -0400 Subject: [PATCH 146/218] media: Introduce helpers to fill pixel format structs Add two new API helpers, v4l2_fill_pixfmt and v4l2_fill_pixfmt_mp, to be used by drivers to calculate plane sizes and bytes per lines. Note that driver-specific padding and alignment are not taken into account, and must be done by drivers using this API. Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-common.c | 164 ++++++++++++++++++++++++++ include/media/v4l2-common.h | 33 ++++++ 2 files changed, 197 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c index 663730f088cd..d869a2910435 100644 --- a/drivers/media/v4l2-core/v4l2-common.c +++ b/drivers/media/v4l2-core/v4l2-common.c @@ -445,3 +445,167 @@ int v4l2_s_parm_cap(struct video_device *vdev, return ret; } EXPORT_SYMBOL_GPL(v4l2_s_parm_cap); + +const struct v4l2_format_info *v4l2_format_info(u32 format) +{ + static const struct v4l2_format_info formats[] = { + /* RGB formats */ + { .format = V4L2_PIX_FMT_BGR24, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_RGB24, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_HSV24, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_BGR32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_XBGR32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_RGB32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_XRGB32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_HSV32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_ARGB32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_ABGR32, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_GREY, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + + /* YUV packed formats */ + { .format = V4L2_PIX_FMT_YUYV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YVYU, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_UYVY, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_VYUY, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, + + /* YUV planar formats */ + { .format = V4L2_PIX_FMT_NV12, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_NV21, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_NV16, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_NV61, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_NV24, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_NV42, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + + { .format = V4L2_PIX_FMT_YUV410, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 }, + { .format = V4L2_PIX_FMT_YVU410, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 }, + { .format = V4L2_PIX_FMT_YUV411P, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YUV420, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_YVU420, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_YUV422P, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 }, + + /* YUV planar formats, non contiguous variant */ + { .format = V4L2_PIX_FMT_YUV420M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_YVU420M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_YUV422M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YVU422M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YUV444M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YVU444M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 1, .vdiv = 1 }, + + { .format = V4L2_PIX_FMT_NV12M, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_NV21M, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_NV16M, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_NV61M, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, + }; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(formats); ++i) + if (formats[i].format == format) + return &formats[i]; + return NULL; +} +EXPORT_SYMBOL(v4l2_format_info); + +static inline unsigned int v4l2_format_block_width(const struct v4l2_format_info *info, int plane) +{ + if (!info->block_w[plane]) + return 1; + return info->block_w[plane]; +} + +static inline unsigned int v4l2_format_block_height(const struct v4l2_format_info *info, int plane) +{ + if (!info->block_h[plane]) + return 1; + return info->block_h[plane]; +} + +int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, + int pixelformat, int width, int height) +{ + const struct v4l2_format_info *info; + struct v4l2_plane_pix_format *plane; + int i; + + info = v4l2_format_info(pixelformat); + if (!info) + return -EINVAL; + + pixfmt->width = width; + pixfmt->height = height; + pixfmt->pixelformat = pixelformat; + pixfmt->num_planes = info->mem_planes; + + if (info->mem_planes == 1) { + plane = &pixfmt->plane_fmt[0]; + plane->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0]; + plane->sizeimage = 0; + + for (i = 0; i < info->comp_planes; i++) { + unsigned int hdiv = (i == 0) ? 1 : info->hdiv; + unsigned int vdiv = (i == 0) ? 1 : info->vdiv; + unsigned int aligned_width; + unsigned int aligned_height; + + aligned_width = ALIGN(width, v4l2_format_block_width(info, i)); + aligned_height = ALIGN(height, v4l2_format_block_height(info, i)); + + plane->sizeimage += info->bpp[i] * + DIV_ROUND_UP(aligned_width, hdiv) * + DIV_ROUND_UP(aligned_height, vdiv); + } + } else { + for (i = 0; i < info->comp_planes; i++) { + unsigned int hdiv = (i == 0) ? 1 : info->hdiv; + unsigned int vdiv = (i == 0) ? 1 : info->vdiv; + unsigned int aligned_width; + unsigned int aligned_height; + + aligned_width = ALIGN(width, v4l2_format_block_width(info, i)); + aligned_height = ALIGN(height, v4l2_format_block_height(info, i)); + + plane = &pixfmt->plane_fmt[i]; + plane->bytesperline = + info->bpp[i] * DIV_ROUND_UP(aligned_width, hdiv); + plane->sizeimage = + plane->bytesperline * DIV_ROUND_UP(aligned_height, vdiv); + } + } + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_fill_pixfmt_mp); + +int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, int pixelformat, int width, int height) +{ + const struct v4l2_format_info *info; + int i; + + info = v4l2_format_info(pixelformat); + if (!info) + return -EINVAL; + + /* Single planar API cannot be used for multi plane formats. */ + if (info->mem_planes > 1) + return -EINVAL; + + pixfmt->width = width; + pixfmt->height = height; + pixfmt->pixelformat = pixelformat; + pixfmt->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0]; + pixfmt->sizeimage = 0; + + for (i = 0; i < info->comp_planes; i++) { + unsigned int hdiv = (i == 0) ? 1 : info->hdiv; + unsigned int vdiv = (i == 0) ? 1 : info->vdiv; + unsigned int aligned_width; + unsigned int aligned_height; + + aligned_width = ALIGN(width, v4l2_format_block_width(info, i)); + aligned_height = ALIGN(height, v4l2_format_block_height(info, i)); + + pixfmt->sizeimage += info->bpp[i] * + DIV_ROUND_UP(aligned_width, hdiv) * + DIV_ROUND_UP(aligned_height, vdiv); + } + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_fill_pixfmt); diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 2b93cb281fa5..0a41bbecf3d3 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -392,4 +392,37 @@ int v4l2_s_parm_cap(struct video_device *vdev, ((u64)(a).numerator * (b).denominator OP \ (u64)(b).numerator * (a).denominator) +/* ------------------------------------------------------------------------- */ + +/* Pixel format and FourCC helpers */ + +/** + * struct v4l2_format_info - information about a V4L2 format + * @format: 4CC format identifier (V4L2_PIX_FMT_*) + * @mem_planes: Number of memory planes, which includes the alpha plane (1 to 4). + * @comp_planes: Number of component planes, which includes the alpha plane (1 to 4). + * @bpp: Array of per-plane bytes per pixel + * @hdiv: Horizontal chroma subsampling factor + * @vdiv: Vertical chroma subsampling factor + * @block_w: Per-plane macroblock pixel width (optional) + * @block_h: Per-plane macroblock pixel height (optional) + */ +struct v4l2_format_info { + u32 format; + u8 mem_planes; + u8 comp_planes; + u8 bpp[4]; + u8 hdiv; + u8 vdiv; + u8 block_w[4]; + u8 block_h[4]; +}; + +const struct v4l2_format_info *v4l2_format_info(u32 format); + +int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, int pixelformat, + int width, int height); +int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, int pixelformat, + int width, int height); + #endif /* V4L2_COMMON_H_ */ From d82b921a7a8a00ec31ba76287245ec663534df9b Mon Sep 17 00:00:00 2001 From: Helen Fornazier Date: Wed, 6 Mar 2019 17:42:40 -0500 Subject: [PATCH 147/218] media: v4l2-common: add bayer formats in v4l2_format_info Add bayer format information in struct v4l2_format_info table. Signed-off-by: Helen Koike Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-common.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c index d869a2910435..b5778b2ffa27 100644 --- a/drivers/media/v4l2-core/v4l2-common.c +++ b/drivers/media/v4l2-core/v4l2-common.c @@ -495,6 +495,28 @@ const struct v4l2_format_info *v4l2_format_info(u32 format) { .format = V4L2_PIX_FMT_NV21M, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, { .format = V4L2_PIX_FMT_NV16M, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, { .format = V4L2_PIX_FMT_NV61M, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, + + /* Bayer RGB formats */ + { .format = V4L2_PIX_FMT_SBGGR8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGBRG8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGRBG8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SRGGB8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SBGGR10, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGBRG10, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGRBG10, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SRGGB10, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SBGGR10ALAW8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGBRG10ALAW8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGRBG10ALAW8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SRGGB10ALAW8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SBGGR10DPCM8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGBRG10DPCM8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGRBG10DPCM8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SRGGB10DPCM8, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SBGGR12, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGBRG12, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGRBG12, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SRGGB12, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, }; unsigned int i; From b6c61a6c37317efd7327199bfe24770af3d7e799 Mon Sep 17 00:00:00 2001 From: Helen Fornazier Date: Wed, 13 Mar 2019 14:29:37 -0400 Subject: [PATCH 148/218] media: vimc: propagate pixel format in the stream Media bus codes were being mapped to pixelformats, which causes a limitation on vimc because not all pixelformats can be mapped to media bus codes. Also, media bus codes are an internal configuration from the device. Userspace only assures media bus codes matches between pads and expects the image in a given pixelformat. So we can allow almost any media bus format to be configured between pads, except for debayer that expects a media bus code of type bayer in the sink pad. [hverkuil-cisco@xs4all.nl: drop use of v4l2_get_fourcc_name: not yet available] [hverkuil-cisco@xs4all.nl: made vimc_mbus_list static] Signed-off-by: Helen Koike Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vimc/vimc-capture.c | 76 +++-- drivers/media/platform/vimc/vimc-common.c | 309 ++++++++------------ drivers/media/platform/vimc/vimc-common.h | 58 ++-- drivers/media/platform/vimc/vimc-debayer.c | 81 +++-- drivers/media/platform/vimc/vimc-scaler.c | 63 ++-- drivers/media/platform/vimc/vimc-sensor.c | 51 +--- drivers/media/platform/vimc/vimc-streamer.c | 2 + drivers/media/platform/vimc/vimc-streamer.h | 6 + 8 files changed, 304 insertions(+), 342 deletions(-) diff --git a/drivers/media/platform/vimc/vimc-capture.c b/drivers/media/platform/vimc/vimc-capture.c index 290b08ebb1b6..e7d0fc2228a6 100644 --- a/drivers/media/platform/vimc/vimc-capture.c +++ b/drivers/media/platform/vimc/vimc-capture.c @@ -28,6 +28,32 @@ #define VIMC_CAP_DRV_NAME "vimc-capture" +static const u32 vimc_cap_supported_pixfmt[] = { + V4L2_PIX_FMT_BGR24, + V4L2_PIX_FMT_RGB24, + V4L2_PIX_FMT_ARGB32, + V4L2_PIX_FMT_SBGGR8, + V4L2_PIX_FMT_SGBRG8, + V4L2_PIX_FMT_SGRBG8, + V4L2_PIX_FMT_SRGGB8, + V4L2_PIX_FMT_SBGGR10, + V4L2_PIX_FMT_SGBRG10, + V4L2_PIX_FMT_SGRBG10, + V4L2_PIX_FMT_SRGGB10, + V4L2_PIX_FMT_SBGGR10ALAW8, + V4L2_PIX_FMT_SGBRG10ALAW8, + V4L2_PIX_FMT_SGRBG10ALAW8, + V4L2_PIX_FMT_SRGGB10ALAW8, + V4L2_PIX_FMT_SBGGR10DPCM8, + V4L2_PIX_FMT_SGBRG10DPCM8, + V4L2_PIX_FMT_SGRBG10DPCM8, + V4L2_PIX_FMT_SRGGB10DPCM8, + V4L2_PIX_FMT_SBGGR12, + V4L2_PIX_FMT_SGBRG12, + V4L2_PIX_FMT_SGRBG12, + V4L2_PIX_FMT_SRGGB12, +}; + struct vimc_cap_device { struct vimc_ent_device ved; struct video_device vdev; @@ -101,29 +127,25 @@ static int vimc_cap_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct v4l2_pix_format *format = &f->fmt.pix; - const struct vimc_pix_map *vpix; format->width = clamp_t(u32, format->width, VIMC_FRAME_MIN_WIDTH, VIMC_FRAME_MAX_WIDTH) & ~1; format->height = clamp_t(u32, format->height, VIMC_FRAME_MIN_HEIGHT, VIMC_FRAME_MAX_HEIGHT) & ~1; - /* Don't accept a pixelformat that is not on the table */ - vpix = vimc_pix_map_by_pixelformat(format->pixelformat); - if (!vpix) { - format->pixelformat = fmt_default.pixelformat; - vpix = vimc_pix_map_by_pixelformat(format->pixelformat); - } - /* TODO: Add support for custom bytesperline values */ - format->bytesperline = format->width * vpix->bpp; - format->sizeimage = format->bytesperline * format->height; + vimc_colorimetry_clamp(format); if (format->field == V4L2_FIELD_ANY) format->field = fmt_default.field; - vimc_colorimetry_clamp(format); + /* TODO: Add support for custom bytesperline values */ - return 0; + /* Don't accept a pixelformat that is not on the table */ + if (!v4l2_format_info(format->pixelformat)) + format->pixelformat = fmt_default.pixelformat; + + return v4l2_fill_pixfmt(format, format->pixelformat, + format->width, format->height); } static int vimc_cap_s_fmt_vid_cap(struct file *file, void *priv, @@ -159,27 +181,31 @@ static int vimc_cap_s_fmt_vid_cap(struct file *file, void *priv, static int vimc_cap_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - const struct vimc_pix_map *vpix = vimc_pix_map_by_index(f->index); - - if (!vpix) + if (f->index >= ARRAY_SIZE(vimc_cap_supported_pixfmt)) return -EINVAL; - f->pixelformat = vpix->pixelformat; + f->pixelformat = vimc_cap_supported_pixfmt[f->index]; return 0; } +static bool vimc_cap_is_pixfmt_supported(u32 pixelformat) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(vimc_cap_supported_pixfmt); i++) + if (vimc_cap_supported_pixfmt[i] == pixelformat) + return true; + return false; +} + static int vimc_cap_enum_framesizes(struct file *file, void *fh, struct v4l2_frmsizeenum *fsize) { - const struct vimc_pix_map *vpix; - if (fsize->index) return -EINVAL; - /* Only accept code in the pix map table */ - vpix = vimc_pix_map_by_code(fsize->pixel_format); - if (!vpix) + if (!vimc_cap_is_pixfmt_supported(fsize->pixel_format)) return -EINVAL; fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; @@ -253,6 +279,7 @@ static int vimc_cap_start_streaming(struct vb2_queue *vq, unsigned int count) return ret; } + vcap->stream.producer_pixfmt = vcap->format.pixelformat; ret = vimc_streamer_s_stream(&vcap->stream, &vcap->ved, 1); if (ret) { media_pipeline_stop(entity); @@ -403,7 +430,6 @@ static int vimc_cap_comp_bind(struct device *comp, struct device *master, { struct v4l2_device *v4l2_dev = master_data; struct vimc_platform_data *pdata = comp->platform_data; - const struct vimc_pix_map *vpix; struct vimc_cap_device *vcap; struct video_device *vdev; struct vb2_queue *q; @@ -458,10 +484,8 @@ static int vimc_cap_comp_bind(struct device *comp, struct device *master, /* Set default frame format */ vcap->format = fmt_default; - vpix = vimc_pix_map_by_pixelformat(vcap->format.pixelformat); - vcap->format.bytesperline = vcap->format.width * vpix->bpp; - vcap->format.sizeimage = vcap->format.bytesperline * - vcap->format.height; + v4l2_fill_pixfmt(&vcap->format, vcap->format.pixelformat, + vcap->format.width, vcap->format.height); /* Fill the vimc_ent_device struct */ vcap->ved.ent = &vcap->vdev.entity; diff --git a/drivers/media/platform/vimc/vimc-common.c b/drivers/media/platform/vimc/vimc-common.c index e8e6c6b95db9..fad7c7c6de93 100644 --- a/drivers/media/platform/vimc/vimc-common.c +++ b/drivers/media/platform/vimc/vimc-common.c @@ -20,192 +20,139 @@ #include "vimc-common.h" -/* - * NOTE: non-bayer formats need to come first (necessary for enum_mbus_code - * in the scaler) - */ -static const struct vimc_pix_map vimc_pix_map_list[] = { - /* TODO: add all missing formats */ - - /* RGB formats */ - { - .code = MEDIA_BUS_FMT_BGR888_1X24, - .pixelformat = V4L2_PIX_FMT_BGR24, - .bpp = 3, - .bayer = false, - }, - { - .code = MEDIA_BUS_FMT_RGB888_1X24, - .pixelformat = V4L2_PIX_FMT_RGB24, - .bpp = 3, - .bayer = false, - }, - { - .code = MEDIA_BUS_FMT_ARGB8888_1X32, - .pixelformat = V4L2_PIX_FMT_ARGB32, - .bpp = 4, - .bayer = false, - }, - - /* Bayer formats */ - { - .code = MEDIA_BUS_FMT_SBGGR8_1X8, - .pixelformat = V4L2_PIX_FMT_SBGGR8, - .bpp = 1, - .bayer = true, - }, - { - .code = MEDIA_BUS_FMT_SGBRG8_1X8, - .pixelformat = V4L2_PIX_FMT_SGBRG8, - .bpp = 1, - .bayer = true, - }, - { - .code = MEDIA_BUS_FMT_SGRBG8_1X8, - .pixelformat = V4L2_PIX_FMT_SGRBG8, - .bpp = 1, - .bayer = true, - }, - { - .code = MEDIA_BUS_FMT_SRGGB8_1X8, - .pixelformat = V4L2_PIX_FMT_SRGGB8, - .bpp = 1, - .bayer = true, - }, - { - .code = MEDIA_BUS_FMT_SBGGR10_1X10, - .pixelformat = V4L2_PIX_FMT_SBGGR10, - .bpp = 2, - .bayer = true, - }, - { - .code = MEDIA_BUS_FMT_SGBRG10_1X10, - .pixelformat = V4L2_PIX_FMT_SGBRG10, - .bpp = 2, - .bayer = true, - }, - { - .code = MEDIA_BUS_FMT_SGRBG10_1X10, - .pixelformat = V4L2_PIX_FMT_SGRBG10, - .bpp = 2, - .bayer = true, - }, - { - .code = MEDIA_BUS_FMT_SRGGB10_1X10, - .pixelformat = V4L2_PIX_FMT_SRGGB10, - .bpp = 2, - .bayer = true, - }, - - /* 10bit raw bayer a-law compressed to 8 bits */ - { - .code = MEDIA_BUS_FMT_SBGGR10_ALAW8_1X8, - .pixelformat = V4L2_PIX_FMT_SBGGR10ALAW8, - .bpp = 1, - .bayer = true, - }, - { - .code = MEDIA_BUS_FMT_SGBRG10_ALAW8_1X8, - .pixelformat = V4L2_PIX_FMT_SGBRG10ALAW8, - .bpp = 1, - .bayer = true, - }, - { - .code = MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8, - .pixelformat = V4L2_PIX_FMT_SGRBG10ALAW8, - .bpp = 1, - .bayer = true, - }, - { - .code = MEDIA_BUS_FMT_SRGGB10_ALAW8_1X8, - .pixelformat = V4L2_PIX_FMT_SRGGB10ALAW8, - .bpp = 1, - .bayer = true, - }, - - /* 10bit raw bayer DPCM compressed to 8 bits */ - { - .code = MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8, - .pixelformat = V4L2_PIX_FMT_SBGGR10DPCM8, - .bpp = 1, - .bayer = true, - }, - { - .code = MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8, - .pixelformat = V4L2_PIX_FMT_SGBRG10DPCM8, - .bpp = 1, - .bayer = true, - }, - { - .code = MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, - .pixelformat = V4L2_PIX_FMT_SGRBG10DPCM8, - .bpp = 1, - .bayer = true, - }, - { - .code = MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8, - .pixelformat = V4L2_PIX_FMT_SRGGB10DPCM8, - .bpp = 1, - .bayer = true, - }, - { - .code = MEDIA_BUS_FMT_SBGGR12_1X12, - .pixelformat = V4L2_PIX_FMT_SBGGR12, - .bpp = 2, - .bayer = true, - }, - { - .code = MEDIA_BUS_FMT_SGBRG12_1X12, - .pixelformat = V4L2_PIX_FMT_SGBRG12, - .bpp = 2, - .bayer = true, - }, - { - .code = MEDIA_BUS_FMT_SGRBG12_1X12, - .pixelformat = V4L2_PIX_FMT_SGRBG12, - .bpp = 2, - .bayer = true, - }, - { - .code = MEDIA_BUS_FMT_SRGGB12_1X12, - .pixelformat = V4L2_PIX_FMT_SRGGB12, - .bpp = 2, - .bayer = true, - }, +static const __u32 vimc_mbus_list[] = { + MEDIA_BUS_FMT_FIXED, + MEDIA_BUS_FMT_RGB444_1X12, + MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE, + MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE, + MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE, + MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, + MEDIA_BUS_FMT_RGB565_1X16, + MEDIA_BUS_FMT_BGR565_2X8_BE, + MEDIA_BUS_FMT_BGR565_2X8_LE, + MEDIA_BUS_FMT_RGB565_2X8_BE, + MEDIA_BUS_FMT_RGB565_2X8_LE, + MEDIA_BUS_FMT_RGB666_1X18, + MEDIA_BUS_FMT_RBG888_1X24, + MEDIA_BUS_FMT_RGB666_1X24_CPADHI, + MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, + MEDIA_BUS_FMT_BGR888_1X24, + MEDIA_BUS_FMT_GBR888_1X24, + MEDIA_BUS_FMT_RGB888_1X24, + MEDIA_BUS_FMT_RGB888_2X12_BE, + MEDIA_BUS_FMT_RGB888_2X12_LE, + MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, + MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, + MEDIA_BUS_FMT_ARGB8888_1X32, + MEDIA_BUS_FMT_RGB888_1X32_PADHI, + MEDIA_BUS_FMT_RGB101010_1X30, + MEDIA_BUS_FMT_RGB121212_1X36, + MEDIA_BUS_FMT_RGB161616_1X48, + MEDIA_BUS_FMT_Y8_1X8, + MEDIA_BUS_FMT_UV8_1X8, + MEDIA_BUS_FMT_UYVY8_1_5X8, + MEDIA_BUS_FMT_VYUY8_1_5X8, + MEDIA_BUS_FMT_YUYV8_1_5X8, + MEDIA_BUS_FMT_YVYU8_1_5X8, + MEDIA_BUS_FMT_UYVY8_2X8, + MEDIA_BUS_FMT_VYUY8_2X8, + MEDIA_BUS_FMT_YUYV8_2X8, + MEDIA_BUS_FMT_YVYU8_2X8, + MEDIA_BUS_FMT_Y10_1X10, + MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, + MEDIA_BUS_FMT_UYVY10_2X10, + MEDIA_BUS_FMT_VYUY10_2X10, + MEDIA_BUS_FMT_YUYV10_2X10, + MEDIA_BUS_FMT_YVYU10_2X10, + MEDIA_BUS_FMT_Y12_1X12, + MEDIA_BUS_FMT_UYVY12_2X12, + MEDIA_BUS_FMT_VYUY12_2X12, + MEDIA_BUS_FMT_YUYV12_2X12, + MEDIA_BUS_FMT_YVYU12_2X12, + MEDIA_BUS_FMT_UYVY8_1X16, + MEDIA_BUS_FMT_VYUY8_1X16, + MEDIA_BUS_FMT_YUYV8_1X16, + MEDIA_BUS_FMT_YVYU8_1X16, + MEDIA_BUS_FMT_YDYUYDYV8_1X16, + MEDIA_BUS_FMT_UYVY10_1X20, + MEDIA_BUS_FMT_VYUY10_1X20, + MEDIA_BUS_FMT_YUYV10_1X20, + MEDIA_BUS_FMT_YVYU10_1X20, + MEDIA_BUS_FMT_VUY8_1X24, + MEDIA_BUS_FMT_YUV8_1X24, + MEDIA_BUS_FMT_UYYVYY8_0_5X24, + MEDIA_BUS_FMT_UYVY12_1X24, + MEDIA_BUS_FMT_VYUY12_1X24, + MEDIA_BUS_FMT_YUYV12_1X24, + MEDIA_BUS_FMT_YVYU12_1X24, + MEDIA_BUS_FMT_YUV10_1X30, + MEDIA_BUS_FMT_UYYVYY10_0_5X30, + MEDIA_BUS_FMT_AYUV8_1X32, + MEDIA_BUS_FMT_UYYVYY12_0_5X36, + MEDIA_BUS_FMT_YUV12_1X36, + MEDIA_BUS_FMT_YUV16_1X48, + MEDIA_BUS_FMT_UYYVYY16_0_5X48, + MEDIA_BUS_FMT_SBGGR8_1X8, + MEDIA_BUS_FMT_SGBRG8_1X8, + MEDIA_BUS_FMT_SGRBG8_1X8, + MEDIA_BUS_FMT_SRGGB8_1X8, + MEDIA_BUS_FMT_SBGGR10_ALAW8_1X8, + MEDIA_BUS_FMT_SGBRG10_ALAW8_1X8, + MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8, + MEDIA_BUS_FMT_SRGGB10_ALAW8_1X8, + MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8, + MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8, + MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, + MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8, + MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE, + MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, + MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE, + MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE, + MEDIA_BUS_FMT_SBGGR10_1X10, + MEDIA_BUS_FMT_SGBRG10_1X10, + MEDIA_BUS_FMT_SGRBG10_1X10, + MEDIA_BUS_FMT_SRGGB10_1X10, + MEDIA_BUS_FMT_SBGGR12_1X12, + MEDIA_BUS_FMT_SGBRG12_1X12, + MEDIA_BUS_FMT_SGRBG12_1X12, + MEDIA_BUS_FMT_SRGGB12_1X12, + MEDIA_BUS_FMT_SBGGR14_1X14, + MEDIA_BUS_FMT_SGBRG14_1X14, + MEDIA_BUS_FMT_SGRBG14_1X14, + MEDIA_BUS_FMT_SRGGB14_1X14, + MEDIA_BUS_FMT_SBGGR16_1X16, + MEDIA_BUS_FMT_SGBRG16_1X16, + MEDIA_BUS_FMT_SGRBG16_1X16, + MEDIA_BUS_FMT_SRGGB16_1X16, + MEDIA_BUS_FMT_JPEG_1X8, + MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8, + MEDIA_BUS_FMT_AHSV8888_1X32, }; -const struct vimc_pix_map *vimc_pix_map_by_index(unsigned int i) -{ - if (i >= ARRAY_SIZE(vimc_pix_map_list)) - return NULL; - - return &vimc_pix_map_list[i]; -} -EXPORT_SYMBOL_GPL(vimc_pix_map_by_index); - -const struct vimc_pix_map *vimc_pix_map_by_code(u32 code) +/* Helper function to check mbus codes */ +bool vimc_mbus_code_supported(__u32 code) { unsigned int i; - for (i = 0; i < ARRAY_SIZE(vimc_pix_map_list); i++) { - if (vimc_pix_map_list[i].code == code) - return &vimc_pix_map_list[i]; - } - return NULL; + for (i = 0; i < ARRAY_SIZE(vimc_mbus_list); i++) + if (code == vimc_mbus_list[i]) + return true; + return false; } -EXPORT_SYMBOL_GPL(vimc_pix_map_by_code); +EXPORT_SYMBOL_GPL(vimc_mbus_code_supported); -const struct vimc_pix_map *vimc_pix_map_by_pixelformat(u32 pixelformat) +/* Helper function to enumerate mbus codes */ +int vimc_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) { - unsigned int i; + if (code->index >= ARRAY_SIZE(vimc_mbus_list)) + return -EINVAL; - for (i = 0; i < ARRAY_SIZE(vimc_pix_map_list); i++) { - if (vimc_pix_map_list[i].pixelformat == pixelformat) - return &vimc_pix_map_list[i]; - } - return NULL; + code->code = vimc_mbus_list[code->index]; + return 0; } -EXPORT_SYMBOL_GPL(vimc_pix_map_by_pixelformat); +EXPORT_SYMBOL_GPL(vimc_enum_mbus_code); /* Helper function to allocate and initialize pads */ struct media_pad *vimc_pads_init(u16 num_pads, const unsigned long *pads_flag) @@ -277,15 +224,13 @@ static int vimc_get_mbus_format(struct media_pad *pad, struct video_device, entity); struct vimc_ent_device *ved = video_get_drvdata(vdev); - const struct vimc_pix_map *vpix; struct v4l2_pix_format vdev_fmt; if (!ved->vdev_get_format) return -ENOIOCTLCMD; ved->vdev_get_format(ved, &vdev_fmt); - vpix = vimc_pix_map_by_pixelformat(vdev_fmt.pixelformat); - v4l2_fill_mbus_format(&fmt->format, &vdev_fmt, vpix->code); + v4l2_fill_mbus_format(&fmt->format, &vdev_fmt, 0); } else { return -EINVAL; } @@ -325,8 +270,12 @@ int vimc_link_validate(struct media_link *link) /* The width, height and code must match. */ if (source_fmt.format.width != sink_fmt.format.width || source_fmt.format.height != sink_fmt.format.height - || source_fmt.format.code != sink_fmt.format.code) + || (source_fmt.format.code && sink_fmt.format.code && + source_fmt.format.code != sink_fmt.format.code)) { + pr_err("vimc: format doesn't match in link %s->%s\n", + link->source->entity->name, link->sink->entity->name); return -EPIPE; + } /* * The field order must match, or the sink field order must be NONE diff --git a/drivers/media/platform/vimc/vimc-common.h b/drivers/media/platform/vimc/vimc-common.h index c439cbf2f030..142ddfa69b3d 100644 --- a/drivers/media/platform/vimc/vimc-common.h +++ b/drivers/media/platform/vimc/vimc-common.h @@ -22,6 +22,8 @@ #include #include +#include "vimc-streamer.h" + #define VIMC_PDEV_NAME "vimc" /* VIMC-specific controls */ @@ -77,23 +79,6 @@ struct vimc_platform_data { char entity_name[32]; }; -/** - * struct vimc_pix_map - maps media bus code with v4l2 pixel format - * - * @code: media bus format code defined by MEDIA_BUS_FMT_* macros - * @bbp: number of bytes each pixel occupies - * @pixelformat: pixel format devined by V4L2_PIX_FMT_* macros - * - * Struct which matches the MEDIA_BUS_FMT_* codes with the corresponding - * V4L2_PIX_FMT_* fourcc pixelformat and its bytes per pixel (bpp) - */ -struct vimc_pix_map { - unsigned int code; - unsigned int bpp; - u32 pixelformat; - bool bayer; -}; - /** * struct vimc_ent_device - core struct that represents a node in the topology * @@ -115,12 +100,30 @@ struct vimc_pix_map { struct vimc_ent_device { struct media_entity *ent; struct media_pad *pads; + struct vimc_stream *stream; void * (*process_frame)(struct vimc_ent_device *ved, const void *frame); void (*vdev_get_format)(struct vimc_ent_device *ved, struct v4l2_pix_format *fmt); }; +/** + * vimc_mbus_code_supported - helper to check supported mbus codes + * + * Helper function to check if mbus code is enumerated by vimc_enum_mbus_code() + */ +bool vimc_mbus_code_supported(__u32 code); + +/** + * vimc_enum_mbus_code - enumerate mbus codes + * + * Helper function to be pluged in .enum_mbus_code from + * struct v4l2_subdev_pad_ops. + */ +int vimc_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code); + /** * vimc_pads_init - initialize pads * @@ -155,27 +158,6 @@ static inline void vimc_pads_cleanup(struct media_pad *pads) */ int vimc_pipeline_s_stream(struct media_entity *ent, int enable); -/** - * vimc_pix_map_by_index - get vimc_pix_map struct by its index - * - * @i: index of the vimc_pix_map struct in vimc_pix_map_list - */ -const struct vimc_pix_map *vimc_pix_map_by_index(unsigned int i); - -/** - * vimc_pix_map_by_code - get vimc_pix_map struct by media bus code - * - * @code: media bus format code defined by MEDIA_BUS_FMT_* macros - */ -const struct vimc_pix_map *vimc_pix_map_by_code(u32 code); - -/** - * vimc_pix_map_by_pixelformat - get vimc_pix_map struct by v4l2 pixel format - * - * @pixelformat: pixel format devined by V4L2_PIX_FMT_* macros - */ -const struct vimc_pix_map *vimc_pix_map_by_pixelformat(u32 pixelformat); - /** * vimc_ent_sd_register - initialize and register a subdev node * diff --git a/drivers/media/platform/vimc/vimc-debayer.c b/drivers/media/platform/vimc/vimc-debayer.c index 20826f209731..281f9c1a7249 100644 --- a/drivers/media/platform/vimc/vimc-debayer.c +++ b/drivers/media/platform/vimc/vimc-debayer.c @@ -26,6 +26,9 @@ #include "vimc-common.h" #define VIMC_DEB_DRV_NAME "vimc-debayer" +/* This module only supports tranforming a bayer format to V4L2_PIX_FMT_RGB24 */ +#define VIMC_DEB_SRC_PIXFMT V4L2_PIX_FMT_RGB24 +#define VIMC_DEB_SRC_MBUS_FMT_DEFAULT MEDIA_BUS_FMT_RGB888_1X24 static unsigned int deb_mean_win_size = 3; module_param(deb_mean_win_size, uint, 0000); @@ -44,6 +47,7 @@ enum vimc_deb_rgb_colors { }; struct vimc_deb_pix_map { + u32 pixelformat; u32 code; enum vimc_deb_rgb_colors order[2][2]; }; @@ -73,61 +77,73 @@ static const struct v4l2_mbus_framefmt sink_fmt_default = { static const struct vimc_deb_pix_map vimc_deb_pix_map_list[] = { { + .pixelformat = V4L2_PIX_FMT_SBGGR8, .code = MEDIA_BUS_FMT_SBGGR8_1X8, .order = { { VIMC_DEB_BLUE, VIMC_DEB_GREEN }, { VIMC_DEB_GREEN, VIMC_DEB_RED } } }, { + .pixelformat = V4L2_PIX_FMT_SGBRG8, .code = MEDIA_BUS_FMT_SGBRG8_1X8, .order = { { VIMC_DEB_GREEN, VIMC_DEB_BLUE }, { VIMC_DEB_RED, VIMC_DEB_GREEN } } }, { + .pixelformat = V4L2_PIX_FMT_SGRBG8, .code = MEDIA_BUS_FMT_SGRBG8_1X8, .order = { { VIMC_DEB_GREEN, VIMC_DEB_RED }, { VIMC_DEB_BLUE, VIMC_DEB_GREEN } } }, { + .pixelformat = V4L2_PIX_FMT_SRGGB8, .code = MEDIA_BUS_FMT_SRGGB8_1X8, .order = { { VIMC_DEB_RED, VIMC_DEB_GREEN }, { VIMC_DEB_GREEN, VIMC_DEB_BLUE } } }, { + .pixelformat = V4L2_PIX_FMT_SBGGR10, .code = MEDIA_BUS_FMT_SBGGR10_1X10, .order = { { VIMC_DEB_BLUE, VIMC_DEB_GREEN }, { VIMC_DEB_GREEN, VIMC_DEB_RED } } }, { + .pixelformat = V4L2_PIX_FMT_SGBRG10, .code = MEDIA_BUS_FMT_SGBRG10_1X10, .order = { { VIMC_DEB_GREEN, VIMC_DEB_BLUE }, { VIMC_DEB_RED, VIMC_DEB_GREEN } } }, { + .pixelformat = V4L2_PIX_FMT_SGRBG10, .code = MEDIA_BUS_FMT_SGRBG10_1X10, .order = { { VIMC_DEB_GREEN, VIMC_DEB_RED }, { VIMC_DEB_BLUE, VIMC_DEB_GREEN } } }, { + .pixelformat = V4L2_PIX_FMT_SRGGB10, .code = MEDIA_BUS_FMT_SRGGB10_1X10, .order = { { VIMC_DEB_RED, VIMC_DEB_GREEN }, { VIMC_DEB_GREEN, VIMC_DEB_BLUE } } }, { + .pixelformat = V4L2_PIX_FMT_SBGGR12, .code = MEDIA_BUS_FMT_SBGGR12_1X12, .order = { { VIMC_DEB_BLUE, VIMC_DEB_GREEN }, { VIMC_DEB_GREEN, VIMC_DEB_RED } } }, { + .pixelformat = V4L2_PIX_FMT_SGBRG12, .code = MEDIA_BUS_FMT_SGBRG12_1X12, .order = { { VIMC_DEB_GREEN, VIMC_DEB_BLUE }, { VIMC_DEB_RED, VIMC_DEB_GREEN } } }, { + .pixelformat = V4L2_PIX_FMT_SGRBG12, .code = MEDIA_BUS_FMT_SGRBG12_1X12, .order = { { VIMC_DEB_GREEN, VIMC_DEB_RED }, { VIMC_DEB_BLUE, VIMC_DEB_GREEN } } }, { + .pixelformat = V4L2_PIX_FMT_SRGGB12, .code = MEDIA_BUS_FMT_SRGGB12_1X12, .order = { { VIMC_DEB_RED, VIMC_DEB_GREEN }, { VIMC_DEB_GREEN, VIMC_DEB_BLUE } } @@ -168,41 +184,32 @@ static int vimc_deb_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code) { - /* We only support one format for source pads */ - if (IS_SRC(code->pad)) { - struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd); - - if (code->index) - return -EINVAL; - - code->code = vdeb->src_code; - } else { + /* For the sink pad we only support codes in the map_list */ + if (IS_SINK(code->pad)) { if (code->index >= ARRAY_SIZE(vimc_deb_pix_map_list)) return -EINVAL; code->code = vimc_deb_pix_map_list[code->index].code; + return 0; } - return 0; + return vimc_enum_mbus_code(sd, cfg, code); } static int vimc_deb_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_frame_size_enum *fse) { - struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd); - if (fse->index) return -EINVAL; + /* For the sink pad we only support codes in the map_list */ if (IS_SINK(fse->pad)) { const struct vimc_deb_pix_map *vpix = vimc_deb_pix_map_by_code(fse->code); if (!vpix) return -EINVAL; - } else if (fse->code != vdeb->src_code) { - return -EINVAL; } fse->min_width = VIMC_FRAME_MIN_WIDTH; @@ -258,6 +265,9 @@ static int vimc_deb_set_fmt(struct v4l2_subdev *sd, struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *sink_fmt; + if (!vimc_mbus_code_supported(fmt->format.code)) + fmt->format.code = sink_fmt_default.code; + if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { /* Do not change the format while stream is on */ if (vdeb->src_frame) @@ -270,11 +280,11 @@ static int vimc_deb_set_fmt(struct v4l2_subdev *sd, /* * Do not change the format of the source pad, - * it is propagated from the sink + * it is propagated from the sink (except for the code) */ if (IS_SRC(fmt->pad)) { + vdeb->src_code = fmt->format.code; fmt->format = *sink_fmt; - /* TODO: Add support for other formats */ fmt->format.code = vdeb->src_code; } else { /* Set the new format in the sink pad */ @@ -306,7 +316,7 @@ static const struct v4l2_subdev_pad_ops vimc_deb_pad_ops = { .set_fmt = vimc_deb_set_fmt, }; -static void vimc_deb_set_rgb_mbus_fmt_rgb888_1x24(struct vimc_deb_device *vdeb, +static void vimc_deb_set_rgb_pix_rgb24(struct vimc_deb_device *vdeb, unsigned int lin, unsigned int col, unsigned int rgb[3]) @@ -323,25 +333,38 @@ static int vimc_deb_s_stream(struct v4l2_subdev *sd, int enable) struct vimc_deb_device *vdeb = v4l2_get_subdevdata(sd); if (enable) { - const struct vimc_pix_map *vpix; + u32 src_pixelformat = vdeb->ved.stream->producer_pixfmt; + const struct v4l2_format_info *pix_info; unsigned int frame_size; if (vdeb->src_frame) return 0; - /* Calculate the frame size of the source pad */ - vpix = vimc_pix_map_by_code(vdeb->src_code); - frame_size = vdeb->sink_fmt.width * vdeb->sink_fmt.height * - vpix->bpp; - - /* Save the bytes per pixel of the sink */ - vpix = vimc_pix_map_by_code(vdeb->sink_fmt.code); - vdeb->sink_bpp = vpix->bpp; + /* We only support translating bayer to RGB24 */ + if (src_pixelformat != V4L2_PIX_FMT_RGB24) { + dev_err(vdeb->dev, + "translating to pixfmt (0x%08x) is not supported\n", + src_pixelformat); + return -EINVAL; + } /* Get the corresponding pixel map from the table */ vdeb->sink_pix_map = vimc_deb_pix_map_by_code(vdeb->sink_fmt.code); + /* Request bayer format from the pipeline for the sink pad */ + vdeb->ved.stream->producer_pixfmt = + vdeb->sink_pix_map->pixelformat; + + /* Calculate frame_size of the source */ + pix_info = v4l2_format_info(src_pixelformat); + frame_size = vdeb->sink_fmt.width * vdeb->sink_fmt.height * + pix_info->bpp[0]; + + /* Get bpp from the sink */ + pix_info = v4l2_format_info(vdeb->sink_pix_map->pixelformat); + vdeb->sink_bpp = pix_info->bpp[0]; + /* * Allocate the frame buffer. Use vmalloc to be able to * allocate a large amount of memory @@ -542,14 +565,14 @@ static int vimc_deb_comp_bind(struct device *comp, struct device *master, /* Initialize the frame format */ vdeb->sink_fmt = sink_fmt_default; + vdeb->src_code = VIMC_DEB_SRC_MBUS_FMT_DEFAULT; /* * TODO: Add support for more output formats, we only support - * RGB888 for now + * RGB24 for now. * NOTE: the src format is always the same as the sink, except * for the code */ - vdeb->src_code = MEDIA_BUS_FMT_RGB888_1X24; - vdeb->set_rgb_src = vimc_deb_set_rgb_mbus_fmt_rgb888_1x24; + vdeb->set_rgb_src = vimc_deb_set_rgb_pix_rgb24; return 0; } diff --git a/drivers/media/platform/vimc/vimc-scaler.c b/drivers/media/platform/vimc/vimc-scaler.c index 2028afa4ef7a..8aecf8e92031 100644 --- a/drivers/media/platform/vimc/vimc-scaler.c +++ b/drivers/media/platform/vimc/vimc-scaler.c @@ -35,6 +35,12 @@ MODULE_PARM_DESC(sca_mult, " the image size multiplier"); #define IS_SRC(pad) (pad) #define MAX_ZOOM 8 +static const u32 vimc_sca_supported_pixfmt[] = { + V4L2_PIX_FMT_BGR24, + V4L2_PIX_FMT_RGB24, + V4L2_PIX_FMT_ARGB32, +}; + struct vimc_sca_device { struct vimc_ent_device ved; struct v4l2_subdev sd; @@ -57,6 +63,16 @@ static const struct v4l2_mbus_framefmt sink_fmt_default = { .colorspace = V4L2_COLORSPACE_DEFAULT, }; +static bool vimc_sca_is_pixfmt_supported(u32 pixelformat) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(vimc_sca_supported_pixfmt); i++) + if (vimc_sca_supported_pixfmt[i] == pixelformat) + return true; + return false; +} + static int vimc_sca_init_cfg(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg) { @@ -76,35 +92,13 @@ static int vimc_sca_init_cfg(struct v4l2_subdev *sd, return 0; } -static int vimc_sca_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code) -{ - const struct vimc_pix_map *vpix = vimc_pix_map_by_index(code->index); - - /* We don't support bayer format */ - if (!vpix || vpix->bayer) - return -EINVAL; - - code->code = vpix->code; - - return 0; -} - static int vimc_sca_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_frame_size_enum *fse) { - const struct vimc_pix_map *vpix; - if (fse->index) return -EINVAL; - /* Only accept code in the pix map table in non bayer format */ - vpix = vimc_pix_map_by_code(fse->code); - if (!vpix || vpix->bayer) - return -EINVAL; - fse->min_width = VIMC_FRAME_MIN_WIDTH; fse->min_height = VIMC_FRAME_MIN_HEIGHT; @@ -141,13 +135,6 @@ static int vimc_sca_get_fmt(struct v4l2_subdev *sd, static void vimc_sca_adjust_sink_fmt(struct v4l2_mbus_framefmt *fmt) { - const struct vimc_pix_map *vpix; - - /* Only accept code in the pix map table in non bayer format */ - vpix = vimc_pix_map_by_code(fmt->code); - if (!vpix || vpix->bayer) - fmt->code = sink_fmt_default.code; - fmt->width = clamp_t(u32, fmt->width, VIMC_FRAME_MIN_WIDTH, VIMC_FRAME_MAX_WIDTH) & ~1; fmt->height = clamp_t(u32, fmt->height, VIMC_FRAME_MIN_HEIGHT, @@ -166,6 +153,9 @@ static int vimc_sca_set_fmt(struct v4l2_subdev *sd, struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *sink_fmt; + if (!vimc_mbus_code_supported(fmt->format.code)) + fmt->format.code = sink_fmt_default.code; + if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { /* Do not change the format while stream is on */ if (vsca->src_frame) @@ -208,7 +198,7 @@ static int vimc_sca_set_fmt(struct v4l2_subdev *sd, static const struct v4l2_subdev_pad_ops vimc_sca_pad_ops = { .init_cfg = vimc_sca_init_cfg, - .enum_mbus_code = vimc_sca_enum_mbus_code, + .enum_mbus_code = vimc_enum_mbus_code, .enum_frame_size = vimc_sca_enum_frame_size, .get_fmt = vimc_sca_get_fmt, .set_fmt = vimc_sca_set_fmt, @@ -219,15 +209,22 @@ static int vimc_sca_s_stream(struct v4l2_subdev *sd, int enable) struct vimc_sca_device *vsca = v4l2_get_subdevdata(sd); if (enable) { - const struct vimc_pix_map *vpix; + u32 pixelformat = vsca->ved.stream->producer_pixfmt; + const struct v4l2_format_info *pix_info; unsigned int frame_size; if (vsca->src_frame) return 0; + if (!vimc_sca_is_pixfmt_supported(pixelformat)) { + dev_err(vsca->dev, "pixfmt (0x%08x) is not supported\n", + pixelformat); + return -EINVAL; + } + /* Save the bytes per pixel of the sink */ - vpix = vimc_pix_map_by_code(vsca->sink_fmt.code); - vsca->bpp = vpix->bpp; + pix_info = v4l2_format_info(pixelformat); + vsca->bpp = pix_info->bpp[0]; /* Calculate the width in bytes of the src frame */ vsca->src_line_size = vsca->sink_fmt.width * diff --git a/drivers/media/platform/vimc/vimc-sensor.c b/drivers/media/platform/vimc/vimc-sensor.c index d7891d3bbeaa..081e54204c9f 100644 --- a/drivers/media/platform/vimc/vimc-sensor.c +++ b/drivers/media/platform/vimc/vimc-sensor.c @@ -65,34 +65,13 @@ static int vimc_sen_init_cfg(struct v4l2_subdev *sd, return 0; } -static int vimc_sen_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code) -{ - const struct vimc_pix_map *vpix = vimc_pix_map_by_index(code->index); - - if (!vpix) - return -EINVAL; - - code->code = vpix->code; - - return 0; -} - static int vimc_sen_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_frame_size_enum *fse) { - const struct vimc_pix_map *vpix; - if (fse->index) return -EINVAL; - /* Only accept code in the pix map table */ - vpix = vimc_pix_map_by_code(fse->code); - if (!vpix) - return -EINVAL; - fse->min_width = VIMC_FRAME_MIN_WIDTH; fse->max_width = VIMC_FRAME_MAX_WIDTH; fse->min_height = VIMC_FRAME_MIN_HEIGHT; @@ -117,14 +96,17 @@ static int vimc_sen_get_fmt(struct v4l2_subdev *sd, static void vimc_sen_tpg_s_format(struct vimc_sen_device *vsen) { - const struct vimc_pix_map *vpix = - vimc_pix_map_by_code(vsen->mbus_format.code); + u32 pixelformat = vsen->ved.stream->producer_pixfmt; + const struct v4l2_format_info *pix_info; + + pix_info = v4l2_format_info(pixelformat); tpg_reset_source(&vsen->tpg, vsen->mbus_format.width, vsen->mbus_format.height, vsen->mbus_format.field); - tpg_s_bytesperline(&vsen->tpg, 0, vsen->mbus_format.width * vpix->bpp); + tpg_s_bytesperline(&vsen->tpg, 0, + vsen->mbus_format.width * pix_info->bpp[0]); tpg_s_buf_height(&vsen->tpg, vsen->mbus_format.height); - tpg_s_fourcc(&vsen->tpg, vpix->pixelformat); + tpg_s_fourcc(&vsen->tpg, pixelformat); /* TODO: add support for V4L2_FIELD_ALTERNATE */ tpg_s_field(&vsen->tpg, vsen->mbus_format.field, false); tpg_s_colorspace(&vsen->tpg, vsen->mbus_format.colorspace); @@ -135,13 +117,6 @@ static void vimc_sen_tpg_s_format(struct vimc_sen_device *vsen) static void vimc_sen_adjust_fmt(struct v4l2_mbus_framefmt *fmt) { - const struct vimc_pix_map *vpix; - - /* Only accept code in the pix map table */ - vpix = vimc_pix_map_by_code(fmt->code); - if (!vpix) - fmt->code = fmt_default.code; - fmt->width = clamp_t(u32, fmt->width, VIMC_FRAME_MIN_WIDTH, VIMC_FRAME_MAX_WIDTH) & ~1; fmt->height = clamp_t(u32, fmt->height, VIMC_FRAME_MIN_HEIGHT, @@ -161,6 +136,9 @@ static int vimc_sen_set_fmt(struct v4l2_subdev *sd, struct vimc_sen_device *vsen = v4l2_get_subdevdata(sd); struct v4l2_mbus_framefmt *mf; + if (!vimc_mbus_code_supported(fmt->format.code)) + fmt->format.code = fmt_default.code; + if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { /* Do not change the format while stream is on */ if (vsen->frame) @@ -193,7 +171,7 @@ static int vimc_sen_set_fmt(struct v4l2_subdev *sd, static const struct v4l2_subdev_pad_ops vimc_sen_pad_ops = { .init_cfg = vimc_sen_init_cfg, - .enum_mbus_code = vimc_sen_enum_mbus_code, + .enum_mbus_code = vimc_enum_mbus_code, .enum_frame_size = vimc_sen_enum_frame_size, .get_fmt = vimc_sen_get_fmt, .set_fmt = vimc_sen_set_fmt, @@ -215,7 +193,8 @@ static int vimc_sen_s_stream(struct v4l2_subdev *sd, int enable) container_of(sd, struct vimc_sen_device, sd); if (enable) { - const struct vimc_pix_map *vpix; + u32 pixelformat = vsen->ved.stream->producer_pixfmt; + const struct v4l2_format_info *pix_info; unsigned int frame_size; if (vsen->kthread_sen) @@ -223,8 +202,8 @@ static int vimc_sen_s_stream(struct v4l2_subdev *sd, int enable) return 0; /* Calculate the frame size */ - vpix = vimc_pix_map_by_code(vsen->mbus_format.code); - frame_size = vsen->mbus_format.width * vpix->bpp * + pix_info = v4l2_format_info(pixelformat); + frame_size = vsen->mbus_format.width * pix_info->bpp[0] * vsen->mbus_format.height; /* diff --git a/drivers/media/platform/vimc/vimc-streamer.c b/drivers/media/platform/vimc/vimc-streamer.c index 6fc18fea2e45..26b674259489 100644 --- a/drivers/media/platform/vimc/vimc-streamer.c +++ b/drivers/media/platform/vimc/vimc-streamer.c @@ -52,6 +52,7 @@ static void vimc_streamer_pipeline_terminate(struct vimc_stream *stream) while (stream->pipe_size) { stream->pipe_size--; ved = stream->ved_pipeline[stream->pipe_size]; + ved->stream = NULL; stream->ved_pipeline[stream->pipe_size] = NULL; if (!is_media_entity_v4l2_subdev(ved->ent)) @@ -87,6 +88,7 @@ static int vimc_streamer_pipeline_init(struct vimc_stream *stream, return -EINVAL; } stream->ved_pipeline[stream->pipe_size++] = ved; + ved->stream = stream; if (is_media_entity_v4l2_subdev(ved->ent)) { sd = media_entity_to_v4l2_subdev(ved->ent); diff --git a/drivers/media/platform/vimc/vimc-streamer.h b/drivers/media/platform/vimc/vimc-streamer.h index a7c5ac5ace4f..2b3667408794 100644 --- a/drivers/media/platform/vimc/vimc-streamer.h +++ b/drivers/media/platform/vimc/vimc-streamer.h @@ -25,6 +25,11 @@ * processed in the pipeline. * @pipe_size: size of @ved_pipeline * @kthread: thread that generates the frames of the stream. + * @producer_pixfmt: the pixel format requested from the pipeline. This must + * be set just before calling vimc_streamer_s_stream(ent, 1). This value is + * propagated up to the source of the base image (usually a sensor node) and + * can be modified by entities during s_stream callback to request a different + * format from rest of the pipeline. * * When the user call stream_on in a video device, struct vimc_stream is * used to keep track of all entities and subdevices that generates and @@ -35,6 +40,7 @@ struct vimc_stream { struct vimc_ent_device *ved_pipeline[VIMC_STREAMER_PIPELINE_MAX_SIZE]; unsigned int pipe_size; struct task_struct *kthread; + u32 producer_pixfmt; }; /** From 27c8e733c03812173380d55049b886db4dc89fe5 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 19 Mar 2019 12:36:22 -0400 Subject: [PATCH 149/218] media: staging: media: imx: imx7-mipi-csis: simplify getting .driver_data We should get 'driver_data' from 'struct device' directly. Going via platform_device is an unneeded step back and forth. Signed-off-by: Wolfram Sang Reviewed-by: Rui Miguel Silva Reviewed-by: Simon Horman Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx7-mipi-csis.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c index 6cae2960eea1..19455f425416 100644 --- a/drivers/staging/media/imx/imx7-mipi-csis.c +++ b/drivers/staging/media/imx/imx7-mipi-csis.c @@ -1027,8 +1027,7 @@ disable_clock: static int mipi_csis_pm_suspend(struct device *dev, bool runtime) { - struct platform_device *pdev = to_platform_device(dev); - struct v4l2_subdev *mipi_sd = platform_get_drvdata(pdev); + struct v4l2_subdev *mipi_sd = dev_get_drvdata(dev); struct csi_state *state = mipi_sd_to_csis_state(mipi_sd); int ret = 0; @@ -1052,8 +1051,7 @@ unlock: static int mipi_csis_pm_resume(struct device *dev, bool runtime) { - struct platform_device *pdev = to_platform_device(dev); - struct v4l2_subdev *mipi_sd = platform_get_drvdata(pdev); + struct v4l2_subdev *mipi_sd = dev_get_drvdata(dev); struct csi_state *state = mipi_sd_to_csis_state(mipi_sd); int ret = 0; From b4ccd7fd062a0b8514a6f04cdd8f8cbb336a3f65 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Tue, 26 Mar 2019 12:12:19 -0400 Subject: [PATCH 150/218] media: dt-bindings: media: Renesas R-Car IMR bindings The image renderer (IMR), or the distortion correction engine, is a drawing processor with a simple instruction system capable of referencing video capture data or data in an external memory as the 2D texture data and performing texture mapping and drawing with respect to any shape that is split into triangular objects. Document the device tree bindings for the image renderer light extended 4 (IMR-LX4) found in the R-Car gen3 SoCs... Signed-off-by: Sergei Shtylyov Acked-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/rcar_imr.txt | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/rcar_imr.txt diff --git a/Documentation/devicetree/bindings/media/rcar_imr.txt b/Documentation/devicetree/bindings/media/rcar_imr.txt new file mode 100644 index 000000000000..b0614153ed36 --- /dev/null +++ b/Documentation/devicetree/bindings/media/rcar_imr.txt @@ -0,0 +1,31 @@ +Renesas R-Car Image Renderer (Distortion Correction Engine) +----------------------------------------------------------- + +The image renderer, or the distortion correction engine, is a drawing processor +with a simple instruction system capable of referencing video capture data or +data in an external memory as 2D texture data and performing texture mapping +and drawing with respect to any shape that is split into triangular objects. + +Required properties: + +- compatible: "renesas,-imr-lx4", "renesas,imr-lx4" as a fallback for + the image renderer light extended 4 (IMR-LX4) found in the R-Car gen3 SoCs, + where the examples with are: + - "renesas,r8a7795-imr-lx4" for R-Car H3, + - "renesas,r8a7796-imr-lx4" for R-Car M3-W. +- reg: offset and length of the register block; +- interrupts: single interrupt specifier; +- clocks: single clock phandle/specifier pair; +- power-domains: power domain phandle/specifier pair; +- resets: reset phandle/specifier pair. + +Example: + + imr-lx4@fe860000 { + compatible = "renesas,r8a7795-imr-lx4", "renesas,imr-lx4"; + reg = <0 0xfe860000 0 0x2000>; + interrupts = ; + clocks = <&cpg CPG_MOD 823>; + power-domains = <&sysc R8A7795_PD_A3VC>; + resets = <&cpg 823>; + }; From b105581a1939b08ce70d8aa437ff68a032960b16 Mon Sep 17 00:00:00 2001 From: Yunfei Dong Date: Fri, 29 Mar 2019 04:37:14 -0400 Subject: [PATCH 151/218] media: mtk-vcodec: enlarge struct vdec_pic_info fields Enlarge the plane number to support more complex case and add the support for fmt change case. Signed-off-by: Yunfei Dong Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../platform/mtk-vcodec/mtk_vcodec_dec.c | 62 +++++++++++++------ .../platform/mtk-vcodec/mtk_vcodec_drv.h | 16 ++--- .../platform/mtk-vcodec/vdec/vdec_h264_if.c | 4 +- .../platform/mtk-vcodec/vdec/vdec_vp8_if.c | 4 +- .../platform/mtk-vcodec/vdec/vdec_vp9_if.c | 11 ++-- 5 files changed, 57 insertions(+), 40 deletions(-) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c index 710dcebb42b3..851903867bc9 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c @@ -129,9 +129,9 @@ static struct vb2_buffer *get_display_buffer(struct mtk_vcodec_ctx *ctx) mutex_lock(&ctx->lock); if (dstbuf->used) { vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, - ctx->picinfo.y_bs_sz); + ctx->picinfo.fb_sz[0]); vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1, - ctx->picinfo.c_bs_sz); + ctx->picinfo.fb_sz[1]); mtk_v4l2_debug(2, "[%d]status=%x queue id=%d to done_list %d", @@ -276,6 +276,27 @@ static void mtk_vdec_flush_decoder(struct mtk_vcodec_ctx *ctx) clean_free_buffer(ctx); } +static void mtk_vdec_update_fmt(struct mtk_vcodec_ctx *ctx, + unsigned int pixelformat) +{ + struct mtk_video_fmt *fmt; + struct mtk_q_data *dst_q_data; + unsigned int k; + + dst_q_data = &ctx->q_data[MTK_Q_DATA_DST]; + for (k = 0; k < NUM_FORMATS; k++) { + fmt = &mtk_video_formats[k]; + if (fmt->fourcc == pixelformat) { + mtk_v4l2_debug(1, "Update cap fourcc(%d -> %d)", + dst_q_data->fmt.fourcc, pixelformat); + dst_q_data->fmt = fmt; + return; + } + } + + mtk_v4l2_err("Cannot get fourcc(%d), using init value", pixelformat); +} + static int mtk_vdec_pic_info_update(struct mtk_vcodec_ctx *ctx) { unsigned int dpbsize = 0; @@ -297,6 +318,10 @@ static int mtk_vdec_pic_info_update(struct mtk_vcodec_ctx *ctx) return -EINVAL; } + if (ctx->last_decoded_picinfo.cap_fourcc != ctx->picinfo.cap_fourcc && + ctx->picinfo.cap_fourcc != 0) + mtk_vdec_update_fmt(ctx, ctx->picinfo.cap_fourcc); + if ((ctx->last_decoded_picinfo.pic_w == ctx->picinfo.pic_w) || (ctx->last_decoded_picinfo.pic_h == ctx->picinfo.pic_h)) return 0; @@ -350,11 +375,11 @@ static void mtk_vdec_worker(struct work_struct *work) pfb = &dst_buf_info->frame_buffer; pfb->base_y.va = vb2_plane_vaddr(&dst_buf->vb2_buf, 0); pfb->base_y.dma_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); - pfb->base_y.size = ctx->picinfo.y_bs_sz + ctx->picinfo.y_len_sz; + pfb->base_y.size = ctx->picinfo.fb_sz[0]; pfb->base_c.va = vb2_plane_vaddr(&dst_buf->vb2_buf, 1); pfb->base_c.dma_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 1); - pfb->base_c.size = ctx->picinfo.c_bs_sz + ctx->picinfo.c_len_sz; + pfb->base_c.size = ctx->picinfo.fb_sz[1]; pfb->status = 0; mtk_v4l2_debug(3, "===>[%d] vdec_if_decode() ===>", ctx->id); @@ -974,14 +999,13 @@ static int vidioc_vdec_g_fmt(struct file *file, void *priv, * So we just return picinfo yet, and update picinfo in * stop_streaming hook function */ - q_data->sizeimage[0] = ctx->picinfo.y_bs_sz + - ctx->picinfo.y_len_sz; - q_data->sizeimage[1] = ctx->picinfo.c_bs_sz + - ctx->picinfo.c_len_sz; + q_data->sizeimage[0] = ctx->picinfo.fb_sz[0]; + q_data->sizeimage[1] = ctx->picinfo.fb_sz[1]; q_data->bytesperline[0] = ctx->last_decoded_picinfo.buf_w; q_data->bytesperline[1] = ctx->last_decoded_picinfo.buf_w; q_data->coded_width = ctx->picinfo.buf_w; q_data->coded_height = ctx->picinfo.buf_h; + ctx->last_decoded_picinfo.cap_fourcc = q_data->fmt->fourcc; /* * Width and height are set to the dimensions @@ -1101,10 +1125,11 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) struct mtk_vcodec_mem src_mem; bool res_chg = false; int ret = 0; - unsigned int dpbsize = 1; + unsigned int dpbsize = 1, i = 0; struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct vb2_v4l2_buffer *vb2_v4l2 = NULL; struct mtk_video_dec_buf *buf = NULL; + struct mtk_q_data *dst_q_data; mtk_v4l2_debug(3, "[%d] (%d) id=%d, vb=%p", ctx->id, vb->vb2_queue->type, @@ -1190,21 +1215,18 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) } ctx->last_decoded_picinfo = ctx->picinfo; - ctx->q_data[MTK_Q_DATA_DST].sizeimage[0] = - ctx->picinfo.y_bs_sz + - ctx->picinfo.y_len_sz; - ctx->q_data[MTK_Q_DATA_DST].bytesperline[0] = - ctx->picinfo.buf_w; - ctx->q_data[MTK_Q_DATA_DST].sizeimage[1] = - ctx->picinfo.c_bs_sz + - ctx->picinfo.c_len_sz; - ctx->q_data[MTK_Q_DATA_DST].bytesperline[1] = ctx->picinfo.buf_w; + dst_q_data = &ctx->q_data[MTK_Q_DATA_DST]; + for (i = 0; i < dst_q_data->fmt->num_planes; i++) { + dst_q_data->sizeimage[i] = ctx->picinfo.fb_sz[i]; + dst_q_data->bytesperline[i] = ctx->picinfo.buf_w; + } + mtk_v4l2_debug(2, "[%d] vdec_if_init() OK wxh=%dx%d pic wxh=%dx%d sz[0]=0x%x sz[1]=0x%x", ctx->id, ctx->picinfo.buf_w, ctx->picinfo.buf_h, ctx->picinfo.pic_w, ctx->picinfo.pic_h, - ctx->q_data[MTK_Q_DATA_DST].sizeimage[0], - ctx->q_data[MTK_Q_DATA_DST].sizeimage[1]); + dst_q_data->sizeimage[0], + dst_q_data->sizeimage[1]); ret = vdec_if_get_param(ctx, GET_PARAM_DPB_SIZE, &dpbsize); if (dpbsize == 0) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h index e7e2a108def9..662a84b822af 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h @@ -211,24 +211,20 @@ struct mtk_vcodec_pm { * @pic_h: picture height * @buf_w: picture buffer width (64 aligned up from pic_w) * @buf_h: picture buffer heiht (64 aligned up from pic_h) - * @y_bs_sz: Y bitstream size - * @c_bs_sz: CbCr bitstream size - * @y_len_sz: additional size required to store decompress information for y - * plane - * @c_len_sz: additional size required to store decompress information for cbcr - * plane + * @fb_sz: bitstream size of each plane * E.g. suppose picture size is 176x144, * buffer size will be aligned to 176x160. + * @cap_fourcc: fourcc number(may changed when resolution change) + * @reserved: align struct to 64-bit in order to adjust 32-bit and 64-bit os. */ struct vdec_pic_info { unsigned int pic_w; unsigned int pic_h; unsigned int buf_w; unsigned int buf_h; - unsigned int y_bs_sz; - unsigned int c_bs_sz; - unsigned int y_len_sz; - unsigned int c_len_sz; + unsigned int fb_sz[VIDEO_MAX_PLANES]; + unsigned int cap_fourcc; + unsigned int reserved; }; /** diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c index 02c960c63ac0..cdbcd6909728 100644 --- a/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c +++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c @@ -253,8 +253,8 @@ static void get_pic_info(struct vdec_h264_inst *inst, *pic = inst->vsi->pic; mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)", pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h); - mtk_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz, - pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz); + mtk_vcodec_debug(inst, "fb size: Y(%d), C(%d)", + pic->fb_sz[0], pic->fb_sz[1]); } static void get_crop_info(struct vdec_h264_inst *inst, struct v4l2_rect *cr) diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c index bac3723038de..ba79136421ef 100644 --- a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c +++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c @@ -294,8 +294,8 @@ static void get_pic_info(struct vdec_vp8_inst *inst, struct vdec_pic_info *pic) mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)", pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h); - mtk_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz, - pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz); + mtk_vcodec_debug(inst, "fb size: Y(%d), C(%d)", + pic->fb_sz[0], pic->fb_sz[1]); } static void vp8_dec_finish(struct vdec_vp8_inst *inst) diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c index bc8349bc2e80..6fe83207bbc4 100644 --- a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c +++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c @@ -702,10 +702,8 @@ static void init_all_fb_lists(struct vdec_vp9_inst *inst) static void get_pic_info(struct vdec_vp9_inst *inst, struct vdec_pic_info *pic) { - pic->y_bs_sz = inst->vsi->buf_sz_y_bs; - pic->c_bs_sz = inst->vsi->buf_sz_c_bs; - pic->y_len_sz = inst->vsi->buf_len_sz_y; - pic->c_len_sz = inst->vsi->buf_len_sz_c; + pic->fb_sz[0] = inst->vsi->buf_sz_y_bs + inst->vsi->buf_len_sz_y; + pic->fb_sz[1] = inst->vsi->buf_sz_c_bs + inst->vsi->buf_len_sz_c; pic->pic_w = inst->vsi->pic_w; pic->pic_h = inst->vsi->pic_h; @@ -714,8 +712,9 @@ static void get_pic_info(struct vdec_vp9_inst *inst, struct vdec_pic_info *pic) mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)", pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h); - mtk_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz, - pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz); + mtk_vcodec_debug(inst, "fb size: Y(%d), C(%d)", + pic->fb_sz[0], + pic->fb_sz[1]); } static void get_disp_fb(struct vdec_vp9_inst *inst, struct vdec_fb **out_fb) From 0646d347bdc2aece81e993e01528b14ffe9029b8 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 30 Mar 2019 11:25:03 -0400 Subject: [PATCH 152/218] media: dvb: clean up redundant break statements There are several places where a break statement occurs before a following break statement; these are unnecessary and can be removed to clean up the code a little. Signed-off-by: Colin Ian King Reviewed-by: Mukesh Ojha Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/drxd_hard.c | 30 +++++-------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/drivers/media/dvb-frontends/drxd_hard.c b/drivers/media/dvb-frontends/drxd_hard.c index 0a5b15bee1d7..c597d6fc3046 100644 --- a/drivers/media/dvb-frontends/drxd_hard.c +++ b/drivers/media/dvb-frontends/drxd_hard.c @@ -2263,61 +2263,41 @@ static int DRX_Start(struct drxd_state *state, s32 off) case DRX_CHANNEL_LOW: transmissionParams |= SC_RA_RAM_OP_PARAM_PRIO_LO; status = Write16(state, EC_SB_REG_PRIOR__A, EC_SB_REG_PRIOR_LO, 0x0000); - if (status < 0) - break; break; case DRX_CHANNEL_HIGH: transmissionParams |= SC_RA_RAM_OP_PARAM_PRIO_HI; status = Write16(state, EC_SB_REG_PRIOR__A, EC_SB_REG_PRIOR_HI, 0x0000); - if (status < 0) - break; break; - } switch (p->code_rate_HP) { case FEC_1_2: transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_1_2; - if (state->type_A) { + if (state->type_A) status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C1_2, 0x0000); - if (status < 0) - break; - } break; default: operationMode |= SC_RA_RAM_OP_AUTO_RATE__M; /* fall through */ case FEC_2_3: transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_2_3; - if (state->type_A) { + if (state->type_A) status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C2_3, 0x0000); - if (status < 0) - break; - } break; case FEC_3_4: transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_3_4; - if (state->type_A) { + if (state->type_A) status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C3_4, 0x0000); - if (status < 0) - break; - } break; case FEC_5_6: transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_5_6; - if (state->type_A) { + if (state->type_A) status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C5_6, 0x0000); - if (status < 0) - break; - } break; case FEC_7_8: transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_7_8; - if (state->type_A) { + if (state->type_A) status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C7_8, 0x0000); - if (status < 0) - break; - } break; } if (status < 0) From d8986600dcb6c55027f171334e4705233cdb8919 Mon Sep 17 00:00:00 2001 From: Hugues Fruchet Date: Mon, 1 Apr 2019 04:54:59 -0400 Subject: [PATCH 153/218] media: stm32-dcmi: fix error messages Revisit and add some error messages. Signed-off-by: Hugues Fruchet Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/stm32/stm32-dcmi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c index 098431d927ac..693415cf8518 100644 --- a/drivers/media/platform/stm32/stm32-dcmi.c +++ b/drivers/media/platform/stm32/stm32-dcmi.c @@ -1611,7 +1611,7 @@ static int dcmi_graph_init(struct stm32_dcmi *dcmi) /* Parse the graph to extract a list of subdevice DT nodes. */ ret = dcmi_graph_parse(dcmi, dcmi->dev->of_node); if (ret < 0) { - dev_err(dcmi->dev, "Graph parsing failed\n"); + dev_err(dcmi->dev, "Failed to parse graph\n"); return ret; } @@ -1620,6 +1620,7 @@ static int dcmi_graph_init(struct stm32_dcmi *dcmi) ret = v4l2_async_notifier_add_subdev(&dcmi->notifier, &dcmi->entity.asd); if (ret) { + dev_err(dcmi->dev, "Failed to add subdev notifier\n"); of_node_put(dcmi->entity.node); return ret; } @@ -1628,7 +1629,7 @@ static int dcmi_graph_init(struct stm32_dcmi *dcmi) ret = v4l2_async_notifier_register(&dcmi->v4l2_dev, &dcmi->notifier); if (ret < 0) { - dev_err(dcmi->dev, "Notifier registration failed\n"); + dev_err(dcmi->dev, "Failed to register notifier\n"); v4l2_async_notifier_cleanup(&dcmi->notifier); return ret; } From 1be0a2b702308f16fc1c1a58ada5aba13afc123e Mon Sep 17 00:00:00 2001 From: Hugues Fruchet Date: Mon, 1 Apr 2019 04:55:00 -0400 Subject: [PATCH 154/218] media: stm32-dcmi: do not emit error trace in case of few overrun Report overrun error only when it exceeds a given threshold. Signed-off-by: Hugues Fruchet Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/stm32/stm32-dcmi.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c index 693415cf8518..b63d57cd89e5 100644 --- a/drivers/media/platform/stm32/stm32-dcmi.c +++ b/drivers/media/platform/stm32/stm32-dcmi.c @@ -97,6 +97,8 @@ enum state { #define TIMEOUT_MS 1000 +#define OVERRUN_ERROR_THRESHOLD 3 + struct dcmi_graph_entity { struct device_node *node; @@ -446,11 +448,13 @@ static irqreturn_t dcmi_irq_thread(int irq, void *arg) spin_lock_irq(&dcmi->irqlock); - if ((dcmi->misr & IT_OVR) || (dcmi->misr & IT_ERR)) { - dcmi->errors_count++; - if (dcmi->misr & IT_OVR) - dcmi->overrun_count++; + if (dcmi->misr & IT_OVR) { + dcmi->overrun_count++; + if (dcmi->overrun_count > OVERRUN_ERROR_THRESHOLD) + dcmi->errors_count++; } + if (dcmi->misr & IT_ERR) + dcmi->errors_count++; if (dcmi->sd_format->fourcc == V4L2_PIX_FMT_JPEG && dcmi->misr & IT_FRAME) { From 33dfeb62e23c31619d2197850f7e8b50e8cc5466 Mon Sep 17 00:00:00 2001 From: Hugues Fruchet Date: Mon, 1 Apr 2019 04:56:09 -0400 Subject: [PATCH 155/218] media: stm32-dcmi: fix crash when subdev do not expose any formats Do not access sd_formats[] if num_of_sd_formats is zero, ie subdev sensor didn't expose any formats. Signed-off-by: Hugues Fruchet Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/stm32/stm32-dcmi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c index b63d57cd89e5..906e71b19039 100644 --- a/drivers/media/platform/stm32/stm32-dcmi.c +++ b/drivers/media/platform/stm32/stm32-dcmi.c @@ -831,6 +831,9 @@ static int dcmi_try_fmt(struct stm32_dcmi *dcmi, struct v4l2_format *f, sd_fmt = find_format_by_fourcc(dcmi, pix->pixelformat); if (!sd_fmt) { + if (!dcmi->num_of_sd_formats) + return -ENODATA; + sd_fmt = dcmi->sd_formats[dcmi->num_of_sd_formats - 1]; pix->pixelformat = sd_fmt->fourcc; } @@ -1009,6 +1012,9 @@ static int dcmi_set_sensor_format(struct stm32_dcmi *dcmi, sd_fmt = find_format_by_fourcc(dcmi, pix->pixelformat); if (!sd_fmt) { + if (!dcmi->num_of_sd_formats) + return -ENODATA; + sd_fmt = dcmi->sd_formats[dcmi->num_of_sd_formats - 1]; pix->pixelformat = sd_fmt->fourcc; } From 6e1d824e7a1d324f7fdd276fb7133013109d3764 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Mon, 1 Apr 2019 20:40:19 -0400 Subject: [PATCH 156/218] media: Media Device Allocator API Media Device Allocator API to allows multiple drivers share a media device. This API solves a very common use-case for media devices where one physical device (an USB stick) provides both audio and video. When such media device exposes a standard USB Audio class, a proprietary Video class, two or more independent drivers will share a single physical USB bridge. In such cases, it is necessary to coordinate access to the shared resource. Using this API, drivers can allocate a media device with the shared struct device as the key. Once the media device is allocated by a driver, other drivers can get a reference to it. The media device is released when all the references are released. Signed-off-by: Shuah Khan Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/kapi/mc-core.rst | 41 ++++++++ drivers/media/Makefile | 6 ++ drivers/media/media-dev-allocator.c | 135 +++++++++++++++++++++++++++ include/media/media-dev-allocator.h | 63 +++++++++++++ 4 files changed, 245 insertions(+) create mode 100644 drivers/media/media-dev-allocator.c create mode 100644 include/media/media-dev-allocator.h diff --git a/Documentation/media/kapi/mc-core.rst b/Documentation/media/kapi/mc-core.rst index f930725e0d6b..05bba0b61748 100644 --- a/Documentation/media/kapi/mc-core.rst +++ b/Documentation/media/kapi/mc-core.rst @@ -259,6 +259,45 @@ Subsystems should facilitate link validation by providing subsystem specific helper functions to provide easy access for commonly needed information, and in the end provide a way to use driver-specific callbacks. +Media Controller Device Allocator API +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When the media device belongs to more than one driver, the shared media +device is allocated with the shared struct device as the key for look ups. + +The shared media device should stay in registered state until the last +driver unregisters it. In addition, the media device should be released when +all the references are released. Each driver gets a reference to the media +device during probe, when it allocates the media device. If media device is +already allocated, the allocate API bumps up the refcount and returns the +existing media device. The driver puts the reference back in its disconnect +routine when it calls :c:func:`media_device_delete()`. + +The media device is unregistered and cleaned up from the kref put handler to +ensure that the media device stays in registered state until the last driver +unregisters the media device. + +**Driver Usage** + +Drivers should use the appropriate media-core routines to manage the shared +media device life-time handling the two states: +1. allocate -> register -> delete +2. get reference to already registered device -> delete + +call :c:func:`media_device_delete()` routine to make sure the shared media +device delete is handled correctly. + +**driver probe:** +Call :c:func:`media_device_usb_allocate()` to allocate or get a reference +Call :c:func:`media_device_register()`, if media devnode isn't registered + +**driver disconnect:** +Call :c:func:`media_device_delete()` to free the media_device. Freeing is +handled by the kref put handler. + +API Definitions +^^^^^^^^^^^^^^^ + .. kernel-doc:: include/media/media-device.h .. kernel-doc:: include/media/media-devnode.h @@ -266,3 +305,5 @@ in the end provide a way to use driver-specific callbacks. .. kernel-doc:: include/media/media-entity.h .. kernel-doc:: include/media/media-request.h + +.. kernel-doc:: include/media/media-dev-allocator.h diff --git a/drivers/media/Makefile b/drivers/media/Makefile index 985d35ec6b29..4a330d0e5e40 100644 --- a/drivers/media/Makefile +++ b/drivers/media/Makefile @@ -6,6 +6,12 @@ media-objs := media-device.o media-devnode.o media-entity.o \ media-request.o +ifeq ($(CONFIG_MEDIA_CONTROLLER),y) + ifeq ($(CONFIG_USB),y) + media-objs += media-dev-allocator.o + endif +endif + # # I2C drivers should come before other drivers, otherwise they'll fail # when compiled as builtin drivers diff --git a/drivers/media/media-dev-allocator.c b/drivers/media/media-dev-allocator.c new file mode 100644 index 000000000000..ae17887dec59 --- /dev/null +++ b/drivers/media/media-dev-allocator.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * media-dev-allocator.c - Media Controller Device Allocator API + * + * Copyright (c) 2019 Shuah Khan + * + * Credits: Suggested by Laurent Pinchart + */ + +/* + * This file adds a global refcounted Media Controller Device Instance API. + * A system wide global media device list is managed and each media device + * includes a kref count. The last put on the media device releases the media + * device instance. + * + */ + +#include +#include +#include +#include + +#include +#include + +static LIST_HEAD(media_device_list); +static DEFINE_MUTEX(media_device_lock); + +struct media_device_instance { + struct media_device mdev; + struct module *owner; + struct list_head list; + struct kref refcount; +}; + +static inline struct media_device_instance * +to_media_device_instance(struct media_device *mdev) +{ + return container_of(mdev, struct media_device_instance, mdev); +} + +static void media_device_instance_release(struct kref *kref) +{ + struct media_device_instance *mdi = + container_of(kref, struct media_device_instance, refcount); + + dev_dbg(mdi->mdev.dev, "%s: releasing Media Device\n", __func__); + + mutex_lock(&media_device_lock); + + media_device_unregister(&mdi->mdev); + media_device_cleanup(&mdi->mdev); + + list_del(&mdi->list); + mutex_unlock(&media_device_lock); + + kfree(mdi); +} + +/* Callers should hold media_device_lock when calling this function */ +static struct media_device *__media_device_get(struct device *dev, + const char *module_name, + struct module *owner) +{ + struct media_device_instance *mdi; + + list_for_each_entry(mdi, &media_device_list, list) { + if (mdi->mdev.dev != dev) + continue; + + kref_get(&mdi->refcount); + + /* get module reference for the media_device owner */ + if (owner != mdi->owner && !try_module_get(mdi->owner)) + dev_err(dev, + "%s: module %s get owner reference error\n", + __func__, module_name); + else + dev_dbg(dev, "%s: module %s got owner reference\n", + __func__, module_name); + return &mdi->mdev; + } + + mdi = kzalloc(sizeof(*mdi), GFP_KERNEL); + if (!mdi) + return NULL; + + mdi->owner = owner; + kref_init(&mdi->refcount); + list_add_tail(&mdi->list, &media_device_list); + + dev_dbg(dev, "%s: Allocated media device for owner %s\n", + __func__, module_name); + return &mdi->mdev; +} + +struct media_device *media_device_usb_allocate(struct usb_device *udev, + const char *module_name, + struct module *owner) +{ + struct media_device *mdev; + + mutex_lock(&media_device_lock); + mdev = __media_device_get(&udev->dev, module_name, owner); + if (!mdev) { + mutex_unlock(&media_device_lock); + return ERR_PTR(-ENOMEM); + } + + /* check if media device is already initialized */ + if (!mdev->dev) + __media_device_usb_init(mdev, udev, udev->product, + module_name); + mutex_unlock(&media_device_lock); + return mdev; +} +EXPORT_SYMBOL_GPL(media_device_usb_allocate); + +void media_device_delete(struct media_device *mdev, const char *module_name, + struct module *owner) +{ + struct media_device_instance *mdi = to_media_device_instance(mdev); + + mutex_lock(&media_device_lock); + /* put module reference for the media_device owner */ + if (mdi->owner != owner) { + module_put(mdi->owner); + dev_dbg(mdi->mdev.dev, + "%s: module %s put owner module reference\n", + __func__, module_name); + } + mutex_unlock(&media_device_lock); + kref_put(&mdi->refcount, media_device_instance_release); +} +EXPORT_SYMBOL_GPL(media_device_delete); diff --git a/include/media/media-dev-allocator.h b/include/media/media-dev-allocator.h new file mode 100644 index 000000000000..b35ea6062596 --- /dev/null +++ b/include/media/media-dev-allocator.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * media-dev-allocator.h - Media Controller Device Allocator API + * + * Copyright (c) 2019 Shuah Khan + * + * Credits: Suggested by Laurent Pinchart + */ + +/* + * This file adds a global ref-counted Media Controller Device Instance API. + * A system wide global media device list is managed and each media device + * includes a kref count. The last put on the media device releases the media + * device instance. + */ + +#ifndef _MEDIA_DEV_ALLOCATOR_H +#define _MEDIA_DEV_ALLOCATOR_H + +struct usb_device; + +#if defined(CONFIG_MEDIA_CONTROLLER) && defined(CONFIG_USB) +/** + * media_device_usb_allocate() - Allocate and return struct &media device + * + * @udev: struct &usb_device pointer + * @module_name: should be filled with %KBUILD_MODNAME + * @owner: struct module pointer %THIS_MODULE for the driver. + * %THIS_MODULE is null for a built-in driver. + * It is safe even when %THIS_MODULE is null. + * + * This interface should be called to allocate a Media Device when multiple + * drivers share usb_device and the media device. This interface allocates + * &media_device structure and calls media_device_usb_init() to initialize + * it. + * + */ +struct media_device *media_device_usb_allocate(struct usb_device *udev, + const char *module_name, + struct module *owner); +/** + * media_device_delete() - Release media device. Calls kref_put(). + * + * @mdev: struct &media_device pointer + * @module_name: should be filled with %KBUILD_MODNAME + * @owner: struct module pointer %THIS_MODULE for the driver. + * %THIS_MODULE is null for a built-in driver. + * It is safe even when %THIS_MODULE is null. + * + * This interface should be called to put Media Device Instance kref. + */ +void media_device_delete(struct media_device *mdev, const char *module_name, + struct module *owner); +#else +static inline struct media_device *media_device_usb_allocate( + struct usb_device *udev, const char *module_name, + struct module *owner) + { return NULL; } +static inline void media_device_delete( + struct media_device *mdev, const char *module_name, + struct module *owner) { } +#endif /* CONFIG_MEDIA_CONTROLLER && CONFIG_USB */ +#endif /* _MEDIA_DEV_ALLOCATOR_H */ From 812658d88d26721079fb76afb037669b9c280028 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Mon, 1 Apr 2019 20:40:20 -0400 Subject: [PATCH 157/218] media: change au0828 to use Media Device Allocator API Media Device Allocator API to allows multiple drivers share a media device. This API solves a very common use-case for media devices where one physical device (an USB stick) provides both audio and video. When such media device exposes a standard USB Audio class, a proprietary Video class, two or more independent drivers will share a single physical USB bridge. In such cases, it is necessary to coordinate access to the shared resource. Using this API, drivers can allocate a media device with the shared struct device as the key. Once the media device is allocated by a driver, other drivers can get a reference to it. The media device is released when all the references are released. Change au0828 to use Media Device Allocator API to allocate media device with the parent usb struct device as the key, so it can be shared with the snd_usb_audio driver. Signed-off-by: Shuah Khan Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/Kconfig | 2 ++ drivers/media/usb/au0828/au0828-core.c | 13 +++++-------- drivers/media/usb/au0828/au0828.h | 1 + 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/media/usb/au0828/Kconfig b/drivers/media/usb/au0828/Kconfig index ab4092bdff69..0ad985542c60 100644 --- a/drivers/media/usb/au0828/Kconfig +++ b/drivers/media/usb/au0828/Kconfig @@ -2,6 +2,8 @@ config VIDEO_AU0828 tristate "Auvitek AU0828 support" depends on I2C && INPUT && DVB_CORE && USB && VIDEO_V4L2 + select MEDIA_CONTROLLER + select MEDIA_CONTROLLER_DVB select I2C_ALGOBIT select VIDEO_TVEEPROM select VIDEOBUF2_VMALLOC if VIDEO_V4L2 diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index 3f8c92a70116..4f8ba6f64d3c 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -155,9 +155,7 @@ static void au0828_unregister_media_device(struct au0828_dev *dev) dev->media_dev->disable_source = NULL; mutex_unlock(&mdev->graph_mutex); - media_device_unregister(dev->media_dev); - media_device_cleanup(dev->media_dev); - kfree(dev->media_dev); + media_device_delete(dev->media_dev, KBUILD_MODNAME, THIS_MODULE); dev->media_dev = NULL; #endif } @@ -210,14 +208,10 @@ static int au0828_media_device_init(struct au0828_dev *dev, #ifdef CONFIG_MEDIA_CONTROLLER struct media_device *mdev; - mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + mdev = media_device_usb_allocate(udev, KBUILD_MODNAME, THIS_MODULE); if (!mdev) return -ENOMEM; - /* check if media device is already initialized */ - if (!mdev->dev) - media_device_usb_init(mdev, udev, udev->product); - dev->media_dev = mdev; #endif return 0; @@ -480,6 +474,9 @@ static int au0828_media_device_register(struct au0828_dev *dev, /* register media device */ ret = media_device_register(dev->media_dev); if (ret) { + media_device_delete(dev->media_dev, KBUILD_MODNAME, + THIS_MODULE); + dev->media_dev = NULL; dev_err(&udev->dev, "Media Device Register Error: %d\n", ret); return ret; diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h index 425c35d16057..57b00de8d3f2 100644 --- a/drivers/media/usb/au0828/au0828.h +++ b/drivers/media/usb/au0828/au0828.h @@ -31,6 +31,7 @@ #include #include #include +#include /* DVB */ #include From e377d3e98e70ecd72b3eda158428d88c36881224 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Mon, 1 Apr 2019 20:40:21 -0400 Subject: [PATCH 158/218] media: media.h: Enable ALSA MEDIA_INTF_T* interface types Move PCM_CAPTURE, PCM_PLAYBACK, and CONTROL ALSA MEDIA_INTF_T* interface types back into __KERNEL__ scope to get ready for adding ALSA support for these to the media controller. Signed-off-by: Shuah Khan Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/uapi/linux/media.h | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index e5d0c5c611b5..9aedb187bc48 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -262,6 +262,11 @@ struct media_links_enum { #define MEDIA_INTF_T_V4L_SWRADIO (MEDIA_INTF_T_V4L_BASE + 4) #define MEDIA_INTF_T_V4L_TOUCH (MEDIA_INTF_T_V4L_BASE + 5) +#define MEDIA_INTF_T_ALSA_BASE 0x00000300 +#define MEDIA_INTF_T_ALSA_PCM_CAPTURE (MEDIA_INTF_T_ALSA_BASE) +#define MEDIA_INTF_T_ALSA_PCM_PLAYBACK (MEDIA_INTF_T_ALSA_BASE + 1) +#define MEDIA_INTF_T_ALSA_CONTROL (MEDIA_INTF_T_ALSA_BASE + 2) + #if defined(__KERNEL__) /* @@ -413,19 +418,19 @@ struct media_v2_topology { #define MEDIA_ENT_F_DTV_DECODER MEDIA_ENT_F_DV_DECODER /* - * There is still no ALSA support in the media controller. These + * There is still no full ALSA support in the media controller. These * defines should not have been added and we leave them here only * in case some application tries to use these defines. + * + * The ALSA defines that are in use have been moved into __KERNEL__ + * scope. As support gets added to these interface types, they should + * be moved into __KERNEL__ scope with the code that uses them. */ -#define MEDIA_INTF_T_ALSA_BASE 0x00000300 -#define MEDIA_INTF_T_ALSA_PCM_CAPTURE (MEDIA_INTF_T_ALSA_BASE) -#define MEDIA_INTF_T_ALSA_PCM_PLAYBACK (MEDIA_INTF_T_ALSA_BASE + 1) -#define MEDIA_INTF_T_ALSA_CONTROL (MEDIA_INTF_T_ALSA_BASE + 2) -#define MEDIA_INTF_T_ALSA_COMPRESS (MEDIA_INTF_T_ALSA_BASE + 3) -#define MEDIA_INTF_T_ALSA_RAWMIDI (MEDIA_INTF_T_ALSA_BASE + 4) -#define MEDIA_INTF_T_ALSA_HWDEP (MEDIA_INTF_T_ALSA_BASE + 5) -#define MEDIA_INTF_T_ALSA_SEQUENCER (MEDIA_INTF_T_ALSA_BASE + 6) -#define MEDIA_INTF_T_ALSA_TIMER (MEDIA_INTF_T_ALSA_BASE + 7) +#define MEDIA_INTF_T_ALSA_COMPRESS (MEDIA_INTF_T_ALSA_BASE + 3) +#define MEDIA_INTF_T_ALSA_RAWMIDI (MEDIA_INTF_T_ALSA_BASE + 4) +#define MEDIA_INTF_T_ALSA_HWDEP (MEDIA_INTF_T_ALSA_BASE + 5) +#define MEDIA_INTF_T_ALSA_SEQUENCER (MEDIA_INTF_T_ALSA_BASE + 6) +#define MEDIA_INTF_T_ALSA_TIMER (MEDIA_INTF_T_ALSA_BASE + 7) /* Obsolete symbol for media_version, no longer used in the kernel */ #define MEDIA_API_VERSION ((0 << 16) | (1 << 8) | 0) From 66354f18fe5fbb65f7b10a519654013d6df09f80 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Mon, 1 Apr 2019 20:40:22 -0400 Subject: [PATCH 159/218] media: sound/usb: Use Media Controller API to share media resources Media Device Allocator API to allows multiple drivers share a media device. This API solves a very common use-case for media devices where one physical device (an USB stick) provides both audio and video. When such media device exposes a standard USB Audio class, a proprietary Video class, two or more independent drivers will share a single physical USB bridge. In such cases, it is necessary to coordinate access to the shared resource. Using this API, drivers can allocate a media device with the shared struct device as the key. Once the media device is allocated by a driver, other drivers can get a reference to it. The media device is released when all the references are released. Change the ALSA driver to use the Media Controller API to share media resources with DVB, and V4L2 drivers on a AU0828 media device. The Media Controller specific initialization is done after sound card is registered. ALSA creates Media interface and entity function graph nodes for Control, Mixer, PCM Playback, and PCM Capture devices. snd_usb_hw_params() will call Media Controller enable source handler interface to request the media resource. If resource request is granted, it will release it from snd_usb_hw_free(). If resource is busy, -EBUSY is returned. Media specific cleanup is done in usb_audio_disconnect(). Reviewed-by: Takashi Iwai Signed-off-by: Shuah Khan Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- sound/usb/Kconfig | 4 + sound/usb/Makefile | 2 + sound/usb/card.c | 14 ++ sound/usb/card.h | 3 + sound/usb/media.c | 327 +++++++++++++++++++++++++++++++++++++++ sound/usb/media.h | 74 +++++++++ sound/usb/mixer.h | 3 + sound/usb/pcm.c | 29 +++- sound/usb/quirks-table.h | 1 + sound/usb/stream.c | 2 + sound/usb/usbaudio.h | 6 + 11 files changed, 461 insertions(+), 4 deletions(-) create mode 100644 sound/usb/media.c create mode 100644 sound/usb/media.h diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index f61b5662bb89..6319b544ba3a 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig @@ -15,6 +15,7 @@ config SND_USB_AUDIO select SND_RAWMIDI select SND_PCM select BITREVERSE + select SND_USB_AUDIO_USE_MEDIA_CONTROLLER if MEDIA_CONTROLLER && (MEDIA_SUPPORT=y || MEDIA_SUPPORT=SND_USB_AUDIO) help Say Y here to include support for USB audio and USB MIDI devices. @@ -22,6 +23,9 @@ config SND_USB_AUDIO To compile this driver as a module, choose M here: the module will be called snd-usb-audio. +config SND_USB_AUDIO_USE_MEDIA_CONTROLLER + bool + config SND_USB_UA101 tristate "Edirol UA-101/UA-1000 driver" select SND_PCM diff --git a/sound/usb/Makefile b/sound/usb/Makefile index d330f74c90e6..e1ce257ab705 100644 --- a/sound/usb/Makefile +++ b/sound/usb/Makefile @@ -18,6 +18,8 @@ snd-usb-audio-objs := card.o \ quirks.o \ stream.o +snd-usb-audio-$(CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER) += media.o + snd-usbmidi-lib-objs := midi.o # Toplevel Module Dependency diff --git a/sound/usb/card.c b/sound/usb/card.c index 719e10034553..04465d581204 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -68,6 +68,7 @@ #include "format.h" #include "power.h" #include "stream.h" +#include "media.h" MODULE_AUTHOR("Takashi Iwai "); MODULE_DESCRIPTION("USB Audio"); @@ -673,6 +674,11 @@ static int usb_audio_probe(struct usb_interface *intf, if (err < 0) goto __error; + if (quirk && quirk->shares_media_device) { + /* don't want to fail when snd_media_device_create() fails */ + snd_media_device_create(chip, intf); + } + usb_chip[chip->index] = chip; chip->num_interfaces++; usb_set_intfdata(intf, chip); @@ -732,6 +738,14 @@ static void usb_audio_disconnect(struct usb_interface *intf) list_for_each(p, &chip->midi_list) { snd_usbmidi_disconnect(p); } + /* + * Nice to check quirk && quirk->shares_media_device and + * then call the snd_media_device_delete(). Don't have + * access to the quirk here. snd_media_device_delete() + * accesses mixer_list + */ + snd_media_device_delete(chip); + /* release mixer resources */ list_for_each_entry(mixer, &chip->mixer_list, list) { snd_usb_mixer_disconnect(mixer); diff --git a/sound/usb/card.h b/sound/usb/card.h index 79fa2a19fb7b..2991b9986f66 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -109,6 +109,8 @@ struct snd_usb_endpoint { struct list_head list; }; +struct media_ctl; + struct snd_usb_substream { struct snd_usb_stream *stream; struct usb_device *dev; @@ -161,6 +163,7 @@ struct snd_usb_substream { } dsd_dop; bool trigger_tstamp_pending_update; /* trigger timestamp being updated from initial estimate */ + struct media_ctl *media_ctl; }; struct snd_usb_stream { diff --git a/sound/usb/media.c b/sound/usb/media.c new file mode 100644 index 000000000000..812017eacbcf --- /dev/null +++ b/sound/usb/media.c @@ -0,0 +1,327 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * media.c - Media Controller specific ALSA driver code + * + * Copyright (c) 2019 Shuah Khan + * + */ + +/* + * This file adds Media Controller support to the ALSA driver + * to use the Media Controller API to share the tuner with DVB + * and V4L2 drivers that control the media device. + * + * The media device is created based on the existing quirks framework. + * Using this approach, the media controller API usage can be added for + * a specific device. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "usbaudio.h" +#include "card.h" +#include "mixer.h" +#include "media.h" + +int snd_media_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm, + int stream) +{ + struct media_device *mdev; + struct media_ctl *mctl; + struct device *pcm_dev = &pcm->streams[stream].dev; + u32 intf_type; + int ret = 0; + u16 mixer_pad; + struct media_entity *entity; + + mdev = subs->stream->chip->media_dev; + if (!mdev) + return 0; + + if (subs->media_ctl) + return 0; + + /* allocate media_ctl */ + mctl = kzalloc(sizeof(*mctl), GFP_KERNEL); + if (!mctl) + return -ENOMEM; + + mctl->media_dev = mdev; + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + intf_type = MEDIA_INTF_T_ALSA_PCM_PLAYBACK; + mctl->media_entity.function = MEDIA_ENT_F_AUDIO_PLAYBACK; + mctl->media_pad.flags = MEDIA_PAD_FL_SOURCE; + mixer_pad = 1; + } else { + intf_type = MEDIA_INTF_T_ALSA_PCM_CAPTURE; + mctl->media_entity.function = MEDIA_ENT_F_AUDIO_CAPTURE; + mctl->media_pad.flags = MEDIA_PAD_FL_SINK; + mixer_pad = 2; + } + mctl->media_entity.name = pcm->name; + media_entity_pads_init(&mctl->media_entity, 1, &mctl->media_pad); + ret = media_device_register_entity(mctl->media_dev, + &mctl->media_entity); + if (ret) + goto free_mctl; + + mctl->intf_devnode = media_devnode_create(mdev, intf_type, 0, + MAJOR(pcm_dev->devt), + MINOR(pcm_dev->devt)); + if (!mctl->intf_devnode) { + ret = -ENOMEM; + goto unregister_entity; + } + mctl->intf_link = media_create_intf_link(&mctl->media_entity, + &mctl->intf_devnode->intf, + MEDIA_LNK_FL_ENABLED); + if (!mctl->intf_link) { + ret = -ENOMEM; + goto devnode_remove; + } + + /* create link between mixer and audio */ + media_device_for_each_entity(entity, mdev) { + switch (entity->function) { + case MEDIA_ENT_F_AUDIO_MIXER: + ret = media_create_pad_link(entity, mixer_pad, + &mctl->media_entity, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + goto remove_intf_link; + break; + } + } + + subs->media_ctl = mctl; + return 0; + +remove_intf_link: + media_remove_intf_link(mctl->intf_link); +devnode_remove: + media_devnode_remove(mctl->intf_devnode); +unregister_entity: + media_device_unregister_entity(&mctl->media_entity); +free_mctl: + kfree(mctl); + return ret; +} + +void snd_media_stream_delete(struct snd_usb_substream *subs) +{ + struct media_ctl *mctl = subs->media_ctl; + + if (mctl) { + struct media_device *mdev; + + mdev = mctl->media_dev; + if (mdev && media_devnode_is_registered(mdev->devnode)) { + media_devnode_remove(mctl->intf_devnode); + media_device_unregister_entity(&mctl->media_entity); + media_entity_cleanup(&mctl->media_entity); + } + kfree(mctl); + subs->media_ctl = NULL; + } +} + +int snd_media_start_pipeline(struct snd_usb_substream *subs) +{ + struct media_ctl *mctl = subs->media_ctl; + int ret = 0; + + if (!mctl) + return 0; + + mutex_lock(&mctl->media_dev->graph_mutex); + if (mctl->media_dev->enable_source) + ret = mctl->media_dev->enable_source(&mctl->media_entity, + &mctl->media_pipe); + mutex_unlock(&mctl->media_dev->graph_mutex); + return ret; +} + +void snd_media_stop_pipeline(struct snd_usb_substream *subs) +{ + struct media_ctl *mctl = subs->media_ctl; + + if (!mctl) + return; + + mutex_lock(&mctl->media_dev->graph_mutex); + if (mctl->media_dev->disable_source) + mctl->media_dev->disable_source(&mctl->media_entity); + mutex_unlock(&mctl->media_dev->graph_mutex); +} + +static int snd_media_mixer_init(struct snd_usb_audio *chip) +{ + struct device *ctl_dev = &chip->card->ctl_dev; + struct media_intf_devnode *ctl_intf; + struct usb_mixer_interface *mixer; + struct media_device *mdev = chip->media_dev; + struct media_mixer_ctl *mctl; + u32 intf_type = MEDIA_INTF_T_ALSA_CONTROL; + int ret; + + if (!mdev) + return -ENODEV; + + ctl_intf = chip->ctl_intf_media_devnode; + if (!ctl_intf) { + ctl_intf = media_devnode_create(mdev, intf_type, 0, + MAJOR(ctl_dev->devt), + MINOR(ctl_dev->devt)); + if (!ctl_intf) + return -ENOMEM; + chip->ctl_intf_media_devnode = ctl_intf; + } + + list_for_each_entry(mixer, &chip->mixer_list, list) { + + if (mixer->media_mixer_ctl) + continue; + + /* allocate media_mixer_ctl */ + mctl = kzalloc(sizeof(*mctl), GFP_KERNEL); + if (!mctl) + return -ENOMEM; + + mctl->media_dev = mdev; + mctl->media_entity.function = MEDIA_ENT_F_AUDIO_MIXER; + mctl->media_entity.name = chip->card->mixername; + mctl->media_pad[0].flags = MEDIA_PAD_FL_SINK; + mctl->media_pad[1].flags = MEDIA_PAD_FL_SOURCE; + mctl->media_pad[2].flags = MEDIA_PAD_FL_SOURCE; + media_entity_pads_init(&mctl->media_entity, MEDIA_MIXER_PAD_MAX, + mctl->media_pad); + ret = media_device_register_entity(mctl->media_dev, + &mctl->media_entity); + if (ret) { + kfree(mctl); + return ret; + } + + mctl->intf_link = media_create_intf_link(&mctl->media_entity, + &ctl_intf->intf, + MEDIA_LNK_FL_ENABLED); + if (!mctl->intf_link) { + media_device_unregister_entity(&mctl->media_entity); + media_entity_cleanup(&mctl->media_entity); + kfree(mctl); + return -ENOMEM; + } + mctl->intf_devnode = ctl_intf; + mixer->media_mixer_ctl = mctl; + } + return 0; +} + +static void snd_media_mixer_delete(struct snd_usb_audio *chip) +{ + struct usb_mixer_interface *mixer; + struct media_device *mdev = chip->media_dev; + + if (!mdev) + return; + + list_for_each_entry(mixer, &chip->mixer_list, list) { + struct media_mixer_ctl *mctl; + + mctl = mixer->media_mixer_ctl; + if (!mixer->media_mixer_ctl) + continue; + + if (media_devnode_is_registered(mdev->devnode)) { + media_device_unregister_entity(&mctl->media_entity); + media_entity_cleanup(&mctl->media_entity); + } + kfree(mctl); + mixer->media_mixer_ctl = NULL; + } + if (media_devnode_is_registered(mdev->devnode)) + media_devnode_remove(chip->ctl_intf_media_devnode); + chip->ctl_intf_media_devnode = NULL; +} + +int snd_media_device_create(struct snd_usb_audio *chip, + struct usb_interface *iface) +{ + struct media_device *mdev; + struct usb_device *usbdev = interface_to_usbdev(iface); + int ret = 0; + + /* usb-audio driver is probed for each usb interface, and + * there are multiple interfaces per device. Avoid calling + * media_device_usb_allocate() each time usb_audio_probe() + * is called. Do it only once. + */ + if (chip->media_dev) { + mdev = chip->media_dev; + goto snd_mixer_init; + } + + mdev = media_device_usb_allocate(usbdev, KBUILD_MODNAME, THIS_MODULE); + if (IS_ERR(mdev)) + return -ENOMEM; + + /* save media device - avoid lookups */ + chip->media_dev = mdev; + +snd_mixer_init: + /* Create media entities for mixer and control dev */ + ret = snd_media_mixer_init(chip); + /* media_device might be registered, print error and continue */ + if (ret) + dev_err(&usbdev->dev, + "Couldn't create media mixer entities. Error: %d\n", + ret); + + if (!media_devnode_is_registered(mdev->devnode)) { + /* dont'register if snd_media_mixer_init() failed */ + if (ret) + goto create_fail; + + /* register media_device */ + ret = media_device_register(mdev); +create_fail: + if (ret) { + snd_media_mixer_delete(chip); + media_device_delete(mdev, KBUILD_MODNAME, THIS_MODULE); + /* clear saved media_dev */ + chip->media_dev = NULL; + dev_err(&usbdev->dev, + "Couldn't register media device. Error: %d\n", + ret); + return ret; + } + } + + return ret; +} + +void snd_media_device_delete(struct snd_usb_audio *chip) +{ + struct media_device *mdev = chip->media_dev; + struct snd_usb_stream *stream; + + /* release resources */ + list_for_each_entry(stream, &chip->pcm_list, list) { + snd_media_stream_delete(&stream->substream[0]); + snd_media_stream_delete(&stream->substream[1]); + } + + snd_media_mixer_delete(chip); + + if (mdev) { + media_device_delete(mdev, KBUILD_MODNAME, THIS_MODULE); + chip->media_dev = NULL; + } +} diff --git a/sound/usb/media.h b/sound/usb/media.h new file mode 100644 index 000000000000..f5bdec1d602f --- /dev/null +++ b/sound/usb/media.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * media.h - Media Controller specific ALSA driver code + * + * Copyright (c) 2019 Shuah Khan + * + */ + +/* + * This file adds Media Controller support to the ALSA driver + * to use the Media Controller API to share the tuner with DVB + * and V4L2 drivers that control the media device. + * + * The media device is created based on the existing quirks framework. + * Using this approach, the media controller API usage can be added for + * a specific device. + */ +#ifndef __MEDIA_H + +#ifdef CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER + +#include +#include +#include +#include +#include + +struct media_ctl { + struct media_device *media_dev; + struct media_entity media_entity; + struct media_intf_devnode *intf_devnode; + struct media_link *intf_link; + struct media_pad media_pad; + struct media_pipeline media_pipe; +}; + +/* + * One source pad each for SNDRV_PCM_STREAM_CAPTURE and + * SNDRV_PCM_STREAM_PLAYBACK. One for sink pad to link + * to AUDIO Source + */ +#define MEDIA_MIXER_PAD_MAX (SNDRV_PCM_STREAM_LAST + 2) + +struct media_mixer_ctl { + struct media_device *media_dev; + struct media_entity media_entity; + struct media_intf_devnode *intf_devnode; + struct media_link *intf_link; + struct media_pad media_pad[MEDIA_MIXER_PAD_MAX]; + struct media_pipeline media_pipe; +}; + +int snd_media_device_create(struct snd_usb_audio *chip, + struct usb_interface *iface); +void snd_media_device_delete(struct snd_usb_audio *chip); +int snd_media_stream_init(struct snd_usb_substream *subs, struct snd_pcm *pcm, + int stream); +void snd_media_stream_delete(struct snd_usb_substream *subs); +int snd_media_start_pipeline(struct snd_usb_substream *subs); +void snd_media_stop_pipeline(struct snd_usb_substream *subs); +#else +static inline int snd_media_device_create(struct snd_usb_audio *chip, + struct usb_interface *iface) + { return 0; } +static inline void snd_media_device_delete(struct snd_usb_audio *chip) { } +static inline int snd_media_stream_init(struct snd_usb_substream *subs, + struct snd_pcm *pcm, int stream) + { return 0; } +static inline void snd_media_stream_delete(struct snd_usb_substream *subs) { } +static inline int snd_media_start_pipeline(struct snd_usb_substream *subs) + { return 0; } +static inline void snd_media_stop_pipeline(struct snd_usb_substream *subs) { } +#endif +#endif /* __MEDIA_H */ diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index 3d12af8bf191..394cd9107507 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -4,6 +4,8 @@ #include +struct media_mixer_ctl; + struct usb_mixer_interface { struct snd_usb_audio *chip; struct usb_host_interface *hostif; @@ -23,6 +25,7 @@ struct usb_mixer_interface { struct urb *rc_urb; struct usb_ctrlrequest *rc_setup_packet; u8 rc_buffer[6]; + struct media_mixer_ctl *media_mixer_ctl; bool disconnected; }; diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 056af0a57b22..5d8494b2a026 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -35,6 +35,7 @@ #include "pcm.h" #include "clock.h" #include "power.h" +#include "media.h" #define SUBSTREAM_FLAG_DATA_EP_STARTED 0 #define SUBSTREAM_FLAG_SYNC_EP_STARTED 1 @@ -787,6 +788,10 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, struct audioformat *fmt; int ret; + ret = snd_media_start_pipeline(subs); + if (ret) + return ret; + if (snd_usb_use_vmalloc) ret = snd_pcm_lib_alloc_vmalloc_buffer(substream, params_buffer_bytes(hw_params)); @@ -794,7 +799,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); if (ret < 0) - return ret; + goto stop_pipeline; subs->pcm_format = params_format(hw_params); subs->period_bytes = params_period_bytes(hw_params); @@ -808,12 +813,13 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, dev_dbg(&subs->dev->dev, "cannot set format: format = %#x, rate = %d, channels = %d\n", subs->pcm_format, subs->cur_rate, subs->channels); - return -EINVAL; + ret = -EINVAL; + goto stop_pipeline; } ret = snd_usb_lock_shutdown(subs->stream->chip); if (ret < 0) - return ret; + goto stop_pipeline; ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0); if (ret < 0) @@ -829,6 +835,12 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, unlock: snd_usb_unlock_shutdown(subs->stream->chip); + if (ret < 0) + goto stop_pipeline; + return ret; + + stop_pipeline: + snd_media_stop_pipeline(subs); return ret; } @@ -841,6 +853,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) { struct snd_usb_substream *subs = substream->runtime->private_data; + snd_media_stop_pipeline(subs); subs->cur_audiofmt = NULL; subs->cur_rate = 0; subs->period_bytes = 0; @@ -1313,6 +1326,7 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream) struct snd_usb_stream *as = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_usb_substream *subs = &as->substream[direction]; + int ret; subs->interface = -1; subs->altset_idx = 0; @@ -1326,7 +1340,13 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream) subs->dsd_dop.channel = 0; subs->dsd_dop.marker = 1; - return setup_hw_info(runtime, subs); + ret = setup_hw_info(runtime, subs); + if (ret == 0) { + ret = snd_media_stream_init(subs, as->pcm, direction); + if (ret) + snd_usb_autosuspend(subs->stream->chip); + } + return ret; } static int snd_usb_pcm_close(struct snd_pcm_substream *substream) @@ -1337,6 +1357,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream) int ret; stop_endpoints(subs, true); + snd_media_stop_pipeline(subs); if (!as->chip->keep_iface && subs->interface >= 0 && diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 86e80916a029..8cbca137ee6f 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2887,6 +2887,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .product_name = pname, \ .ifnum = QUIRK_ANY_INTERFACE, \ .type = QUIRK_AUDIO_ALIGN_TRANSFER, \ + .shares_media_device = 1, \ } \ } diff --git a/sound/usb/stream.c b/sound/usb/stream.c index d9e3de495c16..9f1623e37fb3 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -38,6 +38,7 @@ #include "clock.h" #include "stream.h" #include "power.h" +#include "media.h" /* * free a substream @@ -55,6 +56,7 @@ static void free_substream(struct snd_usb_substream *subs) } kfree(subs->rate_list.list); kfree(subs->str_pd); + snd_media_stream_delete(subs); } diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index b9faeca645fd..0968a45c8925 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -30,6 +30,9 @@ * */ +struct media_device; +struct media_intf_devnode; + struct snd_usb_audio { int index; struct usb_device *dev; @@ -66,6 +69,8 @@ struct snd_usb_audio { */ struct usb_host_interface *ctrl_intf; /* the audio control interface */ + struct media_device *media_dev; + struct media_intf_devnode *ctl_intf_media_devnode; }; #define usb_audio_err(chip, fmt, args...) \ @@ -117,6 +122,7 @@ struct snd_usb_audio_quirk { const char *profile_name; /* override the card->longname */ int16_t ifnum; uint16_t type; + bool shares_media_device; const void *data; }; From 383b0e5b6ebb087bde22fbb5fcd9d567c5dbdb92 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Mon, 1 Apr 2019 20:40:23 -0400 Subject: [PATCH 160/218] media: au0828: fix enable and disable source audio and video inconsistencies Enable and disable source interfaces aren't consistent in enforcing how video and audio share the tuner resource. Fix these issues to enforce the following rules and allow sharing between audio and video applications. - When DVB is streaming, audio/video/vbi/s-video/composite should find the resource busy. DVB holds the tuner in exclusive mode. - When video/VBI is streaming, audio can share the tuner and vice versa. - v4l2 allows multiple applications to open video device. - Video applications call enable source multiple times during their run-time. Resource should stay locked until the last application releases it. - A shared resource should stay in shared state and locked when it is in use by audio and video. More than one video application is allowed to use the tuner as long as video streaming protocol allows such usage. Resource is released when the last video/audio application releases it. - S-Video and Composite hold the resource in exclusive mode. Signed-off-by: Shuah Khan Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828-core.c | 183 ++++++++++++++++++++----- drivers/media/usb/au0828/au0828.h | 5 +- 2 files changed, 149 insertions(+), 39 deletions(-) diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index 4f8ba6f64d3c..925a80437822 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -272,6 +272,28 @@ create_link: } } +static bool au0828_is_link_shareable(struct media_entity *owner, + struct media_entity *entity) +{ + bool shareable = false; + + /* Tuner link can be shared by audio, video, and VBI */ + switch (owner->function) { + case MEDIA_ENT_F_IO_V4L: + case MEDIA_ENT_F_AUDIO_CAPTURE: + case MEDIA_ENT_F_IO_VBI: + if (entity->function == MEDIA_ENT_F_IO_V4L || + entity->function == MEDIA_ENT_F_AUDIO_CAPTURE || + entity->function == MEDIA_ENT_F_IO_VBI) + shareable = true; + break; + case MEDIA_ENT_F_DTV_DEMOD: + default: + break; + } + return shareable; +} + /* Callers should hold graph_mutex */ static int au0828_enable_source(struct media_entity *entity, struct media_pipeline *pipe) @@ -314,18 +336,20 @@ static int au0828_enable_source(struct media_entity *entity, /* * Default input is tuner and default input_type * is AU0828_VMUX_TELEVISION. - * FIXME: + * * There is a problem when s_input is called to * change the default input. s_input will try to * enable_source before attempting to change the * input on the device, and will end up enabling * default source which is tuner. * - * Additional logic is necessary in au0828 - * to detect that the input has changed and - * enable the right source. + * Additional logic is necessary in au0828 to detect + * that the input has changed and enable the right + * source. au0828 handles this case in its s_input. + * It will disable the old source and enable the new + * source. + * */ - if (dev->input_type == AU0828_VMUX_TELEVISION) find_source = dev->tuner; else if (dev->input_type == AU0828_VMUX_SVIDEO || @@ -338,27 +362,33 @@ static int au0828_enable_source(struct media_entity *entity, } } - /* Is an active link between sink and source */ + /* Is there an active link between sink and source */ if (dev->active_link) { - /* - * If DVB is using the tuner and calling entity is - * audio/video, the following check will be false, - * since sink is different. Result is Busy. - */ - if (dev->active_link->sink->entity == sink && - dev->active_link->source->entity == find_source) { - /* - * Either ALSA or Video own tuner. sink is - * the same for both. Prevent Video stepping - * on ALSA when ALSA owns the source. + if (dev->active_link_owner == entity) { + /* This check is necessary to handle multiple + * enable_source calls from v4l_ioctls during + * the course of video/vbi application run-time. */ - if (dev->active_link_owner != entity && - dev->active_link_owner->function == - MEDIA_ENT_F_AUDIO_CAPTURE) { - pr_debug("ALSA has the tuner\n"); - ret = -EBUSY; - goto end; - } + pr_debug("%s already owns the tuner\n", entity->name); + ret = 0; + goto end; + } else if (au0828_is_link_shareable(dev->active_link_owner, + entity)) { + /* Either ALSA or Video own tuner. Sink is the same + * for both. Allow sharing the active link between + * their common source (tuner) and sink (decoder). + * Starting pipeline between sharing entity and sink + * will fail with pipe mismatch, while owner has an + * active pipeline. Switch pipeline ownership from + * user to owner when owner disables the source. + */ + dev->active_link_shared = true; + /* save the user info to use from disable */ + dev->active_link_user = entity; + dev->active_link_user_pipe = pipe; + pr_debug("%s owns the tuner %s can share!\n", + dev->active_link_owner->name, + entity->name); ret = 0; goto end; } else { @@ -385,7 +415,7 @@ static int au0828_enable_source(struct media_entity *entity, source = found_link->source->entity; ret = __media_entity_setup_link(found_link, MEDIA_LNK_FL_ENABLED); if (ret) { - pr_err("Activate tuner link %s->%s. Error %d\n", + pr_err("Activate link from %s->%s. Error %d\n", source->name, sink->name, ret); goto end; } @@ -395,25 +425,26 @@ static int au0828_enable_source(struct media_entity *entity, pr_err("Start Pipeline: %s->%s Error %d\n", source->name, entity->name, ret); ret = __media_entity_setup_link(found_link, 0); - pr_err("Deactivate link Error %d\n", ret); + if (ret) + pr_err("Deactivate link Error %d\n", ret); goto end; } - /* - * save active link and active link owner to avoid audio - * deactivating video owned link from disable_source and - * vice versa + + /* save link state to allow audio and video share the link + * and not disable the link while the other is using it. + * active_link_owner is used to deactivate the link. */ dev->active_link = found_link; dev->active_link_owner = entity; dev->active_source = source; dev->active_sink = sink; - pr_debug("Enabled Source: %s->%s->%s Ret %d\n", + pr_info("Enabled Source: %s->%s->%s Ret %d\n", dev->active_source->name, dev->active_sink->name, dev->active_link_owner->name, ret); end: - pr_debug("au0828_enable_source() end %s %d %d\n", - entity->name, entity->function, ret); + pr_debug("%s end: ent:%s fnc:%d ret %d\n", + __func__, entity->name, entity->function, ret); return ret; } @@ -432,21 +463,95 @@ static void au0828_disable_source(struct media_entity *entity) if (!dev->active_link) return; - /* link is active - stop pipeline from source (tuner) */ + /* link is active - stop pipeline from source + * (tuner/s-video/Composite) to the entity + * When DVB/s-video/Composite owns tuner, it won't be in + * shared state. + */ if (dev->active_link->sink->entity == dev->active_sink && dev->active_link->source->entity == dev->active_source) { /* - * prevent video from deactivating link when audio - * has active pipeline + * Prevent video from deactivating link when audio + * has active pipeline and vice versa. In addition + * handle the case when more than one video/vbi + * application is sharing the link. */ + bool owner_is_audio = false; + + if (dev->active_link_owner->function == + MEDIA_ENT_F_AUDIO_CAPTURE) + owner_is_audio = true; + + if (dev->active_link_shared) { + pr_debug("Shared link owner %s user %s %d\n", + dev->active_link_owner->name, + entity->name, dev->users); + + /* Handle video device users > 1 + * When audio owns the shared link with + * more than one video users, avoid + * disabling the source and/or switching + * the owner until the last disable_source + * call from video _close(). Use dev->users to + * determine when to switch/disable. + */ + if (dev->active_link_owner != entity) { + /* video device has users > 1 */ + if (owner_is_audio && dev->users > 1) + return; + + dev->active_link_user = NULL; + dev->active_link_user_pipe = NULL; + dev->active_link_shared = false; + return; + } + + /* video owns the link and has users > 1 */ + if (!owner_is_audio && dev->users > 1) + return; + + /* stop pipeline */ + __media_pipeline_stop(dev->active_link_owner); + pr_debug("Pipeline stop for %s\n", + dev->active_link_owner->name); + + ret = __media_pipeline_start( + dev->active_link_user, + dev->active_link_user_pipe); + if (ret) { + pr_err("Start Pipeline: %s->%s %d\n", + dev->active_source->name, + dev->active_link_user->name, + ret); + goto deactivate_link; + } + /* link user is now the owner */ + dev->active_link_owner = dev->active_link_user; + dev->active_link_user = NULL; + dev->active_link_user_pipe = NULL; + dev->active_link_shared = false; + + pr_debug("Pipeline started for %s\n", + dev->active_link_owner->name); + return; + } else if (!owner_is_audio && dev->users > 1) + /* video/vbi owns the link and has users > 1 */ + return; + if (dev->active_link_owner != entity) return; - __media_pipeline_stop(entity); + + /* stop pipeline */ + __media_pipeline_stop(dev->active_link_owner); + pr_debug("Pipeline stop for %s\n", + dev->active_link_owner->name); + +deactivate_link: ret = __media_entity_setup_link(dev->active_link, 0); if (ret) pr_err("Deactivate link Error %d\n", ret); - pr_debug("Disabled Source: %s->%s->%s Ret %d\n", + pr_info("Disabled Source: %s->%s->%s Ret %d\n", dev->active_source->name, dev->active_sink->name, dev->active_link_owner->name, ret); @@ -454,6 +559,8 @@ static void au0828_disable_source(struct media_entity *entity) dev->active_link_owner = NULL; dev->active_source = NULL; dev->active_sink = NULL; + dev->active_link_shared = false; + dev->active_link_user = NULL; } } #endif diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h index 57b00de8d3f2..b47ecc9affd8 100644 --- a/drivers/media/usb/au0828/au0828.h +++ b/drivers/media/usb/au0828/au0828.h @@ -284,9 +284,12 @@ struct au0828_dev { struct media_entity_notify entity_notify; struct media_entity *tuner; struct media_link *active_link; - struct media_entity *active_link_owner; struct media_entity *active_source; struct media_entity *active_sink; + struct media_entity *active_link_owner; + struct media_entity *active_link_user; + struct media_pipeline *active_link_user_pipe; + bool active_link_shared; #endif }; From bc81c1c796c7a3892ccd445f15a32e041c2174d6 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Mon, 1 Apr 2019 20:40:24 -0400 Subject: [PATCH 161/218] media: selftests: media_dev_allocator api test Add a new test for Media Device Allocator API. Media Device Allocator API to allows multiple drivers share a media device. This API solves a very common use-case for media devices where one physical device (an USB stick) provides both audio and video. When such media device exposes a standard USB Audio class, a proprietary Video class, two or more independent drivers will share a single physical USB bridge. In such cases, it is necessary to coordinate access to the shared resource. Using this API, drivers can allocate a media device with the shared struct device as the key. Once the media device is allocated by a driver, other drivers can get a reference to it. The media device is released when all the references are released. This test does a series of unbind/bind tests to make sure media device is released correctly when it is no longer is use and when the last driver releases the reference. Signed-off-by: Shuah Khan Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media_tests/media_dev_allocator.sh | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100755 tools/testing/selftests/media_tests/media_dev_allocator.sh diff --git a/tools/testing/selftests/media_tests/media_dev_allocator.sh b/tools/testing/selftests/media_tests/media_dev_allocator.sh new file mode 100755 index 000000000000..ffe00c59a483 --- /dev/null +++ b/tools/testing/selftests/media_tests/media_dev_allocator.sh @@ -0,0 +1,85 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Media Device Allocator API test script +# Copyright (c) 2019 Shuah Khan + +echo "Media Device Allocator testing: unbind and bind" +echo "media driver $1 audio driver $2" + +MDRIVER=/sys/bus/usb/drivers/$1 +cd $MDRIVER +MDEV=$(ls -d *\-*) + +ADRIVER=/sys/bus/usb/drivers/$2 +cd $ADRIVER +ADEV=$(ls -d *\-*.1) + +echo "==================================" +echo "Test unbind both devices - start" +echo "Running unbind of $MDEV from $MDRIVER" +echo $MDEV > $MDRIVER/unbind; + +echo "Media device should still be present!" +ls -l /dev/media* + +echo "sound driver is at: $ADRIVER" +echo "Device is: $ADEV" + +echo "Running unbind of $ADEV from $ADRIVER" +echo $ADEV > $ADRIVER/unbind; + +echo "Media device should have been deleted!" +ls -l /dev/media* +echo "Test unbind both devices - end" + +echo "==================================" + +echo "Test bind both devices - start" +echo "Running bind of $MDEV from $MDRIVER" +echo $MDEV > $MDRIVER/bind; + +echo "Media device should be present!" +ls -l /dev/media* + +echo "Running bind of $ADEV from $ADRIVER" +echo $ADEV > $ADRIVER/bind; + +echo "Media device should be there!" +ls -l /dev/media* + +echo "Test bind both devices - end" + +echo "==================================" + +echo "Test unbind $MDEV - bind $MDEV - unbind $ADEV - bind $ADEV start" + +echo "Running unbind of $MDEV from $MDRIVER" +echo $MDEV > $MDRIVER/unbind; + +echo "Media device should be there!" +ls -l /dev/media* + +sleep 1 + +echo "Running bind of $MDEV from $MDRIVER" +echo $MDEV > $MDRIVER/bind; + +echo "Media device should be there!" +ls -l /dev/media* + +echo "Running unbind of $ADEV from $ADRIVER" +echo $ADEV > $ADRIVER/unbind; + +echo "Media device should be there!" +ls -l /dev/media* + +sleep 1 + +echo "Running bind of $ADEV from $ADRIVER" +echo $ADEV > $ADRIVER/bind; + +echo "Media device should be there!" +ls -l /dev/media* + +echo "Test unbind $MDEV - bind $MDEV - unbind $ADEV - bind $ADEV end" +echo "==================================" From 898bc40bfcc26abb6e06e960d6d4754c36c58b50 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Mon, 1 Apr 2019 20:43:17 -0400 Subject: [PATCH 162/218] media: au0828: Fix NULL pointer dereference in au0828_analog_stream_enable() Fix au0828_analog_stream_enable() to check if device is in the right state first. When unbind happens while bind is in progress, usbdev pointer could be invalid in au0828_analog_stream_enable() and a call to usb_ifnum_to_if() will result in the null pointer dereference. This problem is found with the new media_dev_allocator.sh test. kernel: [ 590.359623] BUG: unable to handle kernel NULL pointer dereference at 00000000000004e8 kernel: [ 590.359627] #PF error: [normal kernel read fault] kernel: [ 590.359629] PGD 0 P4D 0 kernel: [ 590.359632] Oops: 0000 [#1] SMP PTI kernel: [ 590.359634] CPU: 3 PID: 1458 Comm: v4l_id Not tainted 5.1.0-rc2+ #30 kernel: [ 590.359636] Hardware name: Dell Inc. OptiPlex 7 90/0HY9JP, BIOS A18 09/24/2013 kernel: [ 590.359641] RIP: 0010:usb_ifnum_to_if+0x6/0x60 kernel: [ 590.359643] Code: 5d 41 5e 41 5f 5d c3 48 83 c4 10 b8 fa ff ff ff 5b 41 5c 41 5d 41 5e 41 5f 5d c3 b8 fa ff ff ff c3 0f 1f 00 6 6 66 66 66 90 55 <48> 8b 97 e8 04 00 00 48 89 e5 48 85 d2 74 41 0f b6 4a 04 84 c 9 74 kernel: [ 590.359645] RSP: 0018:ffffad3cc3c1fc00 EFLAGS: 00010246 kernel: [ 590.359646] RAX: 0000000000000000 RBX: ffff8ded b1f3c000 RCX: 1f377e4500000000 kernel: [ 590.359648] RDX: ffff8dedfa3a6b50 RSI: 00000000 00000000 RDI: 0000000000000000 kernel: [ 590.359649] RBP: ffffad3cc3c1fc28 R08: 00000000 8574acc2 R09: ffff8dedfa3a6b50 kernel: [ 590.359650] R10: 0000000000000001 R11: 00000000 00000000 R12: 0000000000000000 kernel: [ 590.359652] R13: ffff8dedb1f3f0f0 R14: ffffffff adcf7ec0 R15: 0000000000000000 kernel: [ 590.359654] FS: 00007f7917198540(0000) GS:ffff 8dee258c0000(0000) knlGS:0000000000000000 kernel: [ 590.359655] CS: 0010 DS: 0000 ES: 0000 CR0: 00 00000080050033 kernel: [ 590.359657] CR2: 00000000000004e8 CR3: 00000001 a388e002 CR4: 00000000000606e0 kernel: [ 590.359658] Call Trace: kernel: [ 590.359664] ? au0828_analog_stream_enable+0x2c/0x180 kernel: [ 590.359666] au0828_v4l2_open+0xa4/0x110 kernel: [ 590.359670] v4l2_open+0x8b/0x120 kernel: [ 590.359674] chrdev_open+0xa6/0x1c0 kernel: [ 590.359676] ? cdev_put.part.3+0x20/0x20 kernel: [ 590.359678] do_dentry_open+0x1f6/0x360 kernel: [ 590.359681] vfs_open+0x2f/0x40 kernel: [ 590.359684] path_openat+0x299/0xc20 kernel: [ 590.359688] do_filp_open+0x9b/0x110 kernel: [ 590.359695] ? _raw_spin_unlock+0x27/0x40 kernel: [ 590.359697] ? __alloc_fd+0xb2/0x160 kernel: [ 590.359700] do_sys_open+0x1ba/0x260 kernel: [ 590.359702] ? do_sys_open+0x1ba/0x260 kernel: [ 590.359712] __x64_sys_openat+0x20/0x30 kernel: [ 590.359715] do_syscall_64+0x5a/0x120 kernel: [ 590.359718] entry_SYSCALL_64_after_hwframe+0x44/0xa9 Signed-off-by: Shuah Khan Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828-video.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index e17047b94b87..536bd8bbb624 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -758,6 +758,9 @@ static int au0828_analog_stream_enable(struct au0828_dev *d) dprintk(1, "au0828_analog_stream_enable called\n"); + if (test_bit(DEV_DISCONNECTED, &d->dev_state)) + return -ENODEV; + iface = usb_ifnum_to_if(d->usbdev, 0); if (iface && iface->cur_altsetting->desc.bAlternateSetting != 5) { dprintk(1, "Changing intf#0 to alt 5\n"); From 10cb050459852fd954a5b38c019d2313f3bfb3e2 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Mon, 1 Apr 2019 20:43:18 -0400 Subject: [PATCH 163/218] media: Clear devnode->media_dev holding media_devnode_lock Fix media_devnode_unregister() to clear devnode->media_dev while holding media_devnode_lock. media_devnode_register()'s cdev_add_error handling does this correctly. Signed-off-by: Shuah Khan Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-devnode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c index 61dc05fcc55c..d5aa30eeff4a 100644 --- a/drivers/media/media-devnode.c +++ b/drivers/media/media-devnode.c @@ -291,8 +291,9 @@ void media_devnode_unregister(struct media_devnode *devnode) mutex_lock(&media_devnode_lock); /* Delete the cdev on this minor as well */ cdev_device_del(&devnode->cdev, &devnode->dev); - mutex_unlock(&media_devnode_lock); devnode->media_dev = NULL; + mutex_unlock(&media_devnode_lock); + put_device(&devnode->dev); } From f604f0f5afb88045944567f604409951b5eb6af8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 2 Apr 2019 03:24:15 -0400 Subject: [PATCH 164/218] media: au0828: stop video streaming only when last user stops If the application was streaming from both videoX and vbiX, and streaming from videoX was stopped, then the vbi streaming also stopped. The cause being that stop_streaming for video stopped the subdevs as well, instead of only doing that if dev->streaming_users reached 0. au0828_stop_vbi_streaming was also wrong since it didn't stop the subdevs at all when dev->streaming_users reached 0. Signed-off-by: Hans Verkuil Tested-by: Shuah Khan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828-video.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 536bd8bbb624..4bde3db83aa2 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -842,9 +842,9 @@ int au0828_start_analog_streaming(struct vb2_queue *vq, unsigned int count) return rc; } + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1); + if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - v4l2_device_call_all(&dev->v4l2_dev, 0, video, - s_stream, 1); dev->vid_timeout_running = 1; mod_timer(&dev->vid_timeout, jiffies + (HZ / 10)); } else if (vq->type == V4L2_BUF_TYPE_VBI_CAPTURE) { @@ -864,10 +864,11 @@ static void au0828_stop_streaming(struct vb2_queue *vq) dprintk(1, "au0828_stop_streaming called %d\n", dev->streaming_users); - if (dev->streaming_users-- == 1) + if (dev->streaming_users-- == 1) { au0828_uninit_isoc(dev); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); + } - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); dev->vid_timeout_running = 0; del_timer_sync(&dev->vid_timeout); @@ -896,8 +897,10 @@ void au0828_stop_vbi_streaming(struct vb2_queue *vq) dprintk(1, "au0828_stop_vbi_streaming called %d\n", dev->streaming_users); - if (dev->streaming_users-- == 1) + if (dev->streaming_users-- == 1) { au0828_uninit_isoc(dev); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); + } spin_lock_irqsave(&dev->slock, flags); if (dev->isoc_ctl.vbi_buf != NULL) { From 933c1320847f5ed6b61a7d10f0a948aa98ccd7b0 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Sun, 24 Mar 2019 20:21:12 -0400 Subject: [PATCH 165/218] media: ov6650: Fix sensor possibly not detected on probe After removal of clock_start() from before soc_camera_init_i2c() in soc_camera_probe() by commit 9aea470b399d ("[media] soc-camera: switch I2C subdevice drivers to use v4l2-clk") introduced in v3.11, the ov6650 driver could no longer probe the sensor successfully because its clock was no longer turned on in advance. The issue was initially worked around by adding that missing clock_start() equivalent to OMAP1 camera interface driver - the only user of this sensor - but a propoer fix should be rather implemented in the sensor driver code itself. Fix the issue by inserting a delay between the clock is turned on and the sensor I2C registers are read for the first time. Tested on Amstrad Delta with now out of tree but still locally maintained omap1_camera host driver. Fixes: 9aea470b399d ("[media] soc-camera: switch I2C subdevice drivers to use v4l2-clk") Signed-off-by: Janusz Krzysztofik Cc: stable@vger.kernel.org Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov6650.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/i2c/ov6650.c b/drivers/media/i2c/ov6650.c index c33fd584cb44..f9359b11fa5c 100644 --- a/drivers/media/i2c/ov6650.c +++ b/drivers/media/i2c/ov6650.c @@ -814,6 +814,8 @@ static int ov6650_video_probe(struct i2c_client *client) if (ret < 0) return ret; + msleep(20); + /* * check and show product ID and manufacturer ID */ From ccdd85d518d8b9320ace1d87271f0ba2175f21fa Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Fri, 29 Mar 2019 21:06:09 -0400 Subject: [PATCH 166/218] media: ov6650: Move v4l2_clk_get() to ov6650_video_probe() helper In preparation for adding asynchronous subdevice support to the driver, don't acquire v4l2_clk from the driver .probe() callback as that may fail if the clock is provided by a bridge driver which may be not yet initialized. Move the v4l2_clk_get() to ov6650_video_probe() helper which is going to be converted to v4l2_subdev_internal_ops.registered() callback, executed only when the bridge driver is ready. Signed-off-by: Janusz Krzysztofik Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov6650.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/media/i2c/ov6650.c b/drivers/media/i2c/ov6650.c index f9359b11fa5c..de7d9790f054 100644 --- a/drivers/media/i2c/ov6650.c +++ b/drivers/media/i2c/ov6650.c @@ -810,9 +810,16 @@ static int ov6650_video_probe(struct i2c_client *client) u8 pidh, pidl, midh, midl; int ret; + priv->clk = v4l2_clk_get(&client->dev, NULL); + if (IS_ERR(priv->clk)) { + ret = PTR_ERR(priv->clk); + dev_err(&client->dev, "v4l2_clk request err: %d\n", ret); + return ret; + } + ret = ov6650_s_power(&priv->subdev, 1); if (ret < 0) - return ret; + goto eclkput; msleep(20); @@ -849,6 +856,11 @@ static int ov6650_video_probe(struct i2c_client *client) done: ov6650_s_power(&priv->subdev, 0); + if (!ret) + return 0; +eclkput: + v4l2_clk_put(priv->clk); + return ret; } @@ -991,18 +1003,9 @@ static int ov6650_probe(struct i2c_client *client, priv->code = MEDIA_BUS_FMT_YUYV8_2X8; priv->colorspace = V4L2_COLORSPACE_JPEG; - priv->clk = v4l2_clk_get(&client->dev, NULL); - if (IS_ERR(priv->clk)) { - ret = PTR_ERR(priv->clk); - goto eclkget; - } - ret = ov6650_video_probe(client); - if (ret) { - v4l2_clk_put(priv->clk); -eclkget: + if (ret) v4l2_ctrl_handler_free(&priv->hdl); - } return ret; } From c62b96050bee7f1ffbee5cdf3d002fca7f7ce710 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Fri, 29 Mar 2019 21:06:10 -0400 Subject: [PATCH 167/218] media: ov6650: Register with asynchronous subdevice framework Register V4L2 subdevice implemented by the driver to the V4L2 asynchronous subdevice framework. [Sakari Ailus: Remove extra call to v4l2_i2c_subdev_set_name] Signed-off-by: Janusz Krzysztofik Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov6650.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/ov6650.c b/drivers/media/i2c/ov6650.c index de7d9790f054..1b972e591b48 100644 --- a/drivers/media/i2c/ov6650.c +++ b/drivers/media/i2c/ov6650.c @@ -804,8 +804,9 @@ static int ov6650_prog_dflt(struct i2c_client *client) return ret; } -static int ov6650_video_probe(struct i2c_client *client) +static int ov6650_video_probe(struct v4l2_subdev *sd) { + struct i2c_client *client = v4l2_get_subdevdata(sd); struct ov6650 *priv = to_ov6650(client); u8 pidh, pidl, midh, midl; int ret; @@ -817,7 +818,7 @@ static int ov6650_video_probe(struct i2c_client *client) return ret; } - ret = ov6650_s_power(&priv->subdev, 1); + ret = ov6650_s_power(sd, 1); if (ret < 0) goto eclkput; @@ -855,7 +856,7 @@ static int ov6650_video_probe(struct i2c_client *client) ret = v4l2_ctrl_handler_setup(&priv->hdl); done: - ov6650_s_power(&priv->subdev, 0); + ov6650_s_power(sd, 0); if (!ret) return 0; eclkput: @@ -943,6 +944,10 @@ static const struct v4l2_subdev_ops ov6650_subdev_ops = { .pad = &ov6650_pad_ops, }; +static const struct v4l2_subdev_internal_ops ov6650_internal_ops = { + .registered = ov6650_video_probe, +}; + /* * i2c_driver function */ @@ -1003,7 +1008,10 @@ static int ov6650_probe(struct i2c_client *client, priv->code = MEDIA_BUS_FMT_YUYV8_2X8; priv->colorspace = V4L2_COLORSPACE_JPEG; - ret = ov6650_video_probe(client); + priv->subdev.internal_ops = &ov6650_internal_ops; + priv->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + + ret = v4l2_async_register_subdev(&priv->subdev); if (ret) v4l2_ctrl_handler_free(&priv->hdl); @@ -1015,7 +1023,7 @@ static int ov6650_remove(struct i2c_client *client) struct ov6650 *priv = to_ov6650(client); v4l2_clk_put(priv->clk); - v4l2_device_unregister_subdev(&priv->subdev); + v4l2_async_unregister_subdev(&priv->subdev); v4l2_ctrl_handler_free(&priv->hdl); return 0; } From bccb89cf9cd07a0690d519696a00c00a973b3fe4 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 30 Mar 2019 10:01:31 -0400 Subject: [PATCH 168/218] media: ov2659: make S_FMT succeed even if requested format doesn't match This driver returns an error if unsupported media bus pixel code is requested by VIDIOC_SUBDEV_S_FMT. But according to Documentation/media/uapi/v4l/vidioc-subdev-g-fmt.rst, Drivers must not return an error solely because the requested format doesn't match the device capabilities. They must instead modify the format to match what the hardware can provide. So select default format code and return success in that case. This is detected by v4l2-compliance. Cc: "Lad, Prabhakar" Signed-off-by: Akinobu Mita Acked-by: Lad, Prabhakar Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov2659.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c index 799acce803fe..a1e9a980a445 100644 --- a/drivers/media/i2c/ov2659.c +++ b/drivers/media/i2c/ov2659.c @@ -1117,8 +1117,10 @@ static int ov2659_set_fmt(struct v4l2_subdev *sd, if (ov2659_formats[index].code == mf->code) break; - if (index < 0) - return -EINVAL; + if (index < 0) { + index = 0; + mf->code = ov2659_formats[index].code; + } mf->colorspace = V4L2_COLORSPACE_SRGB; mf->field = V4L2_FIELD_NONE; From 384538bda10913e5c94ec5b5d34bd3075931bcf4 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 30 Mar 2019 10:01:32 -0400 Subject: [PATCH 169/218] media: ov2659: fix unbalanced mutex_lock/unlock Avoid returning with mutex locked. Fixes: fa8cb6444c32 ("[media] ov2659: Don't depend on subdev API") Cc: "Lad, Prabhakar" Signed-off-by: Akinobu Mita Acked-by: Lad, Prabhakar Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov2659.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c index a1e9a980a445..5ed2413eac8a 100644 --- a/drivers/media/i2c/ov2659.c +++ b/drivers/media/i2c/ov2659.c @@ -1132,7 +1132,7 @@ static int ov2659_set_fmt(struct v4l2_subdev *sd, mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad); *mf = fmt->format; #else - return -ENOTTY; + ret = -ENOTTY; #endif } else { s64 val; From e3521f5687b34f5e007d170f029d98f3cb846955 Mon Sep 17 00:00:00 2001 From: Mickael Guene Date: Tue, 9 Apr 2019 02:15:47 -0400 Subject: [PATCH 170/218] media: uapi: Add MEDIA_BUS_FMT_BGR888_3X8 media bus format This patch adds MEDIA_BUS_FMT_BGR888_3X8 used by STM MIPID02 CSI-2 to PARALLEL bridge driver when input format is MEDIA_BUS_FMT_BGR888_1X24. Signed-off-by: Mickael Guene Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- .../media/uapi/v4l/subdev-formats.rst | 107 ++++++++++++++++++ include/uapi/linux/media-bus-format.h | 3 +- 2 files changed, 109 insertions(+), 1 deletion(-) diff --git a/Documentation/media/uapi/v4l/subdev-formats.rst b/Documentation/media/uapi/v4l/subdev-formats.rst index bf1dbb68eebc..ab1a48a5ae80 100644 --- a/Documentation/media/uapi/v4l/subdev-formats.rst +++ b/Documentation/media/uapi/v4l/subdev-formats.rst @@ -980,6 +980,113 @@ The following tables list existing packed RGB formats. - r\ :sub:`2` - r\ :sub:`1` - r\ :sub:`0` + * .. _MEDIA-BUS-FMT-BGR888-3X8: + + - MEDIA_BUS_FMT_BGR888_3X8 + - 0x101b + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - b\ :sub:`7` + - b\ :sub:`6` + - b\ :sub:`5` + - b\ :sub:`4` + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + * - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - g\ :sub:`7` + - g\ :sub:`6` + - g\ :sub:`5` + - g\ :sub:`4` + - g\ :sub:`3` + - g\ :sub:`2` + - g\ :sub:`1` + - g\ :sub:`0` + * - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - r\ :sub:`7` + - r\ :sub:`6` + - r\ :sub:`5` + - r\ :sub:`4` + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` * .. _MEDIA-BUS-FMT-GBR888-1X24: - MEDIA_BUS_FMT_GBR888_1X24 diff --git a/include/uapi/linux/media-bus-format.h b/include/uapi/linux/media-bus-format.h index d6a5a3bfe6c4..2a6b253cfb05 100644 --- a/include/uapi/linux/media-bus-format.h +++ b/include/uapi/linux/media-bus-format.h @@ -34,7 +34,7 @@ #define MEDIA_BUS_FMT_FIXED 0x0001 -/* RGB - next is 0x101b */ +/* RGB - next is 0x101c */ #define MEDIA_BUS_FMT_RGB444_1X12 0x1016 #define MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE 0x1001 #define MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE 0x1002 @@ -50,6 +50,7 @@ #define MEDIA_BUS_FMT_RGB666_1X24_CPADHI 0x1015 #define MEDIA_BUS_FMT_RGB666_1X7X3_SPWG 0x1010 #define MEDIA_BUS_FMT_BGR888_1X24 0x1013 +#define MEDIA_BUS_FMT_BGR888_3X8 0x101b #define MEDIA_BUS_FMT_GBR888_1X24 0x1014 #define MEDIA_BUS_FMT_RGB888_1X24 0x100a #define MEDIA_BUS_FMT_RGB888_2X12_BE 0x100b From cffc3df28450390f0de4d6907387d7c40459acab Mon Sep 17 00:00:00 2001 From: Mickael Guene Date: Tue, 9 Apr 2019 02:15:48 -0400 Subject: [PATCH 171/218] media: dt-bindings: Document MIPID02 bindings This adds documentation of device tree for MIPID02 CSI-2 to PARALLEL bridge. Reviewed-by: Rob Herring Signed-off-by: Mickael Guene Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- .../bindings/media/i2c/st,st-mipid02.txt | 82 +++++++++++++++++++ MAINTAINERS | 7 ++ 2 files changed, 89 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/st,st-mipid02.txt diff --git a/Documentation/devicetree/bindings/media/i2c/st,st-mipid02.txt b/Documentation/devicetree/bindings/media/i2c/st,st-mipid02.txt new file mode 100644 index 000000000000..7976e6c40a80 --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/st,st-mipid02.txt @@ -0,0 +1,82 @@ +STMicroelectronics MIPID02 CSI-2 to PARALLEL bridge + +MIPID02 has two CSI-2 input ports, only one of those ports can be active at a +time. Active port input stream will be de-serialized and its content outputted +through PARALLEL output port. +CSI-2 first input port is a dual lane 800Mbps per lane whereas CSI-2 second +input port is a single lane 800Mbps. Both ports support clock and data lane +polarity swap. First port also supports data lane swap. +PARALLEL output port has a maximum width of 12 bits. +Supported formats are RAW6, RAW7, RAW8, RAW10, RAW12, RGB565, RGB888, RGB444, +YUV420 8-bit, YUV422 8-bit and YUV420 10-bit. + +Required Properties: +- compatible: shall be "st,st-mipid02" +- clocks: reference to the xclk input clock. +- clock-names: shall be "xclk". +- VDDE-supply: sensor digital IO supply. Must be 1.8 volts. +- VDDIN-supply: sensor internal regulator supply. Must be 1.8 volts. + +Optional Properties: +- reset-gpios: reference to the GPIO connected to the xsdn pin, if any. + This is an active low signal to the mipid02. + +Required subnodes: + - ports: A ports node with one port child node per device input and output + port, in accordance with the video interface bindings defined in + Documentation/devicetree/bindings/media/video-interfaces.txt. The + port nodes are numbered as follows: + + Port Description + ----------------------------- + 0 CSI-2 first input port + 1 CSI-2 second input port + 2 PARALLEL output + +Endpoint node required property for CSI-2 connection is: +- data-lanes: shall be <1> for Port 1. for Port 0 dual-lane operation shall be +<1 2> or <2 1>. For Port 0 single-lane operation shall be <1> or <2>. +Endpoint node optional property for CSI-2 connection is: +- lane-polarities: any lane can be inverted or not. + +Endpoint node required property for PARALLEL connection is: +- bus-width: shall be set to <6>, <7>, <8>, <10> or <12>. +Endpoint node optional properties for PARALLEL connection are: +- hsync-active: active state of the HSYNC signal, 0/1 for LOW/HIGH respectively. +LOW being the default. +- vsync-active: active state of the VSYNC signal, 0/1 for LOW/HIGH respectively. +LOW being the default. + +Example: + +mipid02: csi2rx@14 { + compatible = "st,st-mipid02"; + reg = <0x14>; + status = "okay"; + clocks = <&clk_ext_camera_12>; + clock-names = "xclk"; + VDDE-supply = <&vdd>; + VDDIN-supply = <&vdd>; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + + ep0: endpoint { + data-lanes = <1 2>; + remote-endpoint = <&mipi_csi2_in>; + }; + }; + port@2 { + reg = <2>; + + ep2: endpoint { + bus-width = <8>; + hsync-active = <0>; + vsync-active = <0>; + remote-endpoint = <¶llel_out>; + }; + }; + }; +}; diff --git a/MAINTAINERS b/MAINTAINERS index c6c15de0583f..fbcbdf839a15 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14667,6 +14667,13 @@ S: Maintained F: drivers/iio/imu/st_lsm6dsx/ F: Documentation/devicetree/bindings/iio/imu/st_lsm6dsx.txt +ST MIPID02 CSI-2 TO PARALLEL BRIDGE DRIVER +M: Mickael Guene +L: linux-media@vger.kernel.org +T: git git://linuxtv.org/media_tree.git +S: Maintained +F: Documentation/devicetree/bindings/media/i2c/st,st-mipid02.txt + ST STM32 I2C/SMBUS DRIVER M: Pierre-Yves MORDRET L: linux-i2c@vger.kernel.org From 642bb5e88fed89e922239106e8dd9e5e6a39d172 Mon Sep 17 00:00:00 2001 From: Mickael Guene Date: Tue, 9 Apr 2019 02:15:49 -0400 Subject: [PATCH 172/218] media: st-mipid02: MIPID02 CSI-2 to PARALLEL bridge driver This V4L2 subdev driver enables STMicroelectronics MIPID02 device. Signed-off-by: Mickael Guene Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 1 + drivers/media/i2c/Kconfig | 13 + drivers/media/i2c/Makefile | 1 + drivers/media/i2c/st-mipid02.c | 1033 ++++++++++++++++++++++++++++++++ 4 files changed, 1048 insertions(+) create mode 100644 drivers/media/i2c/st-mipid02.c diff --git a/MAINTAINERS b/MAINTAINERS index fbcbdf839a15..ce27db435e81 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14672,6 +14672,7 @@ M: Mickael Guene L: linux-media@vger.kernel.org T: git git://linuxtv.org/media_tree.git S: Maintained +F: drivers/media/i2c/st-mipid02.c F: Documentation/devicetree/bindings/media/i2c/st,st-mipid02.txt ST STM32 I2C/SMBUS DRIVER diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 5f5c36442710..7793358ab8b3 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -1136,6 +1136,19 @@ config VIDEO_I2C To compile this driver as a module, choose M here: the module will be called video-i2c +config VIDEO_ST_MIPID02 + tristate "STMicroelectronics MIPID02 CSI-2 to PARALLEL bridge" + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on MEDIA_CAMERA_SUPPORT + select V4L2_FWNODE + help + Support for STMicroelectronics MIPID02 CSI-2 to PARALLEL bridge. + It is used to allow usage of CSI-2 sensor with PARALLEL port + controller. + + To compile this driver as a module, choose M here: the + module will be called st-mipid02. + endmenu endif diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index a64fca82e0c4..d8ad9dad495d 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -113,5 +113,6 @@ obj-$(CONFIG_VIDEO_IMX258) += imx258.o obj-$(CONFIG_VIDEO_IMX274) += imx274.o obj-$(CONFIG_VIDEO_IMX319) += imx319.o obj-$(CONFIG_VIDEO_IMX355) += imx355.o +obj-$(CONFIG_VIDEO_ST_MIPID02) += st-mipid02.o obj-$(CONFIG_SDR_MAX2175) += max2175.o diff --git a/drivers/media/i2c/st-mipid02.c b/drivers/media/i2c/st-mipid02.c new file mode 100644 index 000000000000..9369f38dbf3d --- /dev/null +++ b/drivers/media/i2c/st-mipid02.c @@ -0,0 +1,1033 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for ST MIPID02 CSI-2 to PARALLEL bridge + * + * Copyright (C) STMicroelectronics SA 2019 + * Authors: Mickael Guene + * for STMicroelectronics. + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MIPID02_CLK_LANE_WR_REG1 0x01 +#define MIPID02_CLK_LANE_REG1 0x02 +#define MIPID02_CLK_LANE_REG3 0x04 +#define MIPID02_DATA_LANE0_REG1 0x05 +#define MIPID02_DATA_LANE0_REG2 0x06 +#define MIPID02_DATA_LANE1_REG1 0x09 +#define MIPID02_DATA_LANE1_REG2 0x0a +#define MIPID02_MODE_REG1 0x14 +#define MIPID02_MODE_REG2 0x15 +#define MIPID02_DATA_ID_RREG 0x17 +#define MIPID02_DATA_SELECTION_CTRL 0x19 +#define MIPID02_PIX_WIDTH_CTRL 0x1e +#define MIPID02_PIX_WIDTH_CTRL_EMB 0x1f + +/* Bits definition for MIPID02_CLK_LANE_REG1 */ +#define CLK_ENABLE BIT(0) +/* Bits definition for MIPID02_CLK_LANE_REG3 */ +#define CLK_MIPI_CSI BIT(1) +/* Bits definition for MIPID02_DATA_LANE0_REG1 */ +#define DATA_ENABLE BIT(0) +/* Bits definition for MIPID02_DATA_LANEx_REG2 */ +#define DATA_MIPI_CSI BIT(0) +/* Bits definition for MIPID02_MODE_REG1 */ +#define MODE_DATA_SWAP BIT(2) +#define MODE_NO_BYPASS BIT(6) +/* Bits definition for MIPID02_MODE_REG2 */ +#define MODE_HSYNC_ACTIVE_HIGH BIT(1) +#define MODE_VSYNC_ACTIVE_HIGH BIT(2) +/* Bits definition for MIPID02_DATA_SELECTION_CTRL */ +#define SELECTION_MANUAL_DATA BIT(2) +#define SELECTION_MANUAL_WIDTH BIT(3) + +static const u32 mipid02_supported_fmt_codes[] = { + MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8, + MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8, + MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10, + MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10, + MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SGBRG12_1X12, + MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SRGGB12_1X12, + MEDIA_BUS_FMT_UYVY8_1X16, MEDIA_BUS_FMT_BGR888_1X24 +}; + +/* regulator supplies */ +static const char * const mipid02_supply_name[] = { + "VDDE", /* 1.8V digital I/O supply */ + "VDDIN", /* 1V8 voltage regulator supply */ +}; + +#define MIPID02_NUM_SUPPLIES ARRAY_SIZE(mipid02_supply_name) + +#define MIPID02_SINK_0 0 +#define MIPID02_SINK_1 1 +#define MIPID02_SOURCE 2 +#define MIPID02_PAD_NB 3 + +struct mipid02_dev { + struct i2c_client *i2c_client; + struct regulator_bulk_data supplies[MIPID02_NUM_SUPPLIES]; + struct v4l2_subdev sd; + struct media_pad pad[MIPID02_PAD_NB]; + struct clk *xclk; + struct gpio_desc *reset_gpio; + /* endpoints info */ + struct v4l2_fwnode_endpoint rx; + u64 link_frequency; + struct v4l2_fwnode_endpoint tx; + /* remote source */ + struct v4l2_async_subdev asd; + struct v4l2_async_notifier notifier; + struct v4l2_subdev *s_subdev; + /* registers */ + struct { + u8 clk_lane_reg1; + u8 data_lane0_reg1; + u8 data_lane1_reg1; + u8 mode_reg1; + u8 mode_reg2; + u8 data_id_rreg; + u8 pix_width_ctrl; + u8 pix_width_ctrl_emb; + } r; + /* lock to protect all members below */ + struct mutex lock; + bool streaming; + struct v4l2_mbus_framefmt fmt; +}; + +static int bpp_from_code(__u32 code) +{ + switch (code) { + case MEDIA_BUS_FMT_SBGGR8_1X8: + case MEDIA_BUS_FMT_SGBRG8_1X8: + case MEDIA_BUS_FMT_SGRBG8_1X8: + case MEDIA_BUS_FMT_SRGGB8_1X8: + return 8; + case MEDIA_BUS_FMT_SBGGR10_1X10: + case MEDIA_BUS_FMT_SGBRG10_1X10: + case MEDIA_BUS_FMT_SGRBG10_1X10: + case MEDIA_BUS_FMT_SRGGB10_1X10: + return 10; + case MEDIA_BUS_FMT_SBGGR12_1X12: + case MEDIA_BUS_FMT_SGBRG12_1X12: + case MEDIA_BUS_FMT_SGRBG12_1X12: + case MEDIA_BUS_FMT_SRGGB12_1X12: + return 12; + case MEDIA_BUS_FMT_UYVY8_1X16: + return 16; + case MEDIA_BUS_FMT_BGR888_1X24: + return 24; + default: + return 0; + } +} + +static u8 data_type_from_code(__u32 code) +{ + switch (code) { + case MEDIA_BUS_FMT_SBGGR8_1X8: + case MEDIA_BUS_FMT_SGBRG8_1X8: + case MEDIA_BUS_FMT_SGRBG8_1X8: + case MEDIA_BUS_FMT_SRGGB8_1X8: + return 0x2a; + case MEDIA_BUS_FMT_SBGGR10_1X10: + case MEDIA_BUS_FMT_SGBRG10_1X10: + case MEDIA_BUS_FMT_SGRBG10_1X10: + case MEDIA_BUS_FMT_SRGGB10_1X10: + return 0x2b; + case MEDIA_BUS_FMT_SBGGR12_1X12: + case MEDIA_BUS_FMT_SGBRG12_1X12: + case MEDIA_BUS_FMT_SGRBG12_1X12: + case MEDIA_BUS_FMT_SRGGB12_1X12: + return 0x2c; + case MEDIA_BUS_FMT_UYVY8_1X16: + return 0x1e; + case MEDIA_BUS_FMT_BGR888_1X24: + return 0x24; + default: + return 0; + } +} + +static void init_format(struct v4l2_mbus_framefmt *fmt) +{ + fmt->code = MEDIA_BUS_FMT_SBGGR8_1X8; + fmt->field = V4L2_FIELD_NONE; + fmt->colorspace = V4L2_COLORSPACE_SRGB; + fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(V4L2_COLORSPACE_SRGB); + fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE; + fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(V4L2_COLORSPACE_SRGB); + fmt->width = 640; + fmt->height = 480; +} + +static __u32 get_fmt_code(__u32 code) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(mipid02_supported_fmt_codes); i++) { + if (code == mipid02_supported_fmt_codes[i]) + return code; + } + + return mipid02_supported_fmt_codes[0]; +} + +static __u32 serial_to_parallel_code(__u32 serial) +{ + if (serial == MEDIA_BUS_FMT_UYVY8_1X16) + return MEDIA_BUS_FMT_UYVY8_2X8; + if (serial == MEDIA_BUS_FMT_BGR888_1X24) + return MEDIA_BUS_FMT_BGR888_3X8; + + return serial; +} + +static inline struct mipid02_dev *to_mipid02_dev(struct v4l2_subdev *sd) +{ + return container_of(sd, struct mipid02_dev, sd); +} + +static int mipid02_read_reg(struct mipid02_dev *bridge, u16 reg, u8 *val) +{ + struct i2c_client *client = bridge->i2c_client; + struct i2c_msg msg[2]; + u8 buf[2]; + int ret; + + buf[0] = reg >> 8; + buf[1] = reg & 0xff; + + msg[0].addr = client->addr; + msg[0].flags = client->flags; + msg[0].buf = buf; + msg[0].len = sizeof(buf); + + msg[1].addr = client->addr; + msg[1].flags = client->flags | I2C_M_RD; + msg[1].buf = val; + msg[1].len = 1; + + ret = i2c_transfer(client->adapter, msg, 2); + if (ret < 0) { + dev_dbg(&client->dev, "%s: %x i2c_transfer, reg: %x => %d\n", + __func__, client->addr, reg, ret); + return ret; + } + + return 0; +} + +static int mipid02_write_reg(struct mipid02_dev *bridge, u16 reg, u8 val) +{ + struct i2c_client *client = bridge->i2c_client; + struct i2c_msg msg; + u8 buf[3]; + int ret; + + buf[0] = reg >> 8; + buf[1] = reg & 0xff; + buf[2] = val; + + msg.addr = client->addr; + msg.flags = client->flags; + msg.buf = buf; + msg.len = sizeof(buf); + + ret = i2c_transfer(client->adapter, &msg, 1); + if (ret < 0) { + dev_dbg(&client->dev, "%s: i2c_transfer, reg: %x => %d\n", + __func__, reg, ret); + return ret; + } + + return 0; +} + +static int mipid02_get_regulators(struct mipid02_dev *bridge) +{ + unsigned int i; + + for (i = 0; i < MIPID02_NUM_SUPPLIES; i++) + bridge->supplies[i].supply = mipid02_supply_name[i]; + + return devm_regulator_bulk_get(&bridge->i2c_client->dev, + MIPID02_NUM_SUPPLIES, + bridge->supplies); +} + +static void mipid02_apply_reset(struct mipid02_dev *bridge) +{ + gpiod_set_value_cansleep(bridge->reset_gpio, 0); + usleep_range(5000, 10000); + gpiod_set_value_cansleep(bridge->reset_gpio, 1); + usleep_range(5000, 10000); + gpiod_set_value_cansleep(bridge->reset_gpio, 0); + usleep_range(5000, 10000); +} + +static int mipid02_set_power_on(struct mipid02_dev *bridge) +{ + struct i2c_client *client = bridge->i2c_client; + int ret; + + ret = clk_prepare_enable(bridge->xclk); + if (ret) { + dev_err(&client->dev, "%s: failed to enable clock\n", __func__); + return ret; + } + + ret = regulator_bulk_enable(MIPID02_NUM_SUPPLIES, + bridge->supplies); + if (ret) { + dev_err(&client->dev, "%s: failed to enable regulators\n", + __func__); + goto xclk_off; + } + + if (bridge->reset_gpio) { + dev_dbg(&client->dev, "apply reset"); + mipid02_apply_reset(bridge); + } else { + dev_dbg(&client->dev, "don't apply reset"); + usleep_range(5000, 10000); + } + + return 0; + +xclk_off: + clk_disable_unprepare(bridge->xclk); + return ret; +} + +static void mipid02_set_power_off(struct mipid02_dev *bridge) +{ + regulator_bulk_disable(MIPID02_NUM_SUPPLIES, bridge->supplies); + clk_disable_unprepare(bridge->xclk); +} + +static int mipid02_detect(struct mipid02_dev *bridge) +{ + u8 reg; + + /* + * There is no version registers. Just try to read register + * MIPID02_CLK_LANE_WR_REG1. + */ + return mipid02_read_reg(bridge, MIPID02_CLK_LANE_WR_REG1, ®); +} + +static u32 mipid02_get_link_freq_from_cid_pixel_rate(struct mipid02_dev *bridge, + struct v4l2_subdev *subdev) +{ + struct v4l2_fwnode_endpoint *ep = &bridge->rx; + struct v4l2_ctrl *ctrl; + u32 pixel_clock; + u32 bpp = bpp_from_code(bridge->fmt.code); + + ctrl = v4l2_ctrl_find(subdev->ctrl_handler, V4L2_CID_PIXEL_RATE); + if (!ctrl) + return 0; + pixel_clock = v4l2_ctrl_g_ctrl_int64(ctrl); + + return pixel_clock * bpp / (2 * ep->bus.mipi_csi2.num_data_lanes); +} + +/* + * We need to know link frequency to setup clk_lane_reg1 timings. Link frequency + * will be computed using connected device V4L2_CID_PIXEL_RATE, bit per pixel + * and number of lanes. + */ +static int mipid02_configure_from_rx_speed(struct mipid02_dev *bridge) +{ + struct i2c_client *client = bridge->i2c_client; + struct v4l2_subdev *subdev = bridge->s_subdev; + u32 link_freq; + + link_freq = mipid02_get_link_freq_from_cid_pixel_rate(bridge, subdev); + if (!link_freq) { + dev_err(&client->dev, "Failed to detect link frequency"); + return -EINVAL; + } + + dev_dbg(&client->dev, "detect link_freq = %d Hz", link_freq); + bridge->r.clk_lane_reg1 |= (2000000000 / link_freq) << 2; + + return 0; +} + +static int mipid02_configure_clk_lane(struct mipid02_dev *bridge) +{ + struct i2c_client *client = bridge->i2c_client; + struct v4l2_fwnode_endpoint *ep = &bridge->rx; + bool *polarities = ep->bus.mipi_csi2.lane_polarities; + + /* midid02 doesn't support clock lane remapping */ + if (ep->bus.mipi_csi2.clock_lane != 0) { + dev_err(&client->dev, "clk lane must be map to lane 0\n"); + return -EINVAL; + } + bridge->r.clk_lane_reg1 |= (polarities[0] << 1) | CLK_ENABLE; + + return 0; +} + +static int mipid02_configure_data0_lane(struct mipid02_dev *bridge, int nb, + bool are_lanes_swap, bool *polarities) +{ + bool are_pin_swap = are_lanes_swap ? polarities[2] : polarities[1]; + + if (nb == 1 && are_lanes_swap) + return 0; + + /* + * data lane 0 as pin swap polarity reversed compared to clock and + * data lane 1 + */ + if (!are_pin_swap) + bridge->r.data_lane0_reg1 = 1 << 1; + bridge->r.data_lane0_reg1 |= DATA_ENABLE; + + return 0; +} + +static int mipid02_configure_data1_lane(struct mipid02_dev *bridge, int nb, + bool are_lanes_swap, bool *polarities) +{ + bool are_pin_swap = are_lanes_swap ? polarities[1] : polarities[2]; + + if (nb == 1 && !are_lanes_swap) + return 0; + + if (are_pin_swap) + bridge->r.data_lane1_reg1 = 1 << 1; + bridge->r.data_lane1_reg1 |= DATA_ENABLE; + + return 0; +} + +static int mipid02_configure_from_rx(struct mipid02_dev *bridge) +{ + struct v4l2_fwnode_endpoint *ep = &bridge->rx; + bool are_lanes_swap = ep->bus.mipi_csi2.data_lanes[0] == 2; + bool *polarities = ep->bus.mipi_csi2.lane_polarities; + int nb = ep->bus.mipi_csi2.num_data_lanes; + int ret; + + ret = mipid02_configure_clk_lane(bridge); + if (ret) + return ret; + + ret = mipid02_configure_data0_lane(bridge, nb, are_lanes_swap, + polarities); + if (ret) + return ret; + + ret = mipid02_configure_data1_lane(bridge, nb, are_lanes_swap, + polarities); + if (ret) + return ret; + + bridge->r.mode_reg1 |= are_lanes_swap ? MODE_DATA_SWAP : 0; + bridge->r.mode_reg1 |= (nb - 1) << 1; + + return mipid02_configure_from_rx_speed(bridge); +} + +static int mipid02_configure_from_tx(struct mipid02_dev *bridge) +{ + struct v4l2_fwnode_endpoint *ep = &bridge->tx; + + bridge->r.pix_width_ctrl = ep->bus.parallel.bus_width; + bridge->r.pix_width_ctrl_emb = ep->bus.parallel.bus_width; + if (ep->bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) + bridge->r.mode_reg2 |= MODE_HSYNC_ACTIVE_HIGH; + if (ep->bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) + bridge->r.mode_reg2 |= MODE_VSYNC_ACTIVE_HIGH; + + return 0; +} + +static int mipid02_configure_from_code(struct mipid02_dev *bridge) +{ + u8 data_type; + + bridge->r.data_id_rreg = 0; + data_type = data_type_from_code(bridge->fmt.code); + if (!data_type) + return -EINVAL; + bridge->r.data_id_rreg = data_type; + + return 0; +} + +static int mipid02_stream_disable(struct mipid02_dev *bridge) +{ + struct i2c_client *client = bridge->i2c_client; + int ret; + + /* Disable all lanes */ + ret = mipid02_write_reg(bridge, MIPID02_CLK_LANE_REG1, 0); + if (ret) + goto error; + ret = mipid02_write_reg(bridge, MIPID02_DATA_LANE0_REG1, 0); + if (ret) + goto error; + ret = mipid02_write_reg(bridge, MIPID02_DATA_LANE1_REG1, 0); + if (ret) + goto error; +error: + if (ret) + dev_err(&client->dev, "failed to stream off %d", ret); + + return ret; +} + +static int mipid02_stream_enable(struct mipid02_dev *bridge) +{ + struct i2c_client *client = bridge->i2c_client; + int ret = -EINVAL; + + if (!bridge->s_subdev) + goto error; + + memset(&bridge->r, 0, sizeof(bridge->r)); + /* build registers content */ + ret = mipid02_configure_from_rx(bridge); + if (ret) + goto error; + ret = mipid02_configure_from_tx(bridge); + if (ret) + goto error; + ret = mipid02_configure_from_code(bridge); + if (ret) + goto error; + + /* write mipi registers */ + ret = mipid02_write_reg(bridge, MIPID02_CLK_LANE_REG1, + bridge->r.clk_lane_reg1); + if (ret) + goto error; + ret = mipid02_write_reg(bridge, MIPID02_CLK_LANE_REG3, CLK_MIPI_CSI); + if (ret) + goto error; + ret = mipid02_write_reg(bridge, MIPID02_DATA_LANE0_REG1, + bridge->r.data_lane0_reg1); + if (ret) + goto error; + ret = mipid02_write_reg(bridge, MIPID02_DATA_LANE0_REG2, + DATA_MIPI_CSI); + if (ret) + goto error; + ret = mipid02_write_reg(bridge, MIPID02_DATA_LANE1_REG1, + bridge->r.data_lane1_reg1); + if (ret) + goto error; + ret = mipid02_write_reg(bridge, MIPID02_DATA_LANE1_REG2, + DATA_MIPI_CSI); + if (ret) + goto error; + ret = mipid02_write_reg(bridge, MIPID02_MODE_REG1, + MODE_NO_BYPASS | bridge->r.mode_reg1); + if (ret) + goto error; + ret = mipid02_write_reg(bridge, MIPID02_MODE_REG2, + bridge->r.mode_reg2); + if (ret) + goto error; + ret = mipid02_write_reg(bridge, MIPID02_DATA_ID_RREG, + bridge->r.data_id_rreg); + if (ret) + goto error; + ret = mipid02_write_reg(bridge, MIPID02_DATA_SELECTION_CTRL, + SELECTION_MANUAL_DATA | SELECTION_MANUAL_WIDTH); + if (ret) + goto error; + ret = mipid02_write_reg(bridge, MIPID02_PIX_WIDTH_CTRL, + bridge->r.pix_width_ctrl); + if (ret) + goto error; + ret = mipid02_write_reg(bridge, MIPID02_PIX_WIDTH_CTRL_EMB, + bridge->r.pix_width_ctrl_emb); + if (ret) + goto error; + + return 0; + +error: + dev_err(&client->dev, "failed to stream on %d", ret); + mipid02_stream_disable(bridge); + + return ret; +} + +static int mipid02_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct mipid02_dev *bridge = to_mipid02_dev(sd); + struct i2c_client *client = bridge->i2c_client; + int ret = 0; + + dev_dbg(&client->dev, "%s : requested %d / current = %d", __func__, + enable, bridge->streaming); + mutex_lock(&bridge->lock); + + if (bridge->streaming == enable) + goto out; + + ret = enable ? mipid02_stream_enable(bridge) : + mipid02_stream_disable(bridge); + if (!ret) + bridge->streaming = enable; + +out: + dev_dbg(&client->dev, "%s current now = %d / %d", __func__, + bridge->streaming, ret); + mutex_unlock(&bridge->lock); + + return ret; +} + +static int mipid02_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) +{ + struct mipid02_dev *bridge = to_mipid02_dev(sd); + int ret = 0; + + switch (code->pad) { + case MIPID02_SINK_0: + if (code->index >= ARRAY_SIZE(mipid02_supported_fmt_codes)) + ret = -EINVAL; + else + code->code = mipid02_supported_fmt_codes[code->index]; + break; + case MIPID02_SOURCE: + if (code->index == 0) + code->code = serial_to_parallel_code(bridge->fmt.code); + else + ret = -EINVAL; + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static int mipid02_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) +{ + struct v4l2_mbus_framefmt *mbus_fmt = &format->format; + struct mipid02_dev *bridge = to_mipid02_dev(sd); + struct i2c_client *client = bridge->i2c_client; + struct v4l2_mbus_framefmt *fmt; + + dev_dbg(&client->dev, "%s probe %d", __func__, format->pad); + + if (format->pad >= MIPID02_PAD_NB) + return -EINVAL; + /* second CSI-2 pad not yet supported */ + if (format->pad == MIPID02_SINK_1) + return -EINVAL; + + if (format->which == V4L2_SUBDEV_FORMAT_TRY) + fmt = v4l2_subdev_get_try_format(&bridge->sd, cfg, format->pad); + else + fmt = &bridge->fmt; + + mutex_lock(&bridge->lock); + + *mbus_fmt = *fmt; + /* code may need to be converted for source */ + if (format->pad == MIPID02_SOURCE) + mbus_fmt->code = serial_to_parallel_code(mbus_fmt->code); + + mutex_unlock(&bridge->lock); + + return 0; +} + +static void mipid02_set_fmt_source(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) +{ + struct mipid02_dev *bridge = to_mipid02_dev(sd); + + /* source pad mirror active sink pad */ + format->format = bridge->fmt; + /* but code may need to be converted */ + format->format.code = serial_to_parallel_code(format->format.code); + + /* only apply format for V4L2_SUBDEV_FORMAT_TRY case */ + if (format->which != V4L2_SUBDEV_FORMAT_TRY) + return; + + *v4l2_subdev_get_try_format(sd, cfg, format->pad) = format->format; +} + +static void mipid02_set_fmt_sink(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) +{ + struct mipid02_dev *bridge = to_mipid02_dev(sd); + struct v4l2_mbus_framefmt *fmt; + + format->format.code = get_fmt_code(format->format.code); + + if (format->which == V4L2_SUBDEV_FORMAT_TRY) + fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad); + else + fmt = &bridge->fmt; + + *fmt = format->format; +} + +static int mipid02_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) +{ + struct mipid02_dev *bridge = to_mipid02_dev(sd); + struct i2c_client *client = bridge->i2c_client; + int ret = 0; + + dev_dbg(&client->dev, "%s for %d", __func__, format->pad); + + if (format->pad >= MIPID02_PAD_NB) + return -EINVAL; + /* second CSI-2 pad not yet supported */ + if (format->pad == MIPID02_SINK_1) + return -EINVAL; + + mutex_lock(&bridge->lock); + + if (bridge->streaming) { + ret = -EBUSY; + goto error; + } + + if (format->pad == MIPID02_SOURCE) + mipid02_set_fmt_source(sd, cfg, format); + else + mipid02_set_fmt_sink(sd, cfg, format); + +error: + mutex_unlock(&bridge->lock); + + return ret; +} + +static const struct v4l2_subdev_video_ops mipid02_video_ops = { + .s_stream = mipid02_s_stream, +}; + +static const struct v4l2_subdev_pad_ops mipid02_pad_ops = { + .enum_mbus_code = mipid02_enum_mbus_code, + .get_fmt = mipid02_get_fmt, + .set_fmt = mipid02_set_fmt, +}; + +static const struct v4l2_subdev_ops mipid02_subdev_ops = { + .video = &mipid02_video_ops, + .pad = &mipid02_pad_ops, +}; + +static const struct media_entity_operations mipid02_subdev_entity_ops = { + .link_validate = v4l2_subdev_link_validate, +}; + +static int mipid02_async_bound(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *s_subdev, + struct v4l2_async_subdev *asd) +{ + struct mipid02_dev *bridge = to_mipid02_dev(notifier->sd); + struct i2c_client *client = bridge->i2c_client; + int source_pad; + int ret; + + dev_dbg(&client->dev, "sensor_async_bound call %p", s_subdev); + + source_pad = media_entity_get_fwnode_pad(&s_subdev->entity, + s_subdev->fwnode, + MEDIA_PAD_FL_SOURCE); + if (source_pad < 0) { + dev_err(&client->dev, "Couldn't find output pad for subdev %s\n", + s_subdev->name); + return source_pad; + } + + ret = media_create_pad_link(&s_subdev->entity, source_pad, + &bridge->sd.entity, 0, + MEDIA_LNK_FL_ENABLED | + MEDIA_LNK_FL_IMMUTABLE); + if (ret) { + dev_err(&client->dev, "Couldn't create media link %d", ret); + return ret; + } + + bridge->s_subdev = s_subdev; + + return 0; +} + +static void mipid02_async_unbind(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *s_subdev, + struct v4l2_async_subdev *asd) +{ + struct mipid02_dev *bridge = to_mipid02_dev(notifier->sd); + + bridge->s_subdev = NULL; +} + +static const struct v4l2_async_notifier_operations mipid02_notifier_ops = { + .bound = mipid02_async_bound, + .unbind = mipid02_async_unbind, +}; + +static int mipid02_parse_rx_ep(struct mipid02_dev *bridge) +{ + struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_CSI2_DPHY }; + struct i2c_client *client = bridge->i2c_client; + struct device_node *ep_node; + int ret; + + /* parse rx (endpoint 0) */ + ep_node = of_graph_get_endpoint_by_regs(bridge->i2c_client->dev.of_node, + 0, 0); + if (!ep_node) { + dev_err(&client->dev, "unable to find port0 ep"); + ret = -EINVAL; + goto error; + } + + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_node), &ep); + if (ret) { + dev_err(&client->dev, "Could not parse v4l2 endpoint %d\n", + ret); + goto error_of_node_put; + } + + /* do some sanity checks */ + if (ep.bus.mipi_csi2.num_data_lanes > 2) { + dev_err(&client->dev, "max supported data lanes is 2 / got %d", + ep.bus.mipi_csi2.num_data_lanes); + ret = -EINVAL; + goto error_of_node_put; + } + + /* register it for later use */ + bridge->rx = ep; + + /* register async notifier so we get noticed when sensor is connected */ + bridge->asd.match.fwnode = + fwnode_graph_get_remote_port_parent(of_fwnode_handle(ep_node)); + bridge->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; + of_node_put(ep_node); + + v4l2_async_notifier_init(&bridge->notifier); + ret = v4l2_async_notifier_add_subdev(&bridge->notifier, &bridge->asd); + if (ret) { + dev_err(&client->dev, "fail to register asd to notifier %d", + ret); + fwnode_handle_put(bridge->asd.match.fwnode); + return ret; + } + bridge->notifier.ops = &mipid02_notifier_ops; + + ret = v4l2_async_subdev_notifier_register(&bridge->sd, + &bridge->notifier); + if (ret) + v4l2_async_notifier_cleanup(&bridge->notifier); + + return ret; + +error_of_node_put: + of_node_put(ep_node); +error: + + return ret; +} + +static int mipid02_parse_tx_ep(struct mipid02_dev *bridge) +{ + struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_PARALLEL }; + struct i2c_client *client = bridge->i2c_client; + struct device_node *ep_node; + int ret; + + /* parse tx (endpoint 2) */ + ep_node = of_graph_get_endpoint_by_regs(bridge->i2c_client->dev.of_node, + 2, 0); + if (!ep_node) { + dev_err(&client->dev, "unable to find port1 ep"); + ret = -EINVAL; + goto error; + } + + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_node), &ep); + if (ret) { + dev_err(&client->dev, "Could not parse v4l2 endpoint\n"); + goto error_of_node_put; + } + + of_node_put(ep_node); + bridge->tx = ep; + + return 0; + +error_of_node_put: + of_node_put(ep_node); +error: + + return -EINVAL; +} + +static int mipid02_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct mipid02_dev *bridge; + u32 clk_freq; + int ret; + + bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL); + if (!bridge) + return -ENOMEM; + + init_format(&bridge->fmt); + + bridge->i2c_client = client; + v4l2_i2c_subdev_init(&bridge->sd, client, &mipid02_subdev_ops); + + /* got and check clock */ + bridge->xclk = devm_clk_get(dev, "xclk"); + if (IS_ERR(bridge->xclk)) { + dev_err(dev, "failed to get xclk\n"); + return PTR_ERR(bridge->xclk); + } + + clk_freq = clk_get_rate(bridge->xclk); + if (clk_freq < 6000000 || clk_freq > 27000000) { + dev_err(dev, "xclk freq must be in 6-27 Mhz range. got %d Hz\n", + clk_freq); + return -EINVAL; + } + + bridge->reset_gpio = devm_gpiod_get_optional(dev, "reset", + GPIOD_OUT_HIGH); + + ret = mipid02_get_regulators(bridge); + if (ret) { + dev_err(dev, "failed to get regulators %d", ret); + return ret; + } + + mutex_init(&bridge->lock); + bridge->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + bridge->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; + bridge->sd.entity.ops = &mipid02_subdev_entity_ops; + bridge->pad[0].flags = MEDIA_PAD_FL_SINK; + bridge->pad[1].flags = MEDIA_PAD_FL_SINK; + bridge->pad[2].flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&bridge->sd.entity, MIPID02_PAD_NB, + bridge->pad); + if (ret) { + dev_err(&client->dev, "pads init failed %d", ret); + goto mutex_cleanup; + } + + /* enable clock, power and reset device if available */ + ret = mipid02_set_power_on(bridge); + if (ret) + goto entity_cleanup; + + ret = mipid02_detect(bridge); + if (ret) { + dev_err(&client->dev, "failed to detect mipid02 %d", ret); + goto power_off; + } + + ret = mipid02_parse_tx_ep(bridge); + if (ret) { + dev_err(&client->dev, "failed to parse tx %d", ret); + goto power_off; + } + + ret = mipid02_parse_rx_ep(bridge); + if (ret) { + dev_err(&client->dev, "failed to parse rx %d", ret); + goto power_off; + } + + ret = v4l2_async_register_subdev(&bridge->sd); + if (ret < 0) { + dev_err(&client->dev, "v4l2_async_register_subdev failed %d", + ret); + goto unregister_notifier; + } + + dev_info(&client->dev, "mipid02 device probe successfully"); + + return 0; + +unregister_notifier: + v4l2_async_notifier_unregister(&bridge->notifier); + v4l2_async_notifier_cleanup(&bridge->notifier); +power_off: + mipid02_set_power_off(bridge); +entity_cleanup: + media_entity_cleanup(&bridge->sd.entity); +mutex_cleanup: + mutex_destroy(&bridge->lock); + + return ret; +} + +static int mipid02_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct mipid02_dev *bridge = to_mipid02_dev(sd); + + v4l2_async_notifier_unregister(&bridge->notifier); + v4l2_async_notifier_cleanup(&bridge->notifier); + v4l2_async_unregister_subdev(&bridge->sd); + mipid02_set_power_off(bridge); + media_entity_cleanup(&bridge->sd.entity); + mutex_destroy(&bridge->lock); + + return 0; +} + +static const struct of_device_id mipid02_dt_ids[] = { + { .compatible = "st,st-mipid02" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mipid02_dt_ids); + +static struct i2c_driver mipid02_i2c_driver = { + .driver = { + .name = "st-mipid02", + .of_match_table = mipid02_dt_ids, + }, + .probe_new = mipid02_probe, + .remove = mipid02_remove, +}; + +module_i2c_driver(mipid02_i2c_driver); + +MODULE_AUTHOR("Mickael Guene "); +MODULE_DESCRIPTION("STMicroelectronics MIPID02 CSI-2 bridge driver"); +MODULE_LICENSE("GPL v2"); From 8ecc7c9da013e702aa889002e1288521d7533293 Mon Sep 17 00:00:00 2001 From: Bingbu Cao Date: Fri, 22 Mar 2019 07:14:45 -0400 Subject: [PATCH 173/218] media: staging/intel-ipu3: parameter buffer refactoring Current ImgU driver processes and releases the parameter buffer immediately after queued from user. This does not align with other image buffers which are grouped in sets and used for the same frame. If user queues multiple parameter buffers continuously, only the last one will take effect. To make consistent buffers usage, this patch changes the parameter buffer handling and group parameter buffer with other image buffers for each frame. Each time driver will queue one more group of buffers when previous frame processed and buffers consumed by css. Signed-off-by: Tianshu Qiu Signed-off-by: Bingbu Cao Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/ipu3/ipu3-css.c | 5 --- drivers/staging/media/ipu3/ipu3-v4l2.c | 52 ++++++++++---------------- drivers/staging/media/ipu3/ipu3.c | 30 +++++++++++++++ 3 files changed, 49 insertions(+), 38 deletions(-) diff --git a/drivers/staging/media/ipu3/ipu3-css.c b/drivers/staging/media/ipu3/ipu3-css.c index e7f1898874fd..23cf5b2cfe8b 100644 --- a/drivers/staging/media/ipu3/ipu3-css.c +++ b/drivers/staging/media/ipu3/ipu3-css.c @@ -2171,11 +2171,6 @@ int imgu_css_set_parameters(struct imgu_css *css, unsigned int pipe, obgrid_size = imgu_css_fw_obgrid_size(bi); stripes = bi->info.isp.sp.iterator.num_stripes ? : 1; - /* - * TODO(b/118782861): If userspace queues more than 4 buffers, the - * parameters from previous buffers will be overwritten. Fix the driver - * not to allow this. - */ imgu_css_pool_get(&css_pipe->pool.parameter_set_info); param_set = imgu_css_pool_last(&css_pipe->pool.parameter_set_info, 0)->vaddr; diff --git a/drivers/staging/media/ipu3/ipu3-v4l2.c b/drivers/staging/media/ipu3/ipu3-v4l2.c index c34b433539c4..be818c29620f 100644 --- a/drivers/staging/media/ipu3/ipu3-v4l2.c +++ b/drivers/staging/media/ipu3/ipu3-v4l2.c @@ -341,8 +341,10 @@ static void imgu_vb2_buf_queue(struct vb2_buffer *vb) struct imgu_video_device *node = container_of(vb->vb2_queue, struct imgu_video_device, vbq); unsigned int queue = imgu_node_to_queue(node->id); + struct imgu_buffer *buf = container_of(vb, struct imgu_buffer, + vid_buf.vbb.vb2_buf); unsigned long need_bytes; - unsigned int pipe = node->pipe; + unsigned long payload = vb2_get_plane_payload(vb, 0); if (vb->vb2_queue->type == V4L2_BUF_TYPE_META_CAPTURE || vb->vb2_queue->type == V4L2_BUF_TYPE_META_OUTPUT) @@ -350,42 +352,26 @@ static void imgu_vb2_buf_queue(struct vb2_buffer *vb) else need_bytes = node->vdev_fmt.fmt.pix_mp.plane_fmt[0].sizeimage; - if (queue == IPU3_CSS_QUEUE_PARAMS) { - unsigned long payload = vb2_get_plane_payload(vb, 0); - struct vb2_v4l2_buffer *buf = - container_of(vb, struct vb2_v4l2_buffer, vb2_buf); - int r = -EINVAL; - - if (payload == 0) { - payload = need_bytes; - vb2_set_plane_payload(vb, 0, payload); - } - if (payload >= need_bytes) - r = imgu_css_set_parameters(&imgu->css, pipe, - vb2_plane_vaddr(vb, 0)); - buf->flags = V4L2_BUF_FLAG_DONE; - vb2_buffer_done(vb, r == 0 ? VB2_BUF_STATE_DONE - : VB2_BUF_STATE_ERROR); - - } else { - struct imgu_buffer *buf = container_of(vb, struct imgu_buffer, - vid_buf.vbb.vb2_buf); - - mutex_lock(&imgu->lock); - imgu_css_buf_init(&buf->css_buf, queue, buf->map.daddr); - list_add_tail(&buf->vid_buf.list, - &node->buffers); - mutex_unlock(&imgu->lock); - - vb2_set_plane_payload(&buf->vid_buf.vbb.vb2_buf, 0, need_bytes); - - if (imgu->streaming) - imgu_queue_buffers(imgu, false, pipe); + if (queue == IPU3_CSS_QUEUE_PARAMS && payload && payload < need_bytes) { + dev_err(&imgu->pci_dev->dev, "invalid data size for params."); + vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); + return; } + mutex_lock(&imgu->lock); + if (queue != IPU3_CSS_QUEUE_PARAMS) + imgu_css_buf_init(&buf->css_buf, queue, buf->map.daddr); + + list_add_tail(&buf->vid_buf.list, &node->buffers); + mutex_unlock(&imgu->lock); + + vb2_set_plane_payload(vb, 0, need_bytes); + + if (imgu->streaming) + imgu_queue_buffers(imgu, false, node->pipe); + dev_dbg(&imgu->pci_dev->dev, "%s for pipe %d node %d", __func__, node->pipe, node->id); - } static int imgu_vb2_queue_setup(struct vb2_queue *vq, diff --git a/drivers/staging/media/ipu3/ipu3.c b/drivers/staging/media/ipu3/ipu3.c index d00d26264c37..17fe2cb4127d 100644 --- a/drivers/staging/media/ipu3/ipu3.c +++ b/drivers/staging/media/ipu3/ipu3.c @@ -236,6 +236,11 @@ int imgu_queue_buffers(struct imgu_device *imgu, bool initial, unsigned int pipe dev_dbg(&imgu->pci_dev->dev, "Queue buffers to pipe %d", pipe); mutex_lock(&imgu->lock); + if (!imgu_css_pipe_queue_empty(&imgu->css, pipe)) { + mutex_unlock(&imgu->lock); + return 0; + } + /* Buffer set is queued to FW only when input buffer is ready */ for (node = IMGU_NODE_NUM - 1; imgu_queue_getbuf(imgu, IMGU_NODE_IN, pipe); @@ -246,6 +251,31 @@ int imgu_queue_buffers(struct imgu_device *imgu, bool initial, unsigned int pipe dev_warn(&imgu->pci_dev->dev, "Vf not enabled, ignore queue"); continue; + } else if (node == IMGU_NODE_PARAMS && + imgu_pipe->nodes[node].enabled) { + struct vb2_buffer *vb; + struct imgu_vb2_buffer *ivb; + + /* No parameters for this frame */ + if (list_empty(&imgu_pipe->nodes[node].buffers)) + continue; + + ivb = list_first_entry(&imgu_pipe->nodes[node].buffers, + struct imgu_vb2_buffer, list); + vb = &ivb->vbb.vb2_buf; + r = imgu_css_set_parameters(&imgu->css, pipe, + vb2_plane_vaddr(vb, 0)); + if (r) { + vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); + dev_warn(&imgu->pci_dev->dev, + "set parameters failed."); + continue; + } + + vb2_buffer_done(vb, VB2_BUF_STATE_DONE); + dev_dbg(&imgu->pci_dev->dev, + "queue user parameters %d to css.", vb->index); + list_del(&ivb->list); } else if (imgu_pipe->queue_enabled[node]) { struct imgu_css_buffer *buf = imgu_queue_getbuf(imgu, node, pipe); From d38b24aab43d2b83fc57bf1186df05210ebb58b6 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 9 Apr 2019 04:06:54 -0400 Subject: [PATCH 174/218] media: ipu3-imgu: Use %u for formatting unsigned values (not %d) The driver used %d for formatting unsigned values. Use %u instead. Signed-off-by: Sakari Ailus Reviewed-by: Bingbu Cao Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/ipu3/ipu3-v4l2.c | 40 +++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/staging/media/ipu3/ipu3-v4l2.c b/drivers/staging/media/ipu3/ipu3-v4l2.c index be818c29620f..a7bc22040ed8 100644 --- a/drivers/staging/media/ipu3/ipu3-v4l2.c +++ b/drivers/staging/media/ipu3/ipu3-v4l2.c @@ -66,7 +66,7 @@ static int imgu_subdev_s_stream(struct v4l2_subdev *sd, int enable) struct imgu_css_pipe *css_pipe = &imgu->css.pipes[pipe]; struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[pipe]; - dev_dbg(dev, "%s %d for pipe %d", __func__, enable, pipe); + dev_dbg(dev, "%s %d for pipe %u", __func__, enable, pipe); /* grab ctrl after streamon and return after off */ v4l2_ctrl_grab(imgu_sd->ctrl, enable); @@ -101,7 +101,7 @@ static int imgu_subdev_s_stream(struct v4l2_subdev *sd, int enable) else css_pipe->pipe_id = IPU3_CSS_PIPE_ID_CAPTURE; - dev_dbg(dev, "IPU3 pipe %d pipe_id %d", pipe, css_pipe->pipe_id); + dev_dbg(dev, "IPU3 pipe %u pipe_id %u", pipe, css_pipe->pipe_id); rects[IPU3_CSS_RECT_EFFECTIVE] = &imgu_sd->rect.eff; rects[IPU3_CSS_RECT_BDS] = &imgu_sd->rect.bds; @@ -109,7 +109,7 @@ static int imgu_subdev_s_stream(struct v4l2_subdev *sd, int enable) r = imgu_css_fmt_set(&imgu->css, fmts, rects, pipe); if (r) { - dev_err(dev, "failed to set initial formats pipe %d with (%d)", + dev_err(dev, "failed to set initial formats pipe %u with (%d)", pipe, r); return r; } @@ -157,7 +157,7 @@ static int imgu_subdev_set_fmt(struct v4l2_subdev *sd, u32 pad = fmt->pad; unsigned int pipe = imgu_sd->pipe; - dev_dbg(&imgu->pci_dev->dev, "set subdev %d pad %d fmt to [%dx%d]", + dev_dbg(&imgu->pci_dev->dev, "set subdev %u pad %u fmt to [%ux%u]", pipe, pad, fmt->format.width, fmt->format.height); imgu_pipe = &imgu->imgu_pipe[pipe]; @@ -233,7 +233,7 @@ static int imgu_subdev_set_selection(struct v4l2_subdev *sd, struct v4l2_rect *rect, *try_sel; dev_dbg(&imgu->pci_dev->dev, - "set subdev %d sel which %d target 0x%4x rect [%dx%d]", + "set subdev %u sel which %u target 0x%4x rect [%ux%u]", imgu_sd->pipe, sel->which, sel->target, sel->r.width, sel->r.height); @@ -279,7 +279,7 @@ static int imgu_link_setup(struct media_entity *entity, WARN_ON(pad >= IMGU_NODE_NUM); - dev_dbg(&imgu->pci_dev->dev, "pipe %d pad %d is %s", pipe, pad, + dev_dbg(&imgu->pci_dev->dev, "pipe %u pad %u is %s", pipe, pad, flags & MEDIA_LNK_FL_ENABLED ? "enabled" : "disabled"); imgu_pipe = &imgu->imgu_pipe[pipe]; @@ -294,7 +294,7 @@ static int imgu_link_setup(struct media_entity *entity, else __clear_bit(pipe, imgu->css.enabled_pipes); - dev_dbg(&imgu->pci_dev->dev, "pipe %d is %s", pipe, + dev_dbg(&imgu->pci_dev->dev, "pipe %u is %s", pipe, flags & MEDIA_LNK_FL_ENABLED ? "enabled" : "disabled"); return 0; @@ -370,7 +370,7 @@ static void imgu_vb2_buf_queue(struct vb2_buffer *vb) if (imgu->streaming) imgu_queue_buffers(imgu, false, node->pipe); - dev_dbg(&imgu->pci_dev->dev, "%s for pipe %d node %d", __func__, + dev_dbg(&imgu->pci_dev->dev, "%s for pipe %u node %u", __func__, node->pipe, node->id); } @@ -421,7 +421,7 @@ static bool imgu_all_nodes_streaming(struct imgu_device *imgu, pipe = except->pipe; if (!test_bit(pipe, imgu->css.enabled_pipes)) { dev_warn(&imgu->pci_dev->dev, - "pipe %d link is not ready yet", pipe); + "pipe %u link is not ready yet", pipe); return false; } @@ -465,7 +465,7 @@ static int imgu_vb2_start_streaming(struct vb2_queue *vq, unsigned int count) int r; unsigned int pipe; - dev_dbg(dev, "%s node name %s pipe %d id %u", __func__, + dev_dbg(dev, "%s node name %s pipe %u id %u", __func__, node->name, node->pipe, node->id); if (imgu->streaming) { @@ -525,7 +525,7 @@ static void imgu_vb2_stop_streaming(struct vb2_queue *vq) WARN_ON(!node->enabled); pipe = node->pipe; - dev_dbg(dev, "Try to stream off node [%d][%d]", pipe, node->id); + dev_dbg(dev, "Try to stream off node [%u][%u]", pipe, node->id); imgu_pipe = &imgu->imgu_pipe[pipe]; r = v4l2_subdev_call(&imgu_pipe->imgu_sd.subdev, video, s_stream, 0); if (r) @@ -659,10 +659,10 @@ static int imgu_fmt(struct imgu_device *imgu, unsigned int pipe, int node, struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[pipe]; struct imgu_v4l2_subdev *imgu_sd = &imgu_pipe->imgu_sd; - dev_dbg(dev, "set fmt node [%u][%u](try = %d)", pipe, node, try); + dev_dbg(dev, "set fmt node [%u][%u](try = %u)", pipe, node, try); for (i = 0; i < IMGU_NODE_NUM; i++) - dev_dbg(dev, "IMGU pipe %d node %d enabled = %d", + dev_dbg(dev, "IMGU pipe %u node %u enabled = %u", pipe, i, imgu_pipe->nodes[i].enabled); if (imgu_pipe->nodes[IMGU_NODE_VF].enabled) @@ -673,7 +673,7 @@ static int imgu_fmt(struct imgu_device *imgu, unsigned int pipe, int node, else css_pipe->pipe_id = IPU3_CSS_PIPE_ID_CAPTURE; - dev_dbg(dev, "IPU3 pipe %d pipe_id = %d", pipe, css_pipe->pipe_id); + dev_dbg(dev, "IPU3 pipe %u pipe_id = %u", pipe, css_pipe->pipe_id); for (i = 0; i < IPU3_CSS_QUEUES; i++) { unsigned int inode = imgu_map_node(imgu, i); @@ -777,7 +777,7 @@ static int imgu_vidioc_try_fmt(struct file *file, void *fh, struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; int r; - dev_dbg(dev, "%s [%ux%u] for node %d\n", __func__, + dev_dbg(dev, "%s [%ux%u] for node %u\n", __func__, pix_mp->width, pix_mp->height, node->id); r = imgu_try_fmt(file, fh, f); @@ -795,7 +795,7 @@ static int imgu_vidioc_s_fmt(struct file *file, void *fh, struct v4l2_format *f) struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; int r; - dev_dbg(dev, "%s [%ux%u] for node %d\n", __func__, + dev_dbg(dev, "%s [%ux%u] for node %u\n", __func__, pix_mp->width, pix_mp->height, node->id); r = imgu_try_fmt(file, fh, f); @@ -1018,7 +1018,7 @@ static int imgu_sd_s_ctrl(struct v4l2_ctrl *ctrl) struct imgu_device *imgu = v4l2_get_subdevdata(&imgu_sd->subdev); struct device *dev = &imgu->pci_dev->dev; - dev_dbg(dev, "set val %d to ctrl 0x%8x for subdev %d", + dev_dbg(dev, "set val %d to ctrl 0x%8x for subdev %u", ctrl->val, ctrl->id, imgu_sd->pipe); switch (ctrl->id) { @@ -1118,7 +1118,7 @@ static int imgu_v4l2_subdev_register(struct imgu_device *imgu, imgu_sd->subdev.flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; snprintf(imgu_sd->subdev.name, sizeof(imgu_sd->subdev.name), - "%s %d", IMGU_NAME, pipe); + "%s %u", IMGU_NAME, pipe); v4l2_set_subdevdata(&imgu_sd->subdev, imgu); atomic_set(&imgu_sd->running_mode, IPU3_RUNNING_MODE_VIDEO); v4l2_ctrl_handler_init(hdl, 1); @@ -1236,7 +1236,7 @@ static int imgu_v4l2_node_setup(struct imgu_device *imgu, unsigned int pipe, } /* Initialize vdev */ - snprintf(vdev->name, sizeof(vdev->name), "%s %d %s", + snprintf(vdev->name, sizeof(vdev->name), "%s %u %s", IMGU_NAME, pipe, node->name); vdev->release = video_device_release_empty; vdev->fops = &imgu_v4l2_fops; @@ -1331,7 +1331,7 @@ static int imgu_v4l2_register_pipes(struct imgu_device *imgu) r = imgu_v4l2_subdev_register(imgu, &imgu_pipe->imgu_sd, i); if (r) { dev_err(&imgu->pci_dev->dev, - "failed to register subdev%d ret (%d)\n", i, r); + "failed to register subdev%u ret (%d)\n", i, r); goto pipes_cleanup; } r = imgu_v4l2_nodes_setup_pipe(imgu, i); From 411a414b26aa107ddbbd6995e464f6cc18a1aa8c Mon Sep 17 00:00:00 2001 From: Maoguang Meng Date: Mon, 1 Apr 2019 04:18:38 -0400 Subject: [PATCH 175/218] media: mtk-vcodec: fix vp9 content playback error with show exist frame Update referenced frame buffer's reference count when playing vp9 content which has show_existing_frame flag, and copy enough buffer data to current shown frame. Signed-off-by: Maoguang Meng Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/mtk-vcodec/vdec/vdec_vp9_if.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c index 6fe83207bbc4..939ea14bf6c5 100644 --- a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c +++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c @@ -481,15 +481,15 @@ static void vp9_swap_frm_bufs(struct vdec_vp9_inst *inst) */ if ((frm_to_show->fb != NULL) && (inst->cur_fb->base_y.size >= - frm_to_show->fb->base_y.size)) { + frm_to_show->fb->base_y.size) && + (inst->cur_fb->base_c.size >= + frm_to_show->fb->base_c.size)) { memcpy((void *)inst->cur_fb->base_y.va, (void *)frm_to_show->fb->base_y.va, - vsi->buf_w * - vsi->buf_h); + frm_to_show->fb->base_y.size); memcpy((void *)inst->cur_fb->base_c.va, (void *)frm_to_show->fb->base_c.va, - vsi->buf_w * - vsi->buf_h / 2); + frm_to_show->fb->base_c.size); } else { /* After resolution change case, current CAPTURE buffer * may have less buffer size than frm_to_show buffer @@ -894,7 +894,7 @@ static int vdec_vp9_decode(unsigned long h_vdec, struct mtk_vcodec_mem *bs, if (vsi->resolution_changed) { if (!vp9_alloc_work_buf(inst)) { - ret = -EINVAL; + ret = -EIO; goto DECODE_ERROR; } } @@ -923,14 +923,12 @@ static int vdec_vp9_decode(unsigned long h_vdec, struct mtk_vcodec_mem *bs, if (vsi->show_existing_frame && (vsi->frm_to_show_idx < VP9_MAX_FRM_BUF_NUM)) { - mtk_vcodec_err(inst, + mtk_vcodec_debug(inst, "Skip Decode drv->new_fb_idx=%d, drv->frm_to_show_idx=%d", vsi->new_fb_idx, vsi->frm_to_show_idx); vp9_ref_cnt_fb(inst, &vsi->new_fb_idx, vsi->frm_to_show_idx); - ret = -EINVAL; - goto DECODE_ERROR; } /* VPU assign the buffer pointer in its address space, From 1f7f11e8ca15366e6c1e62e4d4dc5d1ecb3b2eb4 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 1 Apr 2019 08:41:58 -0400 Subject: [PATCH 176/218] media: videobuf2-v4l2.c: move up STATE_DEQUEUED check If a buffer is queued to a request, followed by an attempt to queue the same buffer again, then the second qbuf returns an error since the buffer is not in the DEQUEUED state anymore. However, before it gets to that check it executes the code under the 'if (!vb->prepared)' condition. This clears previously set data needed for request handling, and now querybuf will no longer report that this buffer is part of a request. Move the state check to before the 'if' and make sure to only do the state check when called from QBUF and if V4L2_BUF_FLAG_REQUEST_FD is set. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/videobuf2/videobuf2-v4l2.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c index 1c3147275785..fb9ac7696fc6 100644 --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c @@ -368,6 +368,12 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md if (ret) return ret; + if (!is_prepare && (b->flags & V4L2_BUF_FLAG_REQUEST_FD) && + vb->state != VB2_BUF_STATE_DEQUEUED) { + dprintk(1, "%s: buffer is not in dequeued state\n", opname); + return -EINVAL; + } + if (!vb->prepared) { /* Copy relevant information provided by the userspace */ memset(vbuf->planes, 0, @@ -423,11 +429,6 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md !q->ops->buf_out_validate)) return -EINVAL; - if (vb->state != VB2_BUF_STATE_DEQUEUED) { - dprintk(1, "%s: buffer is not in dequeued state\n", opname); - return -EINVAL; - } - if (b->request_fd < 0) { dprintk(1, "%s: request_fd < 0\n", opname); return -EINVAL; From dad7e270ba712ba1c99cd2d91018af6044447a06 Mon Sep 17 00:00:00 2001 From: Alexander Potapenko Date: Thu, 4 Apr 2019 10:56:46 -0400 Subject: [PATCH 177/218] media: vivid: use vfree() instead of kfree() for dev->bitmap_cap syzkaller reported crashes on kfree() called from vivid_vid_cap_s_selection(). This looks like a simple typo, as dev->bitmap_cap is allocated with vzalloc() throughout the file. Fixes: ef834f7836ec0 ("[media] vivid: add the video capture and output parts") Signed-off-by: Alexander Potapenko Reported-by: Syzbot Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vivid/vivid-vid-cap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c index 52eeda624d7e..530ac8decb25 100644 --- a/drivers/media/platform/vivid/vivid-vid-cap.c +++ b/drivers/media/platform/vivid/vivid-vid-cap.c @@ -1007,7 +1007,7 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection v4l2_rect_map_inside(&s->r, &dev->fmt_cap_rect); if (dev->bitmap_cap && (compose->width != s->r.width || compose->height != s->r.height)) { - kfree(dev->bitmap_cap); + vfree(dev->bitmap_cap); dev->bitmap_cap = NULL; } *compose = s->r; From bac875349f8525a75760d0eee525186cb59658ea Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Sun, 7 Apr 2019 14:47:28 -0400 Subject: [PATCH 178/218] media: cedrus: Fix initialization order Currently, MEDIA_IOC_G_TOPOLOGY ioctl on cedrus fails due to incorrect initialization order. Fix that by moving video_register_device() before v4l2_m2m_register_media_controller() and while at it, fix error path. Reported-by: Jonas Karlman Signed-off-by: Jernej Skrabec Acked-by: Paul Kocialkowski Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/sunxi/cedrus/cedrus.c | 26 ++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c index b98add3cdedd..d0429c0e6b6b 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus.c @@ -300,7 +300,7 @@ static int cedrus_probe(struct platform_device *pdev) "Failed to initialize V4L2 M2M device\n"); ret = PTR_ERR(dev->m2m_dev); - goto err_video; + goto err_v4l2; } dev->mdev.dev = &pdev->dev; @@ -310,23 +310,23 @@ static int cedrus_probe(struct platform_device *pdev) dev->mdev.ops = &cedrus_m2m_media_ops; dev->v4l2_dev.mdev = &dev->mdev; + ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); + if (ret) { + v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); + goto err_m2m; + } + + v4l2_info(&dev->v4l2_dev, + "Device registered as /dev/video%d\n", vfd->num); + ret = v4l2_m2m_register_media_controller(dev->m2m_dev, vfd, MEDIA_ENT_F_PROC_VIDEO_DECODER); if (ret) { v4l2_err(&dev->v4l2_dev, "Failed to initialize V4L2 M2M media controller\n"); - goto err_m2m; + goto err_video; } - ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); - if (ret) { - v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); - goto err_v4l2; - } - - v4l2_info(&dev->v4l2_dev, - "Device registered as /dev/video%d\n", vfd->num); - ret = media_device_register(&dev->mdev); if (ret) { v4l2_err(&dev->v4l2_dev, "Failed to register media device\n"); @@ -339,10 +339,10 @@ static int cedrus_probe(struct platform_device *pdev) err_m2m_mc: v4l2_m2m_unregister_media_controller(dev->m2m_dev); -err_m2m: - v4l2_m2m_release(dev->m2m_dev); err_video: video_unregister_device(&dev->vfd); +err_m2m: + v4l2_m2m_release(dev->m2m_dev); err_v4l2: v4l2_device_unregister(&dev->v4l2_dev); From c1ced46c7b49ad7bc064e68d966e0ad303f917fb Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 8 Apr 2019 05:52:38 -0400 Subject: [PATCH 179/218] media: pvrusb2: Prevent a buffer overflow The ctrl_check_input() function is called from pvr2_ctrl_range_check(). It's supposed to validate user supplied input and return true or false depending on whether the input is valid or not. The problem is that negative shifts or shifts greater than 31 are undefined in C. In practice with GCC they result in shift wrapping so this function returns true for some inputs which are not valid and this could result in a buffer overflow: drivers/media/usb/pvrusb2/pvrusb2-ctrl.c:205 pvr2_ctrl_get_valname() warn: uncapped user index 'names[val]' The cptr->hdw->input_allowed_mask mask is configured in pvr2_hdw_create() and the highest valid bit is BIT(4). Fixes: 7fb20fa38caa ("V4L/DVB (7299): pvrusb2: Improve logic which handles input choice availability") Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/pvrusb2/pvrusb2-hdw.c | 2 ++ drivers/media/usb/pvrusb2/pvrusb2-hdw.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index 51112b7988e4..816c85786c2a 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -666,6 +666,8 @@ static int ctrl_get_input(struct pvr2_ctrl *cptr,int *vp) static int ctrl_check_input(struct pvr2_ctrl *cptr,int v) { + if (v < 0 || v > PVR2_CVAL_INPUT_MAX) + return 0; return ((1 << v) & cptr->hdw->input_allowed_mask) != 0; } diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.h b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h index 25648add77e5..bd2b7a67b732 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h @@ -50,6 +50,7 @@ #define PVR2_CVAL_INPUT_COMPOSITE 2 #define PVR2_CVAL_INPUT_SVIDEO 3 #define PVR2_CVAL_INPUT_RADIO 4 +#define PVR2_CVAL_INPUT_MAX PVR2_CVAL_INPUT_RADIO enum pvr2_config { pvr2_config_empty, /* No configuration */ From d65842f7126aa1a87fb44b7c9980c12630ed4f33 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 19 Nov 2018 06:09:00 -0500 Subject: [PATCH 180/218] media: vb2: add waiting_in_dqbuf flag Calling VIDIOC_DQBUF can release the core serialization lock pointed to by vb2_queue->lock if it has to wait for a new buffer to arrive. However, if userspace dup()ped the video device filehandle, then it is possible to read or call DQBUF from two filehandles at the same time. It is also possible to call REQBUFS from one filehandle while the other is waiting for a buffer. This will remove all the buffers and reallocate new ones. Removing all the buffers isn't the problem here (that's already handled correctly by DQBUF), but the reallocating part is: DQBUF isn't aware that the buffers have changed. This is fixed by setting a flag whenever the lock is released while waiting for a buffer to arrive. And checking the flag where needed so we can return -EBUSY. Signed-off-by: Hans Verkuil Reported-by: Syzbot Reviewed-by: Tomasz Figa Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/common/videobuf2/videobuf2-core.c | 22 +++++++++++++++++++ include/media/videobuf2-core.h | 1 + 2 files changed, 23 insertions(+) diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index b98ec6e1a222..7ebd58a1c431 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c +++ b/drivers/media/common/videobuf2/videobuf2-core.c @@ -672,6 +672,11 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory, return -EBUSY; } + if (q->waiting_in_dqbuf && *count) { + dprintk(1, "another dup()ped fd is waiting for a buffer\n"); + return -EBUSY; + } + if (*count == 0 || q->num_buffers != 0 || (q->memory != VB2_MEMORY_UNKNOWN && q->memory != memory)) { /* @@ -807,6 +812,10 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory, } if (!q->num_buffers) { + if (q->waiting_in_dqbuf && *count) { + dprintk(1, "another dup()ped fd is waiting for a buffer\n"); + return -EBUSY; + } memset(q->alloc_devs, 0, sizeof(q->alloc_devs)); q->memory = memory; q->waiting_for_buffers = !q->is_output; @@ -1656,6 +1665,11 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking) for (;;) { int ret; + if (q->waiting_in_dqbuf) { + dprintk(1, "another dup()ped fd is waiting for a buffer\n"); + return -EBUSY; + } + if (!q->streaming) { dprintk(1, "streaming off, will not wait for buffers\n"); return -EINVAL; @@ -1683,6 +1697,7 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking) return -EAGAIN; } + q->waiting_in_dqbuf = 1; /* * We are streaming and blocking, wait for another buffer to * become ready or for streamoff. Driver's lock is released to @@ -1703,6 +1718,7 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking) * the locks or return an error if one occurred. */ call_void_qop(q, wait_finish, q); + q->waiting_in_dqbuf = 0; if (ret) { dprintk(1, "sleep was interrupted\n"); return ret; @@ -2585,6 +2601,12 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_ if (!data) return -EINVAL; + if (q->waiting_in_dqbuf) { + dprintk(3, "another dup()ped fd is %s\n", + read ? "reading" : "writing"); + return -EBUSY; + } + /* * Initialize emulator on first call. */ diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index fe010ad62b90..22f3ff76a8b5 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -596,6 +596,7 @@ struct vb2_queue { unsigned int start_streaming_called:1; unsigned int error:1; unsigned int waiting_for_buffers:1; + unsigned int waiting_in_dqbuf:1; unsigned int is_multiplanar:1; unsigned int is_output:1; unsigned int copy_timestamp:1; From 75480ebf49662d10550a32ecd76702fbf0716331 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 8 Apr 2019 08:32:47 -0400 Subject: [PATCH 181/218] media: coda: set codec earlier The chosen codec depends on the coded format, which is known as soon as the S_FMT call on the coded queue. This allows to use the codec in callbacks that may be called before start_streaming, such as buf_queue. Signed-off-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 28 ++++++++++++++++------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index fa0b22fb7991..a403bc2995b4 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -764,6 +764,7 @@ static int coda_s_fmt_vid_cap(struct file *file, void *priv, { struct coda_ctx *ctx = fh_to_ctx(priv); struct coda_q_data *q_data_src; + const struct coda_codec *codec; struct v4l2_rect r; int ret; @@ -784,6 +785,15 @@ static int coda_s_fmt_vid_cap(struct file *file, void *priv, if (ctx->inst_type != CODA_INST_ENCODER) return 0; + /* Setting the coded format determines the selected codec */ + codec = coda_find_codec(ctx->dev, q_data_src->fourcc, + f->fmt.pix.pixelformat); + if (!codec) { + v4l2_err(&ctx->dev->v4l2_dev, "failed to determine codec\n"); + return -EINVAL; + } + ctx->codec = codec; + ctx->colorspace = f->fmt.pix.colorspace; ctx->xfer_func = f->fmt.pix.xfer_func; ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc; @@ -796,6 +806,7 @@ static int coda_s_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { struct coda_ctx *ctx = fh_to_ctx(priv); + const struct coda_codec *codec; struct v4l2_format f_cap; struct vb2_queue *dst_vq; int ret; @@ -811,6 +822,15 @@ static int coda_s_fmt_vid_out(struct file *file, void *priv, if (ctx->inst_type != CODA_INST_DECODER) return 0; + /* Setting the coded format determines the selected codec */ + codec = coda_find_codec(ctx->dev, f->fmt.pix.pixelformat, + V4L2_PIX_FMT_YUV420); + if (!codec) { + v4l2_err(&ctx->dev->v4l2_dev, "failed to determine codec\n"); + return -EINVAL; + } + ctx->codec = codec; + ctx->colorspace = f->fmt.pix.colorspace; ctx->xfer_func = f->fmt.pix.xfer_func; ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc; @@ -1680,14 +1700,6 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) ctx->gopcounter = ctx->params.gop_size - 1; - ctx->codec = coda_find_codec(ctx->dev, q_data_src->fourcc, - q_data_dst->fourcc); - if (!ctx->codec) { - v4l2_err(v4l2_dev, "couldn't tell instance type.\n"); - ret = -EINVAL; - goto err; - } - if (q_data_dst->fourcc == V4L2_PIX_FMT_JPEG) ctx->params.gop_size = 1; ctx->gopcounter = ctx->params.gop_size - 1; From be9dd094e8f38873ba2db49e3edf5f8aab3679d7 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 8 Apr 2019 08:32:48 -0400 Subject: [PATCH 182/218] media: coda: remove mask from decoder h.264 level control Since levels are specified in terms of maximum values, there is no reason to filter out lower levels than the supported maximum. Signed-off-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index a403bc2995b4..de608de62908 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -2027,7 +2027,6 @@ static void coda_jpeg_encode_ctrls(struct coda_ctx *ctx) static void coda_decode_ctrls(struct coda_ctx *ctx) { - u64 mask; u8 max; ctx->h264_profile_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls, @@ -2041,27 +2040,14 @@ static void coda_decode_ctrls(struct coda_ctx *ctx) ctx->h264_profile_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; if (ctx->dev->devtype->product == CODA_HX4 || - ctx->dev->devtype->product == CODA_7541) { + ctx->dev->devtype->product == CODA_7541) max = V4L2_MPEG_VIDEO_H264_LEVEL_4_0; - mask = ~((1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | - (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | - (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | - (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | - (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_0)); - } else if (ctx->dev->devtype->product == CODA_960) { + else if (ctx->dev->devtype->product == CODA_960) max = V4L2_MPEG_VIDEO_H264_LEVEL_4_1; - mask = ~((1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | - (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | - (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | - (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | - (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | - (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_1)); - } else { + else return; - } ctx->h264_level_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls, - &coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_H264_LEVEL, max, mask, - max); + &coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_H264_LEVEL, max, 0, max); if (ctx->h264_level_ctrl) ctx->h264_level_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; } From bbeefa7357a648afe70e7183914c87c3878d528d Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 8 Apr 2019 08:32:49 -0400 Subject: [PATCH 183/218] media: coda: clear error return value before picture run The error return value is not written by some firmware codecs, such as MPEG-2 decode on CodaHx4. Clear the error return value before starting the picture run to avoid misinterpreting unrelated values returned by sequence initialization as error return value. Signed-off-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-bit.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c index b4f396c2e72c..eaa86737fa04 100644 --- a/drivers/media/platform/coda/coda-bit.c +++ b/drivers/media/platform/coda/coda-bit.c @@ -2010,6 +2010,9 @@ static int coda_prepare_decode(struct coda_ctx *ctx) /* Clear decode success flag */ coda_write(dev, 0, CODA_RET_DEC_PIC_SUCCESS); + /* Clear error return value */ + coda_write(dev, 0, CODA_RET_DEC_PIC_ERR_MB); + trace_coda_dec_pic_run(ctx, meta); coda_command_async(ctx, CODA_COMMAND_PIC_RUN); From c1b6761e1f4ea9ca6e858c4b0d6fd5461786f2b9 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 8 Apr 2019 08:32:50 -0400 Subject: [PATCH 184/218] media: coda: add min number of buffers controls Add min number of buffers for capture (decoder) and output (encoder) controls, which are required by the stateful video decoder / encoder interface specification. Signed-off-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index de608de62908..f1d3fb17784a 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -2061,11 +2061,17 @@ static int coda_ctrls_setup(struct coda_ctx *ctx) v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0); if (ctx->inst_type == CODA_INST_ENCODER) { + v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, + V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, + 1, 1, 1, 1); if (ctx->cvd->dst_formats[0] == V4L2_PIX_FMT_JPEG) coda_jpeg_encode_ctrls(ctx); else coda_encode_ctrls(ctx); } else { + v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, + V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, + 1, 1, 1, 1); if (ctx->cvd->src_formats[0] == V4L2_PIX_FMT_H264) coda_decode_ctrls(ctx); } From 784867d2135a1a8ebc213bcc3ca26283a2c0d9b8 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 8 Apr 2019 08:32:51 -0400 Subject: [PATCH 185/218] media: coda: disable encoder command on decoder and vice versa Return -ENOTTY when userspace tries to call VIDIOC_(TRY_)ENCODER_CMD on a decoder instance or VIDIOC_(TRY_)DECODER_CMD on an encoder instance. Signed-off-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index f1d3fb17784a..c0421f06ca48 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -1000,6 +1000,11 @@ static int coda_s_selection(struct file *file, void *fh, static int coda_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *ec) { + struct coda_ctx *ctx = fh_to_ctx(fh); + + if (ctx->inst_type != CODA_INST_ENCODER) + return -ENOTTY; + if (ec->cmd != V4L2_ENC_CMD_STOP) return -EINVAL; @@ -1020,10 +1025,6 @@ static int coda_encoder_cmd(struct file *file, void *fh, if (ret < 0) return ret; - /* Ignore encoder stop command silently in decoder context */ - if (ctx->inst_type != CODA_INST_ENCODER) - return 0; - /* Set the stream-end flag on this context */ ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; @@ -1041,6 +1042,11 @@ static int coda_encoder_cmd(struct file *file, void *fh, static int coda_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dc) { + struct coda_ctx *ctx = fh_to_ctx(fh); + + if (ctx->inst_type != CODA_INST_DECODER) + return -ENOTTY; + if (dc->cmd != V4L2_DEC_CMD_STOP) return -EINVAL; @@ -1063,10 +1069,6 @@ static int coda_decoder_cmd(struct file *file, void *fh, if (ret < 0) return ret; - /* Ignore decoder stop command silently in encoder context */ - if (ctx->inst_type != CODA_INST_DECODER) - return 0; - /* Set the stream-end flag on this context */ coda_bit_stream_end_flag(ctx); ctx->hold = false; From b03abe535d3734601d2e926b2f5e31745b29825b Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 8 Apr 2019 08:32:52 -0400 Subject: [PATCH 186/218] media: coda: implement encoder frame size enumeration The stateful encoder API requires VIDIOC_ENUM_FRAMESIZES to be implemented. Allow enumeration of supported frame sizes for encoding. Signed-off-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 37 +++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index c0421f06ca48..943f003c26c4 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -1077,6 +1077,42 @@ static int coda_decoder_cmd(struct file *file, void *fh, return 0; } +static int coda_enum_framesizes(struct file *file, void *fh, + struct v4l2_frmsizeenum *fsize) +{ + struct coda_ctx *ctx = fh_to_ctx(fh); + struct coda_q_data *q_data_dst; + const struct coda_codec *codec; + + if (ctx->inst_type != CODA_INST_ENCODER) + return -ENOTTY; + + if (fsize->index) + return -EINVAL; + + if (coda_format_normalize_yuv(fsize->pixel_format) == + V4L2_PIX_FMT_YUV420) { + q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); + codec = coda_find_codec(ctx->dev, fsize->pixel_format, + q_data_dst->fourcc); + } else { + codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420, + fsize->pixel_format); + } + if (!codec) + return -EINVAL; + + fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; + fsize->stepwise.min_width = MIN_W; + fsize->stepwise.max_width = codec->max_w; + fsize->stepwise.step_width = 1; + fsize->stepwise.min_height = MIN_H; + fsize->stepwise.max_height = codec->max_h; + fsize->stepwise.step_height = 1; + + return 0; +} + static int coda_enum_frameintervals(struct file *file, void *fh, struct v4l2_frmivalenum *f) { @@ -1255,6 +1291,7 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = { .vidioc_g_parm = coda_g_parm, .vidioc_s_parm = coda_s_parm, + .vidioc_enum_framesizes = coda_enum_framesizes, .vidioc_enum_frameintervals = coda_enum_frameintervals, .vidioc_subscribe_event = coda_subscribe_event, From 01ba2e65e445d9cc5fb87ba1136f7b693dfb92dc Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 8 Apr 2019 08:32:54 -0400 Subject: [PATCH 187/218] media: coda: allow encoder to set colorimetry on the output queue v4l2-compliance sets colorimetry on the output queue and then verifies that querying colorimetry on the capture queue returns the same configuration. For this to work, the encoder must allow setting context colorimetry parameters on the output queue. Signed-off-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index 943f003c26c4..a89d92f5539f 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -819,6 +819,11 @@ static int coda_s_fmt_vid_out(struct file *file, void *priv, if (ret) return ret; + ctx->colorspace = f->fmt.pix.colorspace; + ctx->xfer_func = f->fmt.pix.xfer_func; + ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc; + ctx->quantization = f->fmt.pix.quantization; + if (ctx->inst_type != CODA_INST_DECODER) return 0; @@ -831,11 +836,6 @@ static int coda_s_fmt_vid_out(struct file *file, void *priv, } ctx->codec = codec; - ctx->colorspace = f->fmt.pix.colorspace; - ctx->xfer_func = f->fmt.pix.xfer_func; - ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc; - ctx->quantization = f->fmt.pix.quantization; - dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); if (!dst_vq) return -EINVAL; From 0eecc61947ed329659a9fa9ef7d0959b1c84259d Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 8 Apr 2019 08:32:55 -0400 Subject: [PATCH 188/218] media: coda: throw error on create_bufs with too small size If VIDIOC_CREATE_BUFS is called with a sizeimage smaller than the queue sizeimage, fail with -EINVAL instead of correcting the size and continuing without error. This is required by v4l2-compliance. Signed-off-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index a89d92f5539f..3ce58dee4422 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -1501,6 +1501,9 @@ static int coda_queue_setup(struct vb2_queue *vq, q_data = get_q_data(ctx, vq->type); size = q_data->sizeimage; + if (*nplanes) + return sizes[0] < size ? -EINVAL : 0; + *nplanes = 1; sizes[0] = size; From ffaebccddef0a6320643a9d1c911190db579c09f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Tue, 12 Mar 2019 19:49:29 -0400 Subject: [PATCH 189/218] media: dt-bindings: rcar-csi2: List resets as a mandatory property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The resets property will become mandatory to operate the device, list it as such. All device tree source files have always included the reset property so making it mandatory will not introduce any regressions. While at it improve the description for the clocks property. Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart Reviewed-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt b/Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt index 9932458a0a45..331409259752 100644 --- a/Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt +++ b/Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt @@ -19,7 +19,8 @@ Mandatory properties - reg: the register base and size for the device registers - interrupts: the interrupt for the device - - clocks: reference to the parent clock + - clocks: A phandle + clock specifier for the module clock + - resets: A phandle + reset specifier for the module reset The device node shall contain two 'port' child nodes according to the bindings defined in Documentation/devicetree/bindings/media/ From d245a940d97b5cd0dd4eecd9530fa9ff4c5938c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Tue, 12 Mar 2019 19:49:30 -0400 Subject: [PATCH 190/218] media: rcar-csi2: Use standby mode instead of resetting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Later versions of the datasheet updates the reset procedure to more closely resemble the standby mode. Update the driver to enter and exit the standby mode instead of resetting the hardware before and after streaming is started and stopped. This replaces the software reset (SRST.SRST) control. While at it break out the full start and stop procedures from rcsi2_s_stream() into the existing helper functions. Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/Kconfig | 1 + drivers/media/platform/rcar-vin/rcar-csi2.c | 69 +++++++++++++-------- 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/drivers/media/platform/rcar-vin/Kconfig b/drivers/media/platform/rcar-vin/Kconfig index 2433ec960010..240ac3f3c941 100644 --- a/drivers/media/platform/rcar-vin/Kconfig +++ b/drivers/media/platform/rcar-vin/Kconfig @@ -3,6 +3,7 @@ config VIDEO_RCAR_CSI2 tristate "R-Car MIPI CSI-2 Receiver" depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && OF depends on ARCH_RENESAS || COMPILE_TEST + select RESET_CONTROLLER select V4L2_FWNODE help Support for Renesas R-Car MIPI CSI-2 receiver. diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index a438ec2c218f..75a77fd8d98c 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -350,6 +351,7 @@ struct rcar_csi2 { struct device *dev; void __iomem *base; const struct rcar_csi2_info *info; + struct reset_control *rstc; struct v4l2_subdev subdev; struct media_pad pads[NR_OF_RCAR_CSI2_PAD]; @@ -387,11 +389,19 @@ static void rcsi2_write(struct rcar_csi2 *priv, unsigned int reg, u32 data) iowrite32(data, priv->base + reg); } -static void rcsi2_reset(struct rcar_csi2 *priv) +static void rcsi2_enter_standby(struct rcar_csi2 *priv) { - rcsi2_write(priv, SRST_REG, SRST_SRST); + rcsi2_write(priv, PHYCNT_REG, 0); + rcsi2_write(priv, PHTC_REG, PHTC_TESTCLR); + reset_control_assert(priv->rstc); usleep_range(100, 150); - rcsi2_write(priv, SRST_REG, 0); + pm_runtime_put(priv->dev); +} + +static void rcsi2_exit_standby(struct rcar_csi2 *priv) +{ + pm_runtime_get_sync(priv->dev); + reset_control_deassert(priv->rstc); } static int rcsi2_wait_phy_start(struct rcar_csi2 *priv) @@ -462,7 +472,7 @@ static int rcsi2_calc_mbps(struct rcar_csi2 *priv, unsigned int bpp) return mbps; } -static int rcsi2_start(struct rcar_csi2 *priv) +static int rcsi2_start_receiver(struct rcar_csi2 *priv) { const struct rcar_csi2_format *format; u32 phycnt, vcdt = 0, vcdt2 = 0; @@ -506,7 +516,6 @@ static int rcsi2_start(struct rcar_csi2 *priv) /* Init */ rcsi2_write(priv, TREF_REG, TREF_TREF); - rcsi2_reset(priv); rcsi2_write(priv, PHTC_REG, 0); /* Configure */ @@ -564,19 +573,36 @@ static int rcsi2_start(struct rcar_csi2 *priv) return 0; } +static int rcsi2_start(struct rcar_csi2 *priv) +{ + int ret; + + rcsi2_exit_standby(priv); + + ret = rcsi2_start_receiver(priv); + if (ret) { + rcsi2_enter_standby(priv); + return ret; + } + + ret = v4l2_subdev_call(priv->remote, video, s_stream, 1); + if (ret) { + rcsi2_enter_standby(priv); + return ret; + } + + return 0; +} + static void rcsi2_stop(struct rcar_csi2 *priv) { - rcsi2_write(priv, PHYCNT_REG, 0); - - rcsi2_reset(priv); - - rcsi2_write(priv, PHTC_REG, PHTC_TESTCLR); + rcsi2_enter_standby(priv); + v4l2_subdev_call(priv->remote, video, s_stream, 0); } static int rcsi2_s_stream(struct v4l2_subdev *sd, int enable) { struct rcar_csi2 *priv = sd_to_csi2(sd); - struct v4l2_subdev *nextsd; int ret = 0; mutex_lock(&priv->lock); @@ -586,27 +612,12 @@ static int rcsi2_s_stream(struct v4l2_subdev *sd, int enable) goto out; } - nextsd = priv->remote; - if (enable && priv->stream_count == 0) { - pm_runtime_get_sync(priv->dev); - ret = rcsi2_start(priv); - if (ret) { - pm_runtime_put(priv->dev); + if (ret) goto out; - } - - ret = v4l2_subdev_call(nextsd, video, s_stream, 1); - if (ret) { - rcsi2_stop(priv); - pm_runtime_put(priv->dev); - goto out; - } } else if (!enable && priv->stream_count == 1) { rcsi2_stop(priv); - v4l2_subdev_call(nextsd, video, s_stream, 0); - pm_runtime_put(priv->dev); } priv->stream_count += enable ? 1 : -1; @@ -936,6 +947,10 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv, if (irq < 0) return irq; + priv->rstc = devm_reset_control_get(&pdev->dev, NULL); + if (IS_ERR(priv->rstc)) + return PTR_ERR(priv->rstc); + return 0; } From c1421f1d6c29d6b6234e5b0894ef16b3f2a172e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Tue, 12 Mar 2019 19:50:17 -0400 Subject: [PATCH 191/218] media: rcar-csi2: Update V3M and E3 start procedure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The latest datasheet (rev 1.50) updates the start procedure for V3M and E3. Update the driver to match these changes. Signed-off-by: Niklas Söderlund Reviewed-by: Ulrich Hecht Reviewed-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-csi2.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index 75a77fd8d98c..c39a0c7593fe 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -913,11 +913,11 @@ static int rcsi2_init_phtw_v3m_e3(struct rcar_csi2 *priv, unsigned int mbps) static int rcsi2_confirm_start_v3m_e3(struct rcar_csi2 *priv) { static const struct phtw_value step1[] = { - { .data = 0xed, .code = 0x34 }, - { .data = 0xed, .code = 0x44 }, - { .data = 0xed, .code = 0x54 }, - { .data = 0xed, .code = 0x84 }, - { .data = 0xed, .code = 0x94 }, + { .data = 0xee, .code = 0x34 }, + { .data = 0xee, .code = 0x44 }, + { .data = 0xee, .code = 0x54 }, + { .data = 0xee, .code = 0x84 }, + { .data = 0xee, .code = 0x94 }, { /* sentinel */ }, }; From cb5585797afd06838e6214ebed9a715e12f08980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Tue, 12 Mar 2019 19:50:18 -0400 Subject: [PATCH 192/218] media: rcar-csi2: Update start procedure for H3 ES2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Latest information from hardware engineers reveals that H3 ES2 and ES3 behave differently when working with link speeds bellow 250 Mpbs. Add a SoC match for H3 ES2.* and use the correct startup sequence. Signed-off-by: Niklas Söderlund Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-csi2.c | 35 +++++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index c39a0c7593fe..73c51e9d4a1a 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -865,7 +865,8 @@ static int rcsi2_phtw_write_mbps(struct rcar_csi2 *priv, unsigned int mbps, return rcsi2_phtw_write(priv, value->reg, code); } -static int rcsi2_init_phtw_h3_v3h_m3n(struct rcar_csi2 *priv, unsigned int mbps) +static int __rcsi2_init_phtw_h3_v3h_m3n(struct rcar_csi2 *priv, + unsigned int mbps) { static const struct phtw_value step1[] = { { .data = 0xcc, .code = 0xe2 }, @@ -891,7 +892,7 @@ static int rcsi2_init_phtw_h3_v3h_m3n(struct rcar_csi2 *priv, unsigned int mbps) if (ret) return ret; - if (mbps <= 250) { + if (mbps != 0 && mbps <= 250) { ret = rcsi2_phtw_write(priv, 0x39, 0x05); if (ret) return ret; @@ -905,6 +906,16 @@ static int rcsi2_init_phtw_h3_v3h_m3n(struct rcar_csi2 *priv, unsigned int mbps) return rcsi2_phtw_write_array(priv, step2); } +static int rcsi2_init_phtw_h3_v3h_m3n(struct rcar_csi2 *priv, unsigned int mbps) +{ + return __rcsi2_init_phtw_h3_v3h_m3n(priv, mbps); +} + +static int rcsi2_init_phtw_h3es2(struct rcar_csi2 *priv, unsigned int mbps) +{ + return __rcsi2_init_phtw_h3_v3h_m3n(priv, 0); +} + static int rcsi2_init_phtw_v3m_e3(struct rcar_csi2 *priv, unsigned int mbps) { return rcsi2_phtw_write_mbps(priv, mbps, phtw_mbps_v3m_e3, 0x44); @@ -967,6 +978,14 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a7795es1 = { .num_channels = 4, }; +static const struct rcar_csi2_info rcar_csi2_info_r8a7795es2 = { + .init_phtw = rcsi2_init_phtw_h3es2, + .hsfreqrange = hsfreqrange_h3_v3h_m3n, + .csi0clkfreqrange = 0x20, + .num_channels = 4, + .clear_ulps = true, +}; + static const struct rcar_csi2_info rcar_csi2_info_r8a7796 = { .hsfreqrange = hsfreqrange_m3w_h3es1, .num_channels = 4, @@ -1036,11 +1055,15 @@ static const struct of_device_id rcar_csi2_of_table[] = { }; MODULE_DEVICE_TABLE(of, rcar_csi2_of_table); -static const struct soc_device_attribute r8a7795es1[] = { +static const struct soc_device_attribute r8a7795[] = { { .soc_id = "r8a7795", .revision = "ES1.*", .data = &rcar_csi2_info_r8a7795es1, }, + { + .soc_id = "r8a7795", .revision = "ES2.*", + .data = &rcar_csi2_info_r8a7795es2, + }, { /* sentinel */ }, }; @@ -1058,10 +1081,10 @@ static int rcsi2_probe(struct platform_device *pdev) priv->info = of_device_get_match_data(&pdev->dev); /* - * r8a7795 ES1.x behaves differently than the ES2.0+ but doesn't - * have it's own compatible string. + * The different ES versions of r8a7795 (H3) behave differently but + * share the same compatible string. */ - attr = soc_device_match(r8a7795es1); + attr = soc_device_match(r8a7795); if (attr) priv->info = attr->data; From fdf5de63394f8b7a71359e12bd07ef846d2ba719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Wed, 10 Apr 2019 10:27:15 -0400 Subject: [PATCH 193/218] media: rcar-csi2: Move setting of Field Detection Control Register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Later datasheet versions (rev 1.00) clarifies that the FLD register should be set after LINKCNT. Signed-off-by: Niklas Söderlund Reviewed-by: Ulrich Hecht Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rcar-vin/rcar-csi2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index 73c51e9d4a1a..799e526fd3df 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -519,8 +519,6 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv) rcsi2_write(priv, PHTC_REG, 0); /* Configure */ - rcsi2_write(priv, FLD_REG, FLD_FLD_NUM(2) | FLD_FLD_EN4 | - FLD_FLD_EN3 | FLD_FLD_EN2 | FLD_FLD_EN); rcsi2_write(priv, VCDT_REG, vcdt); if (vcdt2) rcsi2_write(priv, VCDT2_REG, vcdt2); @@ -551,6 +549,8 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv) rcsi2_write(priv, PHYCNT_REG, phycnt); rcsi2_write(priv, LINKCNT_REG, LINKCNT_MONITOR_EN | LINKCNT_REG_MONI_PACT_EN | LINKCNT_ICLK_NONSTOP); + rcsi2_write(priv, FLD_REG, FLD_FLD_NUM(2) | FLD_FLD_EN4 | + FLD_FLD_EN3 | FLD_FLD_EN2 | FLD_FLD_EN); rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ); rcsi2_write(priv, PHYCNT_REG, phycnt | PHYCNT_SHUTDOWNZ | PHYCNT_RSTZ); From 172876928f98e187daa8c7777361670ce2654b28 Mon Sep 17 00:00:00 2001 From: Matthias Reichl Date: Sun, 24 Mar 2019 05:43:51 -0400 Subject: [PATCH 194/218] media: rc: xbox_remote: add protocol and set timeout The timestamps in ir-keytable -t output showed that the Xbox DVD IR dongle decodes scancodes every 64ms. The last scancode of a longer button press is decodes 64ms after the last-but-one which indicates the decoder doesn't use a timeout but decodes on the last edge of the signal. 267.042629: lirc protocol(unknown): scancode = 0xace 267.042665: event type EV_MSC(0x04): scancode = 0xace 267.042665: event type EV_KEY(0x01) key_down: KEY_1(0x0002) 267.042665: event type EV_SYN(0x00). 267.106625: lirc protocol(unknown): scancode = 0xace 267.106643: event type EV_MSC(0x04): scancode = 0xace 267.106643: event type EV_SYN(0x00). 267.170623: lirc protocol(unknown): scancode = 0xace 267.170638: event type EV_MSC(0x04): scancode = 0xace 267.170638: event type EV_SYN(0x00). 267.234621: lirc protocol(unknown): scancode = 0xace 267.234636: event type EV_MSC(0x04): scancode = 0xace 267.234636: event type EV_SYN(0x00). 267.298623: lirc protocol(unknown): scancode = 0xace 267.298638: event type EV_MSC(0x04): scancode = 0xace 267.298638: event type EV_SYN(0x00). 267.543345: event type EV_KEY(0x01) key_down: KEY_1(0x0002) 267.543345: event type EV_SYN(0x00). 267.570015: event type EV_KEY(0x01) key_up: KEY_1(0x0002) 267.570015: event type EV_SYN(0x00). Add a protocol with the repeat value and set the timeout in the driver to 10ms (to have a bit of headroom for delays) so the Xbox DVD remote performs more responsive. Signed-off-by: Matthias Reichl Acked-by: Benjamin Valentin Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/lirc.h.rst.exceptions | 1 + drivers/media/rc/keymaps/rc-xbox-dvd.c | 2 +- drivers/media/rc/rc-main.c | 2 ++ drivers/media/rc/xbox_remote.c | 6 ++++-- include/media/rc-map.h | 4 +++- include/uapi/linux/lirc.h | 2 ++ 6 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Documentation/media/lirc.h.rst.exceptions b/Documentation/media/lirc.h.rst.exceptions index 7a8b8ff4f076..ac768d769113 100644 --- a/Documentation/media/lirc.h.rst.exceptions +++ b/Documentation/media/lirc.h.rst.exceptions @@ -63,6 +63,7 @@ ignore symbol RC_PROTO_IMON ignore symbol RC_PROTO_RCMM12 ignore symbol RC_PROTO_RCMM24 ignore symbol RC_PROTO_RCMM32 +ignore symbol RC_PROTO_XBOX_DVD # Undocumented macros diff --git a/drivers/media/rc/keymaps/rc-xbox-dvd.c b/drivers/media/rc/keymaps/rc-xbox-dvd.c index af387244636b..42815ab57bff 100644 --- a/drivers/media/rc/keymaps/rc-xbox-dvd.c +++ b/drivers/media/rc/keymaps/rc-xbox-dvd.c @@ -42,7 +42,7 @@ static struct rc_map_list xbox_dvd_map = { .map = { .scan = xbox_dvd, .size = ARRAY_SIZE(xbox_dvd), - .rc_proto = RC_PROTO_UNKNOWN, + .rc_proto = RC_PROTO_XBOX_DVD, .name = RC_MAP_XBOX_DVD, } }; diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index e8fa28e20192..be5fd129d728 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -76,6 +76,7 @@ static const struct { .scancode_bits = 0x00ffffff, .repeat_period = 114 }, [RC_PROTO_RCMM32] = { .name = "rc-mm-32", .scancode_bits = 0xffffffff, .repeat_period = 114 }, + [RC_PROTO_XBOX_DVD] = { .name = "xbox-dvd", .repeat_period = 64 }, }; /* Used to keep track of known keymaps */ @@ -1027,6 +1028,7 @@ static const struct { { RC_PROTO_BIT_RCMM12 | RC_PROTO_BIT_RCMM24 | RC_PROTO_BIT_RCMM32, "rc-mm", "ir-rcmm-decoder" }, + { RC_PROTO_BIT_XBOX_DVD, "xbox-dvd", NULL }, }; /** diff --git a/drivers/media/rc/xbox_remote.c b/drivers/media/rc/xbox_remote.c index f959cbb94744..4a3f2cc4ef18 100644 --- a/drivers/media/rc/xbox_remote.c +++ b/drivers/media/rc/xbox_remote.c @@ -107,7 +107,7 @@ static void xbox_remote_input_report(struct urb *urb) return; } - rc_keydown(xbox_remote->rdev, RC_PROTO_UNKNOWN, + rc_keydown(xbox_remote->rdev, RC_PROTO_XBOX_DVD, le16_to_cpup((__le16 *)(data + 2)), 0); } @@ -148,7 +148,7 @@ static void xbox_remote_rc_init(struct xbox_remote *xbox_remote) struct rc_dev *rdev = xbox_remote->rdev; rdev->priv = xbox_remote; - rdev->allowed_protocols = RC_PROTO_BIT_UNKNOWN; + rdev->allowed_protocols = RC_PROTO_BIT_XBOX_DVD; rdev->driver_name = "xbox_remote"; rdev->open = xbox_remote_rc_open; @@ -157,6 +157,8 @@ static void xbox_remote_rc_init(struct xbox_remote *xbox_remote) rdev->device_name = xbox_remote->rc_name; rdev->input_phys = xbox_remote->rc_phys; + rdev->timeout = MS_TO_NS(10); + usb_to_input_id(xbox_remote->udev, &rdev->input_id); rdev->dev.parent = &xbox_remote->interface->dev; } diff --git a/include/media/rc-map.h b/include/media/rc-map.h index 5e684bb0d64c..367d983188f7 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -40,6 +40,7 @@ #define RC_PROTO_BIT_RCMM12 BIT_ULL(RC_PROTO_RCMM12) #define RC_PROTO_BIT_RCMM24 BIT_ULL(RC_PROTO_RCMM24) #define RC_PROTO_BIT_RCMM32 BIT_ULL(RC_PROTO_RCMM32) +#define RC_PROTO_BIT_XBOX_DVD BIT_ULL(RC_PROTO_XBOX_DVD) #define RC_PROTO_BIT_ALL \ (RC_PROTO_BIT_UNKNOWN | RC_PROTO_BIT_OTHER | \ @@ -55,7 +56,8 @@ RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_SHARP | \ RC_PROTO_BIT_XMP | RC_PROTO_BIT_CEC | \ RC_PROTO_BIT_IMON | RC_PROTO_BIT_RCMM12 | \ - RC_PROTO_BIT_RCMM24 | RC_PROTO_BIT_RCMM32) + RC_PROTO_BIT_RCMM24 | RC_PROTO_BIT_RCMM32 | \ + RC_PROTO_BIT_XBOX_DVD) /* All rc protocols for which we have decoders */ #define RC_PROTO_BIT_ALL_IR_DECODER \ (RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC5X_20 | \ diff --git a/include/uapi/linux/lirc.h b/include/uapi/linux/lirc.h index 45fcbf99d72e..f99d9dcae667 100644 --- a/include/uapi/linux/lirc.h +++ b/include/uapi/linux/lirc.h @@ -195,6 +195,7 @@ struct lirc_scancode { * @RC_PROTO_RCMM12: RC-MM protocol 12 bits * @RC_PROTO_RCMM24: RC-MM protocol 24 bits * @RC_PROTO_RCMM32: RC-MM protocol 32 bits + * @RC_PROTO_XBOX_DVD: Xbox DVD Movie Playback Kit protocol */ enum rc_proto { RC_PROTO_UNKNOWN = 0, @@ -224,6 +225,7 @@ enum rc_proto { RC_PROTO_RCMM12 = 24, RC_PROTO_RCMM24 = 25, RC_PROTO_RCMM32 = 26, + RC_PROTO_XBOX_DVD = 27, }; #endif From 1e98a8400ae8712f2b2d52ed6c1c6231607ed854 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 20 Mar 2019 21:45:32 -0400 Subject: [PATCH 195/218] media: si2165: fix platform_no_drv_owner.cocci warnings Remove .owner field if calls are used which set it automatically Generated by: scripts/coccinelle/api/platform_no_drv_owner.cocci Signed-off-by: YueHaibing Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2165.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/dvb-frontends/si2165.c b/drivers/media/dvb-frontends/si2165.c index d55d8f169dca..c9bcd2e95417 100644 --- a/drivers/media/dvb-frontends/si2165.c +++ b/drivers/media/dvb-frontends/si2165.c @@ -1301,7 +1301,6 @@ MODULE_DEVICE_TABLE(i2c, si2165_id_table); static struct i2c_driver si2165_driver = { .driver = { - .owner = THIS_MODULE, .name = "si2165", }, .probe = si2165_probe, From 37d1e62b5bb3b1229d0c49f2ee45e67dc67274be Mon Sep 17 00:00:00 2001 From: Yizhuo Date: Wed, 30 Jan 2019 12:33:30 -0500 Subject: [PATCH 196/218] media: ts2020: Variable "utmp" in function ts2020_set_tuner_rf() could be uninitialized In function ts2020_set_tuner_rf(), local variable "utmp" could be uninitialized if function regmap_read() returns -EINVAL. However, this value is used in if statement and written to the register, which is potentially unsafe. Signed-off-by: Yizhuo Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/ts2020.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/dvb-frontends/ts2020.c b/drivers/media/dvb-frontends/ts2020.c index e5cd2cd414f4..0af9b335be12 100644 --- a/drivers/media/dvb-frontends/ts2020.c +++ b/drivers/media/dvb-frontends/ts2020.c @@ -180,6 +180,9 @@ static int ts2020_set_tuner_rf(struct dvb_frontend *fe) unsigned int utmp; ret = regmap_read(dev->regmap, 0x3d, &utmp); + if (ret) + return ret; + utmp &= 0x7f; if (utmp < 0x16) utmp = 0xa1; From 63604a143fe168094fbbccba56f6e3241683e399 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 13 Mar 2019 17:18:07 -0400 Subject: [PATCH 197/218] media: seco-cec: fix building with RC_CORE=m I previously added an RC_CORE dependency here, but missed the corner case of CONFIG_VIDEO_SECO_CEC=y with CONFIG_RC_CORE=m, which still causes a link error: drivers/media/platform/seco-cec/seco-cec.o: In function `secocec_probe': seco-cec.c:(.text+0x1b8): undefined reference to `devm_rc_allocate_device' seco-cec.c:(.text+0x2e8): undefined reference to `devm_rc_register_device' drivers/media/platform/seco-cec/seco-cec.o: In function `secocec_irq_handler': seco-cec.c:(.text+0xa2c): undefined reference to `rc_keydown' Refine the dependency to disallow building the RC subdriver in this case. This is the same logic we apply in other drivers like it. Fixes: f27dd0ad6885 ("media: seco-cec: fix RC_CORE dependency") Cc: # 5.1 Signed-off-by: Arnd Bergmann Signed-off-by: Sean Young Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 1611ec23d733..9908ecde2585 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -649,7 +649,7 @@ config VIDEO_SECO_CEC config VIDEO_SECO_RC bool "SECO Boards IR RC5 support" depends on VIDEO_SECO_CEC - depends on RC_CORE + depends on RC_CORE=y || RC_CORE = VIDEO_SECO_CEC help If you say yes here you will get support for the SECO Boards Consumer-IR in seco-cec driver. From fbbd403b3286b4467f8b755efa0f10819cef9bba Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 10 Apr 2019 05:13:28 -0400 Subject: [PATCH 198/218] media: cec-notifier: add cec_notifier_parse_hdmi_phandle helper Add helper function to parse the DT for the hdmi-phandle property and return the corresponding struct device pointer. It takes care to avoid increasing the device refcount since all we need is the device pointer. This pointer is used in the notifier list as a key, but it is never accessed by the CEC driver. Signed-off-by: Hans Verkuil Reported-by: Wen Yang Acked-by: Wen Yang Signed-off-by: Mauro Carvalho Chehab --- drivers/media/cec/cec-notifier.c | 30 ++++++++++++++++++++++++++++++ include/media/cec-notifier.h | 19 ++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/drivers/media/cec/cec-notifier.c b/drivers/media/cec/cec-notifier.c index dd2078b27a41..9598c7778871 100644 --- a/drivers/media/cec/cec-notifier.c +++ b/drivers/media/cec/cec-notifier.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -127,3 +128,32 @@ void cec_notifier_unregister(struct cec_notifier *n) cec_notifier_put(n); } EXPORT_SYMBOL_GPL(cec_notifier_unregister); + +struct device *cec_notifier_parse_hdmi_phandle(struct device *dev) +{ + struct platform_device *hdmi_pdev; + struct device *hdmi_dev = NULL; + struct device_node *np; + + np = of_parse_phandle(dev->of_node, "hdmi-phandle", 0); + + if (!np) { + dev_err(dev, "Failed to find HDMI node in device tree\n"); + return ERR_PTR(-ENODEV); + } + hdmi_pdev = of_find_device_by_node(np); + of_node_put(np); + if (hdmi_pdev) { + hdmi_dev = &hdmi_pdev->dev; + /* + * Note that the device struct is only used as a key into the + * cec_notifiers list, it is never actually accessed. + * So we decrement the reference here so we don't leak + * memory. + */ + put_device(hdmi_dev); + return hdmi_dev; + } + return ERR_PTR(-EPROBE_DEFER); +} +EXPORT_SYMBOL_GPL(cec_notifier_parse_hdmi_phandle); diff --git a/include/media/cec-notifier.h b/include/media/cec-notifier.h index 814eeef35a5c..57b3a9f6ea1d 100644 --- a/include/media/cec-notifier.h +++ b/include/media/cec-notifier.h @@ -9,7 +9,7 @@ #ifndef LINUX_CEC_NOTIFIER_H #define LINUX_CEC_NOTIFIER_H -#include +#include #include struct device; @@ -87,6 +87,17 @@ void cec_notifier_unregister(struct cec_notifier *n); void cec_register_cec_notifier(struct cec_adapter *adap, struct cec_notifier *notifier); +/** + * cec_notifier_parse_hdmi_phandle - find the hdmi device from "hdmi-phandle" + * @dev: the device with the "hdmi-phandle" device tree property + * + * Returns the device pointer referenced by the "hdmi-phandle" property. + * Note that the refcount of the returned device is not incremented. + * This device pointer is only used as a key value in the notifier + * list, but it is never accessed by the CEC driver. + */ +struct device *cec_notifier_parse_hdmi_phandle(struct device *dev); + #else static inline struct cec_notifier *cec_notifier_get_conn(struct device *dev, const char *conn) @@ -122,6 +133,12 @@ static inline void cec_register_cec_notifier(struct cec_adapter *adap, struct cec_notifier *notifier) { } + +static inline struct device *cec_notifier_parse_hdmi_phandle(struct device *dev) +{ + return ERR_PTR(-ENODEV); +} + #endif /** From 6bc37729df640748ed1718e3f150d63cbff1dc7e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 10 Apr 2019 05:13:29 -0400 Subject: [PATCH 199/218] media: meson: ao-cec: use new cec_notifier_parse_hdmi_phandle helper The meson CEC driver increased the HDMI device refcount when it shouldn't. Use the new helper function to ensure that that doesn't happen and to simplify the driver code. Signed-off-by: Hans Verkuil Acked-by: Neil Armstrong Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/meson/ao-cec.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/media/platform/meson/ao-cec.c b/drivers/media/platform/meson/ao-cec.c index cd4be38ab5ac..facf9b029e79 100644 --- a/drivers/media/platform/meson/ao-cec.c +++ b/drivers/media/platform/meson/ao-cec.c @@ -601,20 +601,14 @@ static const struct cec_adap_ops meson_ao_cec_ops = { static int meson_ao_cec_probe(struct platform_device *pdev) { struct meson_ao_cec_device *ao_cec; - struct platform_device *hdmi_dev; - struct device_node *np; + struct device *hdmi_dev; struct resource *res; int ret, irq; - np = of_parse_phandle(pdev->dev.of_node, "hdmi-phandle", 0); - if (!np) { - dev_err(&pdev->dev, "Failed to find hdmi node\n"); - return -ENODEV; - } + hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev); - hdmi_dev = of_find_device_by_node(np); - if (hdmi_dev == NULL) - return -EPROBE_DEFER; + if (IS_ERR(hdmi_dev)) + return PTR_ERR(hdmi_dev); ao_cec = devm_kzalloc(&pdev->dev, sizeof(*ao_cec), GFP_KERNEL); if (!ao_cec) @@ -622,7 +616,7 @@ static int meson_ao_cec_probe(struct platform_device *pdev) spin_lock_init(&ao_cec->cec_reg_lock); - ao_cec->notify = cec_notifier_get(&hdmi_dev->dev); + ao_cec->notify = cec_notifier_get(hdmi_dev); if (!ao_cec->notify) return -ENOMEM; From ba9db909d3a4fbc1633bcb18b4118cec84aed668 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 10 Apr 2019 05:13:30 -0400 Subject: [PATCH 200/218] media: s5p_cec: use new cec_notifier_parse_hdmi_phandle helper The S5P CEC driver increased the HDMI device refcount when it shouldn't. Use the new helper function to ensure that that doesn't happen and to simplify the driver code. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-cec/s5p_cec.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/media/platform/s5p-cec/s5p_cec.c b/drivers/media/platform/s5p-cec/s5p_cec.c index 8837e2678bde..7f62f5ef0086 100644 --- a/drivers/media/platform/s5p-cec/s5p_cec.c +++ b/drivers/media/platform/s5p-cec/s5p_cec.c @@ -178,22 +178,16 @@ static const struct cec_adap_ops s5p_cec_adap_ops = { static int s5p_cec_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct device_node *np; - struct platform_device *hdmi_dev; + struct device *hdmi_dev; struct resource *res; struct s5p_cec_dev *cec; bool needs_hpd = of_property_read_bool(pdev->dev.of_node, "needs-hpd"); int ret; - np = of_parse_phandle(pdev->dev.of_node, "hdmi-phandle", 0); + hdmi_dev = cec_notifier_parse_hdmi_phandle(dev); - if (!np) { - dev_err(&pdev->dev, "Failed to find hdmi node in device tree\n"); - return -ENODEV; - } - hdmi_dev = of_find_device_by_node(np); - if (hdmi_dev == NULL) - return -EPROBE_DEFER; + if (IS_ERR(hdmi_dev)) + return PTR_ERR(hdmi_dev); cec = devm_kzalloc(&pdev->dev, sizeof(*cec), GFP_KERNEL); if (!cec) @@ -224,7 +218,7 @@ static int s5p_cec_probe(struct platform_device *pdev) if (IS_ERR(cec->reg)) return PTR_ERR(cec->reg); - cec->notifier = cec_notifier_get(&hdmi_dev->dev); + cec->notifier = cec_notifier_get(hdmi_dev); if (cec->notifier == NULL) return -ENOMEM; From e3a7c52de95629cbb0c2840e787523a9393b1fc6 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 10 Apr 2019 05:13:31 -0400 Subject: [PATCH 201/218] media: stih_cec: use new cec_notifier_parse_hdmi_phandle helper The STI CEC driver increased the HDMI device refcount when it shouldn't. Use the new helper function to ensure that that doesn't happen and to simplify the driver code. Signed-off-by: Hans Verkuil Acked-by: Benjamin Gaignard Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/sti/cec/stih-cec.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/drivers/media/platform/sti/cec/stih-cec.c b/drivers/media/platform/sti/cec/stih-cec.c index d34099f75990..fc37efe1d554 100644 --- a/drivers/media/platform/sti/cec/stih-cec.c +++ b/drivers/media/platform/sti/cec/stih-cec.c @@ -301,26 +301,19 @@ static int stih_cec_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct resource *res; struct stih_cec *cec; - struct device_node *np; - struct platform_device *hdmi_dev; + struct device *hdmi_dev; int ret; + hdmi_dev = cec_notifier_parse_hdmi_phandle(dev); + + if (IS_ERR(hdmi_dev)) + return PTR_ERR(hdmi_dev); + cec = devm_kzalloc(dev, sizeof(*cec), GFP_KERNEL); if (!cec) return -ENOMEM; - np = of_parse_phandle(pdev->dev.of_node, "hdmi-phandle", 0); - - if (!np) { - dev_err(&pdev->dev, "Failed to find hdmi node in device tree\n"); - return -ENODEV; - } - - hdmi_dev = of_find_device_by_node(np); - if (!hdmi_dev) - return -EPROBE_DEFER; - - cec->notifier = cec_notifier_get(&hdmi_dev->dev); + cec->notifier = cec_notifier_get(hdmi_dev); if (!cec->notifier) return -ENOMEM; From 4d34c9267db7af6c23c29adb73a58882a250c2e0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 10 Apr 2019 05:13:32 -0400 Subject: [PATCH 202/218] media: tegra_cec: use new cec_notifier_parse_hdmi_phandle helper The Tegra CEC driver increased the HDMI device refcount when it shouldn't. Use the new helper function to ensure that that doesn't happen and to simplify the driver code. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/tegra-cec/tegra_cec.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/media/platform/tegra-cec/tegra_cec.c b/drivers/media/platform/tegra-cec/tegra_cec.c index aba488cd0e64..7fb3a4fa07c1 100644 --- a/drivers/media/platform/tegra-cec/tegra_cec.c +++ b/drivers/media/platform/tegra-cec/tegra_cec.c @@ -327,21 +327,15 @@ static const struct cec_adap_ops tegra_cec_ops = { static int tegra_cec_probe(struct platform_device *pdev) { - struct platform_device *hdmi_dev; - struct device_node *np; + struct device *hdmi_dev; struct tegra_cec *cec; struct resource *res; int ret = 0; - np = of_parse_phandle(pdev->dev.of_node, "hdmi-phandle", 0); + hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev); - if (!np) { - dev_err(&pdev->dev, "Failed to find hdmi node in device tree\n"); + if (!hdmi_dev) return -ENODEV; - } - hdmi_dev = of_find_device_by_node(np); - if (hdmi_dev == NULL) - return -EPROBE_DEFER; cec = devm_kzalloc(&pdev->dev, sizeof(struct tegra_cec), GFP_KERNEL); @@ -400,7 +394,7 @@ static int tegra_cec_probe(struct platform_device *pdev) goto clk_error; } - cec->notifier = cec_notifier_get(&hdmi_dev->dev); + cec->notifier = cec_notifier_get(hdmi_dev); if (!cec->notifier) { ret = -ENOMEM; goto clk_error; From b7f3be1c53280676a7b6036f699b01ef2e97b605 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 10 Apr 2019 05:13:33 -0400 Subject: [PATCH 203/218] media: seco-cec: decrement HDMI device refcount The SECO CEC driver never decremented the HDMI device refcount. CEC drivers only need the HDMI device pointer as a key in the notifier list, it never accesses the device, so there is no need to keep a reference. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/seco-cec/seco-cec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/seco-cec/seco-cec.c b/drivers/media/platform/seco-cec/seco-cec.c index a425a10540c1..e5080d6f5b2d 100644 --- a/drivers/media/platform/seco-cec/seco-cec.c +++ b/drivers/media/platform/seco-cec/seco-cec.c @@ -536,6 +536,7 @@ static int secocec_cec_get_notifier(struct cec_notifier **notify) return -EPROBE_DEFER; *notify = cec_notifier_get_conn(d, m->conn); + put_device(d); return 0; } From cea053bed8534cb7de0b2092a246a84e8e512f64 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 10 Apr 2019 05:13:34 -0400 Subject: [PATCH 204/218] media: cros-ec-cec: decrement HDMI device refcount The CrosEC CEC driver never decremented the HDMI device refcount. CEC drivers only need the HDMI device pointer as a key in the notifier list, it never accesses the device, so there is no need to keep a reference. Signed-off-by: Hans Verkuil Reviewed-by: Neil Armstrong Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/cros-ec-cec/cros-ec-cec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/cros-ec-cec/cros-ec-cec.c b/drivers/media/platform/cros-ec-cec/cros-ec-cec.c index 7bc4d8a9af28..068df9888dbf 100644 --- a/drivers/media/platform/cros-ec-cec/cros-ec-cec.c +++ b/drivers/media/platform/cros-ec-cec/cros-ec-cec.c @@ -236,6 +236,7 @@ static int cros_ec_cec_get_notifier(struct device *dev, return -EPROBE_DEFER; *notify = cec_notifier_get_conn(d, m->conn); + put_device(d); return 0; } } From 3473ba384de7cf5df33f0ea3650aa4c7aaf1c995 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Fri, 12 Apr 2019 04:30:58 -0400 Subject: [PATCH 205/218] media: dt-bindings: media: meson-ao-cec: Add G12A AO-CEC-B Compatible The Amlogic G12A embeds a second CEC controller named AO-CEC-B, and the other one is AO-CEC-A described by the current bindings. The register interface is very close but the internal architecture is totally different. The other difference is the clock source, the AO-CEC-B takes the "oscin", the Always-On Oscillator clock, as input and embeds a dual-divider clock divider to provide the precise 32768Hz base clock for CEC communication. Signed-off-by: Neil Armstrong Reviewed-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/meson-ao-cec.txt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/media/meson-ao-cec.txt b/Documentation/devicetree/bindings/media/meson-ao-cec.txt index 8671bdb08080..c67fc41d4aa2 100644 --- a/Documentation/devicetree/bindings/media/meson-ao-cec.txt +++ b/Documentation/devicetree/bindings/media/meson-ao-cec.txt @@ -4,16 +4,23 @@ The Amlogic Meson AO-CEC module is present is Amlogic SoCs and its purpose is to handle communication between HDMI connected devices over the CEC bus. Required properties: - - compatible : value should be following + - compatible : value should be following depending on the SoC : + For GXBB, GXL, GXM and G12A (AO_CEC_A module) : "amlogic,meson-gx-ao-cec" + For G12A (AO_CEC_B module) : + "amlogic,meson-g12a-ao-cec" - reg : Physical base address of the IP registers and length of memory mapped region. - interrupts : AO-CEC interrupt number to the CPU. - clocks : from common clock binding: handle to AO-CEC clock. - - clock-names : from common clock binding: must contain "core", - corresponding to entry in the clocks property. + - clock-names : from common clock binding, must contain : + For GXBB, GXL, GXM and G12A (AO_CEC_A module) : + - "core" + For G12A (AO_CEC_B module) : + - "oscin" + corresponding to entry in the clocks property. - hdmi-phandle: phandle to the HDMI controller Example: From b7778c46683ce468f49141a18d984f6f13c6c5d2 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Fri, 12 Apr 2019 04:30:59 -0400 Subject: [PATCH 206/218] media: platform: meson: Add Amlogic Meson G12A AO CEC Controller driver The Amlogic G12A SoC embeds a second CEC controller with a totally different design. The two controller can work in the same time since the CEC line can be set to two different pins on the two controllers. This second CEC controller is documented as "AO-CEC-B", thus the registers will be named "CECB_" to differentiate with the other AO-CEC driver. Unlike the other AO-CEC controller, this one takes the Oscillator clock as input and embeds a dual-divider to provide a precise 32768Hz clock for communication. This is handled by registering a clock in the driver. Unlike the other AO-CEC controller, this controller supports setting up to 15 logical addresses and supports the signal_free_time settings in the transmit function. Unfortunately, this controller does not support "monitor" mode. Signed-off-by: Neil Armstrong Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/Kconfig | 16 + drivers/media/platform/meson/Makefile | 1 + drivers/media/platform/meson/ao-cec-g12a.c | 779 +++++++++++++++++++++ 3 files changed, 796 insertions(+) create mode 100644 drivers/media/platform/meson/ao-cec-g12a.c diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 9908ecde2585..011c1c2fcf19 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -578,6 +578,22 @@ config VIDEO_MESON_AO_CEC generic CEC framework interface. CEC bus is present in the HDMI connector and enables communication +config VIDEO_MESON_G12A_AO_CEC + tristate "Amlogic Meson G12A AO CEC driver" + depends on ARCH_MESON || COMPILE_TEST + depends on COMMON_CLK && OF + select REGMAP + select REGMAP_MMIO + select CEC_CORE + select CEC_NOTIFIER + ---help--- + This is a driver for Amlogic Meson G12A SoCs AO CEC interface. + This driver if for the new AO-CEC module found in G12A SoCs, + usually named AO_CEC_B in documentation. + It uses the generic CEC framework interface. + CEC bus is present in the HDMI connector and enables communication + between compatible devices. + config CEC_GPIO tristate "Generic GPIO-based CEC driver" depends on PREEMPT || COMPILE_TEST diff --git a/drivers/media/platform/meson/Makefile b/drivers/media/platform/meson/Makefile index 597beb8f34d1..f611c23c3718 100644 --- a/drivers/media/platform/meson/Makefile +++ b/drivers/media/platform/meson/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_VIDEO_MESON_AO_CEC) += ao-cec.o +obj-$(CONFIG_VIDEO_MESON_G12A_AO_CEC) += ao-cec-g12a.o diff --git a/drivers/media/platform/meson/ao-cec-g12a.c b/drivers/media/platform/meson/ao-cec-g12a.c new file mode 100644 index 000000000000..3620a1e310f5 --- /dev/null +++ b/drivers/media/platform/meson/ao-cec-g12a.c @@ -0,0 +1,779 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Driver for Amlogic Meson AO CEC G12A Controller + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved + * Copyright (C) 2019 BayLibre, SAS + * Author: Neil Armstrong + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* CEC Registers */ + +#define CECB_CLK_CNTL_REG0 0x00 + +#define CECB_CLK_CNTL_N1 GENMASK(11, 0) +#define CECB_CLK_CNTL_N2 GENMASK(23, 12) +#define CECB_CLK_CNTL_DUAL_EN BIT(28) +#define CECB_CLK_CNTL_OUTPUT_EN BIT(30) +#define CECB_CLK_CNTL_INPUT_EN BIT(31) + +#define CECB_CLK_CNTL_REG1 0x04 + +#define CECB_CLK_CNTL_M1 GENMASK(11, 0) +#define CECB_CLK_CNTL_M2 GENMASK(23, 12) +#define CECB_CLK_CNTL_BYPASS_EN BIT(24) + +/* + * [14:12] Filter_del. For glitch-filtering CEC line, ignore signal + * change pulse width < filter_del * T(filter_tick) * 3. + * [9:8] Filter_tick_sel: Select which periodical pulse for + * glitch-filtering CEC line signal. + * - 0=Use T(xtal)*3 = 125ns; + * - 1=Use once-per-1us pulse; + * - 2=Use once-per-10us pulse; + * - 3=Use once-per-100us pulse. + * [3] Sysclk_en. 0=Disable system clock; 1=Enable system clock. + * [2:1] cntl_clk + * - 0 = Disable clk (Power-off mode) + * - 1 = Enable gated clock (Normal mode) + * - 2 = Enable free-run clk (Debug mode) + * [0] SW_RESET 1=Apply reset; 0=No reset. + */ +#define CECB_GEN_CNTL_REG 0x08 + +#define CECB_GEN_CNTL_RESET BIT(0) +#define CECB_GEN_CNTL_CLK_DISABLE 0 +#define CECB_GEN_CNTL_CLK_ENABLE 1 +#define CECB_GEN_CNTL_CLK_ENABLE_DBG 2 +#define CECB_GEN_CNTL_CLK_CTRL_MASK GENMASK(2, 1) +#define CECB_GEN_CNTL_SYS_CLK_EN BIT(3) +#define CECB_GEN_CNTL_FILTER_TICK_125NS 0 +#define CECB_GEN_CNTL_FILTER_TICK_1US 1 +#define CECB_GEN_CNTL_FILTER_TICK_10US 2 +#define CECB_GEN_CNTL_FILTER_TICK_100US 3 +#define CECB_GEN_CNTL_FILTER_TICK_SEL GENMASK(9, 8) +#define CECB_GEN_CNTL_FILTER_DEL GENMASK(14, 12) + +/* + * [7:0] cec_reg_addr + * [15:8] cec_reg_wrdata + * [16] cec_reg_wr + * - 0 = Read + * - 1 = Write + * [31:24] cec_reg_rddata + */ +#define CECB_RW_REG 0x0c + +#define CECB_RW_ADDR GENMASK(7, 0) +#define CECB_RW_WR_DATA GENMASK(15, 8) +#define CECB_RW_WRITE_EN BIT(16) +#define CECB_RW_BUS_BUSY BIT(23) +#define CECB_RW_RD_DATA GENMASK(31, 24) + +/* + * [0] DONE Interrupt + * [1] End Of Message Interrupt + * [2] Not Acknowlegde Interrupt + * [3] Arbitration Loss Interrupt + * [4] Initiator Error Interrupt + * [5] Follower Error Interrupt + * [6] Wake-Up Interrupt + */ +#define CECB_INTR_MASKN_REG 0x10 +#define CECB_INTR_CLR_REG 0x14 +#define CECB_INTR_STAT_REG 0x18 + +#define CECB_INTR_DONE BIT(0) +#define CECB_INTR_EOM BIT(1) +#define CECB_INTR_NACK BIT(2) +#define CECB_INTR_ARB_LOSS BIT(3) +#define CECB_INTR_INITIATOR_ERR BIT(4) +#define CECB_INTR_FOLLOWER_ERR BIT(5) +#define CECB_INTR_WAKE_UP BIT(6) + +/* CEC Commands */ + +#define CECB_CTRL 0x00 + +#define CECB_CTRL_SEND BIT(0) +#define CECB_CTRL_TYPE GENMASK(2, 1) +#define CECB_CTRL_TYPE_RETRY 0 +#define CECB_CTRL_TYPE_NEW 1 +#define CECB_CTRL_TYPE_NEXT 2 + +#define CECB_CTRL2 0x01 +#define CECB_INTR_MASK 0x02 +#define CECB_LADD_LOW 0x05 +#define CECB_LADD_HIGH 0x06 +#define CECB_TX_CNT 0x07 +#define CECB_RX_CNT 0x08 +#define CECB_STAT0 0x09 +#define CECB_TX_DATA00 0x10 +#define CECB_TX_DATA01 0x11 +#define CECB_TX_DATA02 0x12 +#define CECB_TX_DATA03 0x13 +#define CECB_TX_DATA04 0x14 +#define CECB_TX_DATA05 0x15 +#define CECB_TX_DATA06 0x16 +#define CECB_TX_DATA07 0x17 +#define CECB_TX_DATA08 0x18 +#define CECB_TX_DATA09 0x19 +#define CECB_TX_DATA10 0x1A +#define CECB_TX_DATA11 0x1B +#define CECB_TX_DATA12 0x1C +#define CECB_TX_DATA13 0x1D +#define CECB_TX_DATA14 0x1E +#define CECB_TX_DATA15 0x1F +#define CECB_RX_DATA00 0x20 +#define CECB_RX_DATA01 0x21 +#define CECB_RX_DATA02 0x22 +#define CECB_RX_DATA03 0x23 +#define CECB_RX_DATA04 0x24 +#define CECB_RX_DATA05 0x25 +#define CECB_RX_DATA06 0x26 +#define CECB_RX_DATA07 0x27 +#define CECB_RX_DATA08 0x28 +#define CECB_RX_DATA09 0x29 +#define CECB_RX_DATA10 0x2A +#define CECB_RX_DATA11 0x2B +#define CECB_RX_DATA12 0x2C +#define CECB_RX_DATA13 0x2D +#define CECB_RX_DATA14 0x2E +#define CECB_RX_DATA15 0x2F +#define CECB_LOCK_BUF 0x30 + +#define CECB_LOCK_BUF_EN BIT(0) + +#define CECB_WAKEUPCTRL 0x31 + +struct meson_ao_cec_g12a_device { + struct platform_device *pdev; + struct regmap *regmap; + struct regmap *regmap_cec; + spinlock_t cec_reg_lock; + struct cec_notifier *notify; + struct cec_adapter *adap; + struct cec_msg rx_msg; + struct clk *oscin; + struct clk *core; +}; + +static const struct regmap_config meson_ao_cec_g12a_regmap_conf = { + .reg_bits = 8, + .val_bits = 32, + .reg_stride = 4, + .max_register = CECB_INTR_STAT_REG, +}; + +/* + * The AO-CECB embeds a dual/divider to generate a more precise + * 32,768KHz clock for CEC core clock. + * ______ ______ + * | | | | + * ______ | Div1 |-| Cnt1 | ______ + * | | /|______| |______|\ | | + * Xtal-->| Gate |---| ______ ______ X-X--| Gate |--> + * |______| | \| | | |/ | |______| + * | | Div2 |-| Cnt2 | | + * | |______| |______| | + * |_______________________| + * + * The dividing can be switched to single or dual, with a counter + * for each divider to set when the switching is done. + * The entire dividing mechanism can be also bypassed. + */ + +struct meson_ao_cec_g12a_dualdiv_clk { + struct clk_hw hw; + struct regmap *regmap; +}; + +#define hw_to_meson_ao_cec_g12a_dualdiv_clk(_hw) \ + container_of(_hw, struct meson_ao_cec_g12a_dualdiv_clk, hw) \ + +static unsigned long +meson_ao_cec_g12a_dualdiv_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk = + hw_to_meson_ao_cec_g12a_dualdiv_clk(hw); + unsigned long n1; + u32 reg0, reg1; + + regmap_read(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, ®0); + regmap_read(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, ®1); + + if (reg1 & CECB_CLK_CNTL_BYPASS_EN) + return parent_rate; + + if (reg0 & CECB_CLK_CNTL_DUAL_EN) { + unsigned long n2, m1, m2, f1, f2, p1, p2; + + n1 = FIELD_GET(CECB_CLK_CNTL_N1, reg0) + 1; + n2 = FIELD_GET(CECB_CLK_CNTL_N2, reg0) + 1; + + m1 = FIELD_GET(CECB_CLK_CNTL_M1, reg1) + 1; + m2 = FIELD_GET(CECB_CLK_CNTL_M1, reg1) + 1; + + f1 = DIV_ROUND_CLOSEST(parent_rate, n1); + f2 = DIV_ROUND_CLOSEST(parent_rate, n2); + + p1 = DIV_ROUND_CLOSEST(100000000 * m1, f1 * (m1 + m2)); + p2 = DIV_ROUND_CLOSEST(100000000 * m2, f2 * (m1 + m2)); + + return DIV_ROUND_UP(100000000, p1 + p2); + } + + n1 = FIELD_GET(CECB_CLK_CNTL_N1, reg0) + 1; + + return DIV_ROUND_CLOSEST(parent_rate, n1); +} + +static int meson_ao_cec_g12a_dualdiv_clk_enable(struct clk_hw *hw) +{ + struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk = + hw_to_meson_ao_cec_g12a_dualdiv_clk(hw); + + + /* Disable Input & Output */ + regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, + CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN, + 0); + + /* Set N1 & N2 */ + regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, + CECB_CLK_CNTL_N1, + FIELD_PREP(CECB_CLK_CNTL_N1, 733 - 1)); + + regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, + CECB_CLK_CNTL_N2, + FIELD_PREP(CECB_CLK_CNTL_N2, 732 - 1)); + + /* Set M1 & M2 */ + regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG1, + CECB_CLK_CNTL_M1, + FIELD_PREP(CECB_CLK_CNTL_M1, 8 - 1)); + + regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG1, + CECB_CLK_CNTL_M2, + FIELD_PREP(CECB_CLK_CNTL_M2, 11 - 1)); + + /* Enable Dual divisor */ + regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, + CECB_CLK_CNTL_DUAL_EN, CECB_CLK_CNTL_DUAL_EN); + + /* Disable divisor bypass */ + regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG1, + CECB_CLK_CNTL_BYPASS_EN, 0); + + /* Enable Input & Output */ + regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, + CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN, + CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN); + + return 0; +} + +static void meson_ao_cec_g12a_dualdiv_clk_disable(struct clk_hw *hw) +{ + struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk = + hw_to_meson_ao_cec_g12a_dualdiv_clk(hw); + + regmap_update_bits(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, + CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN, + 0); +} + +static int meson_ao_cec_g12a_dualdiv_clk_is_enabled(struct clk_hw *hw) +{ + struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk = + hw_to_meson_ao_cec_g12a_dualdiv_clk(hw); + int val; + + regmap_read(dualdiv_clk->regmap, CECB_CLK_CNTL_REG0, &val); + + return !!(val & (CECB_CLK_CNTL_INPUT_EN | CECB_CLK_CNTL_OUTPUT_EN)); +} + +static const struct clk_ops meson_ao_cec_g12a_dualdiv_clk_ops = { + .recalc_rate = meson_ao_cec_g12a_dualdiv_clk_recalc_rate, + .is_enabled = meson_ao_cec_g12a_dualdiv_clk_is_enabled, + .enable = meson_ao_cec_g12a_dualdiv_clk_enable, + .disable = meson_ao_cec_g12a_dualdiv_clk_disable, +}; + +static int meson_ao_cec_g12a_setup_clk(struct meson_ao_cec_g12a_device *ao_cec) +{ + struct meson_ao_cec_g12a_dualdiv_clk *dualdiv_clk; + struct device *dev = &ao_cec->pdev->dev; + struct clk_init_data init; + const char *parent_name; + struct clk *clk; + char *name; + + dualdiv_clk = devm_kzalloc(dev, sizeof(*dualdiv_clk), GFP_KERNEL); + if (!dualdiv_clk) + return -ENOMEM; + + name = kasprintf(GFP_KERNEL, "%s#dualdiv_clk", dev_name(dev)); + if (!name) + return -ENOMEM; + + parent_name = __clk_get_name(ao_cec->oscin); + + init.name = name; + init.ops = &meson_ao_cec_g12a_dualdiv_clk_ops; + init.flags = 0; + init.parent_names = &parent_name; + init.num_parents = 1; + dualdiv_clk->regmap = ao_cec->regmap; + dualdiv_clk->hw.init = &init; + + clk = devm_clk_register(dev, &dualdiv_clk->hw); + kfree(name); + if (IS_ERR(clk)) { + dev_err(dev, "failed to register clock\n"); + return PTR_ERR(clk); + } + + ao_cec->core = clk; + + return 0; +} + +static int meson_ao_cec_g12a_read(void *context, unsigned int addr, + unsigned int *data) +{ + struct meson_ao_cec_g12a_device *ao_cec = context; + u32 reg = FIELD_PREP(CECB_RW_ADDR, addr); + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&ao_cec->cec_reg_lock, flags); + + ret = regmap_write(ao_cec->regmap, CECB_RW_REG, reg); + if (ret) + goto read_out; + + ret = regmap_read_poll_timeout(ao_cec->regmap, CECB_RW_REG, reg, + !(reg & CECB_RW_BUS_BUSY), + 5, 1000); + if (ret) + goto read_out; + + ret = regmap_read(ao_cec->regmap, CECB_RW_REG, ®); + + *data = FIELD_GET(CECB_RW_RD_DATA, reg); + +read_out: + spin_unlock_irqrestore(&ao_cec->cec_reg_lock, flags); + + return ret; +} + +static int meson_ao_cec_g12a_write(void *context, unsigned int addr, + unsigned int data) +{ + struct meson_ao_cec_g12a_device *ao_cec = context; + unsigned long flags; + u32 reg = FIELD_PREP(CECB_RW_ADDR, addr) | + FIELD_PREP(CECB_RW_WR_DATA, data) | + CECB_RW_WRITE_EN; + int ret = 0; + + spin_lock_irqsave(&ao_cec->cec_reg_lock, flags); + + ret = regmap_write(ao_cec->regmap, CECB_RW_REG, reg); + + spin_unlock_irqrestore(&ao_cec->cec_reg_lock, flags); + + return ret; +} + +static const struct regmap_config meson_ao_cec_g12a_cec_regmap_conf = { + .reg_bits = 8, + .val_bits = 8, + .reg_read = meson_ao_cec_g12a_read, + .reg_write = meson_ao_cec_g12a_write, + .max_register = 0xffff, + .fast_io = true, +}; + +static inline void +meson_ao_cec_g12a_irq_setup(struct meson_ao_cec_g12a_device *ao_cec, + bool enable) +{ + u32 cfg = CECB_INTR_DONE | CECB_INTR_EOM | CECB_INTR_NACK | + CECB_INTR_ARB_LOSS | CECB_INTR_INITIATOR_ERR | + CECB_INTR_FOLLOWER_ERR; + + regmap_write(ao_cec->regmap, CECB_INTR_MASKN_REG, + enable ? cfg : 0); +} + +static void meson_ao_cec_g12a_irq_rx(struct meson_ao_cec_g12a_device *ao_cec) +{ + int i, ret = 0; + u32 val; + + ret = regmap_read(ao_cec->regmap_cec, CECB_RX_CNT, &val); + + ao_cec->rx_msg.len = val; + if (ao_cec->rx_msg.len > CEC_MAX_MSG_SIZE) + ao_cec->rx_msg.len = CEC_MAX_MSG_SIZE; + + for (i = 0; i < ao_cec->rx_msg.len; i++) { + ret |= regmap_read(ao_cec->regmap_cec, + CECB_RX_DATA00 + i, &val); + + ao_cec->rx_msg.msg[i] = val & 0xff; + } + + ret |= regmap_write(ao_cec->regmap_cec, CECB_LOCK_BUF, 0); + if (ret) + return; + + cec_received_msg(ao_cec->adap, &ao_cec->rx_msg); +} + +static irqreturn_t meson_ao_cec_g12a_irq(int irq, void *data) +{ + struct meson_ao_cec_g12a_device *ao_cec = data; + u32 stat; + + regmap_read(ao_cec->regmap, CECB_INTR_STAT_REG, &stat); + if (stat) + return IRQ_WAKE_THREAD; + + return IRQ_NONE; +} + +static irqreturn_t meson_ao_cec_g12a_irq_thread(int irq, void *data) +{ + struct meson_ao_cec_g12a_device *ao_cec = data; + u32 stat; + + regmap_read(ao_cec->regmap, CECB_INTR_STAT_REG, &stat); + regmap_write(ao_cec->regmap, CECB_INTR_CLR_REG, stat); + + if (stat & CECB_INTR_DONE) + cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_OK); + + if (stat & CECB_INTR_EOM) + meson_ao_cec_g12a_irq_rx(ao_cec); + + if (stat & CECB_INTR_NACK) + cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_NACK); + + if (stat & CECB_INTR_ARB_LOSS) { + regmap_write(ao_cec->regmap_cec, CECB_TX_CNT, 0); + regmap_update_bits(ao_cec->regmap_cec, CECB_CTRL, + CECB_CTRL_SEND | CECB_CTRL_TYPE, 0); + cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_ARB_LOST); + } + + /* Initiator reports an error on the CEC bus */ + if (stat & CECB_INTR_INITIATOR_ERR) + cec_transmit_attempt_done(ao_cec->adap, CEC_TX_STATUS_ERROR); + + /* Follower reports a receive error, just reset RX buffer */ + if (stat & CECB_INTR_FOLLOWER_ERR) + regmap_write(ao_cec->regmap_cec, CECB_LOCK_BUF, 0); + + return IRQ_HANDLED; +} + +static int +meson_ao_cec_g12a_set_log_addr(struct cec_adapter *adap, u8 logical_addr) +{ + struct meson_ao_cec_g12a_device *ao_cec = adap->priv; + int ret = 0; + + if (logical_addr == CEC_LOG_ADDR_INVALID) { + /* Assume this will allways succeed */ + regmap_write(ao_cec->regmap_cec, CECB_LADD_LOW, 0); + regmap_write(ao_cec->regmap_cec, CECB_LADD_HIGH, 0); + + return 0; + } else if (logical_addr < 8) { + ret = regmap_update_bits(ao_cec->regmap_cec, CECB_LADD_LOW, + BIT(logical_addr), + BIT(logical_addr)); + } else { + ret = regmap_update_bits(ao_cec->regmap_cec, CECB_LADD_HIGH, + BIT(logical_addr - 8), + BIT(logical_addr - 8)); + } + + /* Always set Broadcast/Unregistered 15 address */ + ret |= regmap_update_bits(ao_cec->regmap_cec, CECB_LADD_HIGH, + BIT(CEC_LOG_ADDR_UNREGISTERED - 8), + BIT(CEC_LOG_ADDR_UNREGISTERED - 8)); + + return ret ? -EIO : 0; +} + +static int meson_ao_cec_g12a_transmit(struct cec_adapter *adap, u8 attempts, + u32 signal_free_time, struct cec_msg *msg) +{ + struct meson_ao_cec_g12a_device *ao_cec = adap->priv; + unsigned int type; + int ret = 0; + u32 val; + int i; + + /* Check if RX is in progress */ + ret = regmap_read(ao_cec->regmap_cec, CECB_LOCK_BUF, &val); + if (ret) + return ret; + if (val & CECB_LOCK_BUF_EN) + return -EBUSY; + + /* Check if TX Busy */ + ret = regmap_read(ao_cec->regmap_cec, CECB_CTRL, &val); + if (ret) + return ret; + if (val & CECB_CTRL_SEND) + return -EBUSY; + + switch (signal_free_time) { + case CEC_SIGNAL_FREE_TIME_RETRY: + type = CECB_CTRL_TYPE_RETRY; + break; + case CEC_SIGNAL_FREE_TIME_NEXT_XFER: + type = CECB_CTRL_TYPE_NEXT; + break; + case CEC_SIGNAL_FREE_TIME_NEW_INITIATOR: + default: + type = CECB_CTRL_TYPE_NEW; + break; + } + + for (i = 0; i < msg->len; i++) + ret |= regmap_write(ao_cec->regmap_cec, CECB_TX_DATA00 + i, + msg->msg[i]); + + ret |= regmap_write(ao_cec->regmap_cec, CECB_TX_CNT, msg->len); + if (ret) + return -EIO; + + ret = regmap_update_bits(ao_cec->regmap_cec, CECB_CTRL, + CECB_CTRL_SEND | + CECB_CTRL_TYPE, + CECB_CTRL_SEND | + FIELD_PREP(CECB_CTRL_TYPE, type)); + + return ret; +} + +static int meson_ao_cec_g12a_adap_enable(struct cec_adapter *adap, bool enable) +{ + struct meson_ao_cec_g12a_device *ao_cec = adap->priv; + + meson_ao_cec_g12a_irq_setup(ao_cec, false); + + regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG, + CECB_GEN_CNTL_RESET, CECB_GEN_CNTL_RESET); + + if (!enable) + return 0; + + /* Setup Filter */ + regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG, + CECB_GEN_CNTL_FILTER_TICK_SEL | + CECB_GEN_CNTL_FILTER_DEL, + FIELD_PREP(CECB_GEN_CNTL_FILTER_TICK_SEL, + CECB_GEN_CNTL_FILTER_TICK_1US) | + FIELD_PREP(CECB_GEN_CNTL_FILTER_DEL, 7)); + + /* Enable System Clock */ + regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG, + CECB_GEN_CNTL_SYS_CLK_EN, + CECB_GEN_CNTL_SYS_CLK_EN); + + /* Enable gated clock (Normal mode). */ + regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG, + CECB_GEN_CNTL_CLK_CTRL_MASK, + FIELD_PREP(CECB_GEN_CNTL_CLK_CTRL_MASK, + CECB_GEN_CNTL_CLK_ENABLE)); + + /* Release Reset */ + regmap_update_bits(ao_cec->regmap, CECB_GEN_CNTL_REG, + CECB_GEN_CNTL_RESET, 0); + + meson_ao_cec_g12a_irq_setup(ao_cec, true); + + return 0; +} + +static const struct cec_adap_ops meson_ao_cec_g12a_ops = { + .adap_enable = meson_ao_cec_g12a_adap_enable, + .adap_log_addr = meson_ao_cec_g12a_set_log_addr, + .adap_transmit = meson_ao_cec_g12a_transmit, +}; + +static int meson_ao_cec_g12a_probe(struct platform_device *pdev) +{ + struct meson_ao_cec_g12a_device *ao_cec; + struct device *hdmi_dev; + struct resource *res; + void __iomem *base; + int ret, irq; + + hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev); + if (IS_ERR(hdmi_dev)) + return PTR_ERR(hdmi_dev); + + ao_cec = devm_kzalloc(&pdev->dev, sizeof(*ao_cec), GFP_KERNEL); + if (!ao_cec) + return -ENOMEM; + + spin_lock_init(&ao_cec->cec_reg_lock); + ao_cec->pdev = pdev; + + ao_cec->notify = cec_notifier_get(hdmi_dev); + if (!ao_cec->notify) + return -ENOMEM; + + ao_cec->adap = cec_allocate_adapter(&meson_ao_cec_g12a_ops, ao_cec, + "meson_g12a_ao_cec", + CEC_CAP_DEFAULTS, + CEC_MAX_LOG_ADDRS); + if (IS_ERR(ao_cec->adap)) { + ret = PTR_ERR(ao_cec->adap); + goto out_probe_notify; + } + + ao_cec->adap->owner = THIS_MODULE; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) { + ret = PTR_ERR(base); + goto out_probe_adapter; + } + + ao_cec->regmap = devm_regmap_init_mmio(&pdev->dev, base, + &meson_ao_cec_g12a_regmap_conf); + if (IS_ERR(ao_cec->regmap)) { + ret = PTR_ERR(ao_cec->regmap); + goto out_probe_adapter; + } + + ao_cec->regmap_cec = devm_regmap_init(&pdev->dev, NULL, ao_cec, + &meson_ao_cec_g12a_cec_regmap_conf); + if (IS_ERR(ao_cec->regmap_cec)) { + ret = PTR_ERR(ao_cec->regmap_cec); + goto out_probe_adapter; + } + + irq = platform_get_irq(pdev, 0); + ret = devm_request_threaded_irq(&pdev->dev, irq, + meson_ao_cec_g12a_irq, + meson_ao_cec_g12a_irq_thread, + 0, NULL, ao_cec); + if (ret) { + dev_err(&pdev->dev, "irq request failed\n"); + goto out_probe_adapter; + } + + ao_cec->oscin = devm_clk_get(&pdev->dev, "oscin"); + if (IS_ERR(ao_cec->oscin)) { + dev_err(&pdev->dev, "oscin clock request failed\n"); + ret = PTR_ERR(ao_cec->oscin); + goto out_probe_adapter; + } + + ret = meson_ao_cec_g12a_setup_clk(ao_cec); + if (ret) + goto out_probe_adapter; + + ret = clk_prepare_enable(ao_cec->core); + if (ret) { + dev_err(&pdev->dev, "core clock enable failed\n"); + goto out_probe_adapter; + } + + device_reset_optional(&pdev->dev); + + platform_set_drvdata(pdev, ao_cec); + + ret = cec_register_adapter(ao_cec->adap, &pdev->dev); + if (ret < 0) { + cec_notifier_put(ao_cec->notify); + goto out_probe_core_clk; + } + + /* Setup Hardware */ + regmap_write(ao_cec->regmap, CECB_GEN_CNTL_REG, CECB_GEN_CNTL_RESET); + + cec_register_cec_notifier(ao_cec->adap, ao_cec->notify); + + return 0; + +out_probe_core_clk: + clk_disable_unprepare(ao_cec->core); + +out_probe_adapter: + cec_delete_adapter(ao_cec->adap); + +out_probe_notify: + cec_notifier_put(ao_cec->notify); + + dev_err(&pdev->dev, "CEC controller registration failed\n"); + + return ret; +} + +static int meson_ao_cec_g12a_remove(struct platform_device *pdev) +{ + struct meson_ao_cec_g12a_device *ao_cec = platform_get_drvdata(pdev); + + clk_disable_unprepare(ao_cec->core); + + cec_unregister_adapter(ao_cec->adap); + + cec_notifier_put(ao_cec->notify); + + return 0; +} + +static const struct of_device_id meson_ao_cec_g12a_of_match[] = { + { .compatible = "amlogic,meson-g12a-ao-cec", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, meson_ao_cec_g12a_of_match); + +static struct platform_driver meson_ao_cec_g12a_driver = { + .probe = meson_ao_cec_g12a_probe, + .remove = meson_ao_cec_g12a_remove, + .driver = { + .name = "meson-ao-cec-g12a", + .of_match_table = of_match_ptr(meson_ao_cec_g12a_of_match), + }, +}; + +module_platform_driver(meson_ao_cec_g12a_driver); + +MODULE_DESCRIPTION("Meson AO CEC G12A Controller driver"); +MODULE_AUTHOR("Neil Armstrong "); +MODULE_LICENSE("GPL"); From a4dfc8a24796ff312d1d307e11f26f8ca466e938 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Fri, 12 Apr 2019 04:31:00 -0400 Subject: [PATCH 207/218] media: MAINTAINERS: Update AO CEC with ao-cec-g12a driver Update the MAINTAINERS entry with the new AO-CEC driver for G12A. Signed-off-by: Neil Armstrong Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index ce27db435e81..878588cfb453 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10046,6 +10046,7 @@ L: linux-amlogic@lists.infradead.org W: http://linux-meson.com/ S: Supported F: drivers/media/platform/meson/ao-cec.c +F: drivers/media/platform/meson/ao-cec-g12a.c F: Documentation/devicetree/bindings/media/meson-ao-cec.txt T: git git://linuxtv.org/media_tree.git From 8dce4b265a5357731058f69645840dabc718c687 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 10 Apr 2019 07:02:49 -0400 Subject: [PATCH 208/218] media: zoran: remove deprecated driver The zoran driver has been marked deprecated for a year now without any interest to update this driver to the vb2 framework. Time to remove it altogether. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/v4l-drivers/index.rst | 1 - Documentation/media/v4l-drivers/zoran.rst | 583 ---- drivers/staging/media/Kconfig | 2 - drivers/staging/media/Makefile | 1 - drivers/staging/media/zoran/Kconfig | 75 - drivers/staging/media/zoran/Makefile | 7 - drivers/staging/media/zoran/TODO | 4 - drivers/staging/media/zoran/videocodec.c | 391 --- drivers/staging/media/zoran/videocodec.h | 349 --- drivers/staging/media/zoran/zoran.h | 402 --- drivers/staging/media/zoran/zoran_card.c | 1524 ----------- drivers/staging/media/zoran/zoran_card.h | 50 - drivers/staging/media/zoran/zoran_device.c | 1619 ----------- drivers/staging/media/zoran/zoran_device.h | 91 - drivers/staging/media/zoran/zoran_driver.c | 2850 -------------------- drivers/staging/media/zoran/zoran_procfs.c | 221 -- drivers/staging/media/zoran/zoran_procfs.h | 32 - drivers/staging/media/zoran/zr36016.c | 516 ---- drivers/staging/media/zoran/zr36016.h | 107 - drivers/staging/media/zoran/zr36050.c | 896 ------ drivers/staging/media/zoran/zr36050.h | 179 -- drivers/staging/media/zoran/zr36057.h | 164 -- drivers/staging/media/zoran/zr36060.c | 1006 ------- drivers/staging/media/zoran/zr36060.h | 216 -- 24 files changed, 11286 deletions(-) delete mode 100644 Documentation/media/v4l-drivers/zoran.rst delete mode 100644 drivers/staging/media/zoran/Kconfig delete mode 100644 drivers/staging/media/zoran/Makefile delete mode 100644 drivers/staging/media/zoran/TODO delete mode 100644 drivers/staging/media/zoran/videocodec.c delete mode 100644 drivers/staging/media/zoran/videocodec.h delete mode 100644 drivers/staging/media/zoran/zoran.h delete mode 100644 drivers/staging/media/zoran/zoran_card.c delete mode 100644 drivers/staging/media/zoran/zoran_card.h delete mode 100644 drivers/staging/media/zoran/zoran_device.c delete mode 100644 drivers/staging/media/zoran/zoran_device.h delete mode 100644 drivers/staging/media/zoran/zoran_driver.c delete mode 100644 drivers/staging/media/zoran/zoran_procfs.c delete mode 100644 drivers/staging/media/zoran/zoran_procfs.h delete mode 100644 drivers/staging/media/zoran/zr36016.c delete mode 100644 drivers/staging/media/zoran/zr36016.h delete mode 100644 drivers/staging/media/zoran/zr36050.c delete mode 100644 drivers/staging/media/zoran/zr36050.h delete mode 100644 drivers/staging/media/zoran/zr36057.h delete mode 100644 drivers/staging/media/zoran/zr36060.c delete mode 100644 drivers/staging/media/zoran/zr36060.h diff --git a/Documentation/media/v4l-drivers/index.rst b/Documentation/media/v4l-drivers/index.rst index dfd4b205937c..33a055907258 100644 --- a/Documentation/media/v4l-drivers/index.rst +++ b/Documentation/media/v4l-drivers/index.rst @@ -65,5 +65,4 @@ For more details see the file COPYING in the source distribution of Linux. soc-camera uvcvideo vivid - zoran zr364xx diff --git a/Documentation/media/v4l-drivers/zoran.rst b/Documentation/media/v4l-drivers/zoran.rst deleted file mode 100644 index d2724a863d1d..000000000000 --- a/Documentation/media/v4l-drivers/zoran.rst +++ /dev/null @@ -1,583 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 - -The Zoran driver -================ - -unified zoran driver (zr360x7, zoran, buz, dc10(+), dc30(+), lml33) - -website: http://mjpeg.sourceforge.net/driver-zoran/ - - -Frequently Asked Questions --------------------------- - -What cards are supported ------------------------- - -Iomega Buz, Linux Media Labs LML33/LML33R10, Pinnacle/Miro -DC10/DC10+/DC30/DC30+ and related boards (available under various names). - -Iomega Buz -~~~~~~~~~~ - -* Zoran zr36067 PCI controller -* Zoran zr36060 MJPEG codec -* Philips saa7111 TV decoder -* Philips saa7185 TV encoder - -Drivers to use: videodev, i2c-core, i2c-algo-bit, -videocodec, saa7111, saa7185, zr36060, zr36067 - -Inputs/outputs: Composite and S-video - -Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps) - -Card number: 7 - -AverMedia 6 Eyes AVS6EYES -~~~~~~~~~~~~~~~~~~~~~~~~~ - -* Zoran zr36067 PCI controller -* Zoran zr36060 MJPEG codec -* Samsung ks0127 TV decoder -* Conexant bt866 TV encoder - -Drivers to use: videodev, i2c-core, i2c-algo-bit, -videocodec, ks0127, bt866, zr36060, zr36067 - -Inputs/outputs: - Six physical inputs. 1-6 are composite, - 1-2, 3-4, 5-6 doubles as S-video, - 1-3 triples as component. - One composite output. - -Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps) - -Card number: 8 - -.. note:: - - Not autodetected, card=8 is necessary. - -Linux Media Labs LML33 -~~~~~~~~~~~~~~~~~~~~~~ - -* Zoran zr36067 PCI controller -* Zoran zr36060 MJPEG codec -* Brooktree bt819 TV decoder -* Brooktree bt856 TV encoder - -Drivers to use: videodev, i2c-core, i2c-algo-bit, -videocodec, bt819, bt856, zr36060, zr36067 - -Inputs/outputs: Composite and S-video - -Norms: PAL (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps) - -Card number: 5 - -Linux Media Labs LML33R10 -~~~~~~~~~~~~~~~~~~~~~~~~~ - -* Zoran zr36067 PCI controller -* Zoran zr36060 MJPEG codec -* Philips saa7114 TV decoder -* Analog Devices adv7170 TV encoder - -Drivers to use: videodev, i2c-core, i2c-algo-bit, -videocodec, saa7114, adv7170, zr36060, zr36067 - -Inputs/outputs: Composite and S-video - -Norms: PAL (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps) - -Card number: 6 - -Pinnacle/Miro DC10(new) -~~~~~~~~~~~~~~~~~~~~~~~ - -* Zoran zr36057 PCI controller -* Zoran zr36060 MJPEG codec -* Philips saa7110a TV decoder -* Analog Devices adv7176 TV encoder - -Drivers to use: videodev, i2c-core, i2c-algo-bit, -videocodec, saa7110, adv7175, zr36060, zr36067 - -Inputs/outputs: Composite, S-video and Internal - -Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps) - -Card number: 1 - -Pinnacle/Miro DC10+ -~~~~~~~~~~~~~~~~~~~ - -* Zoran zr36067 PCI controller -* Zoran zr36060 MJPEG codec -* Philips saa7110a TV decoder -* Analog Devices adv7176 TV encoder - -Drivers to use: videodev, i2c-core, i2c-algo-bit, -videocodec, sa7110, adv7175, zr36060, zr36067 - -Inputs/outputs: Composite, S-video and Internal - -Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps) - -Card number: 2 - -Pinnacle/Miro DC10(old) -~~~~~~~~~~~~~~~~~~~~~~~ - -* Zoran zr36057 PCI controller -* Zoran zr36050 MJPEG codec -* Zoran zr36016 Video Front End or Fuji md0211 Video Front End (clone?) -* Micronas vpx3220a TV decoder -* mse3000 TV encoder or Analog Devices adv7176 TV encoder - -Drivers to use: videodev, i2c-core, i2c-algo-bit, -videocodec, vpx3220, mse3000/adv7175, zr36050, zr36016, zr36067 - -Inputs/outputs: Composite, S-video and Internal - -Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps) - -Card number: 0 - -Pinnacle/Miro DC30 -~~~~~~~~~~~~~~~~~~ - -* Zoran zr36057 PCI controller -* Zoran zr36050 MJPEG codec -* Zoran zr36016 Video Front End -* Micronas vpx3225d/vpx3220a/vpx3216b TV decoder -* Analog Devices adv7176 TV encoder - -Drivers to use: videodev, i2c-core, i2c-algo-bit, -videocodec, vpx3220/vpx3224, adv7175, zr36050, zr36016, zr36067 - -Inputs/outputs: Composite, S-video and Internal - -Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps) - -Card number: 3 - -Pinnacle/Miro DC30+ -~~~~~~~~~~~~~~~~~~~ - -* Zoran zr36067 PCI controller -* Zoran zr36050 MJPEG codec -* Zoran zr36016 Video Front End -* Micronas vpx3225d/vpx3220a/vpx3216b TV decoder -* Analog Devices adv7176 TV encoder - -Drivers to use: videodev, i2c-core, i2c-algo-bit, -videocodec, vpx3220/vpx3224, adv7175, zr36050, zr36015, zr36067 - -Inputs/outputs: Composite, S-video and Internal - -Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps) - -Card number: 4 - -.. note:: - - #) No module for the mse3000 is available yet - #) No module for the vpx3224 is available yet - -1.1 What the TV decoder can do an what not ------------------------------------------- - -The best know TV standards are NTSC/PAL/SECAM. but for decoding a frame that -information is not enough. There are several formats of the TV standards. -And not every TV decoder is able to handle every format. Also the every -combination is supported by the driver. There are currently 11 different -tv broadcast formats all aver the world. - -The CCIR defines parameters needed for broadcasting the signal. -The CCIR has defined different standards: A,B,D,E,F,G,D,H,I,K,K1,L,M,N,... -The CCIR says not much about the colorsystem used !!! -And talking about a colorsystem says not to much about how it is broadcast. - -The CCIR standards A,E,F are not used any more. - -When you speak about NTSC, you usually mean the standard: CCIR - M using -the NTSC colorsystem which is used in the USA, Japan, Mexico, Canada -and a few others. - -When you talk about PAL, you usually mean: CCIR - B/G using the PAL -colorsystem which is used in many Countries. - -When you talk about SECAM, you mean: CCIR - L using the SECAM Colorsystem -which is used in France, and a few others. - -There the other version of SECAM, CCIR - D/K is used in Bulgaria, China, -Slovakai, Hungary, Korea (Rep.), Poland, Rumania and a others. - -The CCIR - H uses the PAL colorsystem (sometimes SECAM) and is used in -Egypt, Libya, Sri Lanka, Syrain Arab. Rep. - -The CCIR - I uses the PAL colorsystem, and is used in Great Britain, Hong Kong, -Ireland, Nigeria, South Africa. - -The CCIR - N uses the PAL colorsystem and PAL frame size but the NTSC framerate, -and is used in Argentinia, Uruguay, an a few others - -We do not talk about how the audio is broadcast ! - -A rather good sites about the TV standards are: -http://www.sony.jp/support/ -http://info.electronicwerkstatt.de/bereiche/fernsehtechnik/frequenzen_und_normen/Fernsehnormen/ -and http://www.cabl.com/restaurant/channel.html - -Other weird things around: NTSC 4.43 is a modificated NTSC, which is mainly -used in PAL VCR's that are able to play back NTSC. PAL 60 seems to be the same -as NTSC 4.43 . The Datasheets also talk about NTSC 44, It seems as if it would -be the same as NTSC 4.43. -NTSC Combs seems to be a decoder mode where the decoder uses a comb filter -to split coma and luma instead of a Delay line. - -But I did not defiantly find out what NTSC Comb is. - -Philips saa7111 TV decoder -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- was introduced in 1997, is used in the BUZ and -- can handle: PAL B/G/H/I, PAL N, PAL M, NTSC M, NTSC N, NTSC 4.43 and SECAM - -Philips saa7110a TV decoder -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- was introduced in 1995, is used in the Pinnacle/Miro DC10(new), DC10+ and -- can handle: PAL B/G, NTSC M and SECAM - -Philips saa7114 TV decoder -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- was introduced in 2000, is used in the LML33R10 and -- can handle: PAL B/G/D/H/I/N, PAL N, PAL M, NTSC M, NTSC 4.43 and SECAM - -Brooktree bt819 TV decoder -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- was introduced in 1996, and is used in the LML33 and -- can handle: PAL B/D/G/H/I, NTSC M - -Micronas vpx3220a TV decoder -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- was introduced in 1996, is used in the DC30 and DC30+ and -- can handle: PAL B/G/H/I, PAL N, PAL M, NTSC M, NTSC 44, PAL 60, SECAM,NTSC Comb - -Samsung ks0127 TV decoder -~~~~~~~~~~~~~~~~~~~~~~~~~ - -- is used in the AVS6EYES card and -- can handle: NTSC-M/N/44, PAL-M/N/B/G/H/I/D/K/L and SECAM - - -What the TV encoder can do an what not --------------------------------------- - -The TV encoder are doing the "same" as the decoder, but in the oder direction. -You feed them digital data and the generate a Composite or SVHS signal. -For information about the colorsystems and TV norm take a look in the -TV decoder section. - -Philips saa7185 TV Encoder -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- was introduced in 1996, is used in the BUZ -- can generate: PAL B/G, NTSC M - -Brooktree bt856 TV Encoder -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- was introduced in 1994, is used in the LML33 -- can generate: PAL B/D/G/H/I/N, PAL M, NTSC M, PAL-N (Argentina) - -Analog Devices adv7170 TV Encoder -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- was introduced in 2000, is used in the LML300R10 -- can generate: PAL B/D/G/H/I/N, PAL M, NTSC M, PAL 60 - -Analog Devices adv7175 TV Encoder -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- was introduced in 1996, is used in the DC10, DC10+, DC10 old, DC30, DC30+ -- can generate: PAL B/D/G/H/I/N, PAL M, NTSC M - -ITT mse3000 TV encoder -~~~~~~~~~~~~~~~~~~~~~~ - -- was introduced in 1991, is used in the DC10 old -- can generate: PAL , NTSC , SECAM - -Conexant bt866 TV encoder -~~~~~~~~~~~~~~~~~~~~~~~~~ - -- is used in AVS6EYES, and -- can generate: NTSC/PAL, PAL­M, PAL­N - -The adv717x, should be able to produce PAL N. But you find nothing PAL N -specific in the registers. Seem that you have to reuse a other standard -to generate PAL N, maybe it would work if you use the PAL M settings. - -How do I get this damn thing to work ------------------------------------- - -Load zr36067.o. If it can't autodetect your card, use the card=X insmod -option with X being the card number as given in the previous section. -To have more than one card, use card=X1[,X2[,X3,[X4[..]]]] - -To automate this, add the following to your /etc/modprobe.d/zoran.conf: - -options zr36067 card=X1[,X2[,X3[,X4[..]]]] -alias char-major-81-0 zr36067 - -One thing to keep in mind is that this doesn't load zr36067.o itself yet. It -just automates loading. If you start using xawtv, the device won't load on -some systems, since you're trying to load modules as a user, which is not -allowed ("permission denied"). A quick workaround is to add 'Load "v4l"' to -XF86Config-4 when you use X by default, or to run 'v4l-conf -c ' in -one of your startup scripts (normally rc.local) if you don't use X. Both -make sure that the modules are loaded on startup, under the root account. - -What mainboard should I use (or why doesn't my card work) ---------------------------------------------------------- - - -. In short: good=SiS/Intel, bad=VIA. - -Experience tells us that people with a Buz, on average, have more problems -than users with a DC10+/LML33. Also, it tells us that people owning a VIA- -based mainboard (ktXXX, MVP3) have more problems than users with a mainboard -based on a different chipset. Here's some notes from Andrew Stevens: - -Here's my experience of using LML33 and Buz on various motherboards: - -- VIA MVP3 - - Forget it. Pointless. Doesn't work. -- Intel 430FX (Pentium 200) - - LML33 perfect, Buz tolerable (3 or 4 frames dropped per movie) -- Intel 440BX (early stepping) - - LML33 tolerable. Buz starting to get annoying (6-10 frames/hour) -- Intel 440BX (late stepping) - - Buz tolerable, LML3 almost perfect (occasional single frame drops) -- SiS735 - - LML33 perfect, Buz tolerable. -- VIA KT133(*) - - LML33 starting to get annoying, Buz poor enough that I have up. - -- Both 440BX boards were dual CPU versions. - -Bernhard Praschinger later added: - -- AMD 751 - - Buz perfect-tolerable -- AMD 760 - - Buz perfect-tolerable - -In general, people on the user mailinglist won't give you much of a chance -if you have a VIA-based motherboard. They may be cheap, but sometimes, you'd -rather want to spend some more money on better boards. In general, VIA -mainboard's IDE/PCI performance will also suck badly compared to others. -You'll noticed the DC10+/DC30+ aren't mentioned anywhere in the overview. -Basically, you can assume that if the Buz works, the LML33 will work too. If -the LML33 works, the DC10+/DC30+ will work too. They're most tolerant to -different mainboard chipsets from all of the supported cards. - -If you experience timeouts during capture, buy a better mainboard or lower -the quality/buffersize during capture (see 'Concerning buffer sizes, quality, -output size etc.'). If it hangs, there's little we can do as of now. Check -your IRQs and make sure the card has its own interrupts. - -Programming interface ---------------------- - -This driver conforms to video4linux2. Support for V4L1 and for the custom -zoran ioctls has been removed in kernel 2.6.38. - -For programming example, please, look at lavrec.c and lavplay.c code in -the MJPEG-tools (http://mjpeg.sf.net/). - -Additional notes for software developers: - - The driver returns maxwidth and maxheight parameters according to - the current TV standard (norm). Therefore, the software which - communicates with the driver and "asks" for these parameters should - first set the correct norm. Well, it seems logically correct: TV - standard is "more constant" for current country than geometry - settings of a variety of TV capture cards which may work in ITU or - square pixel format. - -Applications ------------- - -Applications known to work with this driver: - -TV viewing: - -* xawtv -* kwintv -* probably any TV application that supports video4linux or video4linux2. - -MJPEG capture/playback: - -* mjpegtools/lavtools (or Linux Video Studio) -* gstreamer -* mplayer - -General raw capture: - -* xawtv -* gstreamer -* probably any application that supports video4linux or video4linux2 - -Video editing: - -* Cinelerra -* MainActor -* mjpegtools (or Linux Video Studio) - - -Concerning buffer sizes, quality, output size etc. --------------------------------------------------- - - -The zr36060 can do 1:2 JPEG compression. This is really the theoretical -maximum that the chipset can reach. The driver can, however, limit compression -to a maximum (size) of 1:4. The reason for this is that some cards (e.g. Buz) -can't handle 1:2 compression without stopping capture after only a few minutes. -With 1:4, it'll mostly work. If you have a Buz, use 'low_bitrate=1' to go into -1:4 max. compression mode. - -100% JPEG quality is thus 1:2 compression in practice. So for a full PAL frame -(size 720x576). The JPEG fields are stored in YUY2 format, so the size of the -fields are 720x288x16/2 bits/field (2 fields/frame) = 207360 bytes/field x 2 = -414720 bytes/frame (add some more bytes for headers and DHT (huffman)/DQT -(quantization) tables, and you'll get to something like 512kB per frame for -1:2 compression. For 1:4 compression, you'd have frames of half this size. - -Some additional explanation by Martin Samuelsson, which also explains the -importance of buffer sizes: --- -> Hmm, I do not think it is really that way. With the current (downloaded -> at 18:00 Monday) driver I get that output sizes for 10 sec: -> -q 50 -b 128 : 24.283.332 Bytes -> -q 50 -b 256 : 48.442.368 -> -q 25 -b 128 : 24.655.992 -> -q 25 -b 256 : 25.859.820 - -I woke up, and can't go to sleep again. I'll kill some time explaining why -this doesn't look strange to me. - -Let's do some math using a width of 704 pixels. I'm not sure whether the Buz -actually use that number or not, but that's not too important right now. - -704x288 pixels, one field, is 202752 pixels. Divided by 64 pixels per block; -3168 blocks per field. Each pixel consist of two bytes; 128 bytes per block; -1024 bits per block. 100% in the new driver mean 1:2 compression; the maximum -output becomes 512 bits per block. Actually 510, but 512 is simpler to use -for calculations. - -Let's say that we specify d1q50. We thus want 256 bits per block; times 3168 -becomes 811008 bits; 101376 bytes per field. We're talking raw bits and bytes -here, so we don't need to do any fancy corrections for bits-per-pixel or such -things. 101376 bytes per field. - -d1 video contains two fields per frame. Those sum up to 202752 bytes per -frame, and one of those frames goes into each buffer. - -But wait a second! -b128 gives 128kB buffers! It's not possible to cram -202752 bytes of JPEG data into 128kB! - -This is what the driver notice and automatically compensate for in your -examples. Let's do some math using this information: - -128kB is 131072 bytes. In this buffer, we want to store two fields, which -leaves 65536 bytes for each field. Using 3168 blocks per field, we get -20.68686868... available bytes per block; 165 bits. We can't allow the -request for 256 bits per block when there's only 165 bits available! The -q50 -option is silently overridden, and the -b128 option takes precedence, leaving -us with the equivalence of -q32. - -This gives us a data rate of 165 bits per block, which, times 3168, sums up -to 65340 bytes per field, out of the allowed 65536. The current driver has -another level of rate limiting; it won't accept -q values that fill more than -6/8 of the specified buffers. (I'm not sure why. "Playing it safe" seem to be -a safe bet. Personally, I think I would have lowered requested-bits-per-block -by one, or something like that.) We can't use 165 bits per block, but have to -lower it again, to 6/8 of the available buffer space: We end up with 124 bits -per block, the equivalence of -q24. With 128kB buffers, you can't use greater -than -q24 at -d1. (And PAL, and 704 pixels width...) - -The third example is limited to -q24 through the same process. The second -example, using very similar calculations, is limited to -q48. The only -example that actually grab at the specified -q value is the last one, which -is clearly visible, looking at the file size. --- - -Conclusion: the quality of the resulting movie depends on buffer size, quality, -whether or not you use 'low_bitrate=1' as insmod option for the zr36060.c -module to do 1:4 instead of 1:2 compression, etc. - -If you experience timeouts, lowering the quality/buffersize or using -'low_bitrate=1 as insmod option for zr36060.o might actually help, as is -proven by the Buz. - -It hangs/crashes/fails/whatevers! Help! ---------------------------------------- - -Make sure that the card has its own interrupts (see /proc/interrupts), check -the output of dmesg at high verbosity (load zr36067.o with debug=2, -load all other modules with debug=1). Check that your mainboard is favorable -(see question 2) and if not, test the card in another computer. Also see the -notes given in question 3 and try lowering quality/buffersize/capturesize -if recording fails after a period of time. - -If all this doesn't help, give a clear description of the problem including -detailed hardware information (memory+brand, mainboard+chipset+brand, which -MJPEG card, processor, other PCI cards that might be of interest), give the -system PnP information (/proc/interrupts, /proc/dma, /proc/devices), and give -the kernel version, driver version, glibc version, gcc version and any other -information that might possibly be of interest. Also provide the dmesg output -at high verbosity. See 'Contacting' on how to contact the developers. - -Maintainers/Contacting ----------------------- - -The driver is currently maintained by Laurent Pinchart and Ronald Bultje -( and ). For bug -reports or questions, please contact the mailinglist instead of the developers -individually. For user questions (i.e. bug reports or how-to questions), send -an email to , for developers (i.e. if you want to -help programming), send an email to . See -http://www.sf.net/projects/mjpeg/ for subscription information. - -For bug reports, be sure to include all the information as described in -the section 'It hangs/crashes/fails/whatevers! Help!'. Please make sure -you're using the latest version (http://mjpeg.sf.net/driver-zoran/). - -Previous maintainers/developers of this driver include Serguei Miridonov -, Wolfgang Scherr , Dave Perks - and Rainer Johanni . - -Driver's License ----------------- - - This driver is distributed under the terms of the General Public License. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - -See http://www.gnu.org/ for more information. diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index 277df2b39384..5486cf5d998f 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -33,8 +33,6 @@ source "drivers/staging/media/sunxi/Kconfig" source "drivers/staging/media/tegra-vde/Kconfig" -source "drivers/staging/media/zoran/Kconfig" - source "drivers/staging/media/ipu3/Kconfig" source "drivers/staging/media/soc_camera/Kconfig" diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index 0355e3030504..99218bfc997f 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -5,7 +5,6 @@ obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/ obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ obj-$(CONFIG_VIDEO_SUNXI) += sunxi/ obj-$(CONFIG_TEGRA_VDE) += tegra-vde/ -obj-$(CONFIG_VIDEO_ZORAN) += zoran/ obj-$(CONFIG_VIDEO_ROCKCHIP_VPU) += rockchip/vpu/ obj-$(CONFIG_VIDEO_IPU3_IMGU) += ipu3/ obj-$(CONFIG_SOC_CAMERA) += soc_camera/ diff --git a/drivers/staging/media/zoran/Kconfig b/drivers/staging/media/zoran/Kconfig deleted file mode 100644 index 34a18135ede0..000000000000 --- a/drivers/staging/media/zoran/Kconfig +++ /dev/null @@ -1,75 +0,0 @@ -config VIDEO_ZORAN - tristate "Zoran ZR36057/36067 Video For Linux (Deprecated)" - depends on PCI && I2C_ALGOBIT && VIDEO_V4L2 && VIRT_TO_BUS - depends on !ALPHA - help - Say Y for support for MJPEG capture cards based on the Zoran - 36057/36067 PCI controller chipset. This includes the Iomega - Buz, Pinnacle DC10+ and the Linux Media Labs LML33. There is - a driver homepage at . For - more information, check . - - To compile this driver as a module, choose M here: the - module will be called zr36067. - -config VIDEO_ZORAN_DC30 - tristate "Pinnacle/Miro DC30(+) support" - depends on VIDEO_ZORAN - select VIDEO_ADV7175 if MEDIA_SUBDRV_AUTOSELECT - select VIDEO_VPX3220 if MEDIA_SUBDRV_AUTOSELECT - help - Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback - card. This also supports really old DC10 cards based on the - zr36050 MJPEG codec and zr36016 VFE. - -config VIDEO_ZORAN_ZR36060 - tristate "Zoran ZR36060" - depends on VIDEO_ZORAN - help - Say Y to support Zoran boards based on 36060 chips. - This includes Iomega Buz, Pinnacle DC10, Linux media Labs 33 - and 33 R10 and AverMedia 6 boards. - -config VIDEO_ZORAN_BUZ - tristate "Iomega Buz support" - depends on VIDEO_ZORAN_ZR36060 - select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT - select VIDEO_SAA7185 if MEDIA_SUBDRV_AUTOSELECT - help - Support for the Iomega Buz MJPEG capture/playback card. - -config VIDEO_ZORAN_DC10 - tristate "Pinnacle/Miro DC10(+) support" - depends on VIDEO_ZORAN_ZR36060 - select VIDEO_SAA7110 if MEDIA_SUBDRV_AUTOSELECT - select VIDEO_ADV7175 if MEDIA_SUBDRV_AUTOSELECT - help - Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback - card. - -config VIDEO_ZORAN_LML33 - tristate "Linux Media Labs LML33 support" - depends on VIDEO_ZORAN_ZR36060 - select VIDEO_BT819 if MEDIA_SUBDRV_AUTOSELECT - select VIDEO_BT856 if MEDIA_SUBDRV_AUTOSELECT - help - Support for the Linux Media Labs LML33 MJPEG capture/playback - card. - -config VIDEO_ZORAN_LML33R10 - tristate "Linux Media Labs LML33R10 support" - depends on VIDEO_ZORAN_ZR36060 - select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT - select VIDEO_ADV7170 if MEDIA_SUBDRV_AUTOSELECT - help - support for the Linux Media Labs LML33R10 MJPEG capture/playback - card. - -config VIDEO_ZORAN_AVS6EYES - tristate "AverMedia 6 Eyes support" - depends on VIDEO_ZORAN_ZR36060 - select VIDEO_BT856 if MEDIA_SUBDRV_AUTOSELECT - select VIDEO_BT866 if MEDIA_SUBDRV_AUTOSELECT - select VIDEO_KS0127 if MEDIA_SUBDRV_AUTOSELECT - help - Support for the AverMedia 6 Eyes video surveillance card. diff --git a/drivers/staging/media/zoran/Makefile b/drivers/staging/media/zoran/Makefile deleted file mode 100644 index 21ac29a71458..000000000000 --- a/drivers/staging/media/zoran/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -zr36067-objs := zoran_procfs.o zoran_device.o \ - zoran_driver.o zoran_card.o - -obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o -obj-$(CONFIG_VIDEO_ZORAN_DC30) += zr36050.o zr36016.o -obj-$(CONFIG_VIDEO_ZORAN_ZR36060) += zr36060.o diff --git a/drivers/staging/media/zoran/TODO b/drivers/staging/media/zoran/TODO deleted file mode 100644 index 54464095d0d7..000000000000 --- a/drivers/staging/media/zoran/TODO +++ /dev/null @@ -1,4 +0,0 @@ -The zoran driver is marked deprecated. It will be removed -around May 2019 unless someone is willing to update this -driver to the latest V4L2 frameworks (especially the vb2 -framework). diff --git a/drivers/staging/media/zoran/videocodec.c b/drivers/staging/media/zoran/videocodec.c deleted file mode 100644 index 044ef8455ba8..000000000000 --- a/drivers/staging/media/zoran/videocodec.c +++ /dev/null @@ -1,391 +0,0 @@ -/* - * VIDEO MOTION CODECs internal API for video devices - * - * Interface for MJPEG (and maybe later MPEG/WAVELETS) codec's - * bound to a master device. - * - * (c) 2002 Wolfgang Scherr - * - * $Id: videocodec.c,v 1.1.2.8 2003/03/29 07:16:04 rbultje Exp $ - * - * ------------------------------------------------------------------------ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * ------------------------------------------------------------------------ - */ - -#define VIDEOCODEC_VERSION "v0.2" - -#include -#include -#include -#include -#include - -// kernel config is here (procfs flag) - -#ifdef CONFIG_PROC_FS -#include -#include -#include -#endif - -#include "videocodec.h" - -static int debug; -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0-4)"); - -#define dprintk(num, format, args...) \ - do { \ - if (debug >= num) \ - printk(format, ##args); \ - } while (0) - -struct attached_list { - struct videocodec *codec; - struct attached_list *next; -}; - -struct codec_list { - const struct videocodec *codec; - int attached; - struct attached_list *list; - struct codec_list *next; -}; - -static struct codec_list *codeclist_top; - -/* ================================================= */ -/* function prototypes of the master/slave interface */ -/* ================================================= */ - -struct videocodec * -videocodec_attach (struct videocodec_master *master) -{ - struct codec_list *h = codeclist_top; - struct attached_list *a, *ptr; - struct videocodec *codec; - int res; - - if (!master) { - dprintk(1, KERN_ERR "videocodec_attach: no data\n"); - return NULL; - } - - dprintk(2, - "videocodec_attach: '%s', flags %lx, magic %lx\n", - master->name, master->flags, master->magic); - - if (!h) { - dprintk(1, - KERN_ERR - "videocodec_attach: no device available\n"); - return NULL; - } - - while (h) { - // attach only if the slave has at least the flags - // expected by the master - if ((master->flags & h->codec->flags) == master->flags) { - dprintk(4, "videocodec_attach: try '%s'\n", - h->codec->name); - - if (!try_module_get(h->codec->owner)) - return NULL; - - codec = kmemdup(h->codec, sizeof(struct videocodec), - GFP_KERNEL); - if (!codec) { - dprintk(1, - KERN_ERR - "videocodec_attach: no mem\n"); - goto out_module_put; - } - - res = strlen(codec->name); - snprintf(codec->name + res, sizeof(codec->name) - res, - "[%d]", h->attached); - codec->master_data = master; - res = codec->setup(codec); - if (res == 0) { - dprintk(3, "videocodec_attach '%s'\n", - codec->name); - ptr = kzalloc(sizeof(struct attached_list), GFP_KERNEL); - if (!ptr) { - dprintk(1, - KERN_ERR - "videocodec_attach: no memory\n"); - goto out_kfree; - } - ptr->codec = codec; - - a = h->list; - if (!a) { - h->list = ptr; - dprintk(4, - "videocodec: first element\n"); - } else { - while (a->next) - a = a->next; // find end - a->next = ptr; - dprintk(4, - "videocodec: in after '%s'\n", - h->codec->name); - } - - h->attached += 1; - return codec; - } else { - kfree(codec); - } - } - h = h->next; - } - - dprintk(1, KERN_ERR "videocodec_attach: no codec found!\n"); - return NULL; - - out_module_put: - module_put(h->codec->owner); - out_kfree: - kfree(codec); - return NULL; -} - -int -videocodec_detach (struct videocodec *codec) -{ - struct codec_list *h = codeclist_top; - struct attached_list *a, *prev; - int res; - - if (!codec) { - dprintk(1, KERN_ERR "videocodec_detach: no data\n"); - return -EINVAL; - } - - dprintk(2, - "videocodec_detach: '%s', type: %x, flags %lx, magic %lx\n", - codec->name, codec->type, codec->flags, codec->magic); - - if (!h) { - dprintk(1, - KERN_ERR "videocodec_detach: no device left...\n"); - return -ENXIO; - } - - while (h) { - a = h->list; - prev = NULL; - while (a) { - if (codec == a->codec) { - res = a->codec->unset(a->codec); - if (res >= 0) { - dprintk(3, - "videocodec_detach: '%s'\n", - a->codec->name); - a->codec->master_data = NULL; - } else { - dprintk(1, - KERN_ERR - "videocodec_detach: '%s'\n", - a->codec->name); - a->codec->master_data = NULL; - } - if (prev == NULL) { - h->list = a->next; - dprintk(4, - "videocodec: delete first\n"); - } else { - prev->next = a->next; - dprintk(4, - "videocodec: delete middle\n"); - } - module_put(a->codec->owner); - kfree(a->codec); - kfree(a); - h->attached -= 1; - return 0; - } - prev = a; - a = a->next; - } - h = h->next; - } - - dprintk(1, KERN_ERR "videocodec_detach: given codec not found!\n"); - return -EINVAL; -} - -int -videocodec_register (const struct videocodec *codec) -{ - struct codec_list *ptr, *h = codeclist_top; - - if (!codec) { - dprintk(1, KERN_ERR "videocodec_register: no data!\n"); - return -EINVAL; - } - - dprintk(2, - "videocodec: register '%s', type: %x, flags %lx, magic %lx\n", - codec->name, codec->type, codec->flags, codec->magic); - - ptr = kzalloc(sizeof(struct codec_list), GFP_KERNEL); - if (!ptr) { - dprintk(1, KERN_ERR "videocodec_register: no memory\n"); - return -ENOMEM; - } - ptr->codec = codec; - - if (!h) { - codeclist_top = ptr; - dprintk(4, "videocodec: hooked in as first element\n"); - } else { - while (h->next) - h = h->next; // find the end - h->next = ptr; - dprintk(4, "videocodec: hooked in after '%s'\n", - h->codec->name); - } - - return 0; -} - -int -videocodec_unregister (const struct videocodec *codec) -{ - struct codec_list *prev = NULL, *h = codeclist_top; - - if (!codec) { - dprintk(1, KERN_ERR "videocodec_unregister: no data!\n"); - return -EINVAL; - } - - dprintk(2, - "videocodec: unregister '%s', type: %x, flags %lx, magic %lx\n", - codec->name, codec->type, codec->flags, codec->magic); - - if (!h) { - dprintk(1, - KERN_ERR - "videocodec_unregister: no device left...\n"); - return -ENXIO; - } - - while (h) { - if (codec == h->codec) { - if (h->attached) { - dprintk(1, - KERN_ERR - "videocodec: '%s' is used\n", - h->codec->name); - return -EBUSY; - } - dprintk(3, "videocodec: unregister '%s' is ok.\n", - h->codec->name); - if (prev == NULL) { - codeclist_top = h->next; - dprintk(4, - "videocodec: delete first element\n"); - } else { - prev->next = h->next; - dprintk(4, - "videocodec: delete middle element\n"); - } - kfree(h); - return 0; - } - prev = h; - h = h->next; - } - - dprintk(1, - KERN_ERR - "videocodec_unregister: given codec not found!\n"); - return -EINVAL; -} - -#ifdef CONFIG_PROC_FS -static int proc_videocodecs_show(struct seq_file *m, void *v) -{ - struct codec_list *h = codeclist_top; - struct attached_list *a; - - seq_printf(m, "lave or attached aster name type flags magic "); - seq_printf(m, "(connected as)\n"); - - while (h) { - seq_printf(m, "S %32s %04x %08lx %08lx (TEMPLATE)\n", - h->codec->name, h->codec->type, - h->codec->flags, h->codec->magic); - a = h->list; - while (a) { - seq_printf(m, "M %32s %04x %08lx %08lx (%s)\n", - a->codec->master_data->name, - a->codec->master_data->type, - a->codec->master_data->flags, - a->codec->master_data->magic, - a->codec->name); - a = a->next; - } - h = h->next; - } - - return 0; -} -#endif - -/* ===================== */ -/* hook in driver module */ -/* ===================== */ -static int __init -videocodec_init (void) -{ -#ifdef CONFIG_PROC_FS - static struct proc_dir_entry *videocodec_proc_entry; -#endif - - printk(KERN_INFO "Linux video codec intermediate layer: %s\n", - VIDEOCODEC_VERSION); - -#ifdef CONFIG_PROC_FS - videocodec_proc_entry = proc_create_single("videocodecs", 0, NULL, - proc_videocodecs_show); - if (!videocodec_proc_entry) { - dprintk(1, KERN_ERR "videocodec: can't init procfs.\n"); - } -#endif - return 0; -} - -static void __exit -videocodec_exit (void) -{ -#ifdef CONFIG_PROC_FS - remove_proc_entry("videocodecs", NULL); -#endif -} - -EXPORT_SYMBOL(videocodec_attach); -EXPORT_SYMBOL(videocodec_detach); -EXPORT_SYMBOL(videocodec_register); -EXPORT_SYMBOL(videocodec_unregister); - -module_init(videocodec_init); -module_exit(videocodec_exit); - -MODULE_AUTHOR("Wolfgang Scherr "); -MODULE_DESCRIPTION("Intermediate API module for video codecs " - VIDEOCODEC_VERSION); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/media/zoran/videocodec.h b/drivers/staging/media/zoran/videocodec.h deleted file mode 100644 index 8ed5a0f7ac01..000000000000 --- a/drivers/staging/media/zoran/videocodec.h +++ /dev/null @@ -1,349 +0,0 @@ -/* - * VIDEO MOTION CODECs internal API for video devices - * - * Interface for MJPEG (and maybe later MPEG/WAVELETS) codec's - * bound to a master device. - * - * (c) 2002 Wolfgang Scherr - * - * $Id: videocodec.h,v 1.1.2.4 2003/01/14 21:15:03 rbultje Exp $ - * - * ------------------------------------------------------------------------ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * ------------------------------------------------------------------------ - */ - -/* =================== */ -/* general description */ -/* =================== */ - -/* Should ease the (re-)usage of drivers supporting cards with (different) - video codecs. The codecs register to this module their functionality, - and the processors (masters) can attach to them if they fit. - - The codecs are typically have a "strong" binding to their master - so I - don't think it makes sense to have a full blown interfacing as with e.g. - i2c. If you have an other opinion, let's discuss & implement it :-))) - - Usage: - - The slave has just to setup the videocodec structure and use two functions: - videocodec_register(codecdata); - videocodec_unregister(codecdata); - The best is just calling them at module (de-)initialisation. - - The master sets up the structure videocodec_master and calls: - codecdata=videocodec_attach(master_codecdata); - videocodec_detach(codecdata); - - The slave is called during attach/detach via functions setup previously - during register. At that time, the master_data pointer is set up - and the slave can access any io registers of the master device (in the case - the slave is bound to it). Otherwise it doesn't need this functions and - therfor they may not be initialized. - - The other functions are just for convenience, as they are for sure used by - most/all of the codecs. The last ones may be omitted, too. - - See the structure declaration below for more information and which data has - to be set up for the master and the slave. - - ---------------------------------------------------------------------------- - The master should have "knowledge" of the slave and vice versa. So the data - structures sent to/from slave via set_data/get_data set_image/get_image are - device dependent and vary between MJPEG/MPEG/WAVELET/... devices. (!!!!) - ---------------------------------------------------------------------------- -*/ - - -/* ========================================== */ -/* description of the videocodec_io structure */ -/* ========================================== */ - -/* - ==== master setup ==== - name -> name of the device structure for reference and debugging - master_data -> data ref. for the master (e.g. the zr36055,57,67) - readreg -> ref. to read-fn from register (setup by master, used by slave) - writereg -> ref. to write-fn to register (setup by master, used by slave) - this two functions do the lowlevel I/O job - - ==== slave functionality setup ==== - slave_data -> data ref. for the slave (e.g. the zr36050,60) - check -> fn-ref. checks availability of an device, returns -EIO on failure or - the type on success - this makes espcecially sense if a driver module supports more than - one codec which may be quite similar to access, nevertheless it - is good for a first functionality check - - -- main functions you always need for compression/decompression -- - - set_mode -> this fn-ref. resets the entire codec, and sets up the mode - with the last defined norm/size (or device default if not - available) - it returns 0 if the mode is possible - set_size -> this fn-ref. sets the norm and image size for - compression/decompression (returns 0 on success) - the norm param is defined in videodev2.h (V4L2_STD_*) - - additional setup may be available, too - but the codec should work with - some default values even without this - - set_data -> sets device-specific data (tables, quality etc.) - get_data -> query device-specific data (tables, quality etc.) - - if the device delivers interrupts, they may be setup/handled here - setup_interrupt -> codec irq setup (not needed for 36050/60) - handle_interrupt -> codec irq handling (not needed for 36050/60) - - if the device delivers pictures, they may be handled here - put_image -> puts image data to the codec (not needed for 36050/60) - get_image -> gets image data from the codec (not needed for 36050/60) - the calls include frame numbers and flags (even/odd/...) - if needed and a flag which allows blocking until its ready -*/ - -/* ============== */ -/* user interface */ -/* ============== */ - -/* - Currently there is only a information display planned, as the layer - is not visible for the user space at all. - - Information is available via procfs. The current entry is "/proc/videocodecs" - but it makes sense to "hide" it in the /proc/video tree of v4l(2) --TODO--. - -A example for such an output is: - -lave or attached aster name type flags magic (connected as) -S zr36050 0002 0000d001 00000000 (TEMPLATE) -M zr36055[0] 0001 0000c001 00000000 (zr36050[0]) -M zr36055[1] 0001 0000c001 00000000 (zr36050[1]) - -*/ - - -/* =============================================== */ -/* special defines for the videocodec_io structure */ -/* =============================================== */ - -#ifndef __LINUX_VIDEOCODEC_H -#define __LINUX_VIDEOCODEC_H - -#include - -#define CODEC_DO_COMPRESSION 0 -#define CODEC_DO_EXPANSION 1 - -/* this are the current codec flags I think they are needed */ -/* -> type value in structure */ -#define CODEC_FLAG_JPEG 0x00000001L // JPEG codec -#define CODEC_FLAG_MPEG 0x00000002L // MPEG1/2/4 codec -#define CODEC_FLAG_DIVX 0x00000004L // DIVX codec -#define CODEC_FLAG_WAVELET 0x00000008L // WAVELET codec - // room for other types - -#define CODEC_FLAG_MAGIC 0x00000800L // magic key must match -#define CODEC_FLAG_HARDWARE 0x00001000L // is a hardware codec -#define CODEC_FLAG_VFE 0x00002000L // has direct video frontend -#define CODEC_FLAG_ENCODER 0x00004000L // compression capability -#define CODEC_FLAG_DECODER 0x00008000L // decompression capability -#define CODEC_FLAG_NEEDIRQ 0x00010000L // needs irq handling -#define CODEC_FLAG_RDWRPIC 0x00020000L // handles picture I/O - -/* a list of modes, some are just examples (is there any HW?) */ -#define CODEC_MODE_BJPG 0x0001 // Baseline JPEG -#define CODEC_MODE_LJPG 0x0002 // Lossless JPEG -#define CODEC_MODE_MPEG1 0x0003 // MPEG 1 -#define CODEC_MODE_MPEG2 0x0004 // MPEG 2 -#define CODEC_MODE_MPEG4 0x0005 // MPEG 4 -#define CODEC_MODE_MSDIVX 0x0006 // MS DivX -#define CODEC_MODE_ODIVX 0x0007 // Open DivX -#define CODEC_MODE_WAVELET 0x0008 // Wavelet - -/* this are the current codec types I want to implement */ -/* -> type value in structure */ -#define CODEC_TYPE_NONE 0 -#define CODEC_TYPE_L64702 1 -#define CODEC_TYPE_ZR36050 2 -#define CODEC_TYPE_ZR36016 3 -#define CODEC_TYPE_ZR36060 4 - -/* the type of data may be enhanced by future implementations (data-fn.'s) */ -/* -> used in command */ -#define CODEC_G_STATUS 0x0000 /* codec status (query only) */ -#define CODEC_S_CODEC_MODE 0x0001 /* codec mode (baseline JPEG, MPEG1,... */ -#define CODEC_G_CODEC_MODE 0x8001 -#define CODEC_S_VFE 0x0002 /* additional video frontend setup */ -#define CODEC_G_VFE 0x8002 -#define CODEC_S_MMAP 0x0003 /* MMAP setup (if available) */ - -#define CODEC_S_JPEG_TDS_BYTE 0x0010 /* target data size in bytes */ -#define CODEC_G_JPEG_TDS_BYTE 0x8010 -#define CODEC_S_JPEG_SCALE 0x0011 /* scaling factor for quant. tables */ -#define CODEC_G_JPEG_SCALE 0x8011 -#define CODEC_S_JPEG_HDT_DATA 0x0018 /* huffman-tables */ -#define CODEC_G_JPEG_HDT_DATA 0x8018 -#define CODEC_S_JPEG_QDT_DATA 0x0019 /* quantizing-tables */ -#define CODEC_G_JPEG_QDT_DATA 0x8019 -#define CODEC_S_JPEG_APP_DATA 0x001A /* APP marker */ -#define CODEC_G_JPEG_APP_DATA 0x801A -#define CODEC_S_JPEG_COM_DATA 0x001B /* COM marker */ -#define CODEC_G_JPEG_COM_DATA 0x801B - -#define CODEC_S_PRIVATE 0x1000 /* "private" commands start here */ -#define CODEC_G_PRIVATE 0x9000 - -#define CODEC_G_FLAG 0x8000 /* this is how 'get' is detected */ - -/* types of transfer, directly user space or a kernel buffer (image-fn.'s) */ -/* -> used in get_image, put_image */ -#define CODEC_TRANSFER_KERNEL 0 /* use "memcopy" */ -#define CODEC_TRANSFER_USER 1 /* use "to/from_user" */ - - -/* ========================= */ -/* the structures itself ... */ -/* ========================= */ - -struct vfe_polarity { - unsigned int vsync_pol:1; - unsigned int hsync_pol:1; - unsigned int field_pol:1; - unsigned int blank_pol:1; - unsigned int subimg_pol:1; - unsigned int poe_pol:1; - unsigned int pvalid_pol:1; - unsigned int vclk_pol:1; -}; - -struct vfe_settings { - __u32 x, y; /* Offsets into image */ - __u32 width, height; /* Area to capture */ - __u16 decimation; /* Decimation divider */ - __u16 flags; /* Flags for capture */ - __u16 quality; /* quality of the video */ -}; - -struct tvnorm { - u16 Wt, Wa, HStart, HSyncStart, Ht, Ha, VStart; -}; - -struct jpeg_com_marker { - int len; /* number of usable bytes in data */ - char data[60]; -}; - -struct jpeg_app_marker { - int appn; /* number app segment */ - int len; /* number of usable bytes in data */ - char data[60]; -}; - -struct videocodec { - struct module *owner; - /* -- filled in by slave device during register -- */ - char name[32]; - unsigned long magic; /* may be used for client<->master attaching */ - unsigned long flags; /* functionality flags */ - unsigned int type; /* codec type */ - - /* -- these is filled in later during master device attach -- */ - - struct videocodec_master *master_data; - - /* -- these are filled in by the slave device during register -- */ - - void *data; /* private slave data */ - - /* attach/detach client functions (indirect call) */ - int (*setup) (struct videocodec * codec); - int (*unset) (struct videocodec * codec); - - /* main functions, every client needs them for sure! */ - // set compression or decompression (or freeze, stop, standby, etc) - int (*set_mode) (struct videocodec * codec, - int mode); - // setup picture size and norm (for the codec's video frontend) - int (*set_video) (struct videocodec * codec, - struct tvnorm * norm, - struct vfe_settings * cap, - struct vfe_polarity * pol); - // other control commands, also mmap setup etc. - int (*control) (struct videocodec * codec, - int type, - int size, - void *data); - - /* additional setup/query/processing (may be NULL pointer) */ - // interrupt setup / handling (for irq's delivered by master) - int (*setup_interrupt) (struct videocodec * codec, - long mode); - int (*handle_interrupt) (struct videocodec * codec, - int source, - long flag); - // picture interface (if any) - long (*put_image) (struct videocodec * codec, - int tr_type, - int block, - long *fr_num, - long *flag, - long size, - void *buf); - long (*get_image) (struct videocodec * codec, - int tr_type, - int block, - long *fr_num, - long *flag, - long size, - void *buf); -}; - -struct videocodec_master { - /* -- filled in by master device for registration -- */ - char name[32]; - unsigned long magic; /* may be used for client<->master attaching */ - unsigned long flags; /* functionality flags */ - unsigned int type; /* master type */ - - void *data; /* private master data */ - - __u32(*readreg) (struct videocodec * codec, - __u16 reg); - void (*writereg) (struct videocodec * codec, - __u16 reg, - __u32 value); -}; - - -/* ================================================= */ -/* function prototypes of the master/slave interface */ -/* ================================================= */ - -/* attach and detach commands for the master */ -// * master structure needs to be kmalloc'ed before calling attach -// and free'd after calling detach -// * returns pointer on success, NULL on failure -extern struct videocodec *videocodec_attach(struct videocodec_master *); -// * 0 on success, <0 (errno) on failure -extern int videocodec_detach(struct videocodec *); - -/* register and unregister commands for the slaves */ -// * 0 on success, <0 (errno) on failure -extern int videocodec_register(const struct videocodec *); -// * 0 on success, <0 (errno) on failure -extern int videocodec_unregister(const struct videocodec *); - -/* the other calls are directly done via the videocodec structure! */ - -#endif /*ifndef __LINUX_VIDEOCODEC_H */ diff --git a/drivers/staging/media/zoran/zoran.h b/drivers/staging/media/zoran/zoran.h deleted file mode 100644 index e84fb604a689..000000000000 --- a/drivers/staging/media/zoran/zoran.h +++ /dev/null @@ -1,402 +0,0 @@ -/* - * zoran - Iomega Buz driver - * - * Copyright (C) 1999 Rainer Johanni - * - * based on - * - * zoran.0.0.3 Copyright (C) 1998 Dave Perks - * - * and - * - * bttv - Bt848 frame grabber driver - * Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - * & Marcus Metzler (mocm@thp.uni-koeln.de) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _BUZ_H_ -#define _BUZ_H_ - -#include -#include -#include - -struct zoran_sync { - unsigned long frame; /* number of buffer that has been free'd */ - unsigned long length; /* number of code bytes in buffer (capture only) */ - unsigned long seq; /* frame sequence number */ - u64 ts; /* timestamp */ -}; - - -#define ZORAN_NAME "ZORAN" /* name of the device */ - -#define ZR_DEVNAME(zr) ((zr)->name) - -#define BUZ_MAX_WIDTH (zr->timing->Wa) -#define BUZ_MAX_HEIGHT (zr->timing->Ha) -#define BUZ_MIN_WIDTH 32 /* never display less than 32 pixels */ -#define BUZ_MIN_HEIGHT 24 /* never display less than 24 rows */ - -#define BUZ_NUM_STAT_COM 4 -#define BUZ_MASK_STAT_COM 3 - -#define BUZ_MAX_FRAME 256 /* Must be a power of 2 */ -#define BUZ_MASK_FRAME 255 /* Must be BUZ_MAX_FRAME-1 */ - -#define BUZ_MAX_INPUT 16 - -#if VIDEO_MAX_FRAME <= 32 -# define V4L_MAX_FRAME 32 -#elif VIDEO_MAX_FRAME <= 64 -# define V4L_MAX_FRAME 64 -#else -# error "Too many video frame buffers to handle" -#endif -#define V4L_MASK_FRAME (V4L_MAX_FRAME - 1) - -#define MAX_FRAME (BUZ_MAX_FRAME > VIDEO_MAX_FRAME ? BUZ_MAX_FRAME : VIDEO_MAX_FRAME) - -#include "zr36057.h" - -enum card_type { - UNKNOWN = -1, - - /* Pinnacle/Miro */ - DC10_old, /* DC30 like */ - DC10_new, /* DC10plus like */ - DC10plus, - DC30, - DC30plus, - - /* Linux Media Labs */ - LML33, - LML33R10, - - /* Iomega */ - BUZ, - - /* AverMedia */ - AVS6EYES, - - /* total number of cards */ - NUM_CARDS -}; - -enum zoran_codec_mode { - BUZ_MODE_IDLE, /* nothing going on */ - BUZ_MODE_MOTION_COMPRESS, /* grabbing frames */ - BUZ_MODE_MOTION_DECOMPRESS, /* playing frames */ - BUZ_MODE_STILL_COMPRESS, /* still frame conversion */ - BUZ_MODE_STILL_DECOMPRESS /* still frame conversion */ -}; - -enum zoran_buffer_state { - BUZ_STATE_USER, /* buffer is owned by application */ - BUZ_STATE_PEND, /* buffer is queued in pend[] ready to feed to I/O */ - BUZ_STATE_DMA, /* buffer is queued in dma[] for I/O */ - BUZ_STATE_DONE /* buffer is ready to return to application */ -}; - -enum zoran_map_mode { - ZORAN_MAP_MODE_RAW, - ZORAN_MAP_MODE_JPG_REC, -#define ZORAN_MAP_MODE_JPG ZORAN_MAP_MODE_JPG_REC - ZORAN_MAP_MODE_JPG_PLAY, -}; - -enum gpio_type { - ZR_GPIO_JPEG_SLEEP = 0, - ZR_GPIO_JPEG_RESET, - ZR_GPIO_JPEG_FRAME, - ZR_GPIO_VID_DIR, - ZR_GPIO_VID_EN, - ZR_GPIO_VID_RESET, - ZR_GPIO_CLK_SEL1, - ZR_GPIO_CLK_SEL2, - ZR_GPIO_MAX, -}; - -enum gpcs_type { - GPCS_JPEG_RESET = 0, - GPCS_JPEG_START, - GPCS_MAX, -}; - -struct zoran_format { - char *name; - __u32 fourcc; - int colorspace; - int depth; - __u32 flags; - __u32 vfespfr; -}; -/* flags */ -#define ZORAN_FORMAT_COMPRESSED 1<<0 -#define ZORAN_FORMAT_OVERLAY 1<<1 -#define ZORAN_FORMAT_CAPTURE 1<<2 -#define ZORAN_FORMAT_PLAYBACK 1<<3 - -/* overlay-settings */ -struct zoran_overlay_settings { - int is_set; - int x, y, width, height; /* position */ - int clipcount; /* position and number of clips */ - const struct zoran_format *format; /* overlay format */ -}; - -/* v4l-capture settings */ -struct zoran_v4l_settings { - int width, height, bytesperline; /* capture size */ - const struct zoran_format *format; /* capture format */ -}; - -/* jpg-capture/-playback settings */ -struct zoran_jpg_settings { - int decimation; /* this bit is used to set everything to default */ - int HorDcm, VerDcm, TmpDcm; /* capture decimation settings (TmpDcm=1 means both fields) */ - int field_per_buff, odd_even; /* field-settings (odd_even=1 (+TmpDcm=1) means top-field-first) */ - int img_x, img_y, img_width, img_height; /* crop settings (subframe capture) */ - struct v4l2_jpegcompression jpg_comp; /* JPEG-specific capture settings */ -}; - -struct zoran_fh; - -struct zoran_mapping { - struct zoran_fh *fh; - atomic_t count; -}; - -struct zoran_buffer { - struct zoran_mapping *map; - enum zoran_buffer_state state; /* state: unused/pending/dma/done */ - struct zoran_sync bs; /* DONE: info to return to application */ - union { - struct { - __le32 *frag_tab; /* addresses of frag table */ - u32 frag_tab_bus; /* same value cached to save time in ISR */ - } jpg; - struct { - char *fbuffer; /* virtual address of frame buffer */ - unsigned long fbuffer_phys;/* physical address of frame buffer */ - unsigned long fbuffer_bus;/* bus address of frame buffer */ - } v4l; - }; -}; - -enum zoran_lock_activity { - ZORAN_FREE, /* free for use */ - ZORAN_ACTIVE, /* active but unlocked */ - ZORAN_LOCKED, /* locked */ -}; - -/* buffer collections */ -struct zoran_buffer_col { - enum zoran_lock_activity active; /* feature currently in use? */ - unsigned int num_buffers, buffer_size; - struct zoran_buffer buffer[MAX_FRAME]; /* buffers */ - u8 allocated; /* Flag if buffers are allocated */ - u8 need_contiguous; /* Flag if contiguous buffers are needed */ - /* only applies to jpg buffers, raw buffers are always contiguous */ -}; - -struct zoran; - -/* zoran_fh contains per-open() settings */ -struct zoran_fh { - struct v4l2_fh fh; - struct zoran *zr; - - enum zoran_map_mode map_mode; /* Flag which bufferset will map by next mmap() */ - - struct zoran_overlay_settings overlay_settings; - u32 *overlay_mask; /* overlay mask */ - enum zoran_lock_activity overlay_active;/* feature currently in use? */ - - struct zoran_buffer_col buffers; /* buffers' info */ - - struct zoran_v4l_settings v4l_settings; /* structure with a lot of things to play with */ - struct zoran_jpg_settings jpg_settings; /* structure with a lot of things to play with */ -}; - -struct card_info { - enum card_type type; - char name[32]; - const char *i2c_decoder; /* i2c decoder device */ - const unsigned short *addrs_decoder; - const char *i2c_encoder; /* i2c encoder device */ - const unsigned short *addrs_encoder; - u16 video_vfe, video_codec; /* videocodec types */ - u16 audio_chip; /* audio type */ - - int inputs; /* number of video inputs */ - struct input { - int muxsel; - char name[32]; - } input[BUZ_MAX_INPUT]; - - v4l2_std_id norms; - struct tvnorm *tvn[3]; /* supported TV norms */ - - u32 jpeg_int; /* JPEG interrupt */ - u32 vsync_int; /* VSYNC interrupt */ - s8 gpio[ZR_GPIO_MAX]; - u8 gpcs[GPCS_MAX]; - - struct vfe_polarity vfe_pol; - u8 gpio_pol[ZR_GPIO_MAX]; - - /* is the /GWS line connected? */ - u8 gws_not_connected; - - /* avs6eyes mux setting */ - u8 input_mux; - - void (*init) (struct zoran * zr); -}; - -struct zoran { - struct v4l2_device v4l2_dev; - struct v4l2_ctrl_handler hdl; - struct video_device *video_dev; - - struct i2c_adapter i2c_adapter; /* */ - struct i2c_algo_bit_data i2c_algo; /* */ - u32 i2cbr; - - struct v4l2_subdev *decoder; /* video decoder sub-device */ - struct v4l2_subdev *encoder; /* video encoder sub-device */ - - struct videocodec *codec; /* video codec */ - struct videocodec *vfe; /* video front end */ - - struct mutex lock; /* file ops serialize lock */ - - u8 initialized; /* flag if zoran has been correctly initialized */ - int user; /* number of current users */ - struct card_info card; - struct tvnorm *timing; - - unsigned short id; /* number of this device */ - char name[32]; /* name of this device */ - struct pci_dev *pci_dev; /* PCI device */ - unsigned char revision; /* revision of zr36057 */ - unsigned char __iomem *zr36057_mem;/* pointer to mapped IO memory */ - - spinlock_t spinlock; /* Spinlock */ - - /* Video for Linux parameters */ - int input; /* card's norm and input */ - v4l2_std_id norm; - - /* Current buffer params */ - void *vbuf_base; - int vbuf_height, vbuf_width; - int vbuf_depth; - int vbuf_bytesperline; - - struct zoran_overlay_settings overlay_settings; - u32 *overlay_mask; /* overlay mask */ - enum zoran_lock_activity overlay_active; /* feature currently in use? */ - - wait_queue_head_t v4l_capq; - - int v4l_overlay_active; /* Overlay grab is activated */ - int v4l_memgrab_active; /* Memory grab is activated */ - - int v4l_grab_frame; /* Frame number being currently grabbed */ -#define NO_GRAB_ACTIVE (-1) - unsigned long v4l_grab_seq; /* Number of frames grabbed */ - struct zoran_v4l_settings v4l_settings; /* structure with a lot of things to play with */ - - /* V4L grab queue of frames pending */ - unsigned long v4l_pend_head; - unsigned long v4l_pend_tail; - unsigned long v4l_sync_tail; - int v4l_pend[V4L_MAX_FRAME]; - struct zoran_buffer_col v4l_buffers; /* V4L buffers' info */ - - /* Buz MJPEG parameters */ - enum zoran_codec_mode codec_mode; /* status of codec */ - struct zoran_jpg_settings jpg_settings; /* structure with a lot of things to play with */ - - wait_queue_head_t jpg_capq; /* wait here for grab to finish */ - - /* grab queue counts/indices, mask with BUZ_MASK_STAT_COM before using as index */ - /* (dma_head - dma_tail) is number active in DMA, must be <= BUZ_NUM_STAT_COM */ - /* (value & BUZ_MASK_STAT_COM) corresponds to index in stat_com table */ - unsigned long jpg_que_head; /* Index where to put next buffer which is queued */ - unsigned long jpg_dma_head; /* Index of next buffer which goes into stat_com */ - unsigned long jpg_dma_tail; /* Index of last buffer in stat_com */ - unsigned long jpg_que_tail; /* Index of last buffer in queue */ - unsigned long jpg_seq_num; /* count of frames since grab/play started */ - unsigned long jpg_err_seq; /* last seq_num before error */ - unsigned long jpg_err_shift; - unsigned long jpg_queued_num; /* count of frames queued since grab/play started */ - - /* zr36057's code buffer table */ - __le32 *stat_com; /* stat_com[i] is indexed by dma_head/tail & BUZ_MASK_STAT_COM */ - - /* (value & BUZ_MASK_FRAME) corresponds to index in pend[] queue */ - int jpg_pend[BUZ_MAX_FRAME]; - - /* array indexed by frame number */ - struct zoran_buffer_col jpg_buffers; /* MJPEG buffers' info */ - - /* Additional stuff for testing */ -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *zoran_proc; -#else - void *zoran_proc; -#endif - int testing; - int jpeg_error; - int intr_counter_GIRQ1; - int intr_counter_GIRQ0; - int intr_counter_CodRepIRQ; - int intr_counter_JPEGRepIRQ; - int field_counter; - int IRQ1_in; - int IRQ1_out; - int JPEG_in; - int JPEG_out; - int JPEG_0; - int JPEG_1; - int END_event_missed; - int JPEG_missed; - int JPEG_error; - int num_errors; - int JPEG_max_missed; - int JPEG_min_missed; - - u32 last_isr; - unsigned long frame_num; - - wait_queue_head_t test_q; -}; - -static inline struct zoran *to_zoran(struct v4l2_device *v4l2_dev) -{ - return container_of(v4l2_dev, struct zoran, v4l2_dev); -} - -/* There was something called _ALPHA_BUZ that used the PCI address instead of - * the kernel iomapped address for btread/btwrite. */ -#define btwrite(dat,adr) writel((dat), zr->zr36057_mem+(adr)) -#define btread(adr) readl(zr->zr36057_mem+(adr)) - -#define btand(dat,adr) btwrite((dat) & btread(adr), adr) -#define btor(dat,adr) btwrite((dat) | btread(adr), adr) -#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr) - -#endif diff --git a/drivers/staging/media/zoran/zoran_card.c b/drivers/staging/media/zoran/zoran_card.c deleted file mode 100644 index ea10523194e8..000000000000 --- a/drivers/staging/media/zoran/zoran_card.c +++ /dev/null @@ -1,1524 +0,0 @@ -/* - * Zoran zr36057/zr36067 PCI controller driver, for the - * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux - * Media Labs LML33/LML33R10. - * - * This part handles card-specific data and detection - * - * Copyright (C) 2000 Serguei Miridonov - * - * Currently maintained by: - * Ronald Bultje - * Laurent Pinchart - * Mailinglist - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "videocodec.h" -#include "zoran.h" -#include "zoran_card.h" -#include "zoran_device.h" -#include "zoran_procfs.h" - -extern const struct zoran_format zoran_formats[]; - -static int card[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 }; -module_param_array(card, int, NULL, 0444); -MODULE_PARM_DESC(card, "Card type"); - -/* - The video mem address of the video card. - The driver has a little database for some videocards - to determine it from there. If your video card is not in there - you have either to give it to the driver as a parameter - or set in in a VIDIOCSFBUF ioctl - */ - -static unsigned long vidmem; /* default = 0 - Video memory base address */ -module_param_hw(vidmem, ulong, iomem, 0444); -MODULE_PARM_DESC(vidmem, "Default video memory base address"); - -/* - Default input and video norm at startup of the driver. -*/ - -static unsigned int default_input; /* default 0 = Composite, 1 = S-Video */ -module_param(default_input, uint, 0444); -MODULE_PARM_DESC(default_input, - "Default input (0=Composite, 1=S-Video, 2=Internal)"); - -static int default_mux = 1; /* 6 Eyes input selection */ -module_param(default_mux, int, 0644); -MODULE_PARM_DESC(default_mux, - "Default 6 Eyes mux setting (Input selection)"); - -static int default_norm; /* default 0 = PAL, 1 = NTSC 2 = SECAM */ -module_param(default_norm, int, 0444); -MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)"); - -/* /dev/videoN, -1 for autodetect */ -static int video_nr[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 }; -module_param_array(video_nr, int, NULL, 0444); -MODULE_PARM_DESC(video_nr, "Video device number (-1=Auto)"); - -int v4l_nbufs = 4; -int v4l_bufsize = 864; /* Everybody should be able to work with this setting */ -module_param(v4l_nbufs, int, 0644); -MODULE_PARM_DESC(v4l_nbufs, "Maximum number of V4L buffers to use"); -module_param(v4l_bufsize, int, 0644); -MODULE_PARM_DESC(v4l_bufsize, "Maximum size per V4L buffer (in kB)"); - -int jpg_nbufs = 32; -int jpg_bufsize = 512; /* max size for 100% quality full-PAL frame */ -module_param(jpg_nbufs, int, 0644); -MODULE_PARM_DESC(jpg_nbufs, "Maximum number of JPG buffers to use"); -module_param(jpg_bufsize, int, 0644); -MODULE_PARM_DESC(jpg_bufsize, "Maximum size per JPG buffer (in kB)"); - -int pass_through = 0; /* 1=Pass through TV signal when device is not used */ - /* 0=Show color bar when device is not used (LML33: only if lml33dpath=1) */ -module_param(pass_through, int, 0644); -MODULE_PARM_DESC(pass_through, - "Pass TV signal through to TV-out when idling"); - -int zr36067_debug = 1; -module_param_named(debug, zr36067_debug, int, 0644); -MODULE_PARM_DESC(debug, "Debug level (0-5)"); - -#define ZORAN_VERSION "0.10.1" - -MODULE_DESCRIPTION("Zoran-36057/36067 JPEG codec driver"); -MODULE_AUTHOR("Serguei Miridonov"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(ZORAN_VERSION); - -#define ZR_DEVICE(subven, subdev, data) { \ - .vendor = PCI_VENDOR_ID_ZORAN, .device = PCI_DEVICE_ID_ZORAN_36057, \ - .subvendor = (subven), .subdevice = (subdev), .driver_data = (data) } - -static const struct pci_device_id zr36067_pci_tbl[] = { - ZR_DEVICE(PCI_VENDOR_ID_MIRO, PCI_DEVICE_ID_MIRO_DC10PLUS, DC10plus), - ZR_DEVICE(PCI_VENDOR_ID_MIRO, PCI_DEVICE_ID_MIRO_DC30PLUS, DC30plus), - ZR_DEVICE(PCI_VENDOR_ID_ELECTRONICDESIGNGMBH, PCI_DEVICE_ID_LML_33R10, LML33R10), - ZR_DEVICE(PCI_VENDOR_ID_IOMEGA, PCI_DEVICE_ID_IOMEGA_BUZ, BUZ), - ZR_DEVICE(PCI_ANY_ID, PCI_ANY_ID, NUM_CARDS), - {0} -}; -MODULE_DEVICE_TABLE(pci, zr36067_pci_tbl); - -static unsigned int zoran_num; /* number of cards found */ - -/* videocodec bus functions ZR36060 */ -static u32 -zr36060_read (struct videocodec *codec, - u16 reg) -{ - struct zoran *zr = (struct zoran *) codec->master_data->data; - __u32 data; - - if (post_office_wait(zr) - || post_office_write(zr, 0, 1, reg >> 8) - || post_office_write(zr, 0, 2, reg & 0xff)) { - return -1; - } - - data = post_office_read(zr, 0, 3) & 0xff; - return data; -} - -static void -zr36060_write (struct videocodec *codec, - u16 reg, - u32 val) -{ - struct zoran *zr = (struct zoran *) codec->master_data->data; - - if (post_office_wait(zr) - || post_office_write(zr, 0, 1, reg >> 8) - || post_office_write(zr, 0, 2, reg & 0xff)) { - return; - } - - post_office_write(zr, 0, 3, val & 0xff); -} - -/* videocodec bus functions ZR36050 */ -static u32 -zr36050_read (struct videocodec *codec, - u16 reg) -{ - struct zoran *zr = (struct zoran *) codec->master_data->data; - __u32 data; - - if (post_office_wait(zr) - || post_office_write(zr, 1, 0, reg >> 2)) { // reg. HIGHBYTES - return -1; - } - - data = post_office_read(zr, 0, reg & 0x03) & 0xff; // reg. LOWBYTES + read - return data; -} - -static void -zr36050_write (struct videocodec *codec, - u16 reg, - u32 val) -{ - struct zoran *zr = (struct zoran *) codec->master_data->data; - - if (post_office_wait(zr) - || post_office_write(zr, 1, 0, reg >> 2)) { // reg. HIGHBYTES - return; - } - - post_office_write(zr, 0, reg & 0x03, val & 0xff); // reg. LOWBYTES + wr. data -} - -/* videocodec bus functions ZR36016 */ -static u32 -zr36016_read (struct videocodec *codec, - u16 reg) -{ - struct zoran *zr = (struct zoran *) codec->master_data->data; - __u32 data; - - if (post_office_wait(zr)) { - return -1; - } - - data = post_office_read(zr, 2, reg & 0x03) & 0xff; // read - return data; -} - -/* hack for in zoran_device.c */ -void -zr36016_write (struct videocodec *codec, - u16 reg, - u32 val) -{ - struct zoran *zr = (struct zoran *) codec->master_data->data; - - if (post_office_wait(zr)) { - return; - } - - post_office_write(zr, 2, reg & 0x03, val & 0x0ff); // wr. data -} - -/* - * Board specific information - */ - -static void -dc10_init (struct zoran *zr) -{ - dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__); - - /* Pixel clock selection */ - GPIO(zr, 4, 0); - GPIO(zr, 5, 1); - /* Enable the video bus sync signals */ - GPIO(zr, 7, 0); -} - -static void -dc10plus_init (struct zoran *zr) -{ - dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__); -} - -static void -buz_init (struct zoran *zr) -{ - dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__); - - /* some stuff from Iomega */ - pci_write_config_dword(zr->pci_dev, 0xfc, 0x90680f15); - pci_write_config_dword(zr->pci_dev, 0x0c, 0x00012020); - pci_write_config_dword(zr->pci_dev, 0xe8, 0xc0200000); -} - -static void -lml33_init (struct zoran *zr) -{ - dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__); - - GPIO(zr, 2, 1); // Set Composite input/output -} - -static void -avs6eyes_init (struct zoran *zr) -{ - // AverMedia 6-Eyes original driver by Christer Weinigel - - // Lifted straight from Christer's old driver and - // modified slightly by Martin Samuelsson. - - int mux = default_mux; /* 1 = BT866, 7 = VID1 */ - - GPIO(zr, 4, 1); /* Bt866 SLEEP on */ - udelay(2); - - GPIO(zr, 0, 1); /* ZR36060 /RESET on */ - GPIO(zr, 1, 0); /* ZR36060 /SLEEP on */ - GPIO(zr, 2, mux & 1); /* MUX S0 */ - GPIO(zr, 3, 0); /* /FRAME on */ - GPIO(zr, 4, 0); /* Bt866 SLEEP off */ - GPIO(zr, 5, mux & 2); /* MUX S1 */ - GPIO(zr, 6, 0); /* ? */ - GPIO(zr, 7, mux & 4); /* MUX S2 */ - -} - -static char * -codecid_to_modulename (u16 codecid) -{ - char *name = NULL; - - switch (codecid) { - case CODEC_TYPE_ZR36060: - name = "zr36060"; - break; - case CODEC_TYPE_ZR36050: - name = "zr36050"; - break; - case CODEC_TYPE_ZR36016: - name = "zr36016"; - break; - } - - return name; -} - -// struct tvnorm { -// u16 Wt, Wa, HStart, HSyncStart, Ht, Ha, VStart; -// }; - -static struct tvnorm f50sqpixel = { 944, 768, 83, 880, 625, 576, 16 }; -static struct tvnorm f60sqpixel = { 780, 640, 51, 716, 525, 480, 12 }; -static struct tvnorm f50ccir601 = { 864, 720, 75, 804, 625, 576, 18 }; -static struct tvnorm f60ccir601 = { 858, 720, 57, 788, 525, 480, 16 }; - -static struct tvnorm f50ccir601_lml33 = { 864, 720, 75+34, 804, 625, 576, 18 }; -static struct tvnorm f60ccir601_lml33 = { 858, 720, 57+34, 788, 525, 480, 16 }; - -/* The DC10 (57/16/50) uses VActive as HSync, so HStart must be 0 */ -static struct tvnorm f50sqpixel_dc10 = { 944, 768, 0, 880, 625, 576, 0 }; -static struct tvnorm f60sqpixel_dc10 = { 780, 640, 0, 716, 525, 480, 12 }; - -/* FIXME: I cannot swap U and V in saa7114, so i do one - * pixel left shift in zoran (75 -> 74) - * (Maxim Yevtyushkin ) */ -static struct tvnorm f50ccir601_lm33r10 = { 864, 720, 74+54, 804, 625, 576, 18 }; -static struct tvnorm f60ccir601_lm33r10 = { 858, 720, 56+54, 788, 525, 480, 16 }; - -/* FIXME: The ks0127 seem incapable of swapping U and V, too, which is why I - * copy Maxim's left shift hack for the 6 Eyes. - * - * Christer's driver used the unshifted norms, though... - * /Sam */ -static struct tvnorm f50ccir601_avs6eyes = { 864, 720, 74, 804, 625, 576, 18 }; -static struct tvnorm f60ccir601_avs6eyes = { 858, 720, 56, 788, 525, 480, 16 }; - -static const unsigned short vpx3220_addrs[] = { 0x43, 0x47, I2C_CLIENT_END }; -static const unsigned short saa7110_addrs[] = { 0x4e, 0x4f, I2C_CLIENT_END }; -static const unsigned short saa7111_addrs[] = { 0x25, 0x24, I2C_CLIENT_END }; -static const unsigned short saa7114_addrs[] = { 0x21, 0x20, I2C_CLIENT_END }; -static const unsigned short adv717x_addrs[] = { 0x6a, 0x6b, 0x2a, 0x2b, I2C_CLIENT_END }; -static const unsigned short ks0127_addrs[] = { 0x6c, 0x6d, I2C_CLIENT_END }; -static const unsigned short saa7185_addrs[] = { 0x44, I2C_CLIENT_END }; -static const unsigned short bt819_addrs[] = { 0x45, I2C_CLIENT_END }; -static const unsigned short bt856_addrs[] = { 0x44, I2C_CLIENT_END }; -static const unsigned short bt866_addrs[] = { 0x44, I2C_CLIENT_END }; - -static struct card_info zoran_cards[NUM_CARDS] = { - { - .type = DC10_old, - .name = "DC10(old)", - .i2c_decoder = "vpx3220a", - .addrs_decoder = vpx3220_addrs, - .video_codec = CODEC_TYPE_ZR36050, - .video_vfe = CODEC_TYPE_ZR36016, - - .inputs = 3, - .input = { - { 1, "Composite" }, - { 2, "S-Video" }, - { 0, "Internal/comp" } - }, - .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM, - .tvn = { - &f50sqpixel_dc10, - &f60sqpixel_dc10, - &f50sqpixel_dc10 - }, - .jpeg_int = 0, - .vsync_int = ZR36057_ISR_GIRQ1, - .gpio = { 2, 1, -1, 3, 7, 0, 4, 5 }, - .gpio_pol = { 0, 0, 0, 1, 0, 0, 0, 0 }, - .gpcs = { -1, 0 }, - .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, - .gws_not_connected = 0, - .input_mux = 0, - .init = &dc10_init, - }, { - .type = DC10_new, - .name = "DC10(new)", - .i2c_decoder = "saa7110", - .addrs_decoder = saa7110_addrs, - .i2c_encoder = "adv7175", - .addrs_encoder = adv717x_addrs, - .video_codec = CODEC_TYPE_ZR36060, - - .inputs = 3, - .input = { - { 0, "Composite" }, - { 7, "S-Video" }, - { 5, "Internal/comp" } - }, - .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM, - .tvn = { - &f50sqpixel, - &f60sqpixel, - &f50sqpixel}, - .jpeg_int = ZR36057_ISR_GIRQ0, - .vsync_int = ZR36057_ISR_GIRQ1, - .gpio = { 3, 0, 6, 1, 2, -1, 4, 5 }, - .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, - .gpcs = { -1, 1}, - .vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 }, - .gws_not_connected = 0, - .input_mux = 0, - .init = &dc10plus_init, - }, { - .type = DC10plus, - .name = "DC10plus", - .i2c_decoder = "saa7110", - .addrs_decoder = saa7110_addrs, - .i2c_encoder = "adv7175", - .addrs_encoder = adv717x_addrs, - .video_codec = CODEC_TYPE_ZR36060, - - .inputs = 3, - .input = { - { 0, "Composite" }, - { 7, "S-Video" }, - { 5, "Internal/comp" } - }, - .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM, - .tvn = { - &f50sqpixel, - &f60sqpixel, - &f50sqpixel - }, - .jpeg_int = ZR36057_ISR_GIRQ0, - .vsync_int = ZR36057_ISR_GIRQ1, - .gpio = { 3, 0, 6, 1, 2, -1, 4, 5 }, - .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, - .gpcs = { -1, 1 }, - .vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 }, - .gws_not_connected = 0, - .input_mux = 0, - .init = &dc10plus_init, - }, { - .type = DC30, - .name = "DC30", - .i2c_decoder = "vpx3220a", - .addrs_decoder = vpx3220_addrs, - .i2c_encoder = "adv7175", - .addrs_encoder = adv717x_addrs, - .video_codec = CODEC_TYPE_ZR36050, - .video_vfe = CODEC_TYPE_ZR36016, - - .inputs = 3, - .input = { - { 1, "Composite" }, - { 2, "S-Video" }, - { 0, "Internal/comp" } - }, - .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM, - .tvn = { - &f50sqpixel_dc10, - &f60sqpixel_dc10, - &f50sqpixel_dc10 - }, - .jpeg_int = 0, - .vsync_int = ZR36057_ISR_GIRQ1, - .gpio = { 2, 1, -1, 3, 7, 0, 4, 5 }, - .gpio_pol = { 0, 0, 0, 1, 0, 0, 0, 0 }, - .gpcs = { -1, 0 }, - .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, - .gws_not_connected = 0, - .input_mux = 0, - .init = &dc10_init, - }, { - .type = DC30plus, - .name = "DC30plus", - .i2c_decoder = "vpx3220a", - .addrs_decoder = vpx3220_addrs, - .i2c_encoder = "adv7175", - .addrs_encoder = adv717x_addrs, - .video_codec = CODEC_TYPE_ZR36050, - .video_vfe = CODEC_TYPE_ZR36016, - - .inputs = 3, - .input = { - { 1, "Composite" }, - { 2, "S-Video" }, - { 0, "Internal/comp" } - }, - .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM, - .tvn = { - &f50sqpixel_dc10, - &f60sqpixel_dc10, - &f50sqpixel_dc10 - }, - .jpeg_int = 0, - .vsync_int = ZR36057_ISR_GIRQ1, - .gpio = { 2, 1, -1, 3, 7, 0, 4, 5 }, - .gpio_pol = { 0, 0, 0, 1, 0, 0, 0, 0 }, - .gpcs = { -1, 0 }, - .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, - .gws_not_connected = 0, - .input_mux = 0, - .init = &dc10_init, - }, { - .type = LML33, - .name = "LML33", - .i2c_decoder = "bt819a", - .addrs_decoder = bt819_addrs, - .i2c_encoder = "bt856", - .addrs_encoder = bt856_addrs, - .video_codec = CODEC_TYPE_ZR36060, - - .inputs = 2, - .input = { - { 0, "Composite" }, - { 7, "S-Video" } - }, - .norms = V4L2_STD_NTSC|V4L2_STD_PAL, - .tvn = { - &f50ccir601_lml33, - &f60ccir601_lml33, - NULL - }, - .jpeg_int = ZR36057_ISR_GIRQ1, - .vsync_int = ZR36057_ISR_GIRQ0, - .gpio = { 1, -1, 3, 5, 7, -1, -1, -1 }, - .gpio_pol = { 0, 0, 0, 0, 1, 0, 0, 0 }, - .gpcs = { 3, 1 }, - .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 }, - .gws_not_connected = 1, - .input_mux = 0, - .init = &lml33_init, - }, { - .type = LML33R10, - .name = "LML33R10", - .i2c_decoder = "saa7114", - .addrs_decoder = saa7114_addrs, - .i2c_encoder = "adv7170", - .addrs_encoder = adv717x_addrs, - .video_codec = CODEC_TYPE_ZR36060, - - .inputs = 2, - .input = { - { 0, "Composite" }, - { 7, "S-Video" } - }, - .norms = V4L2_STD_NTSC|V4L2_STD_PAL, - .tvn = { - &f50ccir601_lm33r10, - &f60ccir601_lm33r10, - NULL - }, - .jpeg_int = ZR36057_ISR_GIRQ1, - .vsync_int = ZR36057_ISR_GIRQ0, - .gpio = { 1, -1, 3, 5, 7, -1, -1, -1 }, - .gpio_pol = { 0, 0, 0, 0, 1, 0, 0, 0 }, - .gpcs = { 3, 1 }, - .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 }, - .gws_not_connected = 1, - .input_mux = 0, - .init = &lml33_init, - }, { - .type = BUZ, - .name = "Buz", - .i2c_decoder = "saa7111", - .addrs_decoder = saa7111_addrs, - .i2c_encoder = "saa7185", - .addrs_encoder = saa7185_addrs, - .video_codec = CODEC_TYPE_ZR36060, - - .inputs = 2, - .input = { - { 3, "Composite" }, - { 7, "S-Video" } - }, - .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM, - .tvn = { - &f50ccir601, - &f60ccir601, - &f50ccir601 - }, - .jpeg_int = ZR36057_ISR_GIRQ1, - .vsync_int = ZR36057_ISR_GIRQ0, - .gpio = { 1, -1, 3, -1, -1, -1, -1, -1 }, - .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, - .gpcs = { 3, 1 }, - .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 }, - .gws_not_connected = 1, - .input_mux = 0, - .init = &buz_init, - }, { - .type = AVS6EYES, - .name = "6-Eyes", - /* AverMedia chose not to brand the 6-Eyes. Thus it - can't be autodetected, and requires card=x. */ - .i2c_decoder = "ks0127", - .addrs_decoder = ks0127_addrs, - .i2c_encoder = "bt866", - .addrs_encoder = bt866_addrs, - .video_codec = CODEC_TYPE_ZR36060, - - .inputs = 10, - .input = { - { 0, "Composite 1" }, - { 1, "Composite 2" }, - { 2, "Composite 3" }, - { 4, "Composite 4" }, - { 5, "Composite 5" }, - { 6, "Composite 6" }, - { 8, "S-Video 1" }, - { 9, "S-Video 2" }, - {10, "S-Video 3" }, - {15, "YCbCr" } - }, - .norms = V4L2_STD_NTSC|V4L2_STD_PAL, - .tvn = { - &f50ccir601_avs6eyes, - &f60ccir601_avs6eyes, - NULL - }, - .jpeg_int = ZR36057_ISR_GIRQ1, - .vsync_int = ZR36057_ISR_GIRQ0, - .gpio = { 1, 0, 3, -1, -1, -1, -1, -1 },// Validity unknown /Sam - .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, // Validity unknown /Sam - .gpcs = { 3, 1 }, // Validity unknown /Sam - .vfe_pol = { 1, 0, 0, 0, 0, 1, 0, 0 }, // Validity unknown /Sam - .gws_not_connected = 1, - .input_mux = 1, - .init = &avs6eyes_init, - } - -}; - -/* - * I2C functions - */ -/* software I2C functions */ -static int -zoran_i2c_getsda (void *data) -{ - struct zoran *zr = (struct zoran *) data; - - return (btread(ZR36057_I2CBR) >> 1) & 1; -} - -static int -zoran_i2c_getscl (void *data) -{ - struct zoran *zr = (struct zoran *) data; - - return btread(ZR36057_I2CBR) & 1; -} - -static void -zoran_i2c_setsda (void *data, - int state) -{ - struct zoran *zr = (struct zoran *) data; - - if (state) - zr->i2cbr |= 2; - else - zr->i2cbr &= ~2; - btwrite(zr->i2cbr, ZR36057_I2CBR); -} - -static void -zoran_i2c_setscl (void *data, - int state) -{ - struct zoran *zr = (struct zoran *) data; - - if (state) - zr->i2cbr |= 1; - else - zr->i2cbr &= ~1; - btwrite(zr->i2cbr, ZR36057_I2CBR); -} - -static const struct i2c_algo_bit_data zoran_i2c_bit_data_template = { - .setsda = zoran_i2c_setsda, - .setscl = zoran_i2c_setscl, - .getsda = zoran_i2c_getsda, - .getscl = zoran_i2c_getscl, - .udelay = 10, - .timeout = 100, -}; - -static int -zoran_register_i2c (struct zoran *zr) -{ - zr->i2c_algo = zoran_i2c_bit_data_template; - zr->i2c_algo.data = zr; - strscpy(zr->i2c_adapter.name, ZR_DEVNAME(zr), - sizeof(zr->i2c_adapter.name)); - i2c_set_adapdata(&zr->i2c_adapter, &zr->v4l2_dev); - zr->i2c_adapter.algo_data = &zr->i2c_algo; - zr->i2c_adapter.dev.parent = &zr->pci_dev->dev; - return i2c_bit_add_bus(&zr->i2c_adapter); -} - -static void -zoran_unregister_i2c (struct zoran *zr) -{ - i2c_del_adapter(&zr->i2c_adapter); -} - -/* Check a zoran_params struct for correctness, insert default params */ - -int -zoran_check_jpg_settings (struct zoran *zr, - struct zoran_jpg_settings *settings, - int try) -{ - int err = 0, err0 = 0; - - dprintk(4, - KERN_DEBUG - "%s: %s - dec: %d, Hdcm: %d, Vdcm: %d, Tdcm: %d\n", - ZR_DEVNAME(zr), __func__, settings->decimation, settings->HorDcm, - settings->VerDcm, settings->TmpDcm); - dprintk(4, - KERN_DEBUG - "%s: %s - x: %d, y: %d, w: %d, y: %d\n", - ZR_DEVNAME(zr), __func__, settings->img_x, settings->img_y, - settings->img_width, settings->img_height); - /* Check decimation, set default values for decimation = 1, 2, 4 */ - switch (settings->decimation) { - case 1: - - settings->HorDcm = 1; - settings->VerDcm = 1; - settings->TmpDcm = 1; - settings->field_per_buff = 2; - settings->img_x = 0; - settings->img_y = 0; - settings->img_width = BUZ_MAX_WIDTH; - settings->img_height = BUZ_MAX_HEIGHT / 2; - break; - case 2: - - settings->HorDcm = 2; - settings->VerDcm = 1; - settings->TmpDcm = 2; - settings->field_per_buff = 1; - settings->img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0; - settings->img_y = 0; - settings->img_width = - (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH; - settings->img_height = BUZ_MAX_HEIGHT / 2; - break; - case 4: - - if (zr->card.type == DC10_new) { - dprintk(1, - KERN_DEBUG - "%s: %s - HDec by 4 is not supported on the DC10\n", - ZR_DEVNAME(zr), __func__); - err0++; - break; - } - - settings->HorDcm = 4; - settings->VerDcm = 2; - settings->TmpDcm = 2; - settings->field_per_buff = 1; - settings->img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0; - settings->img_y = 0; - settings->img_width = - (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH; - settings->img_height = BUZ_MAX_HEIGHT / 2; - break; - case 0: - - /* We have to check the data the user has set */ - - if (settings->HorDcm != 1 && settings->HorDcm != 2 && - (zr->card.type == DC10_new || settings->HorDcm != 4)) { - settings->HorDcm = clamp(settings->HorDcm, 1, 2); - err0++; - } - if (settings->VerDcm != 1 && settings->VerDcm != 2) { - settings->VerDcm = clamp(settings->VerDcm, 1, 2); - err0++; - } - if (settings->TmpDcm != 1 && settings->TmpDcm != 2) { - settings->TmpDcm = clamp(settings->TmpDcm, 1, 2); - err0++; - } - if (settings->field_per_buff != 1 && - settings->field_per_buff != 2) { - settings->field_per_buff = clamp(settings->field_per_buff, 1, 2); - err0++; - } - if (settings->img_x < 0) { - settings->img_x = 0; - err0++; - } - if (settings->img_y < 0) { - settings->img_y = 0; - err0++; - } - if (settings->img_width < 0 || settings->img_width > BUZ_MAX_WIDTH) { - settings->img_width = clamp(settings->img_width, 0, (int)BUZ_MAX_WIDTH); - err0++; - } - if (settings->img_height < 0 || settings->img_height > BUZ_MAX_HEIGHT / 2) { - settings->img_height = clamp(settings->img_height, 0, BUZ_MAX_HEIGHT / 2); - err0++; - } - if (settings->img_x + settings->img_width > BUZ_MAX_WIDTH) { - settings->img_x = BUZ_MAX_WIDTH - settings->img_width; - err0++; - } - if (settings->img_y + settings->img_height > BUZ_MAX_HEIGHT / 2) { - settings->img_y = BUZ_MAX_HEIGHT / 2 - settings->img_height; - err0++; - } - if (settings->img_width % (16 * settings->HorDcm) != 0) { - settings->img_width -= settings->img_width % (16 * settings->HorDcm); - if (settings->img_width == 0) - settings->img_width = 16 * settings->HorDcm; - err0++; - } - if (settings->img_height % (8 * settings->VerDcm) != 0) { - settings->img_height -= settings->img_height % (8 * settings->VerDcm); - if (settings->img_height == 0) - settings->img_height = 8 * settings->VerDcm; - err0++; - } - - if (!try && err0) { - dprintk(1, - KERN_ERR - "%s: %s - error in params for decimation = 0\n", - ZR_DEVNAME(zr), __func__); - err++; - } - break; - default: - dprintk(1, - KERN_ERR - "%s: %s - decimation = %d, must be 0, 1, 2 or 4\n", - ZR_DEVNAME(zr), __func__, settings->decimation); - err++; - break; - } - - if (settings->jpg_comp.quality > 100) - settings->jpg_comp.quality = 100; - if (settings->jpg_comp.quality < 5) - settings->jpg_comp.quality = 5; - if (settings->jpg_comp.APPn < 0) - settings->jpg_comp.APPn = 0; - if (settings->jpg_comp.APPn > 15) - settings->jpg_comp.APPn = 15; - if (settings->jpg_comp.APP_len < 0) - settings->jpg_comp.APP_len = 0; - if (settings->jpg_comp.APP_len > 60) - settings->jpg_comp.APP_len = 60; - if (settings->jpg_comp.COM_len < 0) - settings->jpg_comp.COM_len = 0; - if (settings->jpg_comp.COM_len > 60) - settings->jpg_comp.COM_len = 60; - if (err) - return -EINVAL; - return 0; -} - -void -zoran_open_init_params (struct zoran *zr) -{ - int i; - - /* User must explicitly set a window */ - zr->overlay_settings.is_set = 0; - zr->overlay_mask = NULL; - zr->overlay_active = ZORAN_FREE; - - zr->v4l_memgrab_active = 0; - zr->v4l_overlay_active = 0; - zr->v4l_grab_frame = NO_GRAB_ACTIVE; - zr->v4l_grab_seq = 0; - zr->v4l_settings.width = 192; - zr->v4l_settings.height = 144; - zr->v4l_settings.format = &zoran_formats[7]; /* YUY2 - YUV-4:2:2 packed */ - zr->v4l_settings.bytesperline = - zr->v4l_settings.width * - ((zr->v4l_settings.format->depth + 7) / 8); - - /* DMA ring stuff for V4L */ - zr->v4l_pend_tail = 0; - zr->v4l_pend_head = 0; - zr->v4l_sync_tail = 0; - zr->v4l_buffers.active = ZORAN_FREE; - for (i = 0; i < VIDEO_MAX_FRAME; i++) { - zr->v4l_buffers.buffer[i].state = BUZ_STATE_USER; /* nothing going on */ - } - zr->v4l_buffers.allocated = 0; - - for (i = 0; i < BUZ_MAX_FRAME; i++) { - zr->jpg_buffers.buffer[i].state = BUZ_STATE_USER; /* nothing going on */ - } - zr->jpg_buffers.active = ZORAN_FREE; - zr->jpg_buffers.allocated = 0; - /* Set necessary params and call zoran_check_jpg_settings to set the defaults */ - zr->jpg_settings.decimation = 1; - zr->jpg_settings.jpg_comp.quality = 50; /* default compression factor 8 */ - if (zr->card.type != BUZ) - zr->jpg_settings.odd_even = 1; - else - zr->jpg_settings.odd_even = 0; - zr->jpg_settings.jpg_comp.APPn = 0; - zr->jpg_settings.jpg_comp.APP_len = 0; /* No APPn marker */ - memset(zr->jpg_settings.jpg_comp.APP_data, 0, - sizeof(zr->jpg_settings.jpg_comp.APP_data)); - zr->jpg_settings.jpg_comp.COM_len = 0; /* No COM marker */ - memset(zr->jpg_settings.jpg_comp.COM_data, 0, - sizeof(zr->jpg_settings.jpg_comp.COM_data)); - zr->jpg_settings.jpg_comp.jpeg_markers = - V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT; - i = zoran_check_jpg_settings(zr, &zr->jpg_settings, 0); - if (i) - dprintk(1, KERN_ERR "%s: %s internal error\n", - ZR_DEVNAME(zr), __func__); - - clear_interrupt_counters(zr); - zr->testing = 0; -} - -static void test_interrupts (struct zoran *zr) -{ - DEFINE_WAIT(wait); - int timeout, icr; - - clear_interrupt_counters(zr); - - zr->testing = 1; - icr = btread(ZR36057_ICR); - btwrite(0x78000000 | ZR36057_ICR_IntPinEn, ZR36057_ICR); - prepare_to_wait(&zr->test_q, &wait, TASK_INTERRUPTIBLE); - timeout = schedule_timeout(HZ); - finish_wait(&zr->test_q, &wait); - btwrite(0, ZR36057_ICR); - btwrite(0x78000000, ZR36057_ISR); - zr->testing = 0; - dprintk(5, KERN_INFO "%s: Testing interrupts...\n", ZR_DEVNAME(zr)); - if (timeout) { - dprintk(1, ": time spent: %d\n", 1 * HZ - timeout); - } - if (zr36067_debug > 1) - print_interrupts(zr); - btwrite(icr, ZR36057_ICR); -} - -static int zr36057_init (struct zoran *zr) -{ - int j, err; - - dprintk(1, - KERN_INFO - "%s: %s - initializing card[%d], zr=%p\n", - ZR_DEVNAME(zr), __func__, zr->id, zr); - - /* default setup of all parameters which will persist between opens */ - zr->user = 0; - - init_waitqueue_head(&zr->v4l_capq); - init_waitqueue_head(&zr->jpg_capq); - init_waitqueue_head(&zr->test_q); - zr->jpg_buffers.allocated = 0; - zr->v4l_buffers.allocated = 0; - - zr->vbuf_base = (void *) vidmem; - zr->vbuf_width = 0; - zr->vbuf_height = 0; - zr->vbuf_depth = 0; - zr->vbuf_bytesperline = 0; - - /* Avoid nonsense settings from user for default input/norm */ - if (default_norm < 0 || default_norm > 2) - default_norm = 0; - if (default_norm == 0) { - zr->norm = V4L2_STD_PAL; - zr->timing = zr->card.tvn[0]; - } else if (default_norm == 1) { - zr->norm = V4L2_STD_NTSC; - zr->timing = zr->card.tvn[1]; - } else { - zr->norm = V4L2_STD_SECAM; - zr->timing = zr->card.tvn[2]; - } - if (zr->timing == NULL) { - dprintk(1, - KERN_WARNING - "%s: %s - default TV standard not supported by hardware. PAL will be used.\n", - ZR_DEVNAME(zr), __func__); - zr->norm = V4L2_STD_PAL; - zr->timing = zr->card.tvn[0]; - } - - if (default_input > zr->card.inputs-1) { - dprintk(1, - KERN_WARNING - "%s: default_input value %d out of range (0-%d)\n", - ZR_DEVNAME(zr), default_input, zr->card.inputs-1); - default_input = 0; - } - zr->input = default_input; - - /* default setup (will be repeated at every open) */ - zoran_open_init_params(zr); - - /* allocate memory *before* doing anything to the hardware - * in case allocation fails */ - zr->stat_com = kzalloc(BUZ_NUM_STAT_COM * 4, GFP_KERNEL); - zr->video_dev = video_device_alloc(); - if (!zr->stat_com || !zr->video_dev) { - dprintk(1, - KERN_ERR - "%s: %s - kmalloc (STAT_COM) failed\n", - ZR_DEVNAME(zr), __func__); - err = -ENOMEM; - goto exit_free; - } - for (j = 0; j < BUZ_NUM_STAT_COM; j++) { - zr->stat_com[j] = cpu_to_le32(1); /* mark as unavailable to zr36057 */ - } - - /* - * Now add the template and register the device unit. - */ - *zr->video_dev = zoran_template; - zr->video_dev->v4l2_dev = &zr->v4l2_dev; - zr->video_dev->lock = &zr->lock; - strscpy(zr->video_dev->name, ZR_DEVNAME(zr), sizeof(zr->video_dev->name)); - /* It's not a mem2mem device, but you can both capture and output from - one and the same device. This should really be split up into two - device nodes, but that's a job for another day. */ - zr->video_dev->vfl_dir = VFL_DIR_M2M; - err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr[zr->id]); - if (err < 0) - goto exit_free; - video_set_drvdata(zr->video_dev, zr); - - zoran_init_hardware(zr); - if (zr36067_debug > 2) - detect_guest_activity(zr); - test_interrupts(zr); - if (!pass_through) { - decoder_call(zr, video, s_stream, 0); - encoder_call(zr, video, s_routing, 2, 0, 0); - } - - zr->zoran_proc = NULL; - zr->initialized = 1; - return 0; - -exit_free: - kfree(zr->stat_com); - kfree(zr->video_dev); - return err; -} - -static void zoran_remove(struct pci_dev *pdev) -{ - struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); - struct zoran *zr = to_zoran(v4l2_dev); - - if (!zr->initialized) - goto exit_free; - - /* unregister videocodec bus */ - if (zr->codec) { - struct videocodec_master *master = zr->codec->master_data; - - videocodec_detach(zr->codec); - kfree(master); - } - if (zr->vfe) { - struct videocodec_master *master = zr->vfe->master_data; - - videocodec_detach(zr->vfe); - kfree(master); - } - - /* unregister i2c bus */ - zoran_unregister_i2c(zr); - /* disable PCI bus-mastering */ - zoran_set_pci_master(zr, 0); - /* put chip into reset */ - btwrite(0, ZR36057_SPGPPCR); - free_irq(zr->pci_dev->irq, zr); - /* unmap and free memory */ - kfree(zr->stat_com); - zoran_proc_cleanup(zr); - iounmap(zr->zr36057_mem); - pci_disable_device(zr->pci_dev); - video_unregister_device(zr->video_dev); -exit_free: - v4l2_ctrl_handler_free(&zr->hdl); - v4l2_device_unregister(&zr->v4l2_dev); - kfree(zr); -} - -void -zoran_vdev_release (struct video_device *vdev) -{ - kfree(vdev); -} - -static struct videocodec_master *zoran_setup_videocodec(struct zoran *zr, - int type) -{ - struct videocodec_master *m = NULL; - - m = kmalloc(sizeof(struct videocodec_master), GFP_KERNEL); - if (!m) { - dprintk(1, KERN_ERR "%s: %s - no memory\n", - ZR_DEVNAME(zr), __func__); - return m; - } - - /* magic and type are unused for master struct. Makes sense only at - codec structs. - In the past, .type were initialized to the old V4L1 .hardware - value, as VID_HARDWARE_ZR36067 - */ - m->magic = 0L; - m->type = 0; - - m->flags = CODEC_FLAG_ENCODER | CODEC_FLAG_DECODER; - strscpy(m->name, ZR_DEVNAME(zr), sizeof(m->name)); - m->data = zr; - - switch (type) - { - case CODEC_TYPE_ZR36060: - m->readreg = zr36060_read; - m->writereg = zr36060_write; - m->flags |= CODEC_FLAG_JPEG | CODEC_FLAG_VFE; - break; - case CODEC_TYPE_ZR36050: - m->readreg = zr36050_read; - m->writereg = zr36050_write; - m->flags |= CODEC_FLAG_JPEG; - break; - case CODEC_TYPE_ZR36016: - m->readreg = zr36016_read; - m->writereg = zr36016_write; - m->flags |= CODEC_FLAG_VFE; - break; - } - - return m; -} - -static void zoran_subdev_notify(struct v4l2_subdev *sd, unsigned int cmd, void *arg) -{ - struct zoran *zr = to_zoran(sd->v4l2_dev); - - /* Bt819 needs to reset its FIFO buffer using #FRST pin and - LML33 card uses GPIO(7) for that. */ - if (cmd == BT819_FIFO_RESET_LOW) - GPIO(zr, 7, 0); - else if (cmd == BT819_FIFO_RESET_HIGH) - GPIO(zr, 7, 1); -} - -/* - * Scan for a Buz card (actually for the PCI controller ZR36057), - * request the irq and map the io memory - */ -static int zoran_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - unsigned char latency, need_latency; - struct zoran *zr; - int result; - struct videocodec_master *master_vfe = NULL; - struct videocodec_master *master_codec = NULL; - int card_num; - char *codec_name, *vfe_name; - unsigned int nr; - - - nr = zoran_num++; - if (nr >= BUZ_MAX) { - dprintk(1, KERN_ERR "%s: driver limited to %d card(s) maximum\n", - ZORAN_NAME, BUZ_MAX); - return -ENOENT; - } - - zr = kzalloc(sizeof(struct zoran), GFP_KERNEL); - if (!zr) { - dprintk(1, KERN_ERR "%s: %s - kzalloc failed\n", - ZORAN_NAME, __func__); - return -ENOMEM; - } - zr->v4l2_dev.notify = zoran_subdev_notify; - if (v4l2_device_register(&pdev->dev, &zr->v4l2_dev)) - goto zr_free_mem; - zr->pci_dev = pdev; - zr->id = nr; - snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%u]", zr->id); - if (v4l2_ctrl_handler_init(&zr->hdl, 10)) - goto zr_unreg; - zr->v4l2_dev.ctrl_handler = &zr->hdl; - spin_lock_init(&zr->spinlock); - mutex_init(&zr->lock); - if (pci_enable_device(pdev)) - goto zr_unreg; - zr->revision = zr->pci_dev->revision; - - dprintk(1, - KERN_INFO - "%s: Zoran ZR360%c7 (rev %d), irq: %d, memory: 0x%08llx\n", - ZR_DEVNAME(zr), zr->revision < 2 ? '5' : '6', zr->revision, - zr->pci_dev->irq, (uint64_t)pci_resource_start(zr->pci_dev, 0)); - if (zr->revision >= 2) { - dprintk(1, - KERN_INFO - "%s: Subsystem vendor=0x%04x id=0x%04x\n", - ZR_DEVNAME(zr), zr->pci_dev->subsystem_vendor, - zr->pci_dev->subsystem_device); - } - - /* Use auto-detected card type? */ - if (card[nr] == -1) { - if (zr->revision < 2) { - dprintk(1, - KERN_ERR - "%s: No card type specified, please use the card=X module parameter\n", - ZR_DEVNAME(zr)); - dprintk(1, - KERN_ERR - "%s: It is not possible to auto-detect ZR36057 based cards\n", - ZR_DEVNAME(zr)); - goto zr_unreg; - } - - card_num = ent->driver_data; - if (card_num >= NUM_CARDS) { - dprintk(1, - KERN_ERR - "%s: Unknown card, try specifying card=X module parameter\n", - ZR_DEVNAME(zr)); - goto zr_unreg; - } - dprintk(3, - KERN_DEBUG - "%s: %s() - card %s detected\n", - ZR_DEVNAME(zr), __func__, zoran_cards[card_num].name); - } else { - card_num = card[nr]; - if (card_num >= NUM_CARDS || card_num < 0) { - dprintk(1, - KERN_ERR - "%s: User specified card type %d out of range (0 .. %d)\n", - ZR_DEVNAME(zr), card_num, NUM_CARDS - 1); - goto zr_unreg; - } - } - - /* even though we make this a non pointer and thus - * theoretically allow for making changes to this struct - * on a per-individual card basis at runtime, this is - * strongly discouraged. This structure is intended to - * keep general card information, no settings or anything */ - zr->card = zoran_cards[card_num]; - snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), - "%s[%u]", zr->card.name, zr->id); - - zr->zr36057_mem = pci_ioremap_bar(zr->pci_dev, 0); - if (!zr->zr36057_mem) { - dprintk(1, KERN_ERR "%s: %s() - ioremap failed\n", - ZR_DEVNAME(zr), __func__); - goto zr_unreg; - } - - result = request_irq(zr->pci_dev->irq, zoran_irq, - IRQF_SHARED, ZR_DEVNAME(zr), zr); - if (result < 0) { - if (result == -EINVAL) { - dprintk(1, - KERN_ERR - "%s: %s - bad irq number or handler\n", - ZR_DEVNAME(zr), __func__); - } else if (result == -EBUSY) { - dprintk(1, - KERN_ERR - "%s: %s - IRQ %d busy, change your PnP config in BIOS\n", - ZR_DEVNAME(zr), __func__, zr->pci_dev->irq); - } else { - dprintk(1, - KERN_ERR - "%s: %s - can't assign irq, error code %d\n", - ZR_DEVNAME(zr), __func__, result); - } - goto zr_unmap; - } - - /* set PCI latency timer */ - pci_read_config_byte(zr->pci_dev, PCI_LATENCY_TIMER, - &latency); - need_latency = zr->revision > 1 ? 32 : 48; - if (latency != need_latency) { - dprintk(2, KERN_INFO "%s: Changing PCI latency from %d to %d\n", - ZR_DEVNAME(zr), latency, need_latency); - pci_write_config_byte(zr->pci_dev, PCI_LATENCY_TIMER, - need_latency); - } - - zr36057_restart(zr); - /* i2c */ - dprintk(2, KERN_INFO "%s: Initializing i2c bus...\n", - ZR_DEVNAME(zr)); - - if (zoran_register_i2c(zr) < 0) { - dprintk(1, KERN_ERR "%s: %s - can't initialize i2c bus\n", - ZR_DEVNAME(zr), __func__); - goto zr_free_irq; - } - - zr->decoder = v4l2_i2c_new_subdev(&zr->v4l2_dev, - &zr->i2c_adapter, zr->card.i2c_decoder, - 0, zr->card.addrs_decoder); - - if (zr->card.i2c_encoder) - zr->encoder = v4l2_i2c_new_subdev(&zr->v4l2_dev, - &zr->i2c_adapter, zr->card.i2c_encoder, - 0, zr->card.addrs_encoder); - - dprintk(2, - KERN_INFO "%s: Initializing videocodec bus...\n", - ZR_DEVNAME(zr)); - - if (zr->card.video_codec) { - codec_name = codecid_to_modulename(zr->card.video_codec); - if (codec_name) { - result = request_module(codec_name); - if (result) { - dprintk(1, - KERN_ERR - "%s: failed to load modules %s: %d\n", - ZR_DEVNAME(zr), codec_name, result); - } - } - } - if (zr->card.video_vfe) { - vfe_name = codecid_to_modulename(zr->card.video_vfe); - if (vfe_name) { - result = request_module(vfe_name); - if (result < 0) { - dprintk(1, - KERN_ERR - "%s: failed to load modules %s: %d\n", - ZR_DEVNAME(zr), vfe_name, result); - } - } - } - - /* reset JPEG codec */ - jpeg_codec_sleep(zr, 1); - jpeg_codec_reset(zr); - /* video bus enabled */ - /* display codec revision */ - if (zr->card.video_codec != 0) { - master_codec = zoran_setup_videocodec(zr, zr->card.video_codec); - if (!master_codec) - goto zr_unreg_i2c; - zr->codec = videocodec_attach(master_codec); - if (!zr->codec) { - dprintk(1, KERN_ERR "%s: %s - no codec found\n", - ZR_DEVNAME(zr), __func__); - goto zr_free_codec; - } - if (zr->codec->type != zr->card.video_codec) { - dprintk(1, KERN_ERR "%s: %s - wrong codec\n", - ZR_DEVNAME(zr), __func__); - goto zr_detach_codec; - } - } - if (zr->card.video_vfe != 0) { - master_vfe = zoran_setup_videocodec(zr, zr->card.video_vfe); - if (!master_vfe) - goto zr_detach_codec; - zr->vfe = videocodec_attach(master_vfe); - if (!zr->vfe) { - dprintk(1, KERN_ERR "%s: %s - no VFE found\n", - ZR_DEVNAME(zr), __func__); - goto zr_free_vfe; - } - if (zr->vfe->type != zr->card.video_vfe) { - dprintk(1, KERN_ERR "%s: %s = wrong VFE\n", - ZR_DEVNAME(zr), __func__); - goto zr_detach_vfe; - } - } - - /* take care of Natoma chipset and a revision 1 zr36057 */ - if ((pci_pci_problems & PCIPCI_NATOMA) && zr->revision <= 1) { - zr->jpg_buffers.need_contiguous = 1; - dprintk(1, KERN_INFO - "%s: ZR36057/Natoma bug, max. buffer size is 128K\n", - ZR_DEVNAME(zr)); - } - - if (zr36057_init(zr) < 0) - goto zr_detach_vfe; - - zoran_proc_init(zr); - - return 0; - -zr_detach_vfe: - videocodec_detach(zr->vfe); -zr_free_vfe: - kfree(master_vfe); -zr_detach_codec: - videocodec_detach(zr->codec); -zr_free_codec: - kfree(master_codec); -zr_unreg_i2c: - zoran_unregister_i2c(zr); -zr_free_irq: - btwrite(0, ZR36057_SPGPPCR); - free_irq(zr->pci_dev->irq, zr); -zr_unmap: - iounmap(zr->zr36057_mem); -zr_unreg: - v4l2_ctrl_handler_free(&zr->hdl); - v4l2_device_unregister(&zr->v4l2_dev); -zr_free_mem: - kfree(zr); - - return -ENODEV; -} - -static struct pci_driver zoran_driver = { - .name = "zr36067", - .id_table = zr36067_pci_tbl, - .probe = zoran_probe, - .remove = zoran_remove, -}; - -static int __init zoran_init(void) -{ - int res; - - printk(KERN_INFO "Zoran MJPEG board driver version %s\n", - ZORAN_VERSION); - - /* check the parameters we have been given, adjust if necessary */ - if (v4l_nbufs < 2) - v4l_nbufs = 2; - if (v4l_nbufs > VIDEO_MAX_FRAME) - v4l_nbufs = VIDEO_MAX_FRAME; - /* The user specifies the in KB, we want them in byte - * (and page aligned) */ - v4l_bufsize = PAGE_ALIGN(v4l_bufsize * 1024); - if (v4l_bufsize < 32768) - v4l_bufsize = 32768; - /* 2 MB is arbitrary but sufficient for the maximum possible images */ - if (v4l_bufsize > 2048 * 1024) - v4l_bufsize = 2048 * 1024; - if (jpg_nbufs < 4) - jpg_nbufs = 4; - if (jpg_nbufs > BUZ_MAX_FRAME) - jpg_nbufs = BUZ_MAX_FRAME; - jpg_bufsize = PAGE_ALIGN(jpg_bufsize * 1024); - if (jpg_bufsize < 8192) - jpg_bufsize = 8192; - if (jpg_bufsize > (512 * 1024)) - jpg_bufsize = 512 * 1024; - /* Use parameter for vidmem or try to find a video card */ - if (vidmem) { - dprintk(1, - KERN_INFO - "%s: Using supplied video memory base address @ 0x%lx\n", - ZORAN_NAME, vidmem); - } - - /* some mainboards might not do PCI-PCI data transfer well */ - if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL|PCIPCI_ALIMAGIK)) { - dprintk(1, - KERN_WARNING - "%s: chipset does not support reliable PCI-PCI DMA\n", - ZORAN_NAME); - } - - res = pci_register_driver(&zoran_driver); - if (res) { - dprintk(1, - KERN_ERR - "%s: Unable to register ZR36057 driver\n", - ZORAN_NAME); - return res; - } - - return 0; -} - -static void __exit zoran_exit(void) -{ - pci_unregister_driver(&zoran_driver); -} - -module_init(zoran_init); -module_exit(zoran_exit); diff --git a/drivers/staging/media/zoran/zoran_card.h b/drivers/staging/media/zoran/zoran_card.h deleted file mode 100644 index 0cdb7d34926d..000000000000 --- a/drivers/staging/media/zoran/zoran_card.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Zoran zr36057/zr36067 PCI controller driver, for the - * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux - * Media Labs LML33/LML33R10. - * - * This part handles card-specific data and detection - * - * Copyright (C) 2000 Serguei Miridonov - * - * Currently maintained by: - * Ronald Bultje - * Laurent Pinchart - * Mailinglist - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __ZORAN_CARD_H__ -#define __ZORAN_CARD_H__ - -extern int zr36067_debug; - -#define dprintk(num, format, args...) \ - do { \ - if (zr36067_debug >= num) \ - printk(format, ##args); \ - } while (0) - -/* Anybody who uses more than four? */ -#define BUZ_MAX 4 - -extern const struct video_device zoran_template; - -extern int zoran_check_jpg_settings(struct zoran *zr, - struct zoran_jpg_settings *settings, - int try); -extern void zoran_open_init_params(struct zoran *zr); -extern void zoran_vdev_release(struct video_device *vdev); - -void zr36016_write(struct videocodec *codec, u16 reg, u32 val); - -#endif /* __ZORAN_CARD_H__ */ diff --git a/drivers/staging/media/zoran/zoran_device.c b/drivers/staging/media/zoran/zoran_device.c deleted file mode 100644 index 22b27632762d..000000000000 --- a/drivers/staging/media/zoran/zoran_device.c +++ /dev/null @@ -1,1619 +0,0 @@ -/* - * Zoran zr36057/zr36067 PCI controller driver, for the - * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux - * Media Labs LML33/LML33R10. - * - * This part handles device access (PCI/I2C/codec/...) - * - * Copyright (C) 2000 Serguei Miridonov - * - * Currently maintained by: - * Ronald Bultje - * Laurent Pinchart - * Mailinglist - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include "videocodec.h" -#include "zoran.h" -#include "zoran_device.h" -#include "zoran_card.h" - -#define IRQ_MASK ( ZR36057_ISR_GIRQ0 | \ - ZR36057_ISR_GIRQ1 | \ - ZR36057_ISR_JPEGRepIRQ ) - -static bool lml33dpath; /* default = 0 - * 1 will use digital path in capture - * mode instead of analog. It can be - * used for picture adjustments using - * tool like xawtv while watching image - * on TV monitor connected to the output. - * However, due to absence of 75 Ohm - * load on Bt819 input, there will be - * some image imperfections */ - -module_param(lml33dpath, bool, 0644); -MODULE_PARM_DESC(lml33dpath, - "Use digital path capture mode (on LML33 cards)"); - -static void -zr36057_init_vfe (struct zoran *zr); - -/* - * General Purpose I/O and Guest bus access - */ - -/* - * This is a bit tricky. When a board lacks a GPIO function, the corresponding - * GPIO bit number in the card_info structure is set to 0. - */ - -void -GPIO (struct zoran *zr, - int bit, - unsigned int value) -{ - u32 reg; - u32 mask; - - /* Make sure the bit number is legal - * A bit number of -1 (lacking) gives a mask of 0, - * making it harmless */ - mask = (1 << (24 + bit)) & 0xff000000; - reg = btread(ZR36057_GPPGCR1) & ~mask; - if (value) { - reg |= mask; - } - btwrite(reg, ZR36057_GPPGCR1); - udelay(1); -} - -/* - * Wait til post office is no longer busy - */ - -int -post_office_wait (struct zoran *zr) -{ - u32 por; - -// while (((por = btread(ZR36057_POR)) & (ZR36057_POR_POPen | ZR36057_POR_POTime)) == ZR36057_POR_POPen) { - while ((por = btread(ZR36057_POR)) & ZR36057_POR_POPen) { - /* wait for something to happen */ - } - if ((por & ZR36057_POR_POTime) && !zr->card.gws_not_connected) { - /* In LML33/BUZ \GWS line is not connected, so it has always timeout set */ - dprintk(1, KERN_INFO "%s: pop timeout %08x\n", ZR_DEVNAME(zr), - por); - return -1; - } - - return 0; -} - -int -post_office_write (struct zoran *zr, - unsigned int guest, - unsigned int reg, - unsigned int value) -{ - u32 por; - - por = - ZR36057_POR_PODir | ZR36057_POR_POTime | ((guest & 7) << 20) | - ((reg & 7) << 16) | (value & 0xFF); - btwrite(por, ZR36057_POR); - - return post_office_wait(zr); -} - -int -post_office_read (struct zoran *zr, - unsigned int guest, - unsigned int reg) -{ - u32 por; - - por = ZR36057_POR_POTime | ((guest & 7) << 20) | ((reg & 7) << 16); - btwrite(por, ZR36057_POR); - if (post_office_wait(zr) < 0) { - return -1; - } - - return btread(ZR36057_POR) & 0xFF; -} - -/* - * detect guests - */ - -static void -dump_guests (struct zoran *zr) -{ - if (zr36067_debug > 2) { - int i, guest[8]; - - for (i = 1; i < 8; i++) { // Don't read jpeg codec here - guest[i] = post_office_read(zr, i, 0); - } - - printk(KERN_INFO "%s: Guests: %*ph\n", - ZR_DEVNAME(zr), 8, guest); - } -} - -void -detect_guest_activity (struct zoran *zr) -{ - int timeout, i, j, res, guest[8], guest0[8], change[8][3]; - ktime_t t0, t1; - - dump_guests(zr); - printk(KERN_INFO "%s: Detecting guests activity, please wait...\n", - ZR_DEVNAME(zr)); - for (i = 1; i < 8; i++) { // Don't read jpeg codec here - guest0[i] = guest[i] = post_office_read(zr, i, 0); - } - - timeout = 0; - j = 0; - t0 = ktime_get(); - while (timeout < 10000) { - udelay(10); - timeout++; - for (i = 1; (i < 8) && (j < 8); i++) { - res = post_office_read(zr, i, 0); - if (res != guest[i]) { - t1 = ktime_get(); - change[j][0] = ktime_to_us(ktime_sub(t1, t0)); - t0 = t1; - change[j][1] = i; - change[j][2] = res; - j++; - guest[i] = res; - } - } - if (j >= 8) - break; - } - - printk(KERN_INFO "%s: Guests: %*ph\n", ZR_DEVNAME(zr), 8, guest0); - - if (j == 0) { - printk(KERN_INFO "%s: No activity detected.\n", ZR_DEVNAME(zr)); - return; - } - for (i = 0; i < j; i++) { - printk(KERN_INFO "%s: %6d: %d => 0x%02x\n", ZR_DEVNAME(zr), - change[i][0], change[i][1], change[i][2]); - } -} - -/* - * JPEG Codec access - */ - -void -jpeg_codec_sleep (struct zoran *zr, - int sleep) -{ - GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_SLEEP], !sleep); - if (!sleep) { - dprintk(3, - KERN_DEBUG - "%s: jpeg_codec_sleep() - wake GPIO=0x%08x\n", - ZR_DEVNAME(zr), btread(ZR36057_GPPGCR1)); - udelay(500); - } else { - dprintk(3, - KERN_DEBUG - "%s: jpeg_codec_sleep() - sleep GPIO=0x%08x\n", - ZR_DEVNAME(zr), btread(ZR36057_GPPGCR1)); - udelay(2); - } -} - -int -jpeg_codec_reset (struct zoran *zr) -{ - /* Take the codec out of sleep */ - jpeg_codec_sleep(zr, 0); - - if (zr->card.gpcs[GPCS_JPEG_RESET] != 0xff) { - post_office_write(zr, zr->card.gpcs[GPCS_JPEG_RESET], 0, - 0); - udelay(2); - } else { - GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_RESET], 0); - udelay(2); - GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_RESET], 1); - udelay(2); - } - - return 0; -} - -/* - * Set the registers for the size we have specified. Don't bother - * trying to understand this without the ZR36057 manual in front of - * you [AC]. - * - * PS: The manual is free for download in .pdf format from - * www.zoran.com - nicely done those folks. - */ - -static void -zr36057_adjust_vfe (struct zoran *zr, - enum zoran_codec_mode mode) -{ - u32 reg; - - switch (mode) { - case BUZ_MODE_MOTION_DECOMPRESS: - btand(~ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR); - reg = btread(ZR36057_VFEHCR); - if ((reg & (1 << 10)) && zr->card.type != LML33R10) { - reg += ((1 << 10) | 1); - } - btwrite(reg, ZR36057_VFEHCR); - break; - case BUZ_MODE_MOTION_COMPRESS: - case BUZ_MODE_IDLE: - default: - if ((zr->norm & V4L2_STD_NTSC) || - (zr->card.type == LML33R10 && - (zr->norm & V4L2_STD_PAL))) - btand(~ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR); - else - btor(ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR); - reg = btread(ZR36057_VFEHCR); - if (!(reg & (1 << 10)) && zr->card.type != LML33R10) { - reg -= ((1 << 10) | 1); - } - btwrite(reg, ZR36057_VFEHCR); - break; - } -} - -/* - * set geometry - */ - -static void -zr36057_set_vfe (struct zoran *zr, - int video_width, - int video_height, - const struct zoran_format *format) -{ - struct tvnorm *tvn; - unsigned HStart, HEnd, VStart, VEnd; - unsigned DispMode; - unsigned VidWinWid, VidWinHt; - unsigned hcrop1, hcrop2, vcrop1, vcrop2; - unsigned Wa, We, Ha, He; - unsigned X, Y, HorDcm, VerDcm; - u32 reg; - unsigned mask_line_size; - - tvn = zr->timing; - - Wa = tvn->Wa; - Ha = tvn->Ha; - - dprintk(2, KERN_INFO "%s: set_vfe() - width = %d, height = %d\n", - ZR_DEVNAME(zr), video_width, video_height); - - if (video_width < BUZ_MIN_WIDTH || - video_height < BUZ_MIN_HEIGHT || - video_width > Wa || video_height > Ha) { - dprintk(1, KERN_ERR "%s: set_vfe: w=%d h=%d not valid\n", - ZR_DEVNAME(zr), video_width, video_height); - return; - } - - /**** zr36057 ****/ - - /* horizontal */ - VidWinWid = video_width; - X = DIV_ROUND_UP(VidWinWid * 64, tvn->Wa); - We = (VidWinWid * 64) / X; - HorDcm = 64 - X; - hcrop1 = 2 * ((tvn->Wa - We) / 4); - hcrop2 = tvn->Wa - We - hcrop1; - HStart = tvn->HStart ? tvn->HStart : 1; - /* (Ronald) Original comment: - * "| 1 Doesn't have any effect, tested on both a DC10 and a DC10+" - * this is false. It inverses chroma values on the LML33R10 (so Cr - * suddenly is shown as Cb and reverse, really cool effect if you - * want to see blue faces, not useful otherwise). So don't use |1. - * However, the DC10 has '0' as HStart, but does need |1, so we - * use a dirty check... - */ - HEnd = HStart + tvn->Wa - 1; - HStart += hcrop1; - HEnd -= hcrop2; - reg = ((HStart & ZR36057_VFEHCR_Hmask) << ZR36057_VFEHCR_HStart) - | ((HEnd & ZR36057_VFEHCR_Hmask) << ZR36057_VFEHCR_HEnd); - if (zr->card.vfe_pol.hsync_pol) - reg |= ZR36057_VFEHCR_HSPol; - btwrite(reg, ZR36057_VFEHCR); - - /* Vertical */ - DispMode = !(video_height > BUZ_MAX_HEIGHT / 2); - VidWinHt = DispMode ? video_height : video_height / 2; - Y = DIV_ROUND_UP(VidWinHt * 64 * 2, tvn->Ha); - He = (VidWinHt * 64) / Y; - VerDcm = 64 - Y; - vcrop1 = (tvn->Ha / 2 - He) / 2; - vcrop2 = tvn->Ha / 2 - He - vcrop1; - VStart = tvn->VStart; - VEnd = VStart + tvn->Ha / 2; // - 1; FIXME SnapShot times out with -1 in 768*576 on the DC10 - LP - VStart += vcrop1; - VEnd -= vcrop2; - reg = ((VStart & ZR36057_VFEVCR_Vmask) << ZR36057_VFEVCR_VStart) - | ((VEnd & ZR36057_VFEVCR_Vmask) << ZR36057_VFEVCR_VEnd); - if (zr->card.vfe_pol.vsync_pol) - reg |= ZR36057_VFEVCR_VSPol; - btwrite(reg, ZR36057_VFEVCR); - - /* scaler and pixel format */ - reg = 0; - reg |= (HorDcm << ZR36057_VFESPFR_HorDcm); - reg |= (VerDcm << ZR36057_VFESPFR_VerDcm); - reg |= (DispMode << ZR36057_VFESPFR_DispMode); - /* RJ: I don't know, why the following has to be the opposite - * of the corresponding ZR36060 setting, but only this way - * we get the correct colors when uncompressing to the screen */ - //reg |= ZR36057_VFESPFR_VCLKPol; /**/ - /* RJ: Don't know if that is needed for NTSC also */ - if (!(zr->norm & V4L2_STD_NTSC)) - reg |= ZR36057_VFESPFR_ExtFl; // NEEDED!!!!!!! Wolfgang - reg |= ZR36057_VFESPFR_TopField; - if (HorDcm >= 48) { - reg |= 3 << ZR36057_VFESPFR_HFilter; /* 5 tap filter */ - } else if (HorDcm >= 32) { - reg |= 2 << ZR36057_VFESPFR_HFilter; /* 4 tap filter */ - } else if (HorDcm >= 16) { - reg |= 1 << ZR36057_VFESPFR_HFilter; /* 3 tap filter */ - } - reg |= format->vfespfr; - btwrite(reg, ZR36057_VFESPFR); - - /* display configuration */ - reg = (16 << ZR36057_VDCR_MinPix) - | (VidWinHt << ZR36057_VDCR_VidWinHt) - | (VidWinWid << ZR36057_VDCR_VidWinWid); - if (pci_pci_problems & PCIPCI_TRITON) - // || zr->revision < 1) // Revision 1 has also Triton support - reg &= ~ZR36057_VDCR_Triton; - else - reg |= ZR36057_VDCR_Triton; - btwrite(reg, ZR36057_VDCR); - - /* (Ronald) don't write this if overlay_mask = NULL */ - if (zr->overlay_mask) { - /* Write overlay clipping mask data, but don't enable overlay clipping */ - /* RJ: since this makes only sense on the screen, we use - * zr->overlay_settings.width instead of video_width */ - - mask_line_size = (BUZ_MAX_WIDTH + 31) / 32; - reg = virt_to_bus(zr->overlay_mask); - btwrite(reg, ZR36057_MMTR); - reg = virt_to_bus(zr->overlay_mask + mask_line_size); - btwrite(reg, ZR36057_MMBR); - reg = - mask_line_size - (zr->overlay_settings.width + - 31) / 32; - if (DispMode == 0) - reg += mask_line_size; - reg <<= ZR36057_OCR_MaskStride; - btwrite(reg, ZR36057_OCR); - } - - zr36057_adjust_vfe(zr, zr->codec_mode); -} - -/* - * Switch overlay on or off - */ - -void -zr36057_overlay (struct zoran *zr, - int on) -{ - u32 reg; - - if (on) { - /* do the necessary settings ... */ - btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR); /* switch it off first */ - - zr36057_set_vfe(zr, - zr->overlay_settings.width, - zr->overlay_settings.height, - zr->overlay_settings.format); - - /* Start and length of each line MUST be 4-byte aligned. - * This should be already checked before the call to this routine. - * All error messages are internal driver checking only! */ - - /* video display top and bottom registers */ - reg = (long) zr->vbuf_base + - zr->overlay_settings.x * - ((zr->overlay_settings.format->depth + 7) / 8) + - zr->overlay_settings.y * - zr->vbuf_bytesperline; - btwrite(reg, ZR36057_VDTR); - if (reg & 3) - dprintk(1, - KERN_ERR - "%s: zr36057_overlay() - video_address not aligned\n", - ZR_DEVNAME(zr)); - if (zr->overlay_settings.height > BUZ_MAX_HEIGHT / 2) - reg += zr->vbuf_bytesperline; - btwrite(reg, ZR36057_VDBR); - - /* video stride, status, and frame grab register */ - reg = zr->vbuf_bytesperline - - zr->overlay_settings.width * - ((zr->overlay_settings.format->depth + 7) / 8); - if (zr->overlay_settings.height > BUZ_MAX_HEIGHT / 2) - reg += zr->vbuf_bytesperline; - if (reg & 3) - dprintk(1, - KERN_ERR - "%s: zr36057_overlay() - video_stride not aligned\n", - ZR_DEVNAME(zr)); - reg = (reg << ZR36057_VSSFGR_DispStride); - reg |= ZR36057_VSSFGR_VidOvf; /* clear overflow status */ - btwrite(reg, ZR36057_VSSFGR); - - /* Set overlay clipping */ - if (zr->overlay_settings.clipcount > 0) - btor(ZR36057_OCR_OvlEnable, ZR36057_OCR); - - /* ... and switch it on */ - btor(ZR36057_VDCR_VidEn, ZR36057_VDCR); - } else { - /* Switch it off */ - btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR); - } -} - -/* - * The overlay mask has one bit for each pixel on a scan line, - * and the maximum window size is BUZ_MAX_WIDTH * BUZ_MAX_HEIGHT pixels. - */ - -void write_overlay_mask(struct zoran_fh *fh, struct v4l2_clip *vp, int count) -{ - struct zoran *zr = fh->zr; - unsigned mask_line_size = (BUZ_MAX_WIDTH + 31) / 32; - u32 *mask; - int x, y, width, height; - unsigned i, j, k; - - /* fill mask with one bits */ - memset(fh->overlay_mask, ~0, mask_line_size * 4 * BUZ_MAX_HEIGHT); - - for (i = 0; i < count; ++i) { - /* pick up local copy of clip */ - x = vp[i].c.left; - y = vp[i].c.top; - width = vp[i].c.width; - height = vp[i].c.height; - - /* trim clips that extend beyond the window */ - if (x < 0) { - width += x; - x = 0; - } - if (y < 0) { - height += y; - y = 0; - } - if (x + width > fh->overlay_settings.width) { - width = fh->overlay_settings.width - x; - } - if (y + height > fh->overlay_settings.height) { - height = fh->overlay_settings.height - y; - } - - /* ignore degenerate clips */ - if (height <= 0) { - continue; - } - if (width <= 0) { - continue; - } - - /* apply clip for each scan line */ - for (j = 0; j < height; ++j) { - /* reset bit for each pixel */ - /* this can be optimized later if need be */ - mask = fh->overlay_mask + (y + j) * mask_line_size; - for (k = 0; k < width; ++k) { - mask[(x + k) / 32] &= - ~((u32) 1 << (x + k) % 32); - } - } - } -} - -/* Enable/Disable uncompressed memory grabbing of the 36057 */ - -void -zr36057_set_memgrab (struct zoran *zr, - int mode) -{ - if (mode) { - /* We only check SnapShot and not FrameGrab here. SnapShot==1 - * means a capture is already in progress, but FrameGrab==1 - * doesn't necessary mean that. It's more correct to say a 1 - * to 0 transition indicates a capture completed. If a - * capture is pending when capturing is tuned off, FrameGrab - * will be stuck at 1 until capturing is turned back on. - */ - if (btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_SnapShot) - dprintk(1, - KERN_WARNING - "%s: zr36057_set_memgrab(1) with SnapShot on!?\n", - ZR_DEVNAME(zr)); - - /* switch on VSync interrupts */ - btwrite(IRQ_MASK, ZR36057_ISR); // Clear Interrupts - btor(zr->card.vsync_int, ZR36057_ICR); // SW - - /* enable SnapShot */ - btor(ZR36057_VSSFGR_SnapShot, ZR36057_VSSFGR); - - /* Set zr36057 video front end and enable video */ - zr36057_set_vfe(zr, zr->v4l_settings.width, - zr->v4l_settings.height, - zr->v4l_settings.format); - - zr->v4l_memgrab_active = 1; - } else { - /* switch off VSync interrupts */ - btand(~zr->card.vsync_int, ZR36057_ICR); // SW - - zr->v4l_memgrab_active = 0; - zr->v4l_grab_frame = NO_GRAB_ACTIVE; - - /* re-enable grabbing to screen if it was running */ - if (zr->v4l_overlay_active) { - zr36057_overlay(zr, 1); - } else { - btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR); - btand(~ZR36057_VSSFGR_SnapShot, ZR36057_VSSFGR); - } - } -} - -int -wait_grab_pending (struct zoran *zr) -{ - unsigned long flags; - - /* wait until all pending grabs are finished */ - - if (!zr->v4l_memgrab_active) - return 0; - - wait_event_interruptible(zr->v4l_capq, - (zr->v4l_pend_tail == zr->v4l_pend_head)); - if (signal_pending(current)) - return -ERESTARTSYS; - - spin_lock_irqsave(&zr->spinlock, flags); - zr36057_set_memgrab(zr, 0); - spin_unlock_irqrestore(&zr->spinlock, flags); - - return 0; -} - -/***************************************************************************** - * * - * Set up the Buz-specific MJPEG part * - * * - *****************************************************************************/ - -static inline void -set_frame (struct zoran *zr, - int val) -{ - GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_FRAME], val); -} - -static void -set_videobus_dir (struct zoran *zr, - int val) -{ - switch (zr->card.type) { - case LML33: - case LML33R10: - if (!lml33dpath) - GPIO(zr, 5, val); - else - GPIO(zr, 5, 1); - break; - default: - GPIO(zr, zr->card.gpio[ZR_GPIO_VID_DIR], - zr->card.gpio_pol[ZR_GPIO_VID_DIR] ? !val : val); - break; - } -} - -static void -init_jpeg_queue (struct zoran *zr) -{ - int i; - - /* re-initialize DMA ring stuff */ - zr->jpg_que_head = 0; - zr->jpg_dma_head = 0; - zr->jpg_dma_tail = 0; - zr->jpg_que_tail = 0; - zr->jpg_seq_num = 0; - zr->JPEG_error = 0; - zr->num_errors = 0; - zr->jpg_err_seq = 0; - zr->jpg_err_shift = 0; - zr->jpg_queued_num = 0; - for (i = 0; i < zr->jpg_buffers.num_buffers; i++) { - zr->jpg_buffers.buffer[i].state = BUZ_STATE_USER; /* nothing going on */ - } - for (i = 0; i < BUZ_NUM_STAT_COM; i++) { - zr->stat_com[i] = cpu_to_le32(1); /* mark as unavailable to zr36057 */ - } -} - -static void -zr36057_set_jpg (struct zoran *zr, - enum zoran_codec_mode mode) -{ - struct tvnorm *tvn; - u32 reg; - - tvn = zr->timing; - - /* assert P_Reset, disable code transfer, deassert Active */ - btwrite(0, ZR36057_JPC); - - /* MJPEG compression mode */ - switch (mode) { - - case BUZ_MODE_MOTION_COMPRESS: - default: - reg = ZR36057_JMC_MJPGCmpMode; - break; - - case BUZ_MODE_MOTION_DECOMPRESS: - reg = ZR36057_JMC_MJPGExpMode; - reg |= ZR36057_JMC_SyncMstr; - /* RJ: The following is experimental - improves the output to screen */ - //if(zr->jpg_settings.VFIFO_FB) reg |= ZR36057_JMC_VFIFO_FB; // No, it doesn't. SM - break; - - case BUZ_MODE_STILL_COMPRESS: - reg = ZR36057_JMC_JPGCmpMode; - break; - - case BUZ_MODE_STILL_DECOMPRESS: - reg = ZR36057_JMC_JPGExpMode; - break; - - } - reg |= ZR36057_JMC_JPG; - if (zr->jpg_settings.field_per_buff == 1) - reg |= ZR36057_JMC_Fld_per_buff; - btwrite(reg, ZR36057_JMC); - - /* vertical */ - btor(ZR36057_VFEVCR_VSPol, ZR36057_VFEVCR); - reg = (6 << ZR36057_VSP_VsyncSize) | - (tvn->Ht << ZR36057_VSP_FrmTot); - btwrite(reg, ZR36057_VSP); - reg = ((zr->jpg_settings.img_y + tvn->VStart) << ZR36057_FVAP_NAY) | - (zr->jpg_settings.img_height << ZR36057_FVAP_PAY); - btwrite(reg, ZR36057_FVAP); - - /* horizontal */ - if (zr->card.vfe_pol.hsync_pol) - btor(ZR36057_VFEHCR_HSPol, ZR36057_VFEHCR); - else - btand(~ZR36057_VFEHCR_HSPol, ZR36057_VFEHCR); - reg = ((tvn->HSyncStart) << ZR36057_HSP_HsyncStart) | - (tvn->Wt << ZR36057_HSP_LineTot); - btwrite(reg, ZR36057_HSP); - reg = ((zr->jpg_settings.img_x + - tvn->HStart + 4) << ZR36057_FHAP_NAX) | - (zr->jpg_settings.img_width << ZR36057_FHAP_PAX); - btwrite(reg, ZR36057_FHAP); - - /* field process parameters */ - if (zr->jpg_settings.odd_even) - reg = ZR36057_FPP_Odd_Even; - else - reg = 0; - - btwrite(reg, ZR36057_FPP); - - /* Set proper VCLK Polarity, else colors will be wrong during playback */ - //btor(ZR36057_VFESPFR_VCLKPol, ZR36057_VFESPFR); - - /* code base address */ - reg = virt_to_bus(zr->stat_com); - btwrite(reg, ZR36057_JCBA); - - /* FIFO threshold (FIFO is 160. double words) */ - /* NOTE: decimal values here */ - switch (mode) { - - case BUZ_MODE_STILL_COMPRESS: - case BUZ_MODE_MOTION_COMPRESS: - if (zr->card.type != BUZ) - reg = 140; - else - reg = 60; - break; - - case BUZ_MODE_STILL_DECOMPRESS: - case BUZ_MODE_MOTION_DECOMPRESS: - reg = 20; - break; - - default: - reg = 80; - break; - - } - btwrite(reg, ZR36057_JCFT); - zr36057_adjust_vfe(zr, mode); - -} - -void -print_interrupts (struct zoran *zr) -{ - int res, noerr = 0; - - printk(KERN_INFO "%s: interrupts received:", ZR_DEVNAME(zr)); - if ((res = zr->field_counter) < -1 || res > 1) { - printk(KERN_CONT " FD:%d", res); - } - if ((res = zr->intr_counter_GIRQ1) != 0) { - printk(KERN_CONT " GIRQ1:%d", res); - noerr++; - } - if ((res = zr->intr_counter_GIRQ0) != 0) { - printk(KERN_CONT " GIRQ0:%d", res); - noerr++; - } - if ((res = zr->intr_counter_CodRepIRQ) != 0) { - printk(KERN_CONT " CodRepIRQ:%d", res); - noerr++; - } - if ((res = zr->intr_counter_JPEGRepIRQ) != 0) { - printk(KERN_CONT " JPEGRepIRQ:%d", res); - noerr++; - } - if (zr->JPEG_max_missed) { - printk(KERN_CONT " JPEG delays: max=%d min=%d", zr->JPEG_max_missed, - zr->JPEG_min_missed); - } - if (zr->END_event_missed) { - printk(KERN_CONT " ENDs missed: %d", zr->END_event_missed); - } - //if (zr->jpg_queued_num) { - printk(KERN_CONT " queue_state=%ld/%ld/%ld/%ld", zr->jpg_que_tail, - zr->jpg_dma_tail, zr->jpg_dma_head, zr->jpg_que_head); - //} - if (!noerr) { - printk(KERN_CONT ": no interrupts detected."); - } - printk(KERN_CONT "\n"); -} - -void -clear_interrupt_counters (struct zoran *zr) -{ - zr->intr_counter_GIRQ1 = 0; - zr->intr_counter_GIRQ0 = 0; - zr->intr_counter_CodRepIRQ = 0; - zr->intr_counter_JPEGRepIRQ = 0; - zr->field_counter = 0; - zr->IRQ1_in = 0; - zr->IRQ1_out = 0; - zr->JPEG_in = 0; - zr->JPEG_out = 0; - zr->JPEG_0 = 0; - zr->JPEG_1 = 0; - zr->END_event_missed = 0; - zr->JPEG_missed = 0; - zr->JPEG_max_missed = 0; - zr->JPEG_min_missed = 0x7fffffff; -} - -static u32 -count_reset_interrupt (struct zoran *zr) -{ - u32 isr; - - if ((isr = btread(ZR36057_ISR) & 0x78000000)) { - if (isr & ZR36057_ISR_GIRQ1) { - btwrite(ZR36057_ISR_GIRQ1, ZR36057_ISR); - zr->intr_counter_GIRQ1++; - } - if (isr & ZR36057_ISR_GIRQ0) { - btwrite(ZR36057_ISR_GIRQ0, ZR36057_ISR); - zr->intr_counter_GIRQ0++; - } - if (isr & ZR36057_ISR_CodRepIRQ) { - btwrite(ZR36057_ISR_CodRepIRQ, ZR36057_ISR); - zr->intr_counter_CodRepIRQ++; - } - if (isr & ZR36057_ISR_JPEGRepIRQ) { - btwrite(ZR36057_ISR_JPEGRepIRQ, ZR36057_ISR); - zr->intr_counter_JPEGRepIRQ++; - } - } - return isr; -} - -void -jpeg_start (struct zoran *zr) -{ - int reg; - - zr->frame_num = 0; - - /* deassert P_reset, disable code transfer, deassert Active */ - btwrite(ZR36057_JPC_P_Reset, ZR36057_JPC); - /* stop flushing the internal code buffer */ - btand(~ZR36057_MCTCR_CFlush, ZR36057_MCTCR); - /* enable code transfer */ - btor(ZR36057_JPC_CodTrnsEn, ZR36057_JPC); - - /* clear IRQs */ - btwrite(IRQ_MASK, ZR36057_ISR); - /* enable the JPEG IRQs */ - btwrite(zr->card.jpeg_int | - ZR36057_ICR_JPEGRepIRQ | - ZR36057_ICR_IntPinEn, - ZR36057_ICR); - - set_frame(zr, 0); // \FRAME - - /* set the JPEG codec guest ID */ - reg = (zr->card.gpcs[1] << ZR36057_JCGI_JPEGuestID) | - (0 << ZR36057_JCGI_JPEGuestReg); - btwrite(reg, ZR36057_JCGI); - - if (zr->card.video_vfe == CODEC_TYPE_ZR36016 && - zr->card.video_codec == CODEC_TYPE_ZR36050) { - /* Enable processing on the ZR36016 */ - if (zr->vfe) - zr36016_write(zr->vfe, 0, 1); - - /* load the address of the GO register in the ZR36050 latch */ - post_office_write(zr, 0, 0, 0); - } - - /* assert Active */ - btor(ZR36057_JPC_Active, ZR36057_JPC); - - /* enable the Go generation */ - btor(ZR36057_JMC_Go_en, ZR36057_JMC); - udelay(30); - - set_frame(zr, 1); // /FRAME - - dprintk(3, KERN_DEBUG "%s: jpeg_start\n", ZR_DEVNAME(zr)); -} - -void -zr36057_enable_jpg (struct zoran *zr, - enum zoran_codec_mode mode) -{ - struct vfe_settings cap; - int field_size = - zr->jpg_buffers.buffer_size / zr->jpg_settings.field_per_buff; - - zr->codec_mode = mode; - - cap.x = zr->jpg_settings.img_x; - cap.y = zr->jpg_settings.img_y; - cap.width = zr->jpg_settings.img_width; - cap.height = zr->jpg_settings.img_height; - cap.decimation = - zr->jpg_settings.HorDcm | (zr->jpg_settings.VerDcm << 8); - cap.quality = zr->jpg_settings.jpg_comp.quality; - - switch (mode) { - - case BUZ_MODE_MOTION_COMPRESS: { - struct jpeg_app_marker app; - struct jpeg_com_marker com; - - /* In motion compress mode, the decoder output must be enabled, and - * the video bus direction set to input. - */ - set_videobus_dir(zr, 0); - decoder_call(zr, video, s_stream, 1); - encoder_call(zr, video, s_routing, 0, 0, 0); - - /* Take the JPEG codec and the VFE out of sleep */ - jpeg_codec_sleep(zr, 0); - - /* set JPEG app/com marker */ - app.appn = zr->jpg_settings.jpg_comp.APPn; - app.len = zr->jpg_settings.jpg_comp.APP_len; - memcpy(app.data, zr->jpg_settings.jpg_comp.APP_data, 60); - zr->codec->control(zr->codec, CODEC_S_JPEG_APP_DATA, - sizeof(struct jpeg_app_marker), &app); - - com.len = zr->jpg_settings.jpg_comp.COM_len; - memcpy(com.data, zr->jpg_settings.jpg_comp.COM_data, 60); - zr->codec->control(zr->codec, CODEC_S_JPEG_COM_DATA, - sizeof(struct jpeg_com_marker), &com); - - /* Setup the JPEG codec */ - zr->codec->control(zr->codec, CODEC_S_JPEG_TDS_BYTE, - sizeof(int), &field_size); - zr->codec->set_video(zr->codec, zr->timing, &cap, - &zr->card.vfe_pol); - zr->codec->set_mode(zr->codec, CODEC_DO_COMPRESSION); - - /* Setup the VFE */ - if (zr->vfe) { - zr->vfe->control(zr->vfe, CODEC_S_JPEG_TDS_BYTE, - sizeof(int), &field_size); - zr->vfe->set_video(zr->vfe, zr->timing, &cap, - &zr->card.vfe_pol); - zr->vfe->set_mode(zr->vfe, CODEC_DO_COMPRESSION); - } - - init_jpeg_queue(zr); - zr36057_set_jpg(zr, mode); // \P_Reset, ... Video param, FIFO - - clear_interrupt_counters(zr); - dprintk(2, KERN_INFO "%s: enable_jpg(MOTION_COMPRESS)\n", - ZR_DEVNAME(zr)); - break; - } - - case BUZ_MODE_MOTION_DECOMPRESS: - /* In motion decompression mode, the decoder output must be disabled, and - * the video bus direction set to output. - */ - decoder_call(zr, video, s_stream, 0); - set_videobus_dir(zr, 1); - encoder_call(zr, video, s_routing, 1, 0, 0); - - /* Take the JPEG codec and the VFE out of sleep */ - jpeg_codec_sleep(zr, 0); - /* Setup the VFE */ - if (zr->vfe) { - zr->vfe->set_video(zr->vfe, zr->timing, &cap, - &zr->card.vfe_pol); - zr->vfe->set_mode(zr->vfe, CODEC_DO_EXPANSION); - } - /* Setup the JPEG codec */ - zr->codec->set_video(zr->codec, zr->timing, &cap, - &zr->card.vfe_pol); - zr->codec->set_mode(zr->codec, CODEC_DO_EXPANSION); - - init_jpeg_queue(zr); - zr36057_set_jpg(zr, mode); // \P_Reset, ... Video param, FIFO - - clear_interrupt_counters(zr); - dprintk(2, KERN_INFO "%s: enable_jpg(MOTION_DECOMPRESS)\n", - ZR_DEVNAME(zr)); - break; - - case BUZ_MODE_IDLE: - default: - /* shut down processing */ - btand(~(zr->card.jpeg_int | ZR36057_ICR_JPEGRepIRQ), - ZR36057_ICR); - btwrite(zr->card.jpeg_int | ZR36057_ICR_JPEGRepIRQ, - ZR36057_ISR); - btand(~ZR36057_JMC_Go_en, ZR36057_JMC); // \Go_en - - msleep(50); - - set_videobus_dir(zr, 0); - set_frame(zr, 1); // /FRAME - btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR); // /CFlush - btwrite(0, ZR36057_JPC); // \P_Reset,\CodTrnsEn,\Active - btand(~ZR36057_JMC_VFIFO_FB, ZR36057_JMC); - btand(~ZR36057_JMC_SyncMstr, ZR36057_JMC); - jpeg_codec_reset(zr); - jpeg_codec_sleep(zr, 1); - zr36057_adjust_vfe(zr, mode); - - decoder_call(zr, video, s_stream, 1); - encoder_call(zr, video, s_routing, 0, 0, 0); - - dprintk(2, KERN_INFO "%s: enable_jpg(IDLE)\n", ZR_DEVNAME(zr)); - break; - - } -} - -/* when this is called the spinlock must be held */ -void -zoran_feed_stat_com (struct zoran *zr) -{ - /* move frames from pending queue to DMA */ - - int frame, i, max_stat_com; - - max_stat_com = - (zr->jpg_settings.TmpDcm == - 1) ? BUZ_NUM_STAT_COM : (BUZ_NUM_STAT_COM >> 1); - - while ((zr->jpg_dma_head - zr->jpg_dma_tail) < max_stat_com && - zr->jpg_dma_head < zr->jpg_que_head) { - - frame = zr->jpg_pend[zr->jpg_dma_head & BUZ_MASK_FRAME]; - if (zr->jpg_settings.TmpDcm == 1) { - /* fill 1 stat_com entry */ - i = (zr->jpg_dma_head - - zr->jpg_err_shift) & BUZ_MASK_STAT_COM; - if (!(zr->stat_com[i] & cpu_to_le32(1))) - break; - zr->stat_com[i] = - cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus); - } else { - /* fill 2 stat_com entries */ - i = ((zr->jpg_dma_head - - zr->jpg_err_shift) & 1) * 2; - if (!(zr->stat_com[i] & cpu_to_le32(1))) - break; - zr->stat_com[i] = - cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus); - zr->stat_com[i + 1] = - cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus); - } - zr->jpg_buffers.buffer[frame].state = BUZ_STATE_DMA; - zr->jpg_dma_head++; - - } - if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) - zr->jpg_queued_num++; -} - -/* when this is called the spinlock must be held */ -static void -zoran_reap_stat_com (struct zoran *zr) -{ - /* move frames from DMA queue to done queue */ - - int i; - u32 stat_com; - unsigned int seq; - unsigned int dif; - struct zoran_buffer *buffer; - int frame; - - /* In motion decompress we don't have a hardware frame counter, - * we just count the interrupts here */ - - if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) { - zr->jpg_seq_num++; - } - while (zr->jpg_dma_tail < zr->jpg_dma_head) { - if (zr->jpg_settings.TmpDcm == 1) - i = (zr->jpg_dma_tail - - zr->jpg_err_shift) & BUZ_MASK_STAT_COM; - else - i = ((zr->jpg_dma_tail - - zr->jpg_err_shift) & 1) * 2 + 1; - - stat_com = le32_to_cpu(zr->stat_com[i]); - - if ((stat_com & 1) == 0) { - return; - } - frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME]; - buffer = &zr->jpg_buffers.buffer[frame]; - buffer->bs.ts = ktime_get_ns(); - - if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { - buffer->bs.length = (stat_com & 0x7fffff) >> 1; - - /* update sequence number with the help of the counter in stat_com */ - - seq = ((stat_com >> 24) + zr->jpg_err_seq) & 0xff; - dif = (seq - zr->jpg_seq_num) & 0xff; - zr->jpg_seq_num += dif; - } else { - buffer->bs.length = 0; - } - buffer->bs.seq = - zr->jpg_settings.TmpDcm == - 2 ? (zr->jpg_seq_num >> 1) : zr->jpg_seq_num; - buffer->state = BUZ_STATE_DONE; - - zr->jpg_dma_tail++; - } -} - -static void zoran_restart(struct zoran *zr) -{ - /* Now the stat_comm buffer is ready for restart */ - unsigned int status = 0; - int mode; - - if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { - decoder_call(zr, video, g_input_status, &status); - mode = CODEC_DO_COMPRESSION; - } else { - status = V4L2_IN_ST_NO_SIGNAL; - mode = CODEC_DO_EXPANSION; - } - if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS || - !(status & V4L2_IN_ST_NO_SIGNAL)) { - /********** RESTART code *************/ - jpeg_codec_reset(zr); - zr->codec->set_mode(zr->codec, mode); - zr36057_set_jpg(zr, zr->codec_mode); - jpeg_start(zr); - - if (zr->num_errors <= 8) - dprintk(2, KERN_INFO "%s: Restart\n", - ZR_DEVNAME(zr)); - - zr->JPEG_missed = 0; - zr->JPEG_error = 2; - /********** End RESTART code ***********/ - } -} - -static void -error_handler (struct zoran *zr, - u32 astat, - u32 stat) -{ - int i; - - /* This is JPEG error handling part */ - if (zr->codec_mode != BUZ_MODE_MOTION_COMPRESS && - zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS) { - return; - } - - if ((stat & 1) == 0 && - zr->codec_mode == BUZ_MODE_MOTION_COMPRESS && - zr->jpg_dma_tail - zr->jpg_que_tail >= zr->jpg_buffers.num_buffers) { - /* No free buffers... */ - zoran_reap_stat_com(zr); - zoran_feed_stat_com(zr); - wake_up_interruptible(&zr->jpg_capq); - zr->JPEG_missed = 0; - return; - } - - if (zr->JPEG_error == 1) { - zoran_restart(zr); - return; - } - - /* - * First entry: error just happened during normal operation - * - * In BUZ_MODE_MOTION_COMPRESS: - * - * Possible glitch in TV signal. In this case we should - * stop the codec and wait for good quality signal before - * restarting it to avoid further problems - * - * In BUZ_MODE_MOTION_DECOMPRESS: - * - * Bad JPEG frame: we have to mark it as processed (codec crashed - * and was not able to do it itself), and to remove it from queue. - */ - btand(~ZR36057_JMC_Go_en, ZR36057_JMC); - udelay(1); - stat = stat | (post_office_read(zr, 7, 0) & 3) << 8; - btwrite(0, ZR36057_JPC); - btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR); - jpeg_codec_reset(zr); - jpeg_codec_sleep(zr, 1); - zr->JPEG_error = 1; - zr->num_errors++; - - /* Report error */ - if (zr36067_debug > 1 && zr->num_errors <= 8) { - long frame; - int j; - - frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME]; - printk(KERN_ERR - "%s: JPEG error stat=0x%08x(0x%08x) queue_state=%ld/%ld/%ld/%ld seq=%ld frame=%ld. Codec stopped. ", - ZR_DEVNAME(zr), stat, zr->last_isr, - zr->jpg_que_tail, zr->jpg_dma_tail, - zr->jpg_dma_head, zr->jpg_que_head, - zr->jpg_seq_num, frame); - printk(KERN_INFO "stat_com frames:"); - for (j = 0; j < BUZ_NUM_STAT_COM; j++) { - for (i = 0; i < zr->jpg_buffers.num_buffers; i++) { - if (le32_to_cpu(zr->stat_com[j]) == zr->jpg_buffers.buffer[i].jpg.frag_tab_bus) - printk(KERN_CONT "% d->%d", j, i); - } - } - printk(KERN_CONT "\n"); - } - /* Find an entry in stat_com and rotate contents */ - if (zr->jpg_settings.TmpDcm == 1) - i = (zr->jpg_dma_tail - zr->jpg_err_shift) & BUZ_MASK_STAT_COM; - else - i = ((zr->jpg_dma_tail - zr->jpg_err_shift) & 1) * 2; - if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) { - /* Mimic zr36067 operation */ - zr->stat_com[i] |= cpu_to_le32(1); - if (zr->jpg_settings.TmpDcm != 1) - zr->stat_com[i + 1] |= cpu_to_le32(1); - /* Refill */ - zoran_reap_stat_com(zr); - zoran_feed_stat_com(zr); - wake_up_interruptible(&zr->jpg_capq); - /* Find an entry in stat_com again after refill */ - if (zr->jpg_settings.TmpDcm == 1) - i = (zr->jpg_dma_tail - zr->jpg_err_shift) & BUZ_MASK_STAT_COM; - else - i = ((zr->jpg_dma_tail - zr->jpg_err_shift) & 1) * 2; - } - if (i) { - /* Rotate stat_comm entries to make current entry first */ - int j; - __le32 bus_addr[BUZ_NUM_STAT_COM]; - - /* Here we are copying the stat_com array, which - * is already in little endian format, so - * no endian conversions here - */ - memcpy(bus_addr, zr->stat_com, sizeof(bus_addr)); - - for (j = 0; j < BUZ_NUM_STAT_COM; j++) - zr->stat_com[j] = bus_addr[(i + j) & BUZ_MASK_STAT_COM]; - - zr->jpg_err_shift += i; - zr->jpg_err_shift &= BUZ_MASK_STAT_COM; - } - if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) - zr->jpg_err_seq = zr->jpg_seq_num; /* + 1; */ - zoran_restart(zr); -} - -irqreturn_t -zoran_irq (int irq, - void *dev_id) -{ - u32 stat, astat; - int count; - struct zoran *zr; - unsigned long flags; - - zr = dev_id; - count = 0; - - if (zr->testing) { - /* Testing interrupts */ - spin_lock_irqsave(&zr->spinlock, flags); - while ((stat = count_reset_interrupt(zr))) { - if (count++ > 100) { - btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR); - dprintk(1, - KERN_ERR - "%s: IRQ lockup while testing, isr=0x%08x, cleared int mask\n", - ZR_DEVNAME(zr), stat); - wake_up_interruptible(&zr->test_q); - } - } - zr->last_isr = stat; - spin_unlock_irqrestore(&zr->spinlock, flags); - return IRQ_HANDLED; - } - - spin_lock_irqsave(&zr->spinlock, flags); - while (1) { - /* get/clear interrupt status bits */ - stat = count_reset_interrupt(zr); - astat = stat & IRQ_MASK; - if (!astat) { - break; - } - dprintk(4, - KERN_DEBUG - "zoran_irq: astat: 0x%08x, mask: 0x%08x\n", - astat, btread(ZR36057_ICR)); - if (astat & zr->card.vsync_int) { // SW - - if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS || - zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { - /* count missed interrupts */ - zr->JPEG_missed++; - } - //post_office_read(zr,1,0); - /* Interrupts may still happen when - * zr->v4l_memgrab_active is switched off. - * We simply ignore them */ - - if (zr->v4l_memgrab_active) { - /* A lot more checks should be here ... */ - if ((btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_SnapShot) == 0) - dprintk(1, - KERN_WARNING - "%s: BuzIRQ with SnapShot off ???\n", - ZR_DEVNAME(zr)); - - if (zr->v4l_grab_frame != NO_GRAB_ACTIVE) { - /* There is a grab on a frame going on, check if it has finished */ - if ((btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_FrameGrab) == 0) { - /* it is finished, notify the user */ - - zr->v4l_buffers.buffer[zr->v4l_grab_frame].state = BUZ_STATE_DONE; - zr->v4l_buffers.buffer[zr->v4l_grab_frame].bs.seq = zr->v4l_grab_seq; - zr->v4l_buffers.buffer[zr->v4l_grab_frame].bs.ts = ktime_get_ns(); - zr->v4l_grab_frame = NO_GRAB_ACTIVE; - zr->v4l_pend_tail++; - } - } - - if (zr->v4l_grab_frame == NO_GRAB_ACTIVE) - wake_up_interruptible(&zr->v4l_capq); - - /* Check if there is another grab queued */ - - if (zr->v4l_grab_frame == NO_GRAB_ACTIVE && - zr->v4l_pend_tail != zr->v4l_pend_head) { - int frame = zr->v4l_pend[zr->v4l_pend_tail & V4L_MASK_FRAME]; - u32 reg; - - zr->v4l_grab_frame = frame; - - /* Set zr36057 video front end and enable video */ - - /* Buffer address */ - - reg = zr->v4l_buffers.buffer[frame].v4l.fbuffer_bus; - btwrite(reg, ZR36057_VDTR); - if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2) - reg += zr->v4l_settings.bytesperline; - btwrite(reg, ZR36057_VDBR); - - /* video stride, status, and frame grab register */ - reg = 0; - if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2) - reg += zr->v4l_settings.bytesperline; - reg = (reg << ZR36057_VSSFGR_DispStride); - reg |= ZR36057_VSSFGR_VidOvf; - reg |= ZR36057_VSSFGR_SnapShot; - reg |= ZR36057_VSSFGR_FrameGrab; - btwrite(reg, ZR36057_VSSFGR); - - btor(ZR36057_VDCR_VidEn, - ZR36057_VDCR); - } - } - - /* even if we don't grab, we do want to increment - * the sequence counter to see lost frames */ - zr->v4l_grab_seq++; - } -#if (IRQ_MASK & ZR36057_ISR_CodRepIRQ) - if (astat & ZR36057_ISR_CodRepIRQ) { - zr->intr_counter_CodRepIRQ++; - IDEBUG(printk(KERN_DEBUG "%s: ZR36057_ISR_CodRepIRQ\n", - ZR_DEVNAME(zr))); - btand(~ZR36057_ICR_CodRepIRQ, ZR36057_ICR); - } -#endif /* (IRQ_MASK & ZR36057_ISR_CodRepIRQ) */ - -#if (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ) - if ((astat & ZR36057_ISR_JPEGRepIRQ) && - (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS || - zr->codec_mode == BUZ_MODE_MOTION_COMPRESS)) { - if (zr36067_debug > 1 && (!zr->frame_num || zr->JPEG_error)) { - char sv[BUZ_NUM_STAT_COM + 1]; - int i; - - printk(KERN_INFO - "%s: first frame ready: state=0x%08x odd_even=%d field_per_buff=%d delay=%d\n", - ZR_DEVNAME(zr), stat, - zr->jpg_settings.odd_even, - zr->jpg_settings.field_per_buff, - zr->JPEG_missed); - - for (i = 0; i < BUZ_NUM_STAT_COM; i++) - sv[i] = le32_to_cpu(zr->stat_com[i]) & 1 ? '1' : '0'; - sv[BUZ_NUM_STAT_COM] = 0; - printk(KERN_INFO - "%s: stat_com=%s queue_state=%ld/%ld/%ld/%ld\n", - ZR_DEVNAME(zr), sv, - zr->jpg_que_tail, - zr->jpg_dma_tail, - zr->jpg_dma_head, - zr->jpg_que_head); - } else { - /* Get statistics */ - if (zr->JPEG_missed > zr->JPEG_max_missed) - zr->JPEG_max_missed = zr->JPEG_missed; - if (zr->JPEG_missed < zr->JPEG_min_missed) - zr->JPEG_min_missed = zr->JPEG_missed; - } - - if (zr36067_debug > 2 && zr->frame_num < 6) { - int i; - - printk(KERN_INFO "%s: seq=%ld stat_com:", - ZR_DEVNAME(zr), zr->jpg_seq_num); - for (i = 0; i < 4; i++) { - printk(KERN_CONT " %08x", - le32_to_cpu(zr->stat_com[i])); - } - printk(KERN_CONT "\n"); - } - zr->frame_num++; - zr->JPEG_missed = 0; - zr->JPEG_error = 0; - zoran_reap_stat_com(zr); - zoran_feed_stat_com(zr); - wake_up_interruptible(&zr->jpg_capq); - } -#endif /* (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ) */ - - /* DATERR, too many fields missed, error processing */ - if ((astat & zr->card.jpeg_int) || - zr->JPEG_missed > 25 || - zr->JPEG_error == 1 || - ((zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) && - (zr->frame_num && (zr->JPEG_missed > zr->jpg_settings.field_per_buff)))) { - error_handler(zr, astat, stat); - } - - count++; - if (count > 10) { - dprintk(2, KERN_WARNING "%s: irq loop %d\n", - ZR_DEVNAME(zr), count); - if (count > 20) { - btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR); - dprintk(2, - KERN_ERR - "%s: IRQ lockup, cleared int mask\n", - ZR_DEVNAME(zr)); - break; - } - } - zr->last_isr = stat; - } - spin_unlock_irqrestore(&zr->spinlock, flags); - - return IRQ_HANDLED; -} - -void -zoran_set_pci_master (struct zoran *zr, - int set_master) -{ - if (set_master) { - pci_set_master(zr->pci_dev); - } else { - u16 command; - - pci_read_config_word(zr->pci_dev, PCI_COMMAND, &command); - command &= ~PCI_COMMAND_MASTER; - pci_write_config_word(zr->pci_dev, PCI_COMMAND, command); - } -} - -void -zoran_init_hardware (struct zoran *zr) -{ - /* Enable bus-mastering */ - zoran_set_pci_master(zr, 1); - - /* Initialize the board */ - if (zr->card.init) { - zr->card.init(zr); - } - - decoder_call(zr, core, init, 0); - decoder_call(zr, video, s_std, zr->norm); - decoder_call(zr, video, s_routing, - zr->card.input[zr->input].muxsel, 0, 0); - - encoder_call(zr, core, init, 0); - encoder_call(zr, video, s_std_output, zr->norm); - encoder_call(zr, video, s_routing, 0, 0, 0); - - /* toggle JPEG codec sleep to sync PLL */ - jpeg_codec_sleep(zr, 1); - jpeg_codec_sleep(zr, 0); - - /* - * set individual interrupt enables (without GIRQ1) - * but don't global enable until zoran_open() - */ - zr36057_init_vfe(zr); - - zr36057_enable_jpg(zr, BUZ_MODE_IDLE); - - btwrite(IRQ_MASK, ZR36057_ISR); // Clears interrupts -} - -void -zr36057_restart (struct zoran *zr) -{ - btwrite(0, ZR36057_SPGPPCR); - mdelay(1); - btor(ZR36057_SPGPPCR_SoftReset, ZR36057_SPGPPCR); - mdelay(1); - - /* assert P_Reset */ - btwrite(0, ZR36057_JPC); - /* set up GPIO direction - all output */ - btwrite(ZR36057_SPGPPCR_SoftReset | 0, ZR36057_SPGPPCR); - - /* set up GPIO pins and guest bus timing */ - btwrite((0x81 << 24) | 0x8888, ZR36057_GPPGCR1); -} - -/* - * initialize video front end - */ - -static void -zr36057_init_vfe (struct zoran *zr) -{ - u32 reg; - - reg = btread(ZR36057_VFESPFR); - reg |= ZR36057_VFESPFR_LittleEndian; - reg &= ~ZR36057_VFESPFR_VCLKPol; - reg |= ZR36057_VFESPFR_ExtFl; - reg |= ZR36057_VFESPFR_TopField; - btwrite(reg, ZR36057_VFESPFR); - reg = btread(ZR36057_VDCR); - if (pci_pci_problems & PCIPCI_TRITON) - // || zr->revision < 1) // Revision 1 has also Triton support - reg &= ~ZR36057_VDCR_Triton; - else - reg |= ZR36057_VDCR_Triton; - btwrite(reg, ZR36057_VDCR); -} diff --git a/drivers/staging/media/zoran/zoran_device.h b/drivers/staging/media/zoran/zoran_device.h deleted file mode 100644 index a507aaad4ebb..000000000000 --- a/drivers/staging/media/zoran/zoran_device.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Zoran zr36057/zr36067 PCI controller driver, for the - * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux - * Media Labs LML33/LML33R10. - * - * This part handles card-specific data and detection - * - * Copyright (C) 2000 Serguei Miridonov - * - * Currently maintained by: - * Ronald Bultje - * Laurent Pinchart - * Mailinglist - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __ZORAN_DEVICE_H__ -#define __ZORAN_DEVICE_H__ - -/* general purpose I/O */ -extern void GPIO(struct zoran *zr, - int bit, - unsigned int value); - -/* codec (or actually: guest bus) access */ -extern int post_office_wait(struct zoran *zr); -extern int post_office_write(struct zoran *zr, - unsigned guest, - unsigned reg, - unsigned value); -extern int post_office_read(struct zoran *zr, - unsigned guest, - unsigned reg); - -extern void detect_guest_activity(struct zoran *zr); - -extern void jpeg_codec_sleep(struct zoran *zr, - int sleep); -extern int jpeg_codec_reset(struct zoran *zr); - -/* zr360x7 access to raw capture */ -extern void zr36057_overlay(struct zoran *zr, - int on); -extern void write_overlay_mask(struct zoran_fh *fh, - struct v4l2_clip *vp, - int count); -extern void zr36057_set_memgrab(struct zoran *zr, - int mode); -extern int wait_grab_pending(struct zoran *zr); - -/* interrupts */ -extern void print_interrupts(struct zoran *zr); -extern void clear_interrupt_counters(struct zoran *zr); -extern irqreturn_t zoran_irq(int irq, void *dev_id); - -/* JPEG codec access */ -extern void jpeg_start(struct zoran *zr); -extern void zr36057_enable_jpg(struct zoran *zr, - enum zoran_codec_mode mode); -extern void zoran_feed_stat_com(struct zoran *zr); - -/* general */ -extern void zoran_set_pci_master(struct zoran *zr, - int set_master); -extern void zoran_init_hardware(struct zoran *zr); -extern void zr36057_restart(struct zoran *zr); - -extern const struct zoran_format zoran_formats[]; - -extern int v4l_nbufs; -extern int v4l_bufsize; -extern int jpg_nbufs; -extern int jpg_bufsize; -extern int pass_through; - -/* i2c */ -#define decoder_call(zr, o, f, args...) \ - v4l2_subdev_call(zr->decoder, o, f, ##args) -#define encoder_call(zr, o, f, args...) \ - v4l2_subdev_call(zr->encoder, o, f, ##args) - -#endif /* __ZORAN_DEVICE_H__ */ diff --git a/drivers/staging/media/zoran/zoran_driver.c b/drivers/staging/media/zoran/zoran_driver.c deleted file mode 100644 index c998aa4dc73b..000000000000 --- a/drivers/staging/media/zoran/zoran_driver.c +++ /dev/null @@ -1,2850 +0,0 @@ -/* - * Zoran zr36057/zr36067 PCI controller driver, for the - * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux - * Media Labs LML33/LML33R10. - * - * Copyright (C) 2000 Serguei Miridonov - * - * Changes for BUZ by Wolfgang Scherr - * - * Changes for DC10/DC30 by Laurent Pinchart - * - * Changes for LML33R10 by Maxim Yevtyushkin - * - * Changes for videodev2/v4l2 by Ronald Bultje - * - * Based on - * - * Miro DC10 driver - * Copyright (C) 1999 Wolfgang Scherr - * - * Iomega Buz driver version 1.0 - * Copyright (C) 1999 Rainer Johanni - * - * buz.0.0.3 - * Copyright (C) 1998 Dave Perks - * - * bttv - Bt848 frame grabber driver - * Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - * & Marcus Metzler (mocm@thp.uni-koeln.de) - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include "videocodec.h" - -#include -#include -#include -#include - -#include -#include "zoran.h" -#include "zoran_device.h" -#include "zoran_card.h" - - -const struct zoran_format zoran_formats[] = { - { - .name = "15-bit RGB LE", - .fourcc = V4L2_PIX_FMT_RGB555, - .colorspace = V4L2_COLORSPACE_SRGB, - .depth = 15, - .flags = ZORAN_FORMAT_CAPTURE | - ZORAN_FORMAT_OVERLAY, - .vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif| - ZR36057_VFESPFR_LittleEndian, - }, { - .name = "15-bit RGB BE", - .fourcc = V4L2_PIX_FMT_RGB555X, - .colorspace = V4L2_COLORSPACE_SRGB, - .depth = 15, - .flags = ZORAN_FORMAT_CAPTURE | - ZORAN_FORMAT_OVERLAY, - .vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif, - }, { - .name = "16-bit RGB LE", - .fourcc = V4L2_PIX_FMT_RGB565, - .colorspace = V4L2_COLORSPACE_SRGB, - .depth = 16, - .flags = ZORAN_FORMAT_CAPTURE | - ZORAN_FORMAT_OVERLAY, - .vfespfr = ZR36057_VFESPFR_RGB565|ZR36057_VFESPFR_ErrDif| - ZR36057_VFESPFR_LittleEndian, - }, { - .name = "16-bit RGB BE", - .fourcc = V4L2_PIX_FMT_RGB565X, - .colorspace = V4L2_COLORSPACE_SRGB, - .depth = 16, - .flags = ZORAN_FORMAT_CAPTURE | - ZORAN_FORMAT_OVERLAY, - .vfespfr = ZR36057_VFESPFR_RGB565|ZR36057_VFESPFR_ErrDif, - }, { - .name = "24-bit RGB", - .fourcc = V4L2_PIX_FMT_BGR24, - .colorspace = V4L2_COLORSPACE_SRGB, - .depth = 24, - .flags = ZORAN_FORMAT_CAPTURE | - ZORAN_FORMAT_OVERLAY, - .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_Pack24, - }, { - .name = "32-bit RGB LE", - .fourcc = V4L2_PIX_FMT_BGR32, - .colorspace = V4L2_COLORSPACE_SRGB, - .depth = 32, - .flags = ZORAN_FORMAT_CAPTURE | - ZORAN_FORMAT_OVERLAY, - .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_LittleEndian, - }, { - .name = "32-bit RGB BE", - .fourcc = V4L2_PIX_FMT_RGB32, - .colorspace = V4L2_COLORSPACE_SRGB, - .depth = 32, - .flags = ZORAN_FORMAT_CAPTURE | - ZORAN_FORMAT_OVERLAY, - .vfespfr = ZR36057_VFESPFR_RGB888, - }, { - .name = "4:2:2, packed, YUYV", - .fourcc = V4L2_PIX_FMT_YUYV, - .colorspace = V4L2_COLORSPACE_SMPTE170M, - .depth = 16, - .flags = ZORAN_FORMAT_CAPTURE | - ZORAN_FORMAT_OVERLAY, - .vfespfr = ZR36057_VFESPFR_YUV422, - }, { - .name = "4:2:2, packed, UYVY", - .fourcc = V4L2_PIX_FMT_UYVY, - .colorspace = V4L2_COLORSPACE_SMPTE170M, - .depth = 16, - .flags = ZORAN_FORMAT_CAPTURE | - ZORAN_FORMAT_OVERLAY, - .vfespfr = ZR36057_VFESPFR_YUV422|ZR36057_VFESPFR_LittleEndian, - }, { - .name = "Hardware-encoded Motion-JPEG", - .fourcc = V4L2_PIX_FMT_MJPEG, - .colorspace = V4L2_COLORSPACE_SMPTE170M, - .depth = 0, - .flags = ZORAN_FORMAT_CAPTURE | - ZORAN_FORMAT_PLAYBACK | - ZORAN_FORMAT_COMPRESSED, - } -}; -#define NUM_FORMATS ARRAY_SIZE(zoran_formats) - - /* small helper function for calculating buffersizes for v4l2 - * we calculate the nearest higher power-of-two, which - * will be the recommended buffersize */ -static __u32 -zoran_v4l2_calc_bufsize (struct zoran_jpg_settings *settings) -{ - __u8 div = settings->VerDcm * settings->HorDcm * settings->TmpDcm; - __u32 num = (1024 * 512) / (div); - __u32 result = 2; - - num--; - while (num) { - num >>= 1; - result <<= 1; - } - - if (result > jpg_bufsize) - return jpg_bufsize; - if (result < 8192) - return 8192; - return result; -} - -/* forward references */ -static void v4l_fbuffer_free(struct zoran_fh *fh); -static void jpg_fbuffer_free(struct zoran_fh *fh); - -/* Set mapping mode */ -static void map_mode_raw(struct zoran_fh *fh) -{ - fh->map_mode = ZORAN_MAP_MODE_RAW; - fh->buffers.buffer_size = v4l_bufsize; - fh->buffers.num_buffers = v4l_nbufs; -} -static void map_mode_jpg(struct zoran_fh *fh, int play) -{ - fh->map_mode = play ? ZORAN_MAP_MODE_JPG_PLAY : ZORAN_MAP_MODE_JPG_REC; - fh->buffers.buffer_size = jpg_bufsize; - fh->buffers.num_buffers = jpg_nbufs; -} -static inline const char *mode_name(enum zoran_map_mode mode) -{ - return mode == ZORAN_MAP_MODE_RAW ? "V4L" : "JPG"; -} - -/* - * Allocate the V4L grab buffers - * - * These have to be pysically contiguous. - */ - -static int v4l_fbuffer_alloc(struct zoran_fh *fh) -{ - struct zoran *zr = fh->zr; - int i, off; - unsigned char *mem; - - for (i = 0; i < fh->buffers.num_buffers; i++) { - if (fh->buffers.buffer[i].v4l.fbuffer) - dprintk(2, - KERN_WARNING - "%s: %s - buffer %d already allocated!?\n", - ZR_DEVNAME(zr), __func__, i); - - //udelay(20); - mem = kmalloc(fh->buffers.buffer_size, - GFP_KERNEL | __GFP_NOWARN); - if (!mem) { - dprintk(1, - KERN_ERR - "%s: %s - kmalloc for V4L buf %d failed\n", - ZR_DEVNAME(zr), __func__, i); - v4l_fbuffer_free(fh); - return -ENOBUFS; - } - fh->buffers.buffer[i].v4l.fbuffer = mem; - fh->buffers.buffer[i].v4l.fbuffer_phys = virt_to_phys(mem); - fh->buffers.buffer[i].v4l.fbuffer_bus = virt_to_bus(mem); - for (off = 0; off < fh->buffers.buffer_size; - off += PAGE_SIZE) - SetPageReserved(virt_to_page(mem + off)); - dprintk(4, - KERN_INFO - "%s: %s - V4L frame %d mem %p (bus: 0x%llx)\n", - ZR_DEVNAME(zr), __func__, i, mem, - (unsigned long long)virt_to_bus(mem)); - } - - fh->buffers.allocated = 1; - - return 0; -} - -/* free the V4L grab buffers */ -static void v4l_fbuffer_free(struct zoran_fh *fh) -{ - struct zoran *zr = fh->zr; - int i, off; - unsigned char *mem; - - dprintk(4, KERN_INFO "%s: %s\n", ZR_DEVNAME(zr), __func__); - - for (i = 0; i < fh->buffers.num_buffers; i++) { - if (!fh->buffers.buffer[i].v4l.fbuffer) - continue; - - mem = fh->buffers.buffer[i].v4l.fbuffer; - for (off = 0; off < fh->buffers.buffer_size; - off += PAGE_SIZE) - ClearPageReserved(virt_to_page(mem + off)); - kfree(fh->buffers.buffer[i].v4l.fbuffer); - fh->buffers.buffer[i].v4l.fbuffer = NULL; - } - - fh->buffers.allocated = 0; -} - -/* - * Allocate the MJPEG grab buffers. - * - * If a Natoma chipset is present and this is a revision 1 zr36057, - * each MJPEG buffer needs to be physically contiguous. - * (RJ: This statement is from Dave Perks' original driver, - * I could never check it because I have a zr36067) - * - * RJ: The contents grab buffers needs never be accessed in the driver. - * Therefore there is no need to allocate them with vmalloc in order - * to get a contiguous virtual memory space. - * I don't understand why many other drivers first allocate them with - * vmalloc (which uses internally also get_zeroed_page, but delivers you - * virtual addresses) and then again have to make a lot of efforts - * to get the physical address. - * - * Ben Capper: - * On big-endian architectures (such as ppc) some extra steps - * are needed. When reading and writing to the stat_com array - * and fragment buffers, the device expects to see little- - * endian values. The use of cpu_to_le32() and le32_to_cpu() - * in this function (and one or two others in zoran_device.c) - * ensure that these values are always stored in little-endian - * form, regardless of architecture. The zr36057 does Very Bad - * Things on big endian architectures if the stat_com array - * and fragment buffers are not little-endian. - */ - -static int jpg_fbuffer_alloc(struct zoran_fh *fh) -{ - struct zoran *zr = fh->zr; - int i, j, off; - u8 *mem; - - for (i = 0; i < fh->buffers.num_buffers; i++) { - if (fh->buffers.buffer[i].jpg.frag_tab) - dprintk(2, - KERN_WARNING - "%s: %s - buffer %d already allocated!?\n", - ZR_DEVNAME(zr), __func__, i); - - /* Allocate fragment table for this buffer */ - - mem = (void *)get_zeroed_page(GFP_KERNEL); - if (!mem) { - dprintk(1, - KERN_ERR - "%s: %s - get_zeroed_page (frag_tab) failed for buffer %d\n", - ZR_DEVNAME(zr), __func__, i); - jpg_fbuffer_free(fh); - return -ENOBUFS; - } - fh->buffers.buffer[i].jpg.frag_tab = (__le32 *)mem; - fh->buffers.buffer[i].jpg.frag_tab_bus = virt_to_bus(mem); - - if (fh->buffers.need_contiguous) { - mem = kmalloc(fh->buffers.buffer_size, GFP_KERNEL); - if (mem == NULL) { - dprintk(1, - KERN_ERR - "%s: %s - kmalloc failed for buffer %d\n", - ZR_DEVNAME(zr), __func__, i); - jpg_fbuffer_free(fh); - return -ENOBUFS; - } - fh->buffers.buffer[i].jpg.frag_tab[0] = - cpu_to_le32(virt_to_bus(mem)); - fh->buffers.buffer[i].jpg.frag_tab[1] = - cpu_to_le32((fh->buffers.buffer_size >> 1) | 1); - for (off = 0; off < fh->buffers.buffer_size; off += PAGE_SIZE) - SetPageReserved(virt_to_page(mem + off)); - } else { - /* jpg_bufsize is already page aligned */ - for (j = 0; j < fh->buffers.buffer_size / PAGE_SIZE; j++) { - mem = (void *)get_zeroed_page(GFP_KERNEL); - if (mem == NULL) { - dprintk(1, - KERN_ERR - "%s: %s - get_zeroed_page failed for buffer %d\n", - ZR_DEVNAME(zr), __func__, i); - jpg_fbuffer_free(fh); - return -ENOBUFS; - } - - fh->buffers.buffer[i].jpg.frag_tab[2 * j] = - cpu_to_le32(virt_to_bus(mem)); - fh->buffers.buffer[i].jpg.frag_tab[2 * j + 1] = - cpu_to_le32((PAGE_SIZE >> 2) << 1); - SetPageReserved(virt_to_page(mem)); - } - - fh->buffers.buffer[i].jpg.frag_tab[2 * j - 1] |= cpu_to_le32(1); - } - } - - dprintk(4, - KERN_DEBUG "%s: %s - %d KB allocated\n", - ZR_DEVNAME(zr), __func__, - (fh->buffers.num_buffers * fh->buffers.buffer_size) >> 10); - - fh->buffers.allocated = 1; - - return 0; -} - -/* free the MJPEG grab buffers */ -static void jpg_fbuffer_free(struct zoran_fh *fh) -{ - struct zoran *zr = fh->zr; - int i, j, off; - unsigned char *mem; - __le32 frag_tab; - struct zoran_buffer *buffer; - - dprintk(4, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__); - - for (i = 0, buffer = &fh->buffers.buffer[0]; - i < fh->buffers.num_buffers; i++, buffer++) { - if (!buffer->jpg.frag_tab) - continue; - - if (fh->buffers.need_contiguous) { - frag_tab = buffer->jpg.frag_tab[0]; - - if (frag_tab) { - mem = bus_to_virt(le32_to_cpu(frag_tab)); - for (off = 0; off < fh->buffers.buffer_size; off += PAGE_SIZE) - ClearPageReserved(virt_to_page(mem + off)); - kfree(mem); - buffer->jpg.frag_tab[0] = 0; - buffer->jpg.frag_tab[1] = 0; - } - } else { - for (j = 0; j < fh->buffers.buffer_size / PAGE_SIZE; j++) { - frag_tab = buffer->jpg.frag_tab[2 * j]; - - if (!frag_tab) - break; - ClearPageReserved(virt_to_page(bus_to_virt(le32_to_cpu(frag_tab)))); - free_page((unsigned long)bus_to_virt(le32_to_cpu(frag_tab))); - buffer->jpg.frag_tab[2 * j] = 0; - buffer->jpg.frag_tab[2 * j + 1] = 0; - } - } - - free_page((unsigned long)buffer->jpg.frag_tab); - buffer->jpg.frag_tab = NULL; - } - - fh->buffers.allocated = 0; -} - -/* - * V4L Buffer grabbing - */ - -static int -zoran_v4l_set_format (struct zoran_fh *fh, - int width, - int height, - const struct zoran_format *format) -{ - struct zoran *zr = fh->zr; - int bpp; - - /* Check size and format of the grab wanted */ - - if (height < BUZ_MIN_HEIGHT || width < BUZ_MIN_WIDTH || - height > BUZ_MAX_HEIGHT || width > BUZ_MAX_WIDTH) { - dprintk(1, - KERN_ERR - "%s: %s - wrong frame size (%dx%d)\n", - ZR_DEVNAME(zr), __func__, width, height); - return -EINVAL; - } - - bpp = (format->depth + 7) / 8; - - /* Check against available buffer size */ - if (height * width * bpp > fh->buffers.buffer_size) { - dprintk(1, - KERN_ERR - "%s: %s - video buffer size (%d kB) is too small\n", - ZR_DEVNAME(zr), __func__, fh->buffers.buffer_size >> 10); - return -EINVAL; - } - - /* The video front end needs 4-byte alinged line sizes */ - - if ((bpp == 2 && (width & 1)) || (bpp == 3 && (width & 3))) { - dprintk(1, - KERN_ERR - "%s: %s - wrong frame alignment\n", - ZR_DEVNAME(zr), __func__); - return -EINVAL; - } - - fh->v4l_settings.width = width; - fh->v4l_settings.height = height; - fh->v4l_settings.format = format; - fh->v4l_settings.bytesperline = bpp * fh->v4l_settings.width; - - return 0; -} - -static int zoran_v4l_queue_frame(struct zoran_fh *fh, int num) -{ - struct zoran *zr = fh->zr; - unsigned long flags; - int res = 0; - - if (!fh->buffers.allocated) { - dprintk(1, - KERN_ERR - "%s: %s - buffers not yet allocated\n", - ZR_DEVNAME(zr), __func__); - res = -ENOMEM; - } - - /* No grabbing outside the buffer range! */ - if (num >= fh->buffers.num_buffers || num < 0) { - dprintk(1, - KERN_ERR - "%s: %s - buffer %d is out of range\n", - ZR_DEVNAME(zr), __func__, num); - res = -EINVAL; - } - - spin_lock_irqsave(&zr->spinlock, flags); - - if (fh->buffers.active == ZORAN_FREE) { - if (zr->v4l_buffers.active == ZORAN_FREE) { - zr->v4l_buffers = fh->buffers; - fh->buffers.active = ZORAN_ACTIVE; - } else { - dprintk(1, - KERN_ERR - "%s: %s - another session is already capturing\n", - ZR_DEVNAME(zr), __func__); - res = -EBUSY; - } - } - - /* make sure a grab isn't going on currently with this buffer */ - if (!res) { - switch (zr->v4l_buffers.buffer[num].state) { - default: - case BUZ_STATE_PEND: - if (zr->v4l_buffers.active == ZORAN_FREE) { - fh->buffers.active = ZORAN_FREE; - zr->v4l_buffers.allocated = 0; - } - res = -EBUSY; /* what are you doing? */ - break; - case BUZ_STATE_DONE: - dprintk(2, - KERN_WARNING - "%s: %s - queueing buffer %d in state DONE!?\n", - ZR_DEVNAME(zr), __func__, num); - /* fall through */ - case BUZ_STATE_USER: - /* since there is at least one unused buffer there's room for at least - * one more pend[] entry */ - zr->v4l_pend[zr->v4l_pend_head++ & V4L_MASK_FRAME] = num; - zr->v4l_buffers.buffer[num].state = BUZ_STATE_PEND; - zr->v4l_buffers.buffer[num].bs.length = - fh->v4l_settings.bytesperline * - zr->v4l_settings.height; - fh->buffers.buffer[num] = zr->v4l_buffers.buffer[num]; - break; - } - } - - spin_unlock_irqrestore(&zr->spinlock, flags); - - if (!res && zr->v4l_buffers.active == ZORAN_FREE) - zr->v4l_buffers.active = fh->buffers.active; - - return res; -} - -/* - * Sync on a V4L buffer - */ - -static int v4l_sync(struct zoran_fh *fh, int frame) -{ - struct zoran *zr = fh->zr; - unsigned long flags; - - if (fh->buffers.active == ZORAN_FREE) { - dprintk(1, - KERN_ERR - "%s: %s - no grab active for this session\n", - ZR_DEVNAME(zr), __func__); - return -EINVAL; - } - - /* check passed-in frame number */ - if (frame >= fh->buffers.num_buffers || frame < 0) { - dprintk(1, - KERN_ERR "%s: %s - frame %d is invalid\n", - ZR_DEVNAME(zr), __func__, frame); - return -EINVAL; - } - - /* Check if is buffer was queued at all */ - if (zr->v4l_buffers.buffer[frame].state == BUZ_STATE_USER) { - dprintk(1, - KERN_ERR - "%s: %s - attempt to sync on a buffer which was not queued?\n", - ZR_DEVNAME(zr), __func__); - return -EPROTO; - } - - mutex_unlock(&zr->lock); - /* wait on this buffer to get ready */ - if (!wait_event_interruptible_timeout(zr->v4l_capq, - (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_PEND), 10*HZ)) { - mutex_lock(&zr->lock); - return -ETIME; - } - mutex_lock(&zr->lock); - if (signal_pending(current)) - return -ERESTARTSYS; - - /* buffer should now be in BUZ_STATE_DONE */ - if (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_DONE) - dprintk(2, - KERN_ERR "%s: %s - internal state error\n", - ZR_DEVNAME(zr), __func__); - - zr->v4l_buffers.buffer[frame].state = BUZ_STATE_USER; - fh->buffers.buffer[frame] = zr->v4l_buffers.buffer[frame]; - - spin_lock_irqsave(&zr->spinlock, flags); - - /* Check if streaming capture has finished */ - if (zr->v4l_pend_tail == zr->v4l_pend_head) { - zr36057_set_memgrab(zr, 0); - if (zr->v4l_buffers.active == ZORAN_ACTIVE) { - fh->buffers.active = zr->v4l_buffers.active = ZORAN_FREE; - zr->v4l_buffers.allocated = 0; - } - } - - spin_unlock_irqrestore(&zr->spinlock, flags); - - return 0; -} - -/* - * Queue a MJPEG buffer for capture/playback - */ - -static int zoran_jpg_queue_frame(struct zoran_fh *fh, int num, - enum zoran_codec_mode mode) -{ - struct zoran *zr = fh->zr; - unsigned long flags; - int res = 0; - - /* Check if buffers are allocated */ - if (!fh->buffers.allocated) { - dprintk(1, - KERN_ERR - "%s: %s - buffers not yet allocated\n", - ZR_DEVNAME(zr), __func__); - return -ENOMEM; - } - - /* No grabbing outside the buffer range! */ - if (num >= fh->buffers.num_buffers || num < 0) { - dprintk(1, - KERN_ERR - "%s: %s - buffer %d out of range\n", - ZR_DEVNAME(zr), __func__, num); - return -EINVAL; - } - - /* what is the codec mode right now? */ - if (zr->codec_mode == BUZ_MODE_IDLE) { - zr->jpg_settings = fh->jpg_settings; - } else if (zr->codec_mode != mode) { - /* wrong codec mode active - invalid */ - dprintk(1, - KERN_ERR - "%s: %s - codec in wrong mode\n", - ZR_DEVNAME(zr), __func__); - return -EINVAL; - } - - if (fh->buffers.active == ZORAN_FREE) { - if (zr->jpg_buffers.active == ZORAN_FREE) { - zr->jpg_buffers = fh->buffers; - fh->buffers.active = ZORAN_ACTIVE; - } else { - dprintk(1, - KERN_ERR - "%s: %s - another session is already capturing\n", - ZR_DEVNAME(zr), __func__); - res = -EBUSY; - } - } - - if (!res && zr->codec_mode == BUZ_MODE_IDLE) { - /* Ok load up the jpeg codec */ - zr36057_enable_jpg(zr, mode); - } - - spin_lock_irqsave(&zr->spinlock, flags); - - if (!res) { - switch (zr->jpg_buffers.buffer[num].state) { - case BUZ_STATE_DONE: - dprintk(2, - KERN_WARNING - "%s: %s - queuing frame in BUZ_STATE_DONE state!?\n", - ZR_DEVNAME(zr), __func__); - /* fall through */ - case BUZ_STATE_USER: - /* since there is at least one unused buffer there's room for at - *least one more pend[] entry */ - zr->jpg_pend[zr->jpg_que_head++ & BUZ_MASK_FRAME] = num; - zr->jpg_buffers.buffer[num].state = BUZ_STATE_PEND; - fh->buffers.buffer[num] = zr->jpg_buffers.buffer[num]; - zoran_feed_stat_com(zr); - break; - default: - case BUZ_STATE_DMA: - case BUZ_STATE_PEND: - if (zr->jpg_buffers.active == ZORAN_FREE) { - fh->buffers.active = ZORAN_FREE; - zr->jpg_buffers.allocated = 0; - } - res = -EBUSY; /* what are you doing? */ - break; - } - } - - spin_unlock_irqrestore(&zr->spinlock, flags); - - if (!res && zr->jpg_buffers.active == ZORAN_FREE) - zr->jpg_buffers.active = fh->buffers.active; - - return res; -} - -static int jpg_qbuf(struct zoran_fh *fh, int frame, enum zoran_codec_mode mode) -{ - struct zoran *zr = fh->zr; - int res = 0; - - /* Does the user want to stop streaming? */ - if (frame < 0) { - if (zr->codec_mode == mode) { - if (fh->buffers.active == ZORAN_FREE) { - dprintk(1, - KERN_ERR - "%s: %s(-1) - session not active\n", - ZR_DEVNAME(zr), __func__); - return -EINVAL; - } - fh->buffers.active = zr->jpg_buffers.active = ZORAN_FREE; - zr->jpg_buffers.allocated = 0; - zr36057_enable_jpg(zr, BUZ_MODE_IDLE); - return 0; - } else { - dprintk(1, - KERN_ERR - "%s: %s - stop streaming but not in streaming mode\n", - ZR_DEVNAME(zr), __func__); - return -EINVAL; - } - } - - if ((res = zoran_jpg_queue_frame(fh, frame, mode))) - return res; - - /* Start the jpeg codec when the first frame is queued */ - if (!res && zr->jpg_que_head == 1) - jpeg_start(zr); - - return res; -} - -/* - * Sync on a MJPEG buffer - */ - -static int jpg_sync(struct zoran_fh *fh, struct zoran_sync *bs) -{ - struct zoran *zr = fh->zr; - unsigned long flags; - int frame; - - if (fh->buffers.active == ZORAN_FREE) { - dprintk(1, - KERN_ERR - "%s: %s - capture is not currently active\n", - ZR_DEVNAME(zr), __func__); - return -EINVAL; - } - if (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS && - zr->codec_mode != BUZ_MODE_MOTION_COMPRESS) { - dprintk(1, - KERN_ERR - "%s: %s - codec not in streaming mode\n", - ZR_DEVNAME(zr), __func__); - return -EINVAL; - } - mutex_unlock(&zr->lock); - if (!wait_event_interruptible_timeout(zr->jpg_capq, - (zr->jpg_que_tail != zr->jpg_dma_tail || - zr->jpg_dma_tail == zr->jpg_dma_head), - 10*HZ)) { - int isr; - - btand(~ZR36057_JMC_Go_en, ZR36057_JMC); - udelay(1); - zr->codec->control(zr->codec, CODEC_G_STATUS, - sizeof(isr), &isr); - mutex_lock(&zr->lock); - dprintk(1, - KERN_ERR - "%s: %s - timeout: codec isr=0x%02x\n", - ZR_DEVNAME(zr), __func__, isr); - - return -ETIME; - - } - mutex_lock(&zr->lock); - if (signal_pending(current)) - return -ERESTARTSYS; - - spin_lock_irqsave(&zr->spinlock, flags); - - if (zr->jpg_dma_tail != zr->jpg_dma_head) - frame = zr->jpg_pend[zr->jpg_que_tail++ & BUZ_MASK_FRAME]; - else - frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME]; - - /* buffer should now be in BUZ_STATE_DONE */ - if (zr->jpg_buffers.buffer[frame].state != BUZ_STATE_DONE) - dprintk(2, - KERN_ERR "%s: %s - internal state error\n", - ZR_DEVNAME(zr), __func__); - - *bs = zr->jpg_buffers.buffer[frame].bs; - bs->frame = frame; - zr->jpg_buffers.buffer[frame].state = BUZ_STATE_USER; - fh->buffers.buffer[frame] = zr->jpg_buffers.buffer[frame]; - - spin_unlock_irqrestore(&zr->spinlock, flags); - - return 0; -} - -static void zoran_open_init_session(struct zoran_fh *fh) -{ - int i; - struct zoran *zr = fh->zr; - - /* Per default, map the V4L Buffers */ - map_mode_raw(fh); - - /* take over the card's current settings */ - fh->overlay_settings = zr->overlay_settings; - fh->overlay_settings.is_set = 0; - fh->overlay_settings.format = zr->overlay_settings.format; - fh->overlay_active = ZORAN_FREE; - - /* v4l settings */ - fh->v4l_settings = zr->v4l_settings; - /* jpg settings */ - fh->jpg_settings = zr->jpg_settings; - - /* buffers */ - memset(&fh->buffers, 0, sizeof(fh->buffers)); - for (i = 0; i < MAX_FRAME; i++) { - fh->buffers.buffer[i].state = BUZ_STATE_USER; /* nothing going on */ - fh->buffers.buffer[i].bs.frame = i; - } - fh->buffers.allocated = 0; - fh->buffers.active = ZORAN_FREE; -} - -static void zoran_close_end_session(struct zoran_fh *fh) -{ - struct zoran *zr = fh->zr; - - /* overlay */ - if (fh->overlay_active != ZORAN_FREE) { - fh->overlay_active = zr->overlay_active = ZORAN_FREE; - zr->v4l_overlay_active = 0; - if (!zr->v4l_memgrab_active) - zr36057_overlay(zr, 0); - zr->overlay_mask = NULL; - } - - if (fh->map_mode == ZORAN_MAP_MODE_RAW) { - /* v4l capture */ - if (fh->buffers.active != ZORAN_FREE) { - unsigned long flags; - - spin_lock_irqsave(&zr->spinlock, flags); - zr36057_set_memgrab(zr, 0); - zr->v4l_buffers.allocated = 0; - zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE; - spin_unlock_irqrestore(&zr->spinlock, flags); - } - - /* v4l buffers */ - if (fh->buffers.allocated) - v4l_fbuffer_free(fh); - } else { - /* jpg capture */ - if (fh->buffers.active != ZORAN_FREE) { - zr36057_enable_jpg(zr, BUZ_MODE_IDLE); - zr->jpg_buffers.allocated = 0; - zr->jpg_buffers.active = fh->buffers.active = ZORAN_FREE; - } - - /* jpg buffers */ - if (fh->buffers.allocated) - jpg_fbuffer_free(fh); - } -} - -/* - * Open a zoran card. Right now the flags stuff is just playing - */ - -static int zoran_open(struct file *file) -{ - struct zoran *zr = video_drvdata(file); - struct zoran_fh *fh; - int res, first_open = 0; - - dprintk(2, KERN_INFO "%s: %s(%s, pid=[%d]), users(-)=%d\n", - ZR_DEVNAME(zr), __func__, current->comm, task_pid_nr(current), zr->user + 1); - - mutex_lock(&zr->lock); - - if (zr->user >= 2048) { - dprintk(1, KERN_ERR "%s: too many users (%d) on device\n", - ZR_DEVNAME(zr), zr->user); - res = -EBUSY; - goto fail_unlock; - } - - /* now, create the open()-specific file_ops struct */ - fh = kzalloc(sizeof(struct zoran_fh), GFP_KERNEL); - if (!fh) { - dprintk(1, - KERN_ERR - "%s: %s - allocation of zoran_fh failed\n", - ZR_DEVNAME(zr), __func__); - res = -ENOMEM; - goto fail_unlock; - } - v4l2_fh_init(&fh->fh, video_devdata(file)); - - /* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows - * on norm-change! */ - fh->overlay_mask = - kmalloc(array3_size((768 + 31) / 32, 576, 4), GFP_KERNEL); - if (!fh->overlay_mask) { - dprintk(1, - KERN_ERR - "%s: %s - allocation of overlay_mask failed\n", - ZR_DEVNAME(zr), __func__); - res = -ENOMEM; - goto fail_fh; - } - - if (zr->user++ == 0) - first_open = 1; - - /* default setup - TODO: look at flags */ - if (first_open) { /* First device open */ - zr36057_restart(zr); - zoran_open_init_params(zr); - zoran_init_hardware(zr); - - btor(ZR36057_ICR_IntPinEn, ZR36057_ICR); - } - - /* set file_ops stuff */ - file->private_data = fh; - fh->zr = zr; - zoran_open_init_session(fh); - v4l2_fh_add(&fh->fh); - mutex_unlock(&zr->lock); - - return 0; - -fail_fh: - v4l2_fh_exit(&fh->fh); - kfree(fh); -fail_unlock: - mutex_unlock(&zr->lock); - - dprintk(2, KERN_INFO "%s: open failed (%d), users(-)=%d\n", - ZR_DEVNAME(zr), res, zr->user); - - return res; -} - -static int -zoran_close(struct file *file) -{ - struct zoran_fh *fh = file->private_data; - struct zoran *zr = fh->zr; - - dprintk(2, KERN_INFO "%s: %s(%s, pid=[%d]), users(+)=%d\n", - ZR_DEVNAME(zr), __func__, current->comm, task_pid_nr(current), zr->user - 1); - - /* kernel locks (fs/device.c), so don't do that ourselves - * (prevents deadlocks) */ - mutex_lock(&zr->lock); - - zoran_close_end_session(fh); - - if (zr->user-- == 1) { /* Last process */ - /* Clean up JPEG process */ - wake_up_interruptible(&zr->jpg_capq); - zr36057_enable_jpg(zr, BUZ_MODE_IDLE); - zr->jpg_buffers.allocated = 0; - zr->jpg_buffers.active = ZORAN_FREE; - - /* disable interrupts */ - btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR); - - if (zr36067_debug > 1) - print_interrupts(zr); - - /* Overlay off */ - zr->v4l_overlay_active = 0; - zr36057_overlay(zr, 0); - zr->overlay_mask = NULL; - - /* capture off */ - wake_up_interruptible(&zr->v4l_capq); - zr36057_set_memgrab(zr, 0); - zr->v4l_buffers.allocated = 0; - zr->v4l_buffers.active = ZORAN_FREE; - zoran_set_pci_master(zr, 0); - - if (!pass_through) { /* Switch to color bar */ - decoder_call(zr, video, s_stream, 0); - encoder_call(zr, video, s_routing, 2, 0, 0); - } - } - mutex_unlock(&zr->lock); - - v4l2_fh_del(&fh->fh); - v4l2_fh_exit(&fh->fh); - kfree(fh->overlay_mask); - kfree(fh); - - dprintk(4, KERN_INFO "%s: %s done\n", ZR_DEVNAME(zr), __func__); - - return 0; -} - -static int setup_fbuffer(struct zoran_fh *fh, - void *base, - const struct zoran_format *fmt, - int width, - int height, - int bytesperline) -{ - struct zoran *zr = fh->zr; - - /* (Ronald) v4l/v4l2 guidelines */ - if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO)) - return -EPERM; - - /* Don't allow frame buffer overlay if PCI or AGP is buggy, or on - ALi Magik (that needs very low latency while the card needs a - higher value always) */ - - if (pci_pci_problems & (PCIPCI_FAIL | PCIAGP_FAIL | PCIPCI_ALIMAGIK)) - return -ENXIO; - - /* we need a bytesperline value, even if not given */ - if (!bytesperline) - bytesperline = width * ((fmt->depth + 7) & ~7) / 8; - -#if 0 - if (zr->overlay_active) { - /* dzjee... stupid users... don't even bother to turn off - * overlay before changing the memory location... - * normally, we would return errors here. However, one of - * the tools that does this is... xawtv! and since xawtv - * is used by +/- 99% of the users, we'd rather be user- - * friendly and silently do as if nothing went wrong */ - dprintk(3, - KERN_ERR - "%s: %s - forced overlay turnoff because framebuffer changed\n", - ZR_DEVNAME(zr), __func__); - zr36057_overlay(zr, 0); - } -#endif - - if (!(fmt->flags & ZORAN_FORMAT_OVERLAY)) { - dprintk(1, - KERN_ERR - "%s: %s - no valid overlay format given\n", - ZR_DEVNAME(zr), __func__); - return -EINVAL; - } - if (height <= 0 || width <= 0 || bytesperline <= 0) { - dprintk(1, - KERN_ERR - "%s: %s - invalid height/width/bpl value (%d|%d|%d)\n", - ZR_DEVNAME(zr), __func__, width, height, bytesperline); - return -EINVAL; - } - if (bytesperline & 3) { - dprintk(1, - KERN_ERR - "%s: %s - bytesperline (%d) must be 4-byte aligned\n", - ZR_DEVNAME(zr), __func__, bytesperline); - return -EINVAL; - } - - zr->vbuf_base = (void *) ((unsigned long) base & ~3); - zr->vbuf_height = height; - zr->vbuf_width = width; - zr->vbuf_depth = fmt->depth; - zr->overlay_settings.format = fmt; - zr->vbuf_bytesperline = bytesperline; - - /* The user should set new window parameters */ - zr->overlay_settings.is_set = 0; - - return 0; -} - - -static int setup_window(struct zoran_fh *fh, - int x, - int y, - int width, - int height, - struct v4l2_clip __user *clips, - unsigned int clipcount, - void __user *bitmap) -{ - struct zoran *zr = fh->zr; - struct v4l2_clip *vcp = NULL; - int on, end; - - - if (!zr->vbuf_base) { - dprintk(1, - KERN_ERR - "%s: %s - frame buffer has to be set first\n", - ZR_DEVNAME(zr), __func__); - return -EINVAL; - } - - if (!fh->overlay_settings.format) { - dprintk(1, - KERN_ERR - "%s: %s - no overlay format set\n", - ZR_DEVNAME(zr), __func__); - return -EINVAL; - } - - if (clipcount > 2048) { - dprintk(1, - KERN_ERR - "%s: %s - invalid clipcount\n", - ZR_DEVNAME(zr), __func__); - return -EINVAL; - } - - /* - * The video front end needs 4-byte alinged line sizes, we correct that - * silently here if necessary - */ - if (zr->vbuf_depth == 15 || zr->vbuf_depth == 16) { - end = (x + width) & ~1; /* round down */ - x = (x + 1) & ~1; /* round up */ - width = end - x; - } - - if (zr->vbuf_depth == 24) { - end = (x + width) & ~3; /* round down */ - x = (x + 3) & ~3; /* round up */ - width = end - x; - } - - if (width > BUZ_MAX_WIDTH) - width = BUZ_MAX_WIDTH; - if (height > BUZ_MAX_HEIGHT) - height = BUZ_MAX_HEIGHT; - - /* Check for invalid parameters */ - if (width < BUZ_MIN_WIDTH || height < BUZ_MIN_HEIGHT || - width > BUZ_MAX_WIDTH || height > BUZ_MAX_HEIGHT) { - dprintk(1, - KERN_ERR - "%s: %s - width = %d or height = %d invalid\n", - ZR_DEVNAME(zr), __func__, width, height); - return -EINVAL; - } - - fh->overlay_settings.x = x; - fh->overlay_settings.y = y; - fh->overlay_settings.width = width; - fh->overlay_settings.height = height; - fh->overlay_settings.clipcount = clipcount; - - /* - * If an overlay is running, we have to switch it off - * and switch it on again in order to get the new settings in effect. - * - * We also want to avoid that the overlay mask is written - * when an overlay is running. - */ - - on = zr->v4l_overlay_active && !zr->v4l_memgrab_active && - zr->overlay_active != ZORAN_FREE && - fh->overlay_active != ZORAN_FREE; - if (on) - zr36057_overlay(zr, 0); - - /* - * Write the overlay mask if clips are wanted. - * We prefer a bitmap. - */ - if (bitmap) { - /* fake value - it just means we want clips */ - fh->overlay_settings.clipcount = 1; - - if (copy_from_user(fh->overlay_mask, bitmap, - (width * height + 7) / 8)) { - return -EFAULT; - } - } else if (clipcount) { - /* write our own bitmap from the clips */ - vcp = vmalloc(array_size(sizeof(struct v4l2_clip), - clipcount + 4)); - if (vcp == NULL) { - dprintk(1, - KERN_ERR - "%s: %s - Alloc of clip mask failed\n", - ZR_DEVNAME(zr), __func__); - return -ENOMEM; - } - if (copy_from_user - (vcp, clips, sizeof(struct v4l2_clip) * clipcount)) { - vfree(vcp); - return -EFAULT; - } - write_overlay_mask(fh, vcp, clipcount); - vfree(vcp); - } - - fh->overlay_settings.is_set = 1; - if (fh->overlay_active != ZORAN_FREE && - zr->overlay_active != ZORAN_FREE) - zr->overlay_settings = fh->overlay_settings; - - if (on) - zr36057_overlay(zr, 1); - - /* Make sure the changes come into effect */ - return wait_grab_pending(zr); -} - -static int setup_overlay(struct zoran_fh *fh, int on) -{ - struct zoran *zr = fh->zr; - - /* If there is nothing to do, return immediately */ - if ((on && fh->overlay_active != ZORAN_FREE) || - (!on && fh->overlay_active == ZORAN_FREE)) - return 0; - - /* check whether we're touching someone else's overlay */ - if (on && zr->overlay_active != ZORAN_FREE && - fh->overlay_active == ZORAN_FREE) { - dprintk(1, - KERN_ERR - "%s: %s - overlay is already active for another session\n", - ZR_DEVNAME(zr), __func__); - return -EBUSY; - } - if (!on && zr->overlay_active != ZORAN_FREE && - fh->overlay_active == ZORAN_FREE) { - dprintk(1, - KERN_ERR - "%s: %s - you cannot cancel someone else's session\n", - ZR_DEVNAME(zr), __func__); - return -EPERM; - } - - if (on == 0) { - zr->overlay_active = fh->overlay_active = ZORAN_FREE; - zr->v4l_overlay_active = 0; - /* When a grab is running, the video simply - * won't be switched on any more */ - if (!zr->v4l_memgrab_active) - zr36057_overlay(zr, 0); - zr->overlay_mask = NULL; - } else { - if (!zr->vbuf_base || !fh->overlay_settings.is_set) { - dprintk(1, - KERN_ERR - "%s: %s - buffer or window not set\n", - ZR_DEVNAME(zr), __func__); - return -EINVAL; - } - if (!fh->overlay_settings.format) { - dprintk(1, - KERN_ERR - "%s: %s - no overlay format set\n", - ZR_DEVNAME(zr), __func__); - return -EINVAL; - } - zr->overlay_active = fh->overlay_active = ZORAN_LOCKED; - zr->v4l_overlay_active = 1; - zr->overlay_mask = fh->overlay_mask; - zr->overlay_settings = fh->overlay_settings; - if (!zr->v4l_memgrab_active) - zr36057_overlay(zr, 1); - /* When a grab is running, the video will be - * switched on when grab is finished */ - } - - /* Make sure the changes come into effect */ - return wait_grab_pending(zr); -} - -/* get the status of a buffer in the clients buffer queue */ -static int zoran_v4l2_buffer_status(struct zoran_fh *fh, - struct v4l2_buffer *buf, int num) -{ - struct zoran *zr = fh->zr; - unsigned long flags; - - buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - - switch (fh->map_mode) { - case ZORAN_MAP_MODE_RAW: - /* check range */ - if (num < 0 || num >= fh->buffers.num_buffers || - !fh->buffers.allocated) { - dprintk(1, - KERN_ERR - "%s: %s - wrong number or buffers not allocated\n", - ZR_DEVNAME(zr), __func__); - return -EINVAL; - } - - spin_lock_irqsave(&zr->spinlock, flags); - dprintk(3, - KERN_DEBUG - "%s: %s() - raw active=%c, buffer %d: state=%c, map=%c\n", - ZR_DEVNAME(zr), __func__, - "FAL"[fh->buffers.active], num, - "UPMD"[zr->v4l_buffers.buffer[num].state], - fh->buffers.buffer[num].map ? 'Y' : 'N'); - spin_unlock_irqrestore(&zr->spinlock, flags); - - buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf->length = fh->buffers.buffer_size; - - /* get buffer */ - buf->bytesused = fh->buffers.buffer[num].bs.length; - if (fh->buffers.buffer[num].state == BUZ_STATE_DONE || - fh->buffers.buffer[num].state == BUZ_STATE_USER) { - buf->sequence = fh->buffers.buffer[num].bs.seq; - buf->flags |= V4L2_BUF_FLAG_DONE; - buf->timestamp = ns_to_timeval(fh->buffers.buffer[num].bs.ts); - } else { - buf->flags |= V4L2_BUF_FLAG_QUEUED; - } - - if (fh->v4l_settings.height <= BUZ_MAX_HEIGHT / 2) - buf->field = V4L2_FIELD_TOP; - else - buf->field = V4L2_FIELD_INTERLACED; - - break; - - case ZORAN_MAP_MODE_JPG_REC: - case ZORAN_MAP_MODE_JPG_PLAY: - - /* check range */ - if (num < 0 || num >= fh->buffers.num_buffers || - !fh->buffers.allocated) { - dprintk(1, - KERN_ERR - "%s: %s - wrong number or buffers not allocated\n", - ZR_DEVNAME(zr), __func__); - return -EINVAL; - } - - buf->type = (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ? - V4L2_BUF_TYPE_VIDEO_CAPTURE : - V4L2_BUF_TYPE_VIDEO_OUTPUT; - buf->length = fh->buffers.buffer_size; - - /* these variables are only written after frame has been captured */ - if (fh->buffers.buffer[num].state == BUZ_STATE_DONE || - fh->buffers.buffer[num].state == BUZ_STATE_USER) { - buf->sequence = fh->buffers.buffer[num].bs.seq; - buf->timestamp = ns_to_timeval(fh->buffers.buffer[num].bs.ts); - buf->bytesused = fh->buffers.buffer[num].bs.length; - buf->flags |= V4L2_BUF_FLAG_DONE; - } else { - buf->flags |= V4L2_BUF_FLAG_QUEUED; - } - - /* which fields are these? */ - if (fh->jpg_settings.TmpDcm != 1) - buf->field = fh->jpg_settings.odd_even ? - V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM; - else - buf->field = fh->jpg_settings.odd_even ? - V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT; - - break; - - default: - - dprintk(5, - KERN_ERR - "%s: %s - invalid buffer type|map_mode (%d|%d)\n", - ZR_DEVNAME(zr), __func__, buf->type, fh->map_mode); - return -EINVAL; - } - - buf->memory = V4L2_MEMORY_MMAP; - buf->index = num; - buf->m.offset = buf->length * num; - - return 0; -} - -static int -zoran_set_norm (struct zoran *zr, - v4l2_std_id norm) -{ - int on; - - if (zr->v4l_buffers.active != ZORAN_FREE || - zr->jpg_buffers.active != ZORAN_FREE) { - dprintk(1, - KERN_WARNING - "%s: %s called while in playback/capture mode\n", - ZR_DEVNAME(zr), __func__); - return -EBUSY; - } - - if (!(norm & zr->card.norms)) { - dprintk(1, - KERN_ERR "%s: %s - unsupported norm %llx\n", - ZR_DEVNAME(zr), __func__, norm); - return -EINVAL; - } - - if (norm & V4L2_STD_SECAM) - zr->timing = zr->card.tvn[2]; - else if (norm & V4L2_STD_NTSC) - zr->timing = zr->card.tvn[1]; - else - zr->timing = zr->card.tvn[0]; - - /* We switch overlay off and on since a change in the - * norm needs different VFE settings */ - on = zr->overlay_active && !zr->v4l_memgrab_active; - if (on) - zr36057_overlay(zr, 0); - - decoder_call(zr, video, s_std, norm); - encoder_call(zr, video, s_std_output, norm); - - if (on) - zr36057_overlay(zr, 1); - - /* Make sure the changes come into effect */ - zr->norm = norm; - - return 0; -} - -static int -zoran_set_input (struct zoran *zr, - int input) -{ - if (input == zr->input) { - return 0; - } - - if (zr->v4l_buffers.active != ZORAN_FREE || - zr->jpg_buffers.active != ZORAN_FREE) { - dprintk(1, - KERN_WARNING - "%s: %s called while in playback/capture mode\n", - ZR_DEVNAME(zr), __func__); - return -EBUSY; - } - - if (input < 0 || input >= zr->card.inputs) { - dprintk(1, - KERN_ERR - "%s: %s - unsupported input %d\n", - ZR_DEVNAME(zr), __func__, input); - return -EINVAL; - } - - zr->input = input; - - decoder_call(zr, video, s_routing, - zr->card.input[input].muxsel, 0, 0); - - return 0; -} - -/* - * ioctl routine - */ - -static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability *cap) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - - strscpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)); - strscpy(cap->driver, "zoran", sizeof(cap->driver)); - snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", - pci_name(zr->pci_dev)); - cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OVERLAY; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; -} - -static int zoran_enum_fmt(struct zoran *zr, struct v4l2_fmtdesc *fmt, int flag) -{ - unsigned int num, i; - - for (num = i = 0; i < NUM_FORMATS; i++) { - if (zoran_formats[i].flags & flag && num++ == fmt->index) { - strscpy(fmt->description, zoran_formats[i].name, - sizeof(fmt->description)); - /* fmt struct pre-zeroed, so adding '\0' not needed */ - fmt->pixelformat = zoran_formats[i].fourcc; - if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED) - fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; - return 0; - } - } - return -EINVAL; -} - -static int zoran_enum_fmt_vid_cap(struct file *file, void *__fh, - struct v4l2_fmtdesc *f) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - - return zoran_enum_fmt(zr, f, ZORAN_FORMAT_CAPTURE); -} - -static int zoran_enum_fmt_vid_out(struct file *file, void *__fh, - struct v4l2_fmtdesc *f) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - - return zoran_enum_fmt(zr, f, ZORAN_FORMAT_PLAYBACK); -} - -static int zoran_enum_fmt_vid_overlay(struct file *file, void *__fh, - struct v4l2_fmtdesc *f) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - - return zoran_enum_fmt(zr, f, ZORAN_FORMAT_OVERLAY); -} - -static int zoran_g_fmt_vid_out(struct file *file, void *__fh, - struct v4l2_format *fmt) -{ - struct zoran_fh *fh = __fh; - - fmt->fmt.pix.width = fh->jpg_settings.img_width / fh->jpg_settings.HorDcm; - fmt->fmt.pix.height = fh->jpg_settings.img_height * 2 / - (fh->jpg_settings.VerDcm * fh->jpg_settings.TmpDcm); - fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(&fh->jpg_settings); - fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; - if (fh->jpg_settings.TmpDcm == 1) - fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? - V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT); - else - fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? - V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM); - fmt->fmt.pix.bytesperline = 0; - fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - - return 0; -} - -static int zoran_g_fmt_vid_cap(struct file *file, void *__fh, - struct v4l2_format *fmt) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - - if (fh->map_mode != ZORAN_MAP_MODE_RAW) - return zoran_g_fmt_vid_out(file, fh, fmt); - - fmt->fmt.pix.width = fh->v4l_settings.width; - fmt->fmt.pix.height = fh->v4l_settings.height; - fmt->fmt.pix.sizeimage = fh->v4l_settings.bytesperline * - fh->v4l_settings.height; - fmt->fmt.pix.pixelformat = fh->v4l_settings.format->fourcc; - fmt->fmt.pix.colorspace = fh->v4l_settings.format->colorspace; - fmt->fmt.pix.bytesperline = fh->v4l_settings.bytesperline; - if (BUZ_MAX_HEIGHT < (fh->v4l_settings.height * 2)) - fmt->fmt.pix.field = V4L2_FIELD_INTERLACED; - else - fmt->fmt.pix.field = V4L2_FIELD_TOP; - return 0; -} - -static int zoran_g_fmt_vid_overlay(struct file *file, void *__fh, - struct v4l2_format *fmt) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - - fmt->fmt.win.w.left = fh->overlay_settings.x; - fmt->fmt.win.w.top = fh->overlay_settings.y; - fmt->fmt.win.w.width = fh->overlay_settings.width; - fmt->fmt.win.w.height = fh->overlay_settings.height; - if (fh->overlay_settings.width * 2 > BUZ_MAX_HEIGHT) - fmt->fmt.win.field = V4L2_FIELD_INTERLACED; - else - fmt->fmt.win.field = V4L2_FIELD_TOP; - - return 0; -} - -static int zoran_try_fmt_vid_overlay(struct file *file, void *__fh, - struct v4l2_format *fmt) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - - if (fmt->fmt.win.w.width > BUZ_MAX_WIDTH) - fmt->fmt.win.w.width = BUZ_MAX_WIDTH; - if (fmt->fmt.win.w.width < BUZ_MIN_WIDTH) - fmt->fmt.win.w.width = BUZ_MIN_WIDTH; - if (fmt->fmt.win.w.height > BUZ_MAX_HEIGHT) - fmt->fmt.win.w.height = BUZ_MAX_HEIGHT; - if (fmt->fmt.win.w.height < BUZ_MIN_HEIGHT) - fmt->fmt.win.w.height = BUZ_MIN_HEIGHT; - - return 0; -} - -static int zoran_try_fmt_vid_out(struct file *file, void *__fh, - struct v4l2_format *fmt) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - struct zoran_jpg_settings settings; - int res = 0; - - if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG) - return -EINVAL; - - settings = fh->jpg_settings; - - /* we actually need to set 'real' parameters now */ - if ((fmt->fmt.pix.height * 2) > BUZ_MAX_HEIGHT) - settings.TmpDcm = 1; - else - settings.TmpDcm = 2; - settings.decimation = 0; - if (fmt->fmt.pix.height <= fh->jpg_settings.img_height / 2) - settings.VerDcm = 2; - else - settings.VerDcm = 1; - if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 4) - settings.HorDcm = 4; - else if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 2) - settings.HorDcm = 2; - else - settings.HorDcm = 1; - if (settings.TmpDcm == 1) - settings.field_per_buff = 2; - else - settings.field_per_buff = 1; - - if (settings.HorDcm > 1) { - settings.img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0; - settings.img_width = (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH; - } else { - settings.img_x = 0; - settings.img_width = BUZ_MAX_WIDTH; - } - - /* check */ - res = zoran_check_jpg_settings(zr, &settings, 1); - if (res) - return res; - - /* tell the user what we actually did */ - fmt->fmt.pix.width = settings.img_width / settings.HorDcm; - fmt->fmt.pix.height = settings.img_height * 2 / - (settings.TmpDcm * settings.VerDcm); - if (settings.TmpDcm == 1) - fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? - V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT); - else - fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? - V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM); - - fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(&settings); - fmt->fmt.pix.bytesperline = 0; - fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - return res; -} - -static int zoran_try_fmt_vid_cap(struct file *file, void *__fh, - struct v4l2_format *fmt) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - int bpp; - int i; - - if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) - return zoran_try_fmt_vid_out(file, fh, fmt); - - for (i = 0; i < NUM_FORMATS; i++) - if (zoran_formats[i].fourcc == fmt->fmt.pix.pixelformat) - break; - - if (i == NUM_FORMATS) - return -EINVAL; - - bpp = DIV_ROUND_UP(zoran_formats[i].depth, 8); - v4l_bound_align_image( - &fmt->fmt.pix.width, BUZ_MIN_WIDTH, BUZ_MAX_WIDTH, bpp == 2 ? 1 : 2, - &fmt->fmt.pix.height, BUZ_MIN_HEIGHT, BUZ_MAX_HEIGHT, 0, 0); - return 0; -} - -static int zoran_s_fmt_vid_overlay(struct file *file, void *__fh, - struct v4l2_format *fmt) -{ - struct zoran_fh *fh = __fh; - int res; - - dprintk(3, "x=%d, y=%d, w=%d, h=%d, cnt=%d, map=0x%p\n", - fmt->fmt.win.w.left, fmt->fmt.win.w.top, - fmt->fmt.win.w.width, - fmt->fmt.win.w.height, - fmt->fmt.win.clipcount, - fmt->fmt.win.bitmap); - res = setup_window(fh, fmt->fmt.win.w.left, fmt->fmt.win.w.top, - fmt->fmt.win.w.width, fmt->fmt.win.w.height, - (struct v4l2_clip __user *)fmt->fmt.win.clips, - fmt->fmt.win.clipcount, fmt->fmt.win.bitmap); - return res; -} - -static int zoran_s_fmt_vid_out(struct file *file, void *__fh, - struct v4l2_format *fmt) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - __le32 printformat = __cpu_to_le32(fmt->fmt.pix.pixelformat); - struct zoran_jpg_settings settings; - int res = 0; - - dprintk(3, "size=%dx%d, fmt=0x%x (%4.4s)\n", - fmt->fmt.pix.width, fmt->fmt.pix.height, - fmt->fmt.pix.pixelformat, - (char *) &printformat); - if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG) - return -EINVAL; - - if (fh->buffers.allocated) { - dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - cannot change capture mode\n", - ZR_DEVNAME(zr)); - res = -EBUSY; - return res; - } - - settings = fh->jpg_settings; - - /* we actually need to set 'real' parameters now */ - if (fmt->fmt.pix.height * 2 > BUZ_MAX_HEIGHT) - settings.TmpDcm = 1; - else - settings.TmpDcm = 2; - settings.decimation = 0; - if (fmt->fmt.pix.height <= fh->jpg_settings.img_height / 2) - settings.VerDcm = 2; - else - settings.VerDcm = 1; - if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 4) - settings.HorDcm = 4; - else if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 2) - settings.HorDcm = 2; - else - settings.HorDcm = 1; - if (settings.TmpDcm == 1) - settings.field_per_buff = 2; - else - settings.field_per_buff = 1; - - if (settings.HorDcm > 1) { - settings.img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0; - settings.img_width = (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH; - } else { - settings.img_x = 0; - settings.img_width = BUZ_MAX_WIDTH; - } - - /* check */ - res = zoran_check_jpg_settings(zr, &settings, 0); - if (res) - return res; - - /* it's ok, so set them */ - fh->jpg_settings = settings; - - map_mode_jpg(fh, fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT); - fh->buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings); - - /* tell the user what we actually did */ - fmt->fmt.pix.width = settings.img_width / settings.HorDcm; - fmt->fmt.pix.height = settings.img_height * 2 / - (settings.TmpDcm * settings.VerDcm); - if (settings.TmpDcm == 1) - fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? - V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT); - else - fmt->fmt.pix.field = (fh->jpg_settings.odd_even ? - V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM); - fmt->fmt.pix.bytesperline = 0; - fmt->fmt.pix.sizeimage = fh->buffers.buffer_size; - fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - return res; -} - -static int zoran_s_fmt_vid_cap(struct file *file, void *__fh, - struct v4l2_format *fmt) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - int i; - int res = 0; - - if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG) - return zoran_s_fmt_vid_out(file, fh, fmt); - - for (i = 0; i < NUM_FORMATS; i++) - if (fmt->fmt.pix.pixelformat == zoran_formats[i].fourcc) - break; - if (i == NUM_FORMATS) { - dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - unknown/unsupported format 0x%x\n", - ZR_DEVNAME(zr), fmt->fmt.pix.pixelformat); - return -EINVAL; - } - - if ((fh->map_mode != ZORAN_MAP_MODE_RAW && fh->buffers.allocated) || - fh->buffers.active != ZORAN_FREE) { - dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - cannot change capture mode\n", - ZR_DEVNAME(zr)); - res = -EBUSY; - return res; - } - if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT) - fmt->fmt.pix.height = BUZ_MAX_HEIGHT; - if (fmt->fmt.pix.width > BUZ_MAX_WIDTH) - fmt->fmt.pix.width = BUZ_MAX_WIDTH; - - map_mode_raw(fh); - - res = zoran_v4l_set_format(fh, fmt->fmt.pix.width, fmt->fmt.pix.height, - &zoran_formats[i]); - if (res) - return res; - - /* tell the user the results/missing stuff */ - fmt->fmt.pix.bytesperline = fh->v4l_settings.bytesperline; - fmt->fmt.pix.sizeimage = fh->v4l_settings.height * fh->v4l_settings.bytesperline; - fmt->fmt.pix.colorspace = fh->v4l_settings.format->colorspace; - if (BUZ_MAX_HEIGHT < (fh->v4l_settings.height * 2)) - fmt->fmt.pix.field = V4L2_FIELD_INTERLACED; - else - fmt->fmt.pix.field = V4L2_FIELD_TOP; - return res; -} - -static int zoran_g_fbuf(struct file *file, void *__fh, - struct v4l2_framebuffer *fb) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - - memset(fb, 0, sizeof(*fb)); - fb->base = zr->vbuf_base; - fb->fmt.width = zr->vbuf_width; - fb->fmt.height = zr->vbuf_height; - if (zr->overlay_settings.format) - fb->fmt.pixelformat = fh->overlay_settings.format->fourcc; - fb->fmt.bytesperline = zr->vbuf_bytesperline; - fb->fmt.colorspace = V4L2_COLORSPACE_SRGB; - fb->fmt.field = V4L2_FIELD_INTERLACED; - fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING; - - return 0; -} - -static int zoran_s_fbuf(struct file *file, void *__fh, - const struct v4l2_framebuffer *fb) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - int i, res = 0; - __le32 printformat = __cpu_to_le32(fb->fmt.pixelformat); - - for (i = 0; i < NUM_FORMATS; i++) - if (zoran_formats[i].fourcc == fb->fmt.pixelformat) - break; - if (i == NUM_FORMATS) { - dprintk(1, KERN_ERR "%s: VIDIOC_S_FBUF - format=0x%x (%4.4s) not allowed\n", - ZR_DEVNAME(zr), fb->fmt.pixelformat, - (char *)&printformat); - return -EINVAL; - } - - res = setup_fbuffer(fh, fb->base, &zoran_formats[i], fb->fmt.width, - fb->fmt.height, fb->fmt.bytesperline); - - return res; -} - -static int zoran_overlay(struct file *file, void *__fh, unsigned int on) -{ - struct zoran_fh *fh = __fh; - int res; - - res = setup_overlay(fh, on); - - return res; -} - -static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type); - -static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *req) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - int res = 0; - - if (req->memory != V4L2_MEMORY_MMAP) { - dprintk(2, - KERN_ERR - "%s: only MEMORY_MMAP capture is supported, not %d\n", - ZR_DEVNAME(zr), req->memory); - return -EINVAL; - } - - if (req->count == 0) - return zoran_streamoff(file, fh, req->type); - - if (fh->buffers.allocated) { - dprintk(2, - KERN_ERR - "%s: VIDIOC_REQBUFS - buffers already allocated\n", - ZR_DEVNAME(zr)); - res = -EBUSY; - return res; - } - - if (fh->map_mode == ZORAN_MAP_MODE_RAW && - req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - /* control user input */ - if (req->count < 2) - req->count = 2; - if (req->count > v4l_nbufs) - req->count = v4l_nbufs; - - /* The next mmap will map the V4L buffers */ - map_mode_raw(fh); - fh->buffers.num_buffers = req->count; - - if (v4l_fbuffer_alloc(fh)) { - res = -ENOMEM; - return res; - } - } else if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC || - fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) { - /* we need to calculate size ourselves now */ - if (req->count < 4) - req->count = 4; - if (req->count > jpg_nbufs) - req->count = jpg_nbufs; - - /* The next mmap will map the MJPEG buffers */ - map_mode_jpg(fh, req->type == V4L2_BUF_TYPE_VIDEO_OUTPUT); - fh->buffers.num_buffers = req->count; - fh->buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings); - - if (jpg_fbuffer_alloc(fh)) { - res = -ENOMEM; - return res; - } - } else { - dprintk(1, - KERN_ERR - "%s: VIDIOC_REQBUFS - unknown type %d\n", - ZR_DEVNAME(zr), req->type); - res = -EINVAL; - return res; - } - return res; -} - -static int zoran_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf) -{ - struct zoran_fh *fh = __fh; - int res; - - res = zoran_v4l2_buffer_status(fh, buf, buf->index); - - return res; -} - -static int zoran_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - int res = 0, codec_mode, buf_type; - - switch (fh->map_mode) { - case ZORAN_MAP_MODE_RAW: - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - dprintk(1, KERN_ERR - "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n", - ZR_DEVNAME(zr), buf->type, fh->map_mode); - res = -EINVAL; - return res; - } - - res = zoran_v4l_queue_frame(fh, buf->index); - if (res) - return res; - if (!zr->v4l_memgrab_active && fh->buffers.active == ZORAN_LOCKED) - zr36057_set_memgrab(zr, 1); - break; - - case ZORAN_MAP_MODE_JPG_REC: - case ZORAN_MAP_MODE_JPG_PLAY: - if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) { - buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - codec_mode = BUZ_MODE_MOTION_DECOMPRESS; - } else { - buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - codec_mode = BUZ_MODE_MOTION_COMPRESS; - } - - if (buf->type != buf_type) { - dprintk(1, KERN_ERR - "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n", - ZR_DEVNAME(zr), buf->type, fh->map_mode); - res = -EINVAL; - return res; - } - - res = zoran_jpg_queue_frame(fh, buf->index, codec_mode); - if (res != 0) - return res; - if (zr->codec_mode == BUZ_MODE_IDLE && - fh->buffers.active == ZORAN_LOCKED) - zr36057_enable_jpg(zr, codec_mode); - - break; - - default: - dprintk(1, KERN_ERR - "%s: VIDIOC_QBUF - unsupported type %d\n", - ZR_DEVNAME(zr), buf->type); - res = -EINVAL; - break; - } - return res; -} - -static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - int res = 0, buf_type, num = -1; /* compiler borks here (?) */ - - switch (fh->map_mode) { - case ZORAN_MAP_MODE_RAW: - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - dprintk(1, KERN_ERR - "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n", - ZR_DEVNAME(zr), buf->type, fh->map_mode); - res = -EINVAL; - return res; - } - - num = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME]; - if (file->f_flags & O_NONBLOCK && - zr->v4l_buffers.buffer[num].state != BUZ_STATE_DONE) { - res = -EAGAIN; - return res; - } - res = v4l_sync(fh, num); - if (res) - return res; - zr->v4l_sync_tail++; - res = zoran_v4l2_buffer_status(fh, buf, num); - break; - - case ZORAN_MAP_MODE_JPG_REC: - case ZORAN_MAP_MODE_JPG_PLAY: - { - struct zoran_sync bs; - - if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) - buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - else - buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - if (buf->type != buf_type) { - dprintk(1, KERN_ERR - "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n", - ZR_DEVNAME(zr), buf->type, fh->map_mode); - res = -EINVAL; - return res; - } - - num = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME]; - - if (file->f_flags & O_NONBLOCK && - zr->jpg_buffers.buffer[num].state != BUZ_STATE_DONE) { - res = -EAGAIN; - return res; - } - bs.frame = 0; /* suppress compiler warning */ - res = jpg_sync(fh, &bs); - if (res) - return res; - res = zoran_v4l2_buffer_status(fh, buf, bs.frame); - break; - } - - default: - dprintk(1, KERN_ERR - "%s: VIDIOC_DQBUF - unsupported type %d\n", - ZR_DEVNAME(zr), buf->type); - res = -EINVAL; - break; - } - return res; -} - -static int zoran_streamon(struct file *file, void *__fh, enum v4l2_buf_type type) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - int res = 0; - - switch (fh->map_mode) { - case ZORAN_MAP_MODE_RAW: /* raw capture */ - if (zr->v4l_buffers.active != ZORAN_ACTIVE || - fh->buffers.active != ZORAN_ACTIVE) { - res = -EBUSY; - return res; - } - - zr->v4l_buffers.active = fh->buffers.active = ZORAN_LOCKED; - zr->v4l_settings = fh->v4l_settings; - - zr->v4l_sync_tail = zr->v4l_pend_tail; - if (!zr->v4l_memgrab_active && - zr->v4l_pend_head != zr->v4l_pend_tail) { - zr36057_set_memgrab(zr, 1); - } - break; - - case ZORAN_MAP_MODE_JPG_REC: - case ZORAN_MAP_MODE_JPG_PLAY: - /* what is the codec mode right now? */ - if (zr->jpg_buffers.active != ZORAN_ACTIVE || - fh->buffers.active != ZORAN_ACTIVE) { - res = -EBUSY; - return res; - } - - zr->jpg_buffers.active = fh->buffers.active = ZORAN_LOCKED; - - if (zr->jpg_que_head != zr->jpg_que_tail) { - /* Start the jpeg codec when the first frame is queued */ - jpeg_start(zr); - } - break; - - default: - dprintk(1, - KERN_ERR - "%s: VIDIOC_STREAMON - invalid map mode %d\n", - ZR_DEVNAME(zr), fh->map_mode); - res = -EINVAL; - break; - } - return res; -} - -static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - int i, res = 0; - unsigned long flags; - - switch (fh->map_mode) { - case ZORAN_MAP_MODE_RAW: /* raw capture */ - if (fh->buffers.active == ZORAN_FREE && - zr->v4l_buffers.active != ZORAN_FREE) { - res = -EPERM; /* stay off other's settings! */ - return res; - } - if (zr->v4l_buffers.active == ZORAN_FREE) - return res; - - spin_lock_irqsave(&zr->spinlock, flags); - /* unload capture */ - if (zr->v4l_memgrab_active) { - - zr36057_set_memgrab(zr, 0); - } - - for (i = 0; i < fh->buffers.num_buffers; i++) - zr->v4l_buffers.buffer[i].state = BUZ_STATE_USER; - fh->buffers = zr->v4l_buffers; - - zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE; - - zr->v4l_grab_seq = 0; - zr->v4l_pend_head = zr->v4l_pend_tail = 0; - zr->v4l_sync_tail = 0; - - spin_unlock_irqrestore(&zr->spinlock, flags); - - break; - - case ZORAN_MAP_MODE_JPG_REC: - case ZORAN_MAP_MODE_JPG_PLAY: - if (fh->buffers.active == ZORAN_FREE && - zr->jpg_buffers.active != ZORAN_FREE) { - res = -EPERM; /* stay off other's settings! */ - return res; - } - if (zr->jpg_buffers.active == ZORAN_FREE) - return res; - - res = jpg_qbuf(fh, -1, - (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ? - BUZ_MODE_MOTION_COMPRESS : - BUZ_MODE_MOTION_DECOMPRESS); - if (res) - return res; - break; - default: - dprintk(1, KERN_ERR - "%s: VIDIOC_STREAMOFF - invalid map mode %d\n", - ZR_DEVNAME(zr), fh->map_mode); - res = -EINVAL; - break; - } - return res; -} -static int zoran_g_std(struct file *file, void *__fh, v4l2_std_id *std) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - - *std = zr->norm; - return 0; -} - -static int zoran_s_std(struct file *file, void *__fh, v4l2_std_id std) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - int res = 0; - - res = zoran_set_norm(zr, std); - if (res) - return res; - - res = wait_grab_pending(zr); - return res; -} - -static int zoran_enum_input(struct file *file, void *__fh, - struct v4l2_input *inp) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - - if (inp->index >= zr->card.inputs) - return -EINVAL; - - strscpy(inp->name, zr->card.input[inp->index].name, - sizeof(inp->name)); - inp->type = V4L2_INPUT_TYPE_CAMERA; - inp->std = V4L2_STD_ALL; - - /* Get status of video decoder */ - decoder_call(zr, video, g_input_status, &inp->status); - return 0; -} - -static int zoran_g_input(struct file *file, void *__fh, unsigned int *input) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - - *input = zr->input; - - return 0; -} - -static int zoran_s_input(struct file *file, void *__fh, unsigned int input) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - int res; - - res = zoran_set_input(zr, input); - if (res) - return res; - - /* Make sure the changes come into effect */ - res = wait_grab_pending(zr); - return res; -} - -static int zoran_enum_output(struct file *file, void *__fh, - struct v4l2_output *outp) -{ - if (outp->index != 0) - return -EINVAL; - - outp->index = 0; - outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY; - strscpy(outp->name, "Autodetect", sizeof(outp->name)); - - return 0; -} - -static int zoran_g_output(struct file *file, void *__fh, unsigned int *output) -{ - *output = 0; - - return 0; -} - -static int zoran_s_output(struct file *file, void *__fh, unsigned int output) -{ - if (output != 0) - return -EINVAL; - - return 0; -} - -/* cropping (sub-frame capture) */ -static int zoran_g_selection(struct file *file, void *__fh, struct v4l2_selection *sel) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - - if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && - sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (fh->map_mode == ZORAN_MAP_MODE_RAW) { - dprintk(1, KERN_ERR - "%s: VIDIOC_G_SELECTION - subcapture only supported for compressed capture\n", - ZR_DEVNAME(zr)); - return -EINVAL; - } - - switch (sel->target) { - case V4L2_SEL_TGT_CROP: - sel->r.top = fh->jpg_settings.img_y; - sel->r.left = fh->jpg_settings.img_x; - sel->r.width = fh->jpg_settings.img_width; - sel->r.height = fh->jpg_settings.img_height; - break; - case V4L2_SEL_TGT_CROP_DEFAULT: - sel->r.top = sel->r.left = 0; - sel->r.width = BUZ_MIN_WIDTH; - sel->r.height = BUZ_MIN_HEIGHT; - break; - case V4L2_SEL_TGT_CROP_BOUNDS: - sel->r.top = sel->r.left = 0; - sel->r.width = BUZ_MAX_WIDTH; - sel->r.height = BUZ_MAX_HEIGHT; - break; - default: - return -EINVAL; - } - return 0; -} - -static int zoran_s_selection(struct file *file, void *__fh, struct v4l2_selection *sel) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - struct zoran_jpg_settings settings; - int res; - - if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && - sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - if (sel->target != V4L2_SEL_TGT_CROP) - return -EINVAL; - - if (fh->map_mode == ZORAN_MAP_MODE_RAW) { - dprintk(1, KERN_ERR - "%s: VIDIOC_S_SELECTION - subcapture only supported for compressed capture\n", - ZR_DEVNAME(zr)); - return -EINVAL; - } - - settings = fh->jpg_settings; - - if (fh->buffers.allocated) { - dprintk(1, KERN_ERR - "%s: VIDIOC_S_SELECTION - cannot change settings while active\n", - ZR_DEVNAME(zr)); - return -EBUSY; - } - - /* move into a form that we understand */ - settings.img_x = sel->r.left; - settings.img_y = sel->r.top; - settings.img_width = sel->r.width; - settings.img_height = sel->r.height; - - /* check validity */ - res = zoran_check_jpg_settings(zr, &settings, 0); - if (res) - return res; - - /* accept */ - fh->jpg_settings = settings; - return res; -} - -static int zoran_g_jpegcomp(struct file *file, void *__fh, - struct v4l2_jpegcompression *params) -{ - struct zoran_fh *fh = __fh; - memset(params, 0, sizeof(*params)); - - params->quality = fh->jpg_settings.jpg_comp.quality; - params->APPn = fh->jpg_settings.jpg_comp.APPn; - memcpy(params->APP_data, - fh->jpg_settings.jpg_comp.APP_data, - fh->jpg_settings.jpg_comp.APP_len); - params->APP_len = fh->jpg_settings.jpg_comp.APP_len; - memcpy(params->COM_data, - fh->jpg_settings.jpg_comp.COM_data, - fh->jpg_settings.jpg_comp.COM_len); - params->COM_len = fh->jpg_settings.jpg_comp.COM_len; - params->jpeg_markers = - fh->jpg_settings.jpg_comp.jpeg_markers; - - return 0; -} - -static int zoran_s_jpegcomp(struct file *file, void *__fh, - const struct v4l2_jpegcompression *params) -{ - struct zoran_fh *fh = __fh; - struct zoran *zr = fh->zr; - int res = 0; - struct zoran_jpg_settings settings; - - settings = fh->jpg_settings; - - settings.jpg_comp = *params; - - if (fh->buffers.active != ZORAN_FREE) { - dprintk(1, KERN_WARNING - "%s: VIDIOC_S_JPEGCOMP called while in playback/capture mode\n", - ZR_DEVNAME(zr)); - res = -EBUSY; - return res; - } - - res = zoran_check_jpg_settings(zr, &settings, 0); - if (res) - return res; - if (!fh->buffers.allocated) - fh->buffers.buffer_size = - zoran_v4l2_calc_bufsize(&fh->jpg_settings); - fh->jpg_settings.jpg_comp = settings.jpg_comp; - return res; -} - -static __poll_t -zoran_poll (struct file *file, - poll_table *wait) -{ - struct zoran_fh *fh = file->private_data; - struct zoran *zr = fh->zr; - __poll_t res = v4l2_ctrl_poll(file, wait); - int frame; - unsigned long flags; - - /* we should check whether buffers are ready to be synced on - * (w/o waits - O_NONBLOCK) here - * if ready for read (sync), return EPOLLIN|EPOLLRDNORM, - * if ready for write (sync), return EPOLLOUT|EPOLLWRNORM, - * if error, return EPOLLERR, - * if no buffers queued or so, return EPOLLNVAL - */ - - switch (fh->map_mode) { - case ZORAN_MAP_MODE_RAW: - poll_wait(file, &zr->v4l_capq, wait); - frame = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME]; - - spin_lock_irqsave(&zr->spinlock, flags); - dprintk(3, - KERN_DEBUG - "%s: %s() raw - active=%c, sync_tail=%lu/%c, pend_tail=%lu, pend_head=%lu\n", - ZR_DEVNAME(zr), __func__, - "FAL"[fh->buffers.active], zr->v4l_sync_tail, - "UPMD"[zr->v4l_buffers.buffer[frame].state], - zr->v4l_pend_tail, zr->v4l_pend_head); - /* Process is the one capturing? */ - if (fh->buffers.active != ZORAN_FREE && - /* Buffer ready to DQBUF? */ - zr->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE) - res |= EPOLLIN | EPOLLRDNORM; - spin_unlock_irqrestore(&zr->spinlock, flags); - - break; - - case ZORAN_MAP_MODE_JPG_REC: - case ZORAN_MAP_MODE_JPG_PLAY: - poll_wait(file, &zr->jpg_capq, wait); - frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME]; - - spin_lock_irqsave(&zr->spinlock, flags); - dprintk(3, - KERN_DEBUG - "%s: %s() jpg - active=%c, que_tail=%lu/%c, que_head=%lu, dma=%lu/%lu\n", - ZR_DEVNAME(zr), __func__, - "FAL"[fh->buffers.active], zr->jpg_que_tail, - "UPMD"[zr->jpg_buffers.buffer[frame].state], - zr->jpg_que_head, zr->jpg_dma_tail, zr->jpg_dma_head); - if (fh->buffers.active != ZORAN_FREE && - zr->jpg_buffers.buffer[frame].state == BUZ_STATE_DONE) { - if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) - res |= EPOLLIN | EPOLLRDNORM; - else - res |= EPOLLOUT | EPOLLWRNORM; - } - spin_unlock_irqrestore(&zr->spinlock, flags); - - break; - - default: - dprintk(1, - KERN_ERR - "%s: %s - internal error, unknown map_mode=%d\n", - ZR_DEVNAME(zr), __func__, fh->map_mode); - res |= EPOLLERR; - } - - return res; -} - - -/* - * This maps the buffers to user space. - * - * Depending on the state of fh->map_mode - * the V4L or the MJPEG buffers are mapped - * per buffer or all together - * - * Note that we need to connect to some - * unmap signal event to unmap the de-allocate - * the buffer accordingly (zoran_vm_close()) - */ - -static void -zoran_vm_open (struct vm_area_struct *vma) -{ - struct zoran_mapping *map = vma->vm_private_data; - atomic_inc(&map->count); -} - -static void -zoran_vm_close (struct vm_area_struct *vma) -{ - struct zoran_mapping *map = vma->vm_private_data; - struct zoran_fh *fh = map->fh; - struct zoran *zr = fh->zr; - int i; - - dprintk(3, KERN_INFO "%s: %s - munmap(%s)\n", ZR_DEVNAME(zr), - __func__, mode_name(fh->map_mode)); - - for (i = 0; i < fh->buffers.num_buffers; i++) { - if (fh->buffers.buffer[i].map == map) - fh->buffers.buffer[i].map = NULL; - } - kfree(map); - - /* Any buffers still mapped? */ - for (i = 0; i < fh->buffers.num_buffers; i++) { - if (fh->buffers.buffer[i].map) { - return; - } - } - - dprintk(3, KERN_INFO "%s: %s - free %s buffers\n", ZR_DEVNAME(zr), - __func__, mode_name(fh->map_mode)); - - if (fh->map_mode == ZORAN_MAP_MODE_RAW) { - if (fh->buffers.active != ZORAN_FREE) { - unsigned long flags; - - spin_lock_irqsave(&zr->spinlock, flags); - zr36057_set_memgrab(zr, 0); - zr->v4l_buffers.allocated = 0; - zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE; - spin_unlock_irqrestore(&zr->spinlock, flags); - } - v4l_fbuffer_free(fh); - } else { - if (fh->buffers.active != ZORAN_FREE) { - jpg_qbuf(fh, -1, zr->codec_mode); - zr->jpg_buffers.allocated = 0; - zr->jpg_buffers.active = fh->buffers.active = ZORAN_FREE; - } - jpg_fbuffer_free(fh); - } -} - -static const struct vm_operations_struct zoran_vm_ops = { - .open = zoran_vm_open, - .close = zoran_vm_close, -}; - -static int -zoran_mmap (struct file *file, - struct vm_area_struct *vma) -{ - struct zoran_fh *fh = file->private_data; - struct zoran *zr = fh->zr; - unsigned long size = (vma->vm_end - vma->vm_start); - unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; - int i, j; - unsigned long page, start = vma->vm_start, todo, pos, fraglen; - int first, last; - struct zoran_mapping *map; - int res = 0; - - dprintk(3, - KERN_INFO "%s: %s(%s) of 0x%08lx-0x%08lx (size=%lu)\n", - ZR_DEVNAME(zr), __func__, - mode_name(fh->map_mode), vma->vm_start, vma->vm_end, size); - - if (!(vma->vm_flags & VM_SHARED) || !(vma->vm_flags & VM_READ) || - !(vma->vm_flags & VM_WRITE)) { - dprintk(1, - KERN_ERR - "%s: %s - no MAP_SHARED/PROT_{READ,WRITE} given\n", - ZR_DEVNAME(zr), __func__); - return -EINVAL; - } - - if (!fh->buffers.allocated) { - dprintk(1, - KERN_ERR - "%s: %s(%s) - buffers not yet allocated\n", - ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode)); - res = -ENOMEM; - return res; - } - - first = offset / fh->buffers.buffer_size; - last = first - 1 + size / fh->buffers.buffer_size; - if (offset % fh->buffers.buffer_size != 0 || - size % fh->buffers.buffer_size != 0 || first < 0 || - last < 0 || first >= fh->buffers.num_buffers || - last >= fh->buffers.buffer_size) { - dprintk(1, - KERN_ERR - "%s: %s(%s) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n", - ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode), offset, size, - fh->buffers.buffer_size, - fh->buffers.num_buffers); - res = -EINVAL; - return res; - } - - /* Check if any buffers are already mapped */ - for (i = first; i <= last; i++) { - if (fh->buffers.buffer[i].map) { - dprintk(1, - KERN_ERR - "%s: %s(%s) - buffer %d already mapped\n", - ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode), i); - res = -EBUSY; - return res; - } - } - - /* map these buffers */ - map = kmalloc(sizeof(struct zoran_mapping), GFP_KERNEL); - if (!map) { - res = -ENOMEM; - return res; - } - map->fh = fh; - atomic_set(&map->count, 1); - - vma->vm_ops = &zoran_vm_ops; - vma->vm_flags |= VM_DONTEXPAND; - vma->vm_private_data = map; - - if (fh->map_mode == ZORAN_MAP_MODE_RAW) { - for (i = first; i <= last; i++) { - todo = size; - if (todo > fh->buffers.buffer_size) - todo = fh->buffers.buffer_size; - page = fh->buffers.buffer[i].v4l.fbuffer_phys; - if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, - todo, PAGE_SHARED)) { - dprintk(1, - KERN_ERR - "%s: %s(V4L) - remap_pfn_range failed\n", - ZR_DEVNAME(zr), __func__); - res = -EAGAIN; - return res; - } - size -= todo; - start += todo; - fh->buffers.buffer[i].map = map; - if (size == 0) - break; - } - } else { - for (i = first; i <= last; i++) { - for (j = 0; - j < fh->buffers.buffer_size / PAGE_SIZE; - j++) { - fraglen = - (le32_to_cpu(fh->buffers.buffer[i].jpg. - frag_tab[2 * j + 1]) & ~1) << 1; - todo = size; - if (todo > fraglen) - todo = fraglen; - pos = - le32_to_cpu(fh->buffers. - buffer[i].jpg.frag_tab[2 * j]); - /* should just be pos on i386 */ - page = virt_to_phys(bus_to_virt(pos)) - >> PAGE_SHIFT; - if (remap_pfn_range(vma, start, page, - todo, PAGE_SHARED)) { - dprintk(1, - KERN_ERR - "%s: %s(V4L) - remap_pfn_range failed\n", - ZR_DEVNAME(zr), __func__); - res = -EAGAIN; - return res; - } - size -= todo; - start += todo; - if (size == 0) - break; - if (le32_to_cpu(fh->buffers.buffer[i].jpg. - frag_tab[2 * j + 1]) & 1) - break; /* was last fragment */ - } - fh->buffers.buffer[i].map = map; - if (size == 0) - break; - - } - } - return res; -} - -static const struct v4l2_ioctl_ops zoran_ioctl_ops = { - .vidioc_querycap = zoran_querycap, - .vidioc_s_selection = zoran_s_selection, - .vidioc_g_selection = zoran_g_selection, - .vidioc_enum_input = zoran_enum_input, - .vidioc_g_input = zoran_g_input, - .vidioc_s_input = zoran_s_input, - .vidioc_enum_output = zoran_enum_output, - .vidioc_g_output = zoran_g_output, - .vidioc_s_output = zoran_s_output, - .vidioc_g_fbuf = zoran_g_fbuf, - .vidioc_s_fbuf = zoran_s_fbuf, - .vidioc_g_std = zoran_g_std, - .vidioc_s_std = zoran_s_std, - .vidioc_g_jpegcomp = zoran_g_jpegcomp, - .vidioc_s_jpegcomp = zoran_s_jpegcomp, - .vidioc_overlay = zoran_overlay, - .vidioc_reqbufs = zoran_reqbufs, - .vidioc_querybuf = zoran_querybuf, - .vidioc_qbuf = zoran_qbuf, - .vidioc_dqbuf = zoran_dqbuf, - .vidioc_streamon = zoran_streamon, - .vidioc_streamoff = zoran_streamoff, - .vidioc_enum_fmt_vid_cap = zoran_enum_fmt_vid_cap, - .vidioc_enum_fmt_vid_out = zoran_enum_fmt_vid_out, - .vidioc_enum_fmt_vid_overlay = zoran_enum_fmt_vid_overlay, - .vidioc_g_fmt_vid_cap = zoran_g_fmt_vid_cap, - .vidioc_g_fmt_vid_out = zoran_g_fmt_vid_out, - .vidioc_g_fmt_vid_overlay = zoran_g_fmt_vid_overlay, - .vidioc_s_fmt_vid_cap = zoran_s_fmt_vid_cap, - .vidioc_s_fmt_vid_out = zoran_s_fmt_vid_out, - .vidioc_s_fmt_vid_overlay = zoran_s_fmt_vid_overlay, - .vidioc_try_fmt_vid_cap = zoran_try_fmt_vid_cap, - .vidioc_try_fmt_vid_out = zoran_try_fmt_vid_out, - .vidioc_try_fmt_vid_overlay = zoran_try_fmt_vid_overlay, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -static const struct v4l2_file_operations zoran_fops = { - .owner = THIS_MODULE, - .open = zoran_open, - .release = zoran_close, - .unlocked_ioctl = video_ioctl2, - .mmap = zoran_mmap, - .poll = zoran_poll, -}; - -const struct video_device zoran_template = { - .name = ZORAN_NAME, - .fops = &zoran_fops, - .ioctl_ops = &zoran_ioctl_ops, - .release = &zoran_vdev_release, - .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, -}; - diff --git a/drivers/staging/media/zoran/zoran_procfs.c b/drivers/staging/media/zoran/zoran_procfs.c deleted file mode 100644 index 78ac8f853748..000000000000 --- a/drivers/staging/media/zoran/zoran_procfs.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Zoran zr36057/zr36067 PCI controller driver, for the - * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux - * Media Labs LML33/LML33R10. - * - * This part handles the procFS entries (/proc/ZORAN[%d]) - * - * Copyright (C) 2000 Serguei Miridonov - * - * Currently maintained by: - * Ronald Bultje - * Laurent Pinchart - * Mailinglist - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "videocodec.h" -#include "zoran.h" -#include "zoran_procfs.h" -#include "zoran_card.h" - -#ifdef CONFIG_PROC_FS -struct procfs_params_zr36067 { - char *name; - short reg; - u32 mask; - short bit; -}; - -static const struct procfs_params_zr36067 zr67[] = { - {"HSPol", 0x000, 1, 30}, - {"HStart", 0x000, 0x3ff, 10}, - {"HEnd", 0x000, 0x3ff, 0}, - - {"VSPol", 0x004, 1, 30}, - {"VStart", 0x004, 0x3ff, 10}, - {"VEnd", 0x004, 0x3ff, 0}, - - {"ExtFl", 0x008, 1, 26}, - {"TopField", 0x008, 1, 25}, - {"VCLKPol", 0x008, 1, 24}, - {"DupFld", 0x008, 1, 20}, - {"LittleEndian", 0x008, 1, 0}, - - {"HsyncStart", 0x10c, 0xffff, 16}, - {"LineTot", 0x10c, 0xffff, 0}, - - {"NAX", 0x110, 0xffff, 16}, - {"PAX", 0x110, 0xffff, 0}, - - {"NAY", 0x114, 0xffff, 16}, - {"PAY", 0x114, 0xffff, 0}, - - /* {"",,,}, */ - - {NULL, 0, 0, 0}, -}; - -static void -setparam (struct zoran *zr, - char *name, - char *sval) -{ - int i = 0, reg0, reg, val; - - while (zr67[i].name != NULL) { - if (!strncmp(name, zr67[i].name, strlen(zr67[i].name))) { - reg = reg0 = btread(zr67[i].reg); - reg &= ~(zr67[i].mask << zr67[i].bit); - if (!isdigit(sval[0])) - break; - val = simple_strtoul(sval, NULL, 0); - if ((val & ~zr67[i].mask)) - break; - reg |= (val & zr67[i].mask) << zr67[i].bit; - dprintk(4, - KERN_INFO - "%s: setparam: setting ZR36067 register 0x%03x: 0x%08x=>0x%08x %s=%d\n", - ZR_DEVNAME(zr), zr67[i].reg, reg0, reg, - zr67[i].name, val); - btwrite(reg, zr67[i].reg); - break; - } - i++; - } -} - -static int zoran_show(struct seq_file *p, void *v) -{ - struct zoran *zr = p->private; - int i; - - seq_printf(p, "ZR36067 registers:\n"); - for (i = 0; i < 0x130; i += 16) - seq_printf(p, "%03X %08X %08X %08X %08X \n", i, - btread(i), btread(i+4), btread(i+8), btread(i+12)); - return 0; -} - -static int zoran_open(struct inode *inode, struct file *file) -{ - struct zoran *data = PDE_DATA(inode); - return single_open(file, zoran_show, data); -} - -static ssize_t zoran_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos) -{ - struct zoran *zr = PDE_DATA(file_inode(file)); - char *string, *sp; - char *line, *ldelim, *varname, *svar, *tdelim; - - if (count > 32768) /* Stupidity filter */ - return -EINVAL; - - string = sp = vmalloc(count + 1); - if (!string) { - dprintk(1, - KERN_ERR - "%s: write_proc: can not allocate memory\n", - ZR_DEVNAME(zr)); - return -ENOMEM; - } - if (copy_from_user(string, buffer, count)) { - vfree (string); - return -EFAULT; - } - string[count] = 0; - dprintk(4, KERN_INFO "%s: write_proc: name=%pD count=%zu zr=%p\n", - ZR_DEVNAME(zr), file, count, zr); - ldelim = " \t\n"; - tdelim = "="; - line = strpbrk(sp, ldelim); - while (line) { - *line = 0; - svar = strpbrk(sp, tdelim); - if (svar) { - *svar = 0; - varname = sp; - svar++; - setparam(zr, varname, svar); - } - sp = line + 1; - line = strpbrk(sp, ldelim); - } - vfree(string); - - return count; -} - -static const struct file_operations zoran_operations = { - .owner = THIS_MODULE, - .open = zoran_open, - .read = seq_read, - .write = zoran_write, - .llseek = seq_lseek, - .release = single_release, -}; -#endif - -int -zoran_proc_init (struct zoran *zr) -{ -#ifdef CONFIG_PROC_FS - char name[8]; - - snprintf(name, 7, "zoran%d", zr->id); - zr->zoran_proc = proc_create_data(name, 0, NULL, &zoran_operations, zr); - if (zr->zoran_proc != NULL) { - dprintk(2, - KERN_INFO - "%s: procfs entry /proc/%s allocated. data=%p\n", - ZR_DEVNAME(zr), name, zr); - } else { - dprintk(1, KERN_ERR "%s: Unable to initialise /proc/%s\n", - ZR_DEVNAME(zr), name); - return 1; - } -#endif - return 0; -} - -void -zoran_proc_cleanup (struct zoran *zr) -{ -#ifdef CONFIG_PROC_FS - char name[8]; - - snprintf(name, 7, "zoran%d", zr->id); - if (zr->zoran_proc) - remove_proc_entry(name, NULL); - zr->zoran_proc = NULL; -#endif -} diff --git a/drivers/staging/media/zoran/zoran_procfs.h b/drivers/staging/media/zoran/zoran_procfs.h deleted file mode 100644 index 0ac7cb0011f2..000000000000 --- a/drivers/staging/media/zoran/zoran_procfs.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Zoran zr36057/zr36067 PCI controller driver, for the - * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux - * Media Labs LML33/LML33R10. - * - * This part handles card-specific data and detection - * - * Copyright (C) 2000 Serguei Miridonov - * - * Currently maintained by: - * Ronald Bultje - * Laurent Pinchart - * Mailinglist - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __ZORAN_PROCFS_H__ -#define __ZORAN_PROCFS_H__ - -extern int zoran_proc_init(struct zoran *zr); -extern void zoran_proc_cleanup(struct zoran *zr); - -#endif /* __ZORAN_PROCFS_H__ */ diff --git a/drivers/staging/media/zoran/zr36016.c b/drivers/staging/media/zoran/zr36016.c deleted file mode 100644 index 8736b9d8d97e..000000000000 --- a/drivers/staging/media/zoran/zr36016.c +++ /dev/null @@ -1,516 +0,0 @@ -/* - * Zoran ZR36016 basic configuration functions - * - * Copyright (C) 2001 Wolfgang Scherr - * - * $Id: zr36016.c,v 1.1.2.14 2003/08/20 19:46:55 rbultje Exp $ - * - * ------------------------------------------------------------------------ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * ------------------------------------------------------------------------ - */ - -#define ZR016_VERSION "v0.7" - -#include -#include -#include -#include - -#include -#include - -/* I/O commands, error codes */ -#include - -/* v4l API */ - -/* headerfile of this module */ -#include "zr36016.h" - -/* codec io API */ -#include "videocodec.h" - -/* it doesn't make sense to have more than 20 or so, - just to prevent some unwanted loops */ -#define MAX_CODECS 20 - -/* amount of chips attached via this driver */ -static int zr36016_codecs; - -/* debugging is available via module parameter */ -static int debug; -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0-4)"); - -#define dprintk(num, format, args...) \ - do { \ - if (debug >= num) \ - printk(format, ##args); \ - } while (0) - -/* ========================================================================= - Local hardware I/O functions: - - read/write via codec layer (registers are located in the master device) - ========================================================================= */ - -/* read and write functions */ -static u8 -zr36016_read (struct zr36016 *ptr, - u16 reg) -{ - u8 value = 0; - - // just in case something is wrong... - if (ptr->codec->master_data->readreg) - value = - (ptr->codec->master_data-> - readreg(ptr->codec, reg)) & 0xFF; - else - dprintk(1, - KERN_ERR "%s: invalid I/O setup, nothing read!\n", - ptr->name); - - dprintk(4, "%s: reading from 0x%04x: %02x\n", ptr->name, reg, - value); - - return value; -} - -static void -zr36016_write (struct zr36016 *ptr, - u16 reg, - u8 value) -{ - dprintk(4, "%s: writing 0x%02x to 0x%04x\n", ptr->name, value, - reg); - - // just in case something is wrong... - if (ptr->codec->master_data->writereg) { - ptr->codec->master_data->writereg(ptr->codec, reg, value); - } else - dprintk(1, - KERN_ERR - "%s: invalid I/O setup, nothing written!\n", - ptr->name); -} - -/* indirect read and write functions */ -/* the 016 supports auto-addr-increment, but - * writing it all time cost not much and is safer... */ -static u8 -zr36016_readi (struct zr36016 *ptr, - u16 reg) -{ - u8 value = 0; - - // just in case something is wrong... - if ((ptr->codec->master_data->writereg) && - (ptr->codec->master_data->readreg)) { - ptr->codec->master_data->writereg(ptr->codec, ZR016_IADDR, reg & 0x0F); // ADDR - value = (ptr->codec->master_data->readreg(ptr->codec, ZR016_IDATA)) & 0xFF; // DATA - } else - dprintk(1, - KERN_ERR - "%s: invalid I/O setup, nothing read (i)!\n", - ptr->name); - - dprintk(4, "%s: reading indirect from 0x%04x: %02x\n", ptr->name, - reg, value); - return value; -} - -static void -zr36016_writei (struct zr36016 *ptr, - u16 reg, - u8 value) -{ - dprintk(4, "%s: writing indirect 0x%02x to 0x%04x\n", ptr->name, - value, reg); - - // just in case something is wrong... - if (ptr->codec->master_data->writereg) { - ptr->codec->master_data->writereg(ptr->codec, ZR016_IADDR, reg & 0x0F); // ADDR - ptr->codec->master_data->writereg(ptr->codec, ZR016_IDATA, value & 0x0FF); // DATA - } else - dprintk(1, - KERN_ERR - "%s: invalid I/O setup, nothing written (i)!\n", - ptr->name); -} - -/* ========================================================================= - Local helper function: - - version read - ========================================================================= */ - -/* version kept in datastructure */ -static u8 -zr36016_read_version (struct zr36016 *ptr) -{ - ptr->version = zr36016_read(ptr, 0) >> 4; - return ptr->version; -} - -/* ========================================================================= - Local helper function: - - basic test of "connectivity", writes/reads to/from PAX-Lo register - ========================================================================= */ - -static int -zr36016_basic_test (struct zr36016 *ptr) -{ - if (debug) { - int i; - zr36016_writei(ptr, ZR016I_PAX_LO, 0x55); - dprintk(1, KERN_INFO "%s: registers: ", ptr->name); - for (i = 0; i <= 0x0b; i++) - dprintk(1, "%02x ", zr36016_readi(ptr, i)); - dprintk(1, "\n"); - } - // for testing just write 0, then the default value to a register and read - // it back in both cases - zr36016_writei(ptr, ZR016I_PAX_LO, 0x00); - if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0) { - dprintk(1, - KERN_ERR - "%s: attach failed, can't connect to vfe processor!\n", - ptr->name); - return -ENXIO; - } - zr36016_writei(ptr, ZR016I_PAX_LO, 0x0d0); - if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0d0) { - dprintk(1, - KERN_ERR - "%s: attach failed, can't connect to vfe processor!\n", - ptr->name); - return -ENXIO; - } - // we allow version numbers from 0-3, should be enough, though - zr36016_read_version(ptr); - if (ptr->version & 0x0c) { - dprintk(1, - KERN_ERR - "%s: attach failed, suspicious version %d found...\n", - ptr->name, ptr->version); - return -ENXIO; - } - - return 0; /* looks good! */ -} - -/* ========================================================================= - Local helper function: - - simple loop for pushing the init datasets - NO USE -- - ========================================================================= */ - -#if 0 -static int zr36016_pushit (struct zr36016 *ptr, - u16 startreg, - u16 len, - const char *data) -{ - int i=0; - - dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", - ptr->name, startreg,len); - while (imode == CODEC_DO_COMPRESSION ? - ZR016_COMPRESSION : ZR016_EXPANSION)); - - // misc setup - zr36016_writei(ptr, ZR016I_SETUP1, - (ptr->xdec ? (ZR016_HRFL | ZR016_HORZ) : 0) | - (ptr->ydec ? ZR016_VERT : 0) | ZR016_CNTI); - zr36016_writei(ptr, ZR016I_SETUP2, ZR016_CCIR); - - // Window setup - // (no extra offset for now, norm defines offset, default width height) - zr36016_writei(ptr, ZR016I_PAX_HI, ptr->width >> 8); - zr36016_writei(ptr, ZR016I_PAX_LO, ptr->width & 0xFF); - zr36016_writei(ptr, ZR016I_PAY_HI, ptr->height >> 8); - zr36016_writei(ptr, ZR016I_PAY_LO, ptr->height & 0xFF); - zr36016_writei(ptr, ZR016I_NAX_HI, ptr->xoff >> 8); - zr36016_writei(ptr, ZR016I_NAX_LO, ptr->xoff & 0xFF); - zr36016_writei(ptr, ZR016I_NAY_HI, ptr->yoff >> 8); - zr36016_writei(ptr, ZR016I_NAY_LO, ptr->yoff & 0xFF); - - /* shall we continue now, please? */ - zr36016_write(ptr, ZR016_GOSTOP, 1); -} - -/* ========================================================================= - CODEC API FUNCTIONS - - this functions are accessed by the master via the API structure - ========================================================================= */ - -/* set compression/expansion mode and launches codec - - this should be the last call from the master before starting processing */ -static int -zr36016_set_mode (struct videocodec *codec, - int mode) -{ - struct zr36016 *ptr = (struct zr36016 *) codec->data; - - dprintk(2, "%s: set_mode %d call\n", ptr->name, mode); - - if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION)) - return -EINVAL; - - ptr->mode = mode; - zr36016_init(ptr); - - return 0; -} - -/* set picture size */ -static int -zr36016_set_video (struct videocodec *codec, - struct tvnorm *norm, - struct vfe_settings *cap, - struct vfe_polarity *pol) -{ - struct zr36016 *ptr = (struct zr36016 *) codec->data; - - dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) call\n", - ptr->name, norm->HStart, norm->VStart, - cap->x, cap->y, cap->width, cap->height, - cap->decimation); - - /* if () return -EINVAL; - * trust the master driver that it knows what it does - so - * we allow invalid startx/y for now ... */ - ptr->width = cap->width; - ptr->height = cap->height; - /* (Ronald) This is ugly. zoran_device.c, line 387 - * already mentions what happens if HStart is even - * (blue faces, etc., cr/cb inversed). There's probably - * some good reason why HStart is 0 instead of 1, so I'm - * leaving it to this for now, but really... This can be - * done a lot simpler */ - ptr->xoff = (norm->HStart ? norm->HStart : 1) + cap->x; - /* Something to note here (I don't understand it), setting - * VStart too high will cause the codec to 'not work'. I - * really don't get it. values of 16 (VStart) already break - * it here. Just '0' seems to work. More testing needed! */ - ptr->yoff = norm->VStart + cap->y; - /* (Ronald) dzjeeh, can't this thing do hor_decimation = 4? */ - ptr->xdec = ((cap->decimation & 0xff) == 1) ? 0 : 1; - ptr->ydec = (((cap->decimation >> 8) & 0xff) == 1) ? 0 : 1; - - return 0; -} - -/* additional control functions */ -static int -zr36016_control (struct videocodec *codec, - int type, - int size, - void *data) -{ - struct zr36016 *ptr = (struct zr36016 *) codec->data; - int *ival = (int *) data; - - dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type, - size); - - switch (type) { - case CODEC_G_STATUS: /* get last status - we don't know it ... */ - if (size != sizeof(int)) - return -EFAULT; - *ival = 0; - break; - - case CODEC_G_CODEC_MODE: - if (size != sizeof(int)) - return -EFAULT; - *ival = 0; - break; - - case CODEC_S_CODEC_MODE: - if (size != sizeof(int)) - return -EFAULT; - if (*ival != 0) - return -EINVAL; - /* not needed, do nothing */ - return 0; - - case CODEC_G_VFE: - case CODEC_S_VFE: - return 0; - - case CODEC_S_MMAP: - /* not available, give an error */ - return -ENXIO; - - default: - return -EINVAL; - } - - return size; -} - -/* ========================================================================= - Exit and unregister function: - - Deinitializes Zoran's JPEG processor - ========================================================================= */ - -static int -zr36016_unset (struct videocodec *codec) -{ - struct zr36016 *ptr = codec->data; - - if (ptr) { - /* do wee need some codec deinit here, too ???? */ - - dprintk(1, "%s: finished codec #%d\n", ptr->name, - ptr->num); - kfree(ptr); - codec->data = NULL; - - zr36016_codecs--; - return 0; - } - - return -EFAULT; -} - -/* ========================================================================= - Setup and registry function: - - Initializes Zoran's JPEG processor - - Also sets pixel size, average code size, mode (compr./decompr.) - (the given size is determined by the processor with the video interface) - ========================================================================= */ - -static int -zr36016_setup (struct videocodec *codec) -{ - struct zr36016 *ptr; - int res; - - dprintk(2, "zr36016: initializing VFE subsystem #%d.\n", - zr36016_codecs); - - if (zr36016_codecs == MAX_CODECS) { - dprintk(1, - KERN_ERR "zr36016: Can't attach more codecs!\n"); - return -ENOSPC; - } - //mem structure init - codec->data = ptr = kzalloc(sizeof(struct zr36016), GFP_KERNEL); - if (NULL == ptr) { - dprintk(1, KERN_ERR "zr36016: Can't get enough memory!\n"); - return -ENOMEM; - } - - snprintf(ptr->name, sizeof(ptr->name), "zr36016[%d]", - zr36016_codecs); - ptr->num = zr36016_codecs++; - ptr->codec = codec; - - //testing - res = zr36016_basic_test(ptr); - if (res < 0) { - zr36016_unset(codec); - return res; - } - //final setup - ptr->mode = CODEC_DO_COMPRESSION; - ptr->width = 768; - ptr->height = 288; - ptr->xdec = 1; - ptr->ydec = 0; - zr36016_init(ptr); - - dprintk(1, KERN_INFO "%s: codec v%d attached and running\n", - ptr->name, ptr->version); - - return 0; -} - -static const struct videocodec zr36016_codec = { - .owner = THIS_MODULE, - .name = "zr36016", - .magic = 0L, // magic not used - .flags = - CODEC_FLAG_HARDWARE | CODEC_FLAG_VFE | CODEC_FLAG_ENCODER | - CODEC_FLAG_DECODER, - .type = CODEC_TYPE_ZR36016, - .setup = zr36016_setup, // functionality - .unset = zr36016_unset, - .set_mode = zr36016_set_mode, - .set_video = zr36016_set_video, - .control = zr36016_control, - // others are not used -}; - -/* ========================================================================= - HOOK IN DRIVER AS KERNEL MODULE - ========================================================================= */ - -static int __init -zr36016_init_module (void) -{ - //dprintk(1, "ZR36016 driver %s\n",ZR016_VERSION); - zr36016_codecs = 0; - return videocodec_register(&zr36016_codec); -} - -static void __exit -zr36016_cleanup_module (void) -{ - if (zr36016_codecs) { - dprintk(1, - "zr36016: something's wrong - %d codecs left somehow.\n", - zr36016_codecs); - } - videocodec_unregister(&zr36016_codec); -} - -module_init(zr36016_init_module); -module_exit(zr36016_cleanup_module); - -MODULE_AUTHOR("Wolfgang Scherr "); -MODULE_DESCRIPTION("Driver module for ZR36016 video frontends " - ZR016_VERSION); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/media/zoran/zr36016.h b/drivers/staging/media/zoran/zr36016.h deleted file mode 100644 index 784bcf5727b8..000000000000 --- a/drivers/staging/media/zoran/zr36016.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Zoran ZR36016 basic configuration functions - header file - * - * Copyright (C) 2001 Wolfgang Scherr - * - * $Id: zr36016.h,v 1.1.2.3 2003/01/14 21:18:07 rbultje Exp $ - * - * ------------------------------------------------------------------------ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * ------------------------------------------------------------------------ - */ - -#ifndef ZR36016_H -#define ZR36016_H - -/* data stored for each zoran jpeg codec chip */ -struct zr36016 { - char name[32]; - int num; - /* io datastructure */ - struct videocodec *codec; - // coder status - __u8 version; - // actual coder setup - int mode; - - __u16 xoff; - __u16 yoff; - __u16 width; - __u16 height; - __u16 xdec; - __u16 ydec; -}; - -/* direct register addresses */ -#define ZR016_GOSTOP 0x00 -#define ZR016_MODE 0x01 -#define ZR016_IADDR 0x02 -#define ZR016_IDATA 0x03 - -/* indirect register addresses */ -#define ZR016I_SETUP1 0x00 -#define ZR016I_SETUP2 0x01 -#define ZR016I_NAX_LO 0x02 -#define ZR016I_NAX_HI 0x03 -#define ZR016I_PAX_LO 0x04 -#define ZR016I_PAX_HI 0x05 -#define ZR016I_NAY_LO 0x06 -#define ZR016I_NAY_HI 0x07 -#define ZR016I_PAY_LO 0x08 -#define ZR016I_PAY_HI 0x09 -#define ZR016I_NOL_LO 0x0a -#define ZR016I_NOL_HI 0x0b - -/* possible values for mode register */ -#define ZR016_RGB444_YUV444 0x00 -#define ZR016_RGB444_YUV422 0x01 -#define ZR016_RGB444_YUV411 0x02 -#define ZR016_RGB444_Y400 0x03 -#define ZR016_RGB444_RGB444 0x04 -#define ZR016_YUV444_YUV444 0x08 -#define ZR016_YUV444_YUV422 0x09 -#define ZR016_YUV444_YUV411 0x0a -#define ZR016_YUV444_Y400 0x0b -#define ZR016_YUV444_RGB444 0x0c -#define ZR016_YUV422_YUV422 0x11 -#define ZR016_YUV422_YUV411 0x12 -#define ZR016_YUV422_Y400 0x13 -#define ZR016_YUV411_YUV411 0x16 -#define ZR016_YUV411_Y400 0x17 -#define ZR016_4444_4444 0x19 -#define ZR016_100_100 0x1b - -#define ZR016_RGB444 0x00 -#define ZR016_YUV444 0x20 -#define ZR016_YUV422 0x40 - -#define ZR016_COMPRESSION 0x80 -#define ZR016_EXPANSION 0x80 - -/* possible values for setup 1 register */ -#define ZR016_CKRT 0x80 -#define ZR016_VERT 0x40 -#define ZR016_HORZ 0x20 -#define ZR016_HRFL 0x10 -#define ZR016_DSFL 0x08 -#define ZR016_SBFL 0x04 -#define ZR016_RSTR 0x02 -#define ZR016_CNTI 0x01 - -/* possible values for setup 2 register */ -#define ZR016_SYEN 0x40 -#define ZR016_CCIR 0x04 -#define ZR016_SIGN 0x02 -#define ZR016_YMCS 0x01 - -#endif /*fndef ZR36016_H */ diff --git a/drivers/staging/media/zoran/zr36050.c b/drivers/staging/media/zoran/zr36050.c deleted file mode 100644 index 5ebfc16672f3..000000000000 --- a/drivers/staging/media/zoran/zr36050.c +++ /dev/null @@ -1,896 +0,0 @@ -/* - * Zoran ZR36050 basic configuration functions - * - * Copyright (C) 2001 Wolfgang Scherr - * - * $Id: zr36050.c,v 1.1.2.11 2003/08/03 14:54:53 rbultje Exp $ - * - * ------------------------------------------------------------------------ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * ------------------------------------------------------------------------ - */ - -#define ZR050_VERSION "v0.7.1" - -#include -#include -#include -#include - -#include -#include - -/* I/O commands, error codes */ -#include - -/* headerfile of this module */ -#include "zr36050.h" - -/* codec io API */ -#include "videocodec.h" - -/* it doesn't make sense to have more than 20 or so, - just to prevent some unwanted loops */ -#define MAX_CODECS 20 - -/* amount of chips attached via this driver */ -static int zr36050_codecs; - -/* debugging is available via module parameter */ -static int debug; -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0-4)"); - -#define dprintk(num, format, args...) \ - do { \ - if (debug >= num) \ - printk(format, ##args); \ - } while (0) - -/* ========================================================================= - Local hardware I/O functions: - - read/write via codec layer (registers are located in the master device) - ========================================================================= */ - -/* read and write functions */ -static u8 -zr36050_read (struct zr36050 *ptr, - u16 reg) -{ - u8 value = 0; - - // just in case something is wrong... - if (ptr->codec->master_data->readreg) - value = (ptr->codec->master_data->readreg(ptr->codec, - reg)) & 0xFF; - else - dprintk(1, - KERN_ERR "%s: invalid I/O setup, nothing read!\n", - ptr->name); - - dprintk(4, "%s: reading from 0x%04x: %02x\n", ptr->name, reg, - value); - - return value; -} - -static void -zr36050_write (struct zr36050 *ptr, - u16 reg, - u8 value) -{ - dprintk(4, "%s: writing 0x%02x to 0x%04x\n", ptr->name, value, - reg); - - // just in case something is wrong... - if (ptr->codec->master_data->writereg) - ptr->codec->master_data->writereg(ptr->codec, reg, value); - else - dprintk(1, - KERN_ERR - "%s: invalid I/O setup, nothing written!\n", - ptr->name); -} - -/* ========================================================================= - Local helper function: - - status read - ========================================================================= */ - -/* status is kept in datastructure */ -static u8 -zr36050_read_status1 (struct zr36050 *ptr) -{ - ptr->status1 = zr36050_read(ptr, ZR050_STATUS_1); - - zr36050_read(ptr, 0); - return ptr->status1; -} - -/* ========================================================================= - Local helper function: - - scale factor read - ========================================================================= */ - -/* scale factor is kept in datastructure */ -static u16 -zr36050_read_scalefactor (struct zr36050 *ptr) -{ - ptr->scalefact = (zr36050_read(ptr, ZR050_SF_HI) << 8) | - (zr36050_read(ptr, ZR050_SF_LO) & 0xFF); - - /* leave 0 selected for an eventually GO from master */ - zr36050_read(ptr, 0); - return ptr->scalefact; -} - -/* ========================================================================= - Local helper function: - - wait if codec is ready to proceed (end of processing) or time is over - ========================================================================= */ - -static void -zr36050_wait_end (struct zr36050 *ptr) -{ - int i = 0; - - while (!(zr36050_read_status1(ptr) & 0x4)) { - udelay(1); - if (i++ > 200000) { // 200ms, there is for sure something wrong!!! - dprintk(1, - "%s: timeout at wait_end (last status: 0x%02x)\n", - ptr->name, ptr->status1); - break; - } - } -} - -/* ========================================================================= - Local helper function: - - basic test of "connectivity", writes/reads to/from memory the SOF marker - ========================================================================= */ - -static int -zr36050_basic_test (struct zr36050 *ptr) -{ - zr36050_write(ptr, ZR050_SOF_IDX, 0x00); - zr36050_write(ptr, ZR050_SOF_IDX + 1, 0x00); - if ((zr36050_read(ptr, ZR050_SOF_IDX) | - zr36050_read(ptr, ZR050_SOF_IDX + 1)) != 0x0000) { - dprintk(1, - KERN_ERR - "%s: attach failed, can't connect to jpeg processor!\n", - ptr->name); - return -ENXIO; - } - zr36050_write(ptr, ZR050_SOF_IDX, 0xff); - zr36050_write(ptr, ZR050_SOF_IDX + 1, 0xc0); - if (((zr36050_read(ptr, ZR050_SOF_IDX) << 8) | - zr36050_read(ptr, ZR050_SOF_IDX + 1)) != 0xffc0) { - dprintk(1, - KERN_ERR - "%s: attach failed, can't connect to jpeg processor!\n", - ptr->name); - return -ENXIO; - } - - zr36050_wait_end(ptr); - if ((ptr->status1 & 0x4) == 0) { - dprintk(1, - KERN_ERR - "%s: attach failed, jpeg processor failed (end flag)!\n", - ptr->name); - return -EBUSY; - } - - return 0; /* looks good! */ -} - -/* ========================================================================= - Local helper function: - - simple loop for pushing the init datasets - ========================================================================= */ - -static int -zr36050_pushit (struct zr36050 *ptr, - u16 startreg, - u16 len, - const char *data) -{ - int i = 0; - - dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", ptr->name, - startreg, len); - while (i < len) { - zr36050_write(ptr, startreg++, data[i++]); - } - - return i; -} - -/* ========================================================================= - Basic datasets: - - jpeg baseline setup data (you find it on lots places in internet, or just - extract it from any regular .jpg image...) - - Could be variable, but until it's not needed it they are just fixed to save - memory. Otherwise expand zr36050 structure with arrays, push the values to - it and initialize from there, as e.g. the linux zr36057/60 driver does it. - ========================================================================= */ - -static const char zr36050_dqt[0x86] = { - 0xff, 0xdb, //Marker: DQT - 0x00, 0x84, //Length: 2*65+2 - 0x00, //Pq,Tq first table - 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, - 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, - 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, - 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, - 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44, - 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, - 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, - 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63, - 0x01, //Pq,Tq second table - 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, - 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63 -}; - -static const char zr36050_dht[0x1a4] = { - 0xff, 0xc4, //Marker: DHT - 0x01, 0xa2, //Length: 2*AC, 2*DC - 0x00, //DC first table - 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, - 0x01, //DC second table - 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, - 0x10, //AC first table - 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, - 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, - 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, - 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, - 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, - 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, - 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, - 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, - 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, - 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, - 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, - 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, - 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, - 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, - 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, - 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, - 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, - 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, - 0xF8, 0xF9, 0xFA, - 0x11, //AC second table - 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, - 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, - 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, - 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, - 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, - 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, - 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, - 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, - 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, - 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, - 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, - 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, - 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, - 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, - 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, - 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, - 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, - 0xF9, 0xFA -}; - -/* jpeg baseline setup, this is just fixed in this driver (YUV pictures) */ -#define NO_OF_COMPONENTS 0x3 //Y,U,V -#define BASELINE_PRECISION 0x8 //MCU size (?) -static const char zr36050_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's QT -static const char zr36050_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's DC -static const char zr36050_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's AC - -/* horizontal 422 decimation setup (maybe we support 411 or so later, too) */ -static const char zr36050_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 }; -static const char zr36050_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 }; - -/* ========================================================================= - Local helper functions: - - calculation and setup of parameter-dependent JPEG baseline segments - (needed for compression only) - ========================================================================= */ - -/* ------------------------------------------------------------------------- */ - -/* SOF (start of frame) segment depends on width, height and sampling ratio - of each color component */ - -static int -zr36050_set_sof (struct zr36050 *ptr) -{ - char sof_data[34]; // max. size of register set - int i; - - dprintk(3, "%s: write SOF (%dx%d, %d components)\n", ptr->name, - ptr->width, ptr->height, NO_OF_COMPONENTS); - sof_data[0] = 0xff; - sof_data[1] = 0xc0; - sof_data[2] = 0x00; - sof_data[3] = (3 * NO_OF_COMPONENTS) + 8; - sof_data[4] = BASELINE_PRECISION; // only '8' possible with zr36050 - sof_data[5] = (ptr->height) >> 8; - sof_data[6] = (ptr->height) & 0xff; - sof_data[7] = (ptr->width) >> 8; - sof_data[8] = (ptr->width) & 0xff; - sof_data[9] = NO_OF_COMPONENTS; - for (i = 0; i < NO_OF_COMPONENTS; i++) { - sof_data[10 + (i * 3)] = i; // index identifier - sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) | (ptr->v_samp_ratio[i]); // sampling ratios - sof_data[12 + (i * 3)] = zr36050_tq[i]; // Q table selection - } - return zr36050_pushit(ptr, ZR050_SOF_IDX, - (3 * NO_OF_COMPONENTS) + 10, sof_data); -} - -/* ------------------------------------------------------------------------- */ - -/* SOS (start of scan) segment depends on the used scan components - of each color component */ - -static int -zr36050_set_sos (struct zr36050 *ptr) -{ - char sos_data[16]; // max. size of register set - int i; - - dprintk(3, "%s: write SOS\n", ptr->name); - sos_data[0] = 0xff; - sos_data[1] = 0xda; - sos_data[2] = 0x00; - sos_data[3] = 2 + 1 + (2 * NO_OF_COMPONENTS) + 3; - sos_data[4] = NO_OF_COMPONENTS; - for (i = 0; i < NO_OF_COMPONENTS; i++) { - sos_data[5 + (i * 2)] = i; // index - sos_data[6 + (i * 2)] = (zr36050_td[i] << 4) | zr36050_ta[i]; // AC/DC tbl.sel. - } - sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00; // scan start - sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3F; - sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 4] = 00; - return zr36050_pushit(ptr, ZR050_SOS1_IDX, - 4 + 1 + (2 * NO_OF_COMPONENTS) + 3, - sos_data); -} - -/* ------------------------------------------------------------------------- */ - -/* DRI (define restart interval) */ - -static int -zr36050_set_dri (struct zr36050 *ptr) -{ - char dri_data[6]; // max. size of register set - - dprintk(3, "%s: write DRI\n", ptr->name); - dri_data[0] = 0xff; - dri_data[1] = 0xdd; - dri_data[2] = 0x00; - dri_data[3] = 0x04; - dri_data[4] = ptr->dri >> 8; - dri_data[5] = ptr->dri & 0xff; - return zr36050_pushit(ptr, ZR050_DRI_IDX, 6, dri_data); -} - -/* ========================================================================= - Setup function: - - Setup compression/decompression of Zoran's JPEG processor - ( see also zoran 36050 manual ) - - ... sorry for the spaghetti code ... - ========================================================================= */ -static void -zr36050_init (struct zr36050 *ptr) -{ - int sum = 0; - long bitcnt, tmp; - - if (ptr->mode == CODEC_DO_COMPRESSION) { - dprintk(2, "%s: COMPRESSION SETUP\n", ptr->name); - - /* 050 communicates with 057 in master mode */ - zr36050_write(ptr, ZR050_HARDWARE, ZR050_HW_MSTR); - - /* encoding table preload for compression */ - zr36050_write(ptr, ZR050_MODE, - ZR050_MO_COMP | ZR050_MO_TLM); - zr36050_write(ptr, ZR050_OPTIONS, 0); - - /* disable all IRQs */ - zr36050_write(ptr, ZR050_INT_REQ_0, 0); - zr36050_write(ptr, ZR050_INT_REQ_1, 3); // low 2 bits always 1 - - /* volume control settings */ - /*zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol);*/ - zr36050_write(ptr, ZR050_SF_HI, ptr->scalefact >> 8); - zr36050_write(ptr, ZR050_SF_LO, ptr->scalefact & 0xff); - - zr36050_write(ptr, ZR050_AF_HI, 0xff); - zr36050_write(ptr, ZR050_AF_M, 0xff); - zr36050_write(ptr, ZR050_AF_LO, 0xff); - - /* setup the variable jpeg tables */ - sum += zr36050_set_sof(ptr); - sum += zr36050_set_sos(ptr); - sum += zr36050_set_dri(ptr); - - /* setup the fixed jpeg tables - maybe variable, though - - * (see table init section above) */ - dprintk(3, "%s: write DQT, DHT, APP\n", ptr->name); - sum += zr36050_pushit(ptr, ZR050_DQT_IDX, - sizeof(zr36050_dqt), zr36050_dqt); - sum += zr36050_pushit(ptr, ZR050_DHT_IDX, - sizeof(zr36050_dht), zr36050_dht); - zr36050_write(ptr, ZR050_APP_IDX, 0xff); - zr36050_write(ptr, ZR050_APP_IDX + 1, 0xe0 + ptr->app.appn); - zr36050_write(ptr, ZR050_APP_IDX + 2, 0x00); - zr36050_write(ptr, ZR050_APP_IDX + 3, ptr->app.len + 2); - sum += zr36050_pushit(ptr, ZR050_APP_IDX + 4, 60, - ptr->app.data) + 4; - zr36050_write(ptr, ZR050_COM_IDX, 0xff); - zr36050_write(ptr, ZR050_COM_IDX + 1, 0xfe); - zr36050_write(ptr, ZR050_COM_IDX + 2, 0x00); - zr36050_write(ptr, ZR050_COM_IDX + 3, ptr->com.len + 2); - sum += zr36050_pushit(ptr, ZR050_COM_IDX + 4, 60, - ptr->com.data) + 4; - - /* do the internal huffman table preload */ - zr36050_write(ptr, ZR050_MARKERS_EN, ZR050_ME_DHTI); - - zr36050_write(ptr, ZR050_GO, 1); // launch codec - zr36050_wait_end(ptr); - dprintk(2, "%s: Status after table preload: 0x%02x\n", - ptr->name, ptr->status1); - - if ((ptr->status1 & 0x4) == 0) { - dprintk(1, KERN_ERR "%s: init aborted!\n", - ptr->name); - return; // something is wrong, its timed out!!!! - } - - /* setup misc. data for compression (target code sizes) */ - - /* size of compressed code to reach without header data */ - sum = ptr->real_code_vol - sum; - bitcnt = sum << 3; /* need the size in bits */ - - tmp = bitcnt >> 16; - dprintk(3, - "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n", - ptr->name, sum, ptr->real_code_vol, bitcnt, tmp); - zr36050_write(ptr, ZR050_TCV_NET_HI, tmp >> 8); - zr36050_write(ptr, ZR050_TCV_NET_MH, tmp & 0xff); - tmp = bitcnt & 0xffff; - zr36050_write(ptr, ZR050_TCV_NET_ML, tmp >> 8); - zr36050_write(ptr, ZR050_TCV_NET_LO, tmp & 0xff); - - bitcnt -= bitcnt >> 7; // bits without stuffing - bitcnt -= ((bitcnt * 5) >> 6); // bits without eob - - tmp = bitcnt >> 16; - dprintk(3, "%s: code: nettobit=%ld, highnettobits=%ld\n", - ptr->name, bitcnt, tmp); - zr36050_write(ptr, ZR050_TCV_DATA_HI, tmp >> 8); - zr36050_write(ptr, ZR050_TCV_DATA_MH, tmp & 0xff); - tmp = bitcnt & 0xffff; - zr36050_write(ptr, ZR050_TCV_DATA_ML, tmp >> 8); - zr36050_write(ptr, ZR050_TCV_DATA_LO, tmp & 0xff); - - /* compression setup with or without bitrate control */ - zr36050_write(ptr, ZR050_MODE, - ZR050_MO_COMP | ZR050_MO_PASS2 | - (ptr->bitrate_ctrl ? ZR050_MO_BRC : 0)); - - /* this headers seem to deliver "valid AVI" jpeg frames */ - zr36050_write(ptr, ZR050_MARKERS_EN, - ZR050_ME_DQT | ZR050_ME_DHT | - ((ptr->app.len > 0) ? ZR050_ME_APP : 0) | - ((ptr->com.len > 0) ? ZR050_ME_COM : 0)); - } else { - dprintk(2, "%s: EXPANSION SETUP\n", ptr->name); - - /* 050 communicates with 055 in master mode */ - zr36050_write(ptr, ZR050_HARDWARE, - ZR050_HW_MSTR | ZR050_HW_CFIS_2_CLK); - - /* encoding table preload */ - zr36050_write(ptr, ZR050_MODE, ZR050_MO_TLM); - - /* disable all IRQs */ - zr36050_write(ptr, ZR050_INT_REQ_0, 0); - zr36050_write(ptr, ZR050_INT_REQ_1, 3); // low 2 bits always 1 - - dprintk(3, "%s: write DHT\n", ptr->name); - zr36050_pushit(ptr, ZR050_DHT_IDX, sizeof(zr36050_dht), - zr36050_dht); - - /* do the internal huffman table preload */ - zr36050_write(ptr, ZR050_MARKERS_EN, ZR050_ME_DHTI); - - zr36050_write(ptr, ZR050_GO, 1); // launch codec - zr36050_wait_end(ptr); - dprintk(2, "%s: Status after table preload: 0x%02x\n", - ptr->name, ptr->status1); - - if ((ptr->status1 & 0x4) == 0) { - dprintk(1, KERN_ERR "%s: init aborted!\n", - ptr->name); - return; // something is wrong, its timed out!!!! - } - - /* setup misc. data for expansion */ - zr36050_write(ptr, ZR050_MODE, 0); - zr36050_write(ptr, ZR050_MARKERS_EN, 0); - } - - /* adr on selected, to allow GO from master */ - zr36050_read(ptr, 0); -} - -/* ========================================================================= - CODEC API FUNCTIONS - - this functions are accessed by the master via the API structure - ========================================================================= */ - -/* set compression/expansion mode and launches codec - - this should be the last call from the master before starting processing */ -static int -zr36050_set_mode (struct videocodec *codec, - int mode) -{ - struct zr36050 *ptr = (struct zr36050 *) codec->data; - - dprintk(2, "%s: set_mode %d call\n", ptr->name, mode); - - if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION)) - return -EINVAL; - - ptr->mode = mode; - zr36050_init(ptr); - - return 0; -} - -/* set picture size (norm is ignored as the codec doesn't know about it) */ -static int -zr36050_set_video (struct videocodec *codec, - struct tvnorm *norm, - struct vfe_settings *cap, - struct vfe_polarity *pol) -{ - struct zr36050 *ptr = (struct zr36050 *) codec->data; - int size; - - dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) q%d call\n", - ptr->name, norm->HStart, norm->VStart, - cap->x, cap->y, cap->width, cap->height, - cap->decimation, cap->quality); - /* if () return -EINVAL; - * trust the master driver that it knows what it does - so - * we allow invalid startx/y and norm for now ... */ - ptr->width = cap->width / (cap->decimation & 0xff); - ptr->height = cap->height / ((cap->decimation >> 8) & 0xff); - - /* (KM) JPEG quality */ - size = ptr->width * ptr->height; - size *= 16; /* size in bits */ - /* apply quality setting */ - size = size * cap->quality / 200; - - /* Minimum: 1kb */ - if (size < 8192) - size = 8192; - /* Maximum: 7/8 of code buffer */ - if (size > ptr->total_code_vol * 7) - size = ptr->total_code_vol * 7; - - ptr->real_code_vol = size >> 3; /* in bytes */ - - /* Set max_block_vol here (previously in zr36050_init, moved - * here for consistency with zr36060 code */ - zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol); - - return 0; -} - -/* additional control functions */ -static int -zr36050_control (struct videocodec *codec, - int type, - int size, - void *data) -{ - struct zr36050 *ptr = (struct zr36050 *) codec->data; - int *ival = (int *) data; - - dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type, - size); - - switch (type) { - case CODEC_G_STATUS: /* get last status */ - if (size != sizeof(int)) - return -EFAULT; - zr36050_read_status1(ptr); - *ival = ptr->status1; - break; - - case CODEC_G_CODEC_MODE: - if (size != sizeof(int)) - return -EFAULT; - *ival = CODEC_MODE_BJPG; - break; - - case CODEC_S_CODEC_MODE: - if (size != sizeof(int)) - return -EFAULT; - if (*ival != CODEC_MODE_BJPG) - return -EINVAL; - /* not needed, do nothing */ - return 0; - - case CODEC_G_VFE: - case CODEC_S_VFE: - /* not needed, do nothing */ - return 0; - - case CODEC_S_MMAP: - /* not available, give an error */ - return -ENXIO; - - case CODEC_G_JPEG_TDS_BYTE: /* get target volume in byte */ - if (size != sizeof(int)) - return -EFAULT; - *ival = ptr->total_code_vol; - break; - - case CODEC_S_JPEG_TDS_BYTE: /* get target volume in byte */ - if (size != sizeof(int)) - return -EFAULT; - ptr->total_code_vol = *ival; - /* (Kieran Morrissey) - * code copied from zr36060.c to ensure proper bitrate */ - ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3; - break; - - case CODEC_G_JPEG_SCALE: /* get scaling factor */ - if (size != sizeof(int)) - return -EFAULT; - *ival = zr36050_read_scalefactor(ptr); - break; - - case CODEC_S_JPEG_SCALE: /* set scaling factor */ - if (size != sizeof(int)) - return -EFAULT; - ptr->scalefact = *ival; - break; - - case CODEC_G_JPEG_APP_DATA: { /* get appn marker data */ - struct jpeg_app_marker *app = data; - - if (size != sizeof(struct jpeg_app_marker)) - return -EFAULT; - - *app = ptr->app; - break; - } - - case CODEC_S_JPEG_APP_DATA: { /* set appn marker data */ - struct jpeg_app_marker *app = data; - - if (size != sizeof(struct jpeg_app_marker)) - return -EFAULT; - - ptr->app = *app; - break; - } - - case CODEC_G_JPEG_COM_DATA: { /* get comment marker data */ - struct jpeg_com_marker *com = data; - - if (size != sizeof(struct jpeg_com_marker)) - return -EFAULT; - - *com = ptr->com; - break; - } - - case CODEC_S_JPEG_COM_DATA: { /* set comment marker data */ - struct jpeg_com_marker *com = data; - - if (size != sizeof(struct jpeg_com_marker)) - return -EFAULT; - - ptr->com = *com; - break; - } - - default: - return -EINVAL; - } - - return size; -} - -/* ========================================================================= - Exit and unregister function: - - Deinitializes Zoran's JPEG processor - ========================================================================= */ - -static int -zr36050_unset (struct videocodec *codec) -{ - struct zr36050 *ptr = codec->data; - - if (ptr) { - /* do wee need some codec deinit here, too ???? */ - - dprintk(1, "%s: finished codec #%d\n", ptr->name, - ptr->num); - kfree(ptr); - codec->data = NULL; - - zr36050_codecs--; - return 0; - } - - return -EFAULT; -} - -/* ========================================================================= - Setup and registry function: - - Initializes Zoran's JPEG processor - - Also sets pixel size, average code size, mode (compr./decompr.) - (the given size is determined by the processor with the video interface) - ========================================================================= */ - -static int -zr36050_setup (struct videocodec *codec) -{ - struct zr36050 *ptr; - int res; - - dprintk(2, "zr36050: initializing MJPEG subsystem #%d.\n", - zr36050_codecs); - - if (zr36050_codecs == MAX_CODECS) { - dprintk(1, - KERN_ERR "zr36050: Can't attach more codecs!\n"); - return -ENOSPC; - } - //mem structure init - codec->data = ptr = kzalloc(sizeof(struct zr36050), GFP_KERNEL); - if (NULL == ptr) { - dprintk(1, KERN_ERR "zr36050: Can't get enough memory!\n"); - return -ENOMEM; - } - - snprintf(ptr->name, sizeof(ptr->name), "zr36050[%d]", - zr36050_codecs); - ptr->num = zr36050_codecs++; - ptr->codec = codec; - - //testing - res = zr36050_basic_test(ptr); - if (res < 0) { - zr36050_unset(codec); - return res; - } - //final setup - memcpy(ptr->h_samp_ratio, zr36050_decimation_h, 8); - memcpy(ptr->v_samp_ratio, zr36050_decimation_v, 8); - - ptr->bitrate_ctrl = 0; /* 0 or 1 - fixed file size flag - * (what is the difference?) */ - ptr->mode = CODEC_DO_COMPRESSION; - ptr->width = 384; - ptr->height = 288; - ptr->total_code_vol = 16000; - ptr->max_block_vol = 240; - ptr->scalefact = 0x100; - ptr->dri = 1; - - /* no app/com marker by default */ - ptr->app.appn = 0; - ptr->app.len = 0; - ptr->com.len = 0; - - zr36050_init(ptr); - - dprintk(1, KERN_INFO "%s: codec attached and running\n", - ptr->name); - - return 0; -} - -static const struct videocodec zr36050_codec = { - .owner = THIS_MODULE, - .name = "zr36050", - .magic = 0L, // magic not used - .flags = - CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER | - CODEC_FLAG_DECODER, - .type = CODEC_TYPE_ZR36050, - .setup = zr36050_setup, // functionality - .unset = zr36050_unset, - .set_mode = zr36050_set_mode, - .set_video = zr36050_set_video, - .control = zr36050_control, - // others are not used -}; - -/* ========================================================================= - HOOK IN DRIVER AS KERNEL MODULE - ========================================================================= */ - -static int __init -zr36050_init_module (void) -{ - //dprintk(1, "ZR36050 driver %s\n",ZR050_VERSION); - zr36050_codecs = 0; - return videocodec_register(&zr36050_codec); -} - -static void __exit -zr36050_cleanup_module (void) -{ - if (zr36050_codecs) { - dprintk(1, - "zr36050: something's wrong - %d codecs left somehow.\n", - zr36050_codecs); - } - videocodec_unregister(&zr36050_codec); -} - -module_init(zr36050_init_module); -module_exit(zr36050_cleanup_module); - -MODULE_AUTHOR("Wolfgang Scherr "); -MODULE_DESCRIPTION("Driver module for ZR36050 jpeg processors " - ZR050_VERSION); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/media/zoran/zr36050.h b/drivers/staging/media/zoran/zr36050.h deleted file mode 100644 index 9236486d3c2b..000000000000 --- a/drivers/staging/media/zoran/zr36050.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Zoran ZR36050 basic configuration functions - header file - * - * Copyright (C) 2001 Wolfgang Scherr - * - * $Id: zr36050.h,v 1.1.2.2 2003/01/14 21:18:22 rbultje Exp $ - * - * ------------------------------------------------------------------------ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * ------------------------------------------------------------------------ - */ - -#ifndef ZR36050_H -#define ZR36050_H - -#include "videocodec.h" - -/* data stored for each zoran jpeg codec chip */ -struct zr36050 { - char name[32]; - int num; - /* io datastructure */ - struct videocodec *codec; - // last coder status - __u8 status1; - // actual coder setup - int mode; - - __u16 width; - __u16 height; - - __u16 bitrate_ctrl; - - __u32 total_code_vol; - __u32 real_code_vol; - __u16 max_block_vol; - - __u8 h_samp_ratio[8]; - __u8 v_samp_ratio[8]; - __u16 scalefact; - __u16 dri; - - /* com/app marker */ - struct jpeg_com_marker com; - struct jpeg_app_marker app; -}; - -/* zr36050 register addresses */ -#define ZR050_GO 0x000 -#define ZR050_HARDWARE 0x002 -#define ZR050_MODE 0x003 -#define ZR050_OPTIONS 0x004 -#define ZR050_MBCV 0x005 -#define ZR050_MARKERS_EN 0x006 -#define ZR050_INT_REQ_0 0x007 -#define ZR050_INT_REQ_1 0x008 -#define ZR050_TCV_NET_HI 0x009 -#define ZR050_TCV_NET_MH 0x00a -#define ZR050_TCV_NET_ML 0x00b -#define ZR050_TCV_NET_LO 0x00c -#define ZR050_TCV_DATA_HI 0x00d -#define ZR050_TCV_DATA_MH 0x00e -#define ZR050_TCV_DATA_ML 0x00f -#define ZR050_TCV_DATA_LO 0x010 -#define ZR050_SF_HI 0x011 -#define ZR050_SF_LO 0x012 -#define ZR050_AF_HI 0x013 -#define ZR050_AF_M 0x014 -#define ZR050_AF_LO 0x015 -#define ZR050_ACV_HI 0x016 -#define ZR050_ACV_MH 0x017 -#define ZR050_ACV_ML 0x018 -#define ZR050_ACV_LO 0x019 -#define ZR050_ACT_HI 0x01a -#define ZR050_ACT_MH 0x01b -#define ZR050_ACT_ML 0x01c -#define ZR050_ACT_LO 0x01d -#define ZR050_ACV_TRUN_HI 0x01e -#define ZR050_ACV_TRUN_MH 0x01f -#define ZR050_ACV_TRUN_ML 0x020 -#define ZR050_ACV_TRUN_LO 0x021 -#define ZR050_STATUS_0 0x02e -#define ZR050_STATUS_1 0x02f - -#define ZR050_SOF_IDX 0x040 -#define ZR050_SOS1_IDX 0x07a -#define ZR050_SOS2_IDX 0x08a -#define ZR050_SOS3_IDX 0x09a -#define ZR050_SOS4_IDX 0x0aa -#define ZR050_DRI_IDX 0x0c0 -#define ZR050_DNL_IDX 0x0c6 -#define ZR050_DQT_IDX 0x0cc -#define ZR050_DHT_IDX 0x1d4 -#define ZR050_APP_IDX 0x380 -#define ZR050_COM_IDX 0x3c0 - -/* zr36050 hardware register bits */ - -#define ZR050_HW_BSWD 0x80 -#define ZR050_HW_MSTR 0x40 -#define ZR050_HW_DMA 0x20 -#define ZR050_HW_CFIS_1_CLK 0x00 -#define ZR050_HW_CFIS_2_CLK 0x04 -#define ZR050_HW_CFIS_3_CLK 0x08 -#define ZR050_HW_CFIS_4_CLK 0x0C -#define ZR050_HW_CFIS_5_CLK 0x10 -#define ZR050_HW_CFIS_6_CLK 0x14 -#define ZR050_HW_CFIS_7_CLK 0x18 -#define ZR050_HW_CFIS_8_CLK 0x1C -#define ZR050_HW_BELE 0x01 - -/* zr36050 mode register bits */ - -#define ZR050_MO_COMP 0x80 -#define ZR050_MO_ATP 0x40 -#define ZR050_MO_PASS2 0x20 -#define ZR050_MO_TLM 0x10 -#define ZR050_MO_DCONLY 0x08 -#define ZR050_MO_BRC 0x04 - -#define ZR050_MO_ATP 0x40 -#define ZR050_MO_PASS2 0x20 -#define ZR050_MO_TLM 0x10 -#define ZR050_MO_DCONLY 0x08 - -/* zr36050 option register bits */ - -#define ZR050_OP_NSCN_1 0x00 -#define ZR050_OP_NSCN_2 0x20 -#define ZR050_OP_NSCN_3 0x40 -#define ZR050_OP_NSCN_4 0x60 -#define ZR050_OP_NSCN_5 0x80 -#define ZR050_OP_NSCN_6 0xA0 -#define ZR050_OP_NSCN_7 0xC0 -#define ZR050_OP_NSCN_8 0xE0 -#define ZR050_OP_OVF 0x10 - - -/* zr36050 markers-enable register bits */ - -#define ZR050_ME_APP 0x80 -#define ZR050_ME_COM 0x40 -#define ZR050_ME_DRI 0x20 -#define ZR050_ME_DQT 0x10 -#define ZR050_ME_DHT 0x08 -#define ZR050_ME_DNL 0x04 -#define ZR050_ME_DQTI 0x02 -#define ZR050_ME_DHTI 0x01 - -/* zr36050 status0/1 register bit masks */ - -#define ZR050_ST_RST_MASK 0x20 -#define ZR050_ST_SOF_MASK 0x02 -#define ZR050_ST_SOS_MASK 0x02 -#define ZR050_ST_DATRDY_MASK 0x80 -#define ZR050_ST_MRKDET_MASK 0x40 -#define ZR050_ST_RFM_MASK 0x10 -#define ZR050_ST_RFD_MASK 0x08 -#define ZR050_ST_END_MASK 0x04 -#define ZR050_ST_TCVOVF_MASK 0x02 -#define ZR050_ST_DATOVF_MASK 0x01 - -/* pixel component idx */ - -#define ZR050_Y_COMPONENT 0 -#define ZR050_U_COMPONENT 1 -#define ZR050_V_COMPONENT 2 - -#endif /*fndef ZR36050_H */ diff --git a/drivers/staging/media/zoran/zr36057.h b/drivers/staging/media/zoran/zr36057.h deleted file mode 100644 index c8acb21dcb5c..000000000000 --- a/drivers/staging/media/zoran/zr36057.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * zr36057.h - zr36057 register offsets - * - * Copyright (C) 1998 Dave Perks - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _ZR36057_H_ -#define _ZR36057_H_ - - -/* Zoran ZR36057 registers */ - -#define ZR36057_VFEHCR 0x000 /* Video Front End, Horizontal Configuration Register */ -#define ZR36057_VFEHCR_HSPol (1<<30) -#define ZR36057_VFEHCR_HStart 10 -#define ZR36057_VFEHCR_HEnd 0 -#define ZR36057_VFEHCR_Hmask 0x3ff - -#define ZR36057_VFEVCR 0x004 /* Video Front End, Vertical Configuration Register */ -#define ZR36057_VFEVCR_VSPol (1<<30) -#define ZR36057_VFEVCR_VStart 10 -#define ZR36057_VFEVCR_VEnd 0 -#define ZR36057_VFEVCR_Vmask 0x3ff - -#define ZR36057_VFESPFR 0x008 /* Video Front End, Scaler and Pixel Format Register */ -#define ZR36057_VFESPFR_ExtFl (1<<26) -#define ZR36057_VFESPFR_TopField (1<<25) -#define ZR36057_VFESPFR_VCLKPol (1<<24) -#define ZR36057_VFESPFR_HFilter 21 -#define ZR36057_VFESPFR_HorDcm 14 -#define ZR36057_VFESPFR_VerDcm 8 -#define ZR36057_VFESPFR_DispMode 6 -#define ZR36057_VFESPFR_YUV422 (0<<3) -#define ZR36057_VFESPFR_RGB888 (1<<3) -#define ZR36057_VFESPFR_RGB565 (2<<3) -#define ZR36057_VFESPFR_RGB555 (3<<3) -#define ZR36057_VFESPFR_ErrDif (1<<2) -#define ZR36057_VFESPFR_Pack24 (1<<1) -#define ZR36057_VFESPFR_LittleEndian (1<<0) - -#define ZR36057_VDTR 0x00c /* Video Display "Top" Register */ - -#define ZR36057_VDBR 0x010 /* Video Display "Bottom" Register */ - -#define ZR36057_VSSFGR 0x014 /* Video Stride, Status, and Frame Grab Register */ -#define ZR36057_VSSFGR_DispStride 16 -#define ZR36057_VSSFGR_VidOvf (1<<8) -#define ZR36057_VSSFGR_SnapShot (1<<1) -#define ZR36057_VSSFGR_FrameGrab (1<<0) - -#define ZR36057_VDCR 0x018 /* Video Display Configuration Register */ -#define ZR36057_VDCR_VidEn (1<<31) -#define ZR36057_VDCR_MinPix 24 -#define ZR36057_VDCR_Triton (1<<24) -#define ZR36057_VDCR_VidWinHt 12 -#define ZR36057_VDCR_VidWinWid 0 - -#define ZR36057_MMTR 0x01c /* Masking Map "Top" Register */ - -#define ZR36057_MMBR 0x020 /* Masking Map "Bottom" Register */ - -#define ZR36057_OCR 0x024 /* Overlay Control Register */ -#define ZR36057_OCR_OvlEnable (1 << 15) -#define ZR36057_OCR_MaskStride 0 - -#define ZR36057_SPGPPCR 0x028 /* System, PCI, and General Purpose Pins Control Register */ -#define ZR36057_SPGPPCR_SoftReset (1<<24) - -#define ZR36057_GPPGCR1 0x02c /* General Purpose Pins and GuestBus Control Register (1) */ - -#define ZR36057_MCSAR 0x030 /* MPEG Code Source Address Register */ - -#define ZR36057_MCTCR 0x034 /* MPEG Code Transfer Control Register */ -#define ZR36057_MCTCR_CodTime (1 << 30) -#define ZR36057_MCTCR_CEmpty (1 << 29) -#define ZR36057_MCTCR_CFlush (1 << 28) -#define ZR36057_MCTCR_CodGuestID 20 -#define ZR36057_MCTCR_CodGuestReg 16 - -#define ZR36057_MCMPR 0x038 /* MPEG Code Memory Pointer Register */ - -#define ZR36057_ISR 0x03c /* Interrupt Status Register */ -#define ZR36057_ISR_GIRQ1 (1<<30) -#define ZR36057_ISR_GIRQ0 (1<<29) -#define ZR36057_ISR_CodRepIRQ (1<<28) -#define ZR36057_ISR_JPEGRepIRQ (1<<27) - -#define ZR36057_ICR 0x040 /* Interrupt Control Register */ -#define ZR36057_ICR_GIRQ1 (1<<30) -#define ZR36057_ICR_GIRQ0 (1<<29) -#define ZR36057_ICR_CodRepIRQ (1<<28) -#define ZR36057_ICR_JPEGRepIRQ (1<<27) -#define ZR36057_ICR_IntPinEn (1<<24) - -#define ZR36057_I2CBR 0x044 /* I2C Bus Register */ -#define ZR36057_I2CBR_SDA (1<<1) -#define ZR36057_I2CBR_SCL (1<<0) - -#define ZR36057_JMC 0x100 /* JPEG Mode and Control */ -#define ZR36057_JMC_JPG (1 << 31) -#define ZR36057_JMC_JPGExpMode (0 << 29) -#define ZR36057_JMC_JPGCmpMode (1 << 29) -#define ZR36057_JMC_MJPGExpMode (2 << 29) -#define ZR36057_JMC_MJPGCmpMode (3 << 29) -#define ZR36057_JMC_RTBUSY_FB (1 << 6) -#define ZR36057_JMC_Go_en (1 << 5) -#define ZR36057_JMC_SyncMstr (1 << 4) -#define ZR36057_JMC_Fld_per_buff (1 << 3) -#define ZR36057_JMC_VFIFO_FB (1 << 2) -#define ZR36057_JMC_CFIFO_FB (1 << 1) -#define ZR36057_JMC_Stll_LitEndian (1 << 0) - -#define ZR36057_JPC 0x104 /* JPEG Process Control */ -#define ZR36057_JPC_P_Reset (1 << 7) -#define ZR36057_JPC_CodTrnsEn (1 << 5) -#define ZR36057_JPC_Active (1 << 0) - -#define ZR36057_VSP 0x108 /* Vertical Sync Parameters */ -#define ZR36057_VSP_VsyncSize 16 -#define ZR36057_VSP_FrmTot 0 - -#define ZR36057_HSP 0x10c /* Horizontal Sync Parameters */ -#define ZR36057_HSP_HsyncStart 16 -#define ZR36057_HSP_LineTot 0 - -#define ZR36057_FHAP 0x110 /* Field Horizontal Active Portion */ -#define ZR36057_FHAP_NAX 16 -#define ZR36057_FHAP_PAX 0 - -#define ZR36057_FVAP 0x114 /* Field Vertical Active Portion */ -#define ZR36057_FVAP_NAY 16 -#define ZR36057_FVAP_PAY 0 - -#define ZR36057_FPP 0x118 /* Field Process Parameters */ -#define ZR36057_FPP_Odd_Even (1 << 0) - -#define ZR36057_JCBA 0x11c /* JPEG Code Base Address */ - -#define ZR36057_JCFT 0x120 /* JPEG Code FIFO Threshold */ - -#define ZR36057_JCGI 0x124 /* JPEG Codec Guest ID */ -#define ZR36057_JCGI_JPEGuestID 4 -#define ZR36057_JCGI_JPEGuestReg 0 - -#define ZR36057_GCR2 0x12c /* GuestBus Control Register (2) */ - -#define ZR36057_POR 0x200 /* Post Office Register */ -#define ZR36057_POR_POPen (1<<25) -#define ZR36057_POR_POTime (1<<24) -#define ZR36057_POR_PODir (1<<23) - -#define ZR36057_STR 0x300 /* "Still" Transfer Register */ - -#endif diff --git a/drivers/staging/media/zoran/zr36060.c b/drivers/staging/media/zoran/zr36060.c deleted file mode 100644 index 2c2e8130fc96..000000000000 --- a/drivers/staging/media/zoran/zr36060.c +++ /dev/null @@ -1,1006 +0,0 @@ -/* - * Zoran ZR36060 basic configuration functions - * - * Copyright (C) 2002 Laurent Pinchart - * - * $Id: zr36060.c,v 1.1.2.22 2003/05/06 09:35:36 rbultje Exp $ - * - * ------------------------------------------------------------------------ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * ------------------------------------------------------------------------ - */ - -#define ZR060_VERSION "v0.7" - -#include -#include -#include -#include - -#include -#include - -/* I/O commands, error codes */ -#include - -/* headerfile of this module */ -#include "zr36060.h" - -/* codec io API */ -#include "videocodec.h" - -/* it doesn't make sense to have more than 20 or so, - just to prevent some unwanted loops */ -#define MAX_CODECS 20 - -/* amount of chips attached via this driver */ -static int zr36060_codecs; - -static bool low_bitrate; -module_param(low_bitrate, bool, 0); -MODULE_PARM_DESC(low_bitrate, "Buz compatibility option, halves bitrate"); - -/* debugging is available via module parameter */ -static int debug; -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0-4)"); - -#define dprintk(num, format, args...) \ - do { \ - if (debug >= num) \ - printk(format, ##args); \ - } while (0) - -/* ========================================================================= - Local hardware I/O functions: - - read/write via codec layer (registers are located in the master device) - ========================================================================= */ - -/* read and write functions */ -static u8 -zr36060_read (struct zr36060 *ptr, - u16 reg) -{ - u8 value = 0; - - // just in case something is wrong... - if (ptr->codec->master_data->readreg) - value = (ptr->codec->master_data->readreg(ptr->codec, - reg)) & 0xff; - else - dprintk(1, - KERN_ERR "%s: invalid I/O setup, nothing read!\n", - ptr->name); - - //dprintk(4, "%s: reading from 0x%04x: %02x\n",ptr->name,reg,value); - - return value; -} - -static void -zr36060_write(struct zr36060 *ptr, - u16 reg, - u8 value) -{ - //dprintk(4, "%s: writing 0x%02x to 0x%04x\n",ptr->name,value,reg); - dprintk(4, "0x%02x @0x%04x\n", value, reg); - - // just in case something is wrong... - if (ptr->codec->master_data->writereg) - ptr->codec->master_data->writereg(ptr->codec, reg, value); - else - dprintk(1, - KERN_ERR - "%s: invalid I/O setup, nothing written!\n", - ptr->name); -} - -/* ========================================================================= - Local helper function: - - status read - ========================================================================= */ - -/* status is kept in datastructure */ -static u8 -zr36060_read_status (struct zr36060 *ptr) -{ - ptr->status = zr36060_read(ptr, ZR060_CFSR); - - zr36060_read(ptr, 0); - return ptr->status; -} - -/* ========================================================================= - Local helper function: - - scale factor read - ========================================================================= */ - -/* scale factor is kept in datastructure */ -static u16 -zr36060_read_scalefactor (struct zr36060 *ptr) -{ - ptr->scalefact = (zr36060_read(ptr, ZR060_SF_HI) << 8) | - (zr36060_read(ptr, ZR060_SF_LO) & 0xFF); - - /* leave 0 selected for an eventually GO from master */ - zr36060_read(ptr, 0); - return ptr->scalefact; -} - -/* ========================================================================= - Local helper function: - - wait if codec is ready to proceed (end of processing) or time is over - ========================================================================= */ - -static void -zr36060_wait_end (struct zr36060 *ptr) -{ - int i = 0; - - while (zr36060_read_status(ptr) & ZR060_CFSR_Busy) { - udelay(1); - if (i++ > 200000) { // 200ms, there is for sure something wrong!!! - dprintk(1, - "%s: timeout at wait_end (last status: 0x%02x)\n", - ptr->name, ptr->status); - break; - } - } -} - -/* ========================================================================= - Local helper function: - - basic test of "connectivity", writes/reads to/from memory the SOF marker - ========================================================================= */ - -static int -zr36060_basic_test (struct zr36060 *ptr) -{ - if ((zr36060_read(ptr, ZR060_IDR_DEV) != 0x33) && - (zr36060_read(ptr, ZR060_IDR_REV) != 0x01)) { - dprintk(1, - KERN_ERR - "%s: attach failed, can't connect to jpeg processor!\n", - ptr->name); - return -ENXIO; - } - - zr36060_wait_end(ptr); - if (ptr->status & ZR060_CFSR_Busy) { - dprintk(1, - KERN_ERR - "%s: attach failed, jpeg processor failed (end flag)!\n", - ptr->name); - return -EBUSY; - } - - return 0; /* looks good! */ -} - -/* ========================================================================= - Local helper function: - - simple loop for pushing the init datasets - ========================================================================= */ - -static int -zr36060_pushit (struct zr36060 *ptr, - u16 startreg, - u16 len, - const char *data) -{ - int i = 0; - - dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", ptr->name, - startreg, len); - while (i < len) { - zr36060_write(ptr, startreg++, data[i++]); - } - - return i; -} - -/* ========================================================================= - Basic datasets: - - jpeg baseline setup data (you find it on lots places in internet, or just - extract it from any regular .jpg image...) - - Could be variable, but until it's not needed it they are just fixed to save - memory. Otherwise expand zr36060 structure with arrays, push the values to - it and initialize from there, as e.g. the linux zr36057/60 driver does it. - ========================================================================= */ - -static const char zr36060_dqt[0x86] = { - 0xff, 0xdb, //Marker: DQT - 0x00, 0x84, //Length: 2*65+2 - 0x00, //Pq,Tq first table - 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, - 0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, - 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, - 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, - 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44, - 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, - 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, - 0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63, - 0x01, //Pq,Tq second table - 0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, - 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, - 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63 -}; - -static const char zr36060_dht[0x1a4] = { - 0xff, 0xc4, //Marker: DHT - 0x01, 0xa2, //Length: 2*AC, 2*DC - 0x00, //DC first table - 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, - 0x01, //DC second table - 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, - 0x10, //AC first table - 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, - 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, - 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, - 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, - 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, - 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, - 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, - 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, - 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, - 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, - 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, - 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, - 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, - 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, - 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, - 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, - 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, - 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, - 0xF8, 0xF9, 0xFA, - 0x11, //AC second table - 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, - 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, - 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, - 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, - 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, - 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, - 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, - 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, - 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, - 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, - 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, - 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, - 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, - 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, - 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, - 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, - 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, - 0xF9, 0xFA -}; - -/* jpeg baseline setup, this is just fixed in this driver (YUV pictures) */ -#define NO_OF_COMPONENTS 0x3 //Y,U,V -#define BASELINE_PRECISION 0x8 //MCU size (?) -static const char zr36060_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's QT -static const char zr36060_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's DC -static const char zr36060_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; //table idx's AC - -/* horizontal 422 decimation setup (maybe we support 411 or so later, too) */ -static const char zr36060_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 }; -static const char zr36060_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 }; - -/* ========================================================================= - Local helper functions: - - calculation and setup of parameter-dependent JPEG baseline segments - (needed for compression only) - ========================================================================= */ - -/* ------------------------------------------------------------------------- */ - -/* SOF (start of frame) segment depends on width, height and sampling ratio - of each color component */ - -static int -zr36060_set_sof (struct zr36060 *ptr) -{ - char sof_data[34]; // max. size of register set - int i; - - dprintk(3, "%s: write SOF (%dx%d, %d components)\n", ptr->name, - ptr->width, ptr->height, NO_OF_COMPONENTS); - sof_data[0] = 0xff; - sof_data[1] = 0xc0; - sof_data[2] = 0x00; - sof_data[3] = (3 * NO_OF_COMPONENTS) + 8; - sof_data[4] = BASELINE_PRECISION; // only '8' possible with zr36060 - sof_data[5] = (ptr->height) >> 8; - sof_data[6] = (ptr->height) & 0xff; - sof_data[7] = (ptr->width) >> 8; - sof_data[8] = (ptr->width) & 0xff; - sof_data[9] = NO_OF_COMPONENTS; - for (i = 0; i < NO_OF_COMPONENTS; i++) { - sof_data[10 + (i * 3)] = i; // index identifier - sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) | - (ptr->v_samp_ratio[i]); // sampling ratios - sof_data[12 + (i * 3)] = zr36060_tq[i]; // Q table selection - } - return zr36060_pushit(ptr, ZR060_SOF_IDX, - (3 * NO_OF_COMPONENTS) + 10, sof_data); -} - -/* ------------------------------------------------------------------------- */ - -/* SOS (start of scan) segment depends on the used scan components - of each color component */ - -static int -zr36060_set_sos (struct zr36060 *ptr) -{ - char sos_data[16]; // max. size of register set - int i; - - dprintk(3, "%s: write SOS\n", ptr->name); - sos_data[0] = 0xff; - sos_data[1] = 0xda; - sos_data[2] = 0x00; - sos_data[3] = 2 + 1 + (2 * NO_OF_COMPONENTS) + 3; - sos_data[4] = NO_OF_COMPONENTS; - for (i = 0; i < NO_OF_COMPONENTS; i++) { - sos_data[5 + (i * 2)] = i; // index - sos_data[6 + (i * 2)] = (zr36060_td[i] << 4) | - zr36060_ta[i]; // AC/DC tbl.sel. - } - sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00; // scan start - sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3f; - sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 4] = 00; - return zr36060_pushit(ptr, ZR060_SOS_IDX, - 4 + 1 + (2 * NO_OF_COMPONENTS) + 3, - sos_data); -} - -/* ------------------------------------------------------------------------- */ - -/* DRI (define restart interval) */ - -static int -zr36060_set_dri (struct zr36060 *ptr) -{ - char dri_data[6]; // max. size of register set - - dprintk(3, "%s: write DRI\n", ptr->name); - dri_data[0] = 0xff; - dri_data[1] = 0xdd; - dri_data[2] = 0x00; - dri_data[3] = 0x04; - dri_data[4] = (ptr->dri) >> 8; - dri_data[5] = (ptr->dri) & 0xff; - return zr36060_pushit(ptr, ZR060_DRI_IDX, 6, dri_data); -} - -/* ========================================================================= - Setup function: - - Setup compression/decompression of Zoran's JPEG processor - ( see also zoran 36060 manual ) - - ... sorry for the spaghetti code ... - ========================================================================= */ -static void -zr36060_init (struct zr36060 *ptr) -{ - int sum = 0; - long bitcnt, tmp; - - if (ptr->mode == CODEC_DO_COMPRESSION) { - dprintk(2, "%s: COMPRESSION SETUP\n", ptr->name); - - zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst); - - /* 060 communicates with 067 in master mode */ - zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CodeMstr); - - /* Compression with or without variable scale factor */ - /*FIXME: What about ptr->bitrate_ctrl? */ - zr36060_write(ptr, ZR060_CMR, - ZR060_CMR_Comp | ZR060_CMR_Pass2 | - ZR060_CMR_BRB); - - /* Must be zero */ - zr36060_write(ptr, ZR060_MBZ, 0x00); - zr36060_write(ptr, ZR060_TCR_HI, 0x00); - zr36060_write(ptr, ZR060_TCR_LO, 0x00); - - /* Disable all IRQs - no DataErr means autoreset */ - zr36060_write(ptr, ZR060_IMR, 0); - - /* volume control settings */ - zr36060_write(ptr, ZR060_SF_HI, ptr->scalefact >> 8); - zr36060_write(ptr, ZR060_SF_LO, ptr->scalefact & 0xff); - - zr36060_write(ptr, ZR060_AF_HI, 0xff); - zr36060_write(ptr, ZR060_AF_M, 0xff); - zr36060_write(ptr, ZR060_AF_LO, 0xff); - - /* setup the variable jpeg tables */ - sum += zr36060_set_sof(ptr); - sum += zr36060_set_sos(ptr); - sum += zr36060_set_dri(ptr); - - /* setup the fixed jpeg tables - maybe variable, though - - * (see table init section above) */ - sum += - zr36060_pushit(ptr, ZR060_DQT_IDX, sizeof(zr36060_dqt), - zr36060_dqt); - sum += - zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht), - zr36060_dht); - zr36060_write(ptr, ZR060_APP_IDX, 0xff); - zr36060_write(ptr, ZR060_APP_IDX + 1, 0xe0 + ptr->app.appn); - zr36060_write(ptr, ZR060_APP_IDX + 2, 0x00); - zr36060_write(ptr, ZR060_APP_IDX + 3, ptr->app.len + 2); - sum += zr36060_pushit(ptr, ZR060_APP_IDX + 4, 60, - ptr->app.data) + 4; - zr36060_write(ptr, ZR060_COM_IDX, 0xff); - zr36060_write(ptr, ZR060_COM_IDX + 1, 0xfe); - zr36060_write(ptr, ZR060_COM_IDX + 2, 0x00); - zr36060_write(ptr, ZR060_COM_IDX + 3, ptr->com.len + 2); - sum += zr36060_pushit(ptr, ZR060_COM_IDX + 4, 60, - ptr->com.data) + 4; - - /* setup misc. data for compression (target code sizes) */ - - /* size of compressed code to reach without header data */ - sum = ptr->real_code_vol - sum; - bitcnt = sum << 3; /* need the size in bits */ - - tmp = bitcnt >> 16; - dprintk(3, - "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n", - ptr->name, sum, ptr->real_code_vol, bitcnt, tmp); - zr36060_write(ptr, ZR060_TCV_NET_HI, tmp >> 8); - zr36060_write(ptr, ZR060_TCV_NET_MH, tmp & 0xff); - tmp = bitcnt & 0xffff; - zr36060_write(ptr, ZR060_TCV_NET_ML, tmp >> 8); - zr36060_write(ptr, ZR060_TCV_NET_LO, tmp & 0xff); - - bitcnt -= bitcnt >> 7; // bits without stuffing - bitcnt -= ((bitcnt * 5) >> 6); // bits without eob - - tmp = bitcnt >> 16; - dprintk(3, "%s: code: nettobit=%ld, highnettobits=%ld\n", - ptr->name, bitcnt, tmp); - zr36060_write(ptr, ZR060_TCV_DATA_HI, tmp >> 8); - zr36060_write(ptr, ZR060_TCV_DATA_MH, tmp & 0xff); - tmp = bitcnt & 0xffff; - zr36060_write(ptr, ZR060_TCV_DATA_ML, tmp >> 8); - zr36060_write(ptr, ZR060_TCV_DATA_LO, tmp & 0xff); - - /* JPEG markers to be included in the compressed stream */ - zr36060_write(ptr, ZR060_MER, - ZR060_MER_DQT | ZR060_MER_DHT | - ((ptr->com.len > 0) ? ZR060_MER_Com : 0) | - ((ptr->app.len > 0) ? ZR060_MER_App : 0)); - - /* Setup the Video Frontend */ - /* Limit pixel range to 16..235 as per CCIR-601 */ - zr36060_write(ptr, ZR060_VCR, ZR060_VCR_Range); - - } else { - dprintk(2, "%s: EXPANSION SETUP\n", ptr->name); - - zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst); - - /* 060 communicates with 067 in master mode */ - zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CodeMstr); - - /* Decompression */ - zr36060_write(ptr, ZR060_CMR, 0); - - /* Must be zero */ - zr36060_write(ptr, ZR060_MBZ, 0x00); - zr36060_write(ptr, ZR060_TCR_HI, 0x00); - zr36060_write(ptr, ZR060_TCR_LO, 0x00); - - /* Disable all IRQs - no DataErr means autoreset */ - zr36060_write(ptr, ZR060_IMR, 0); - - /* setup misc. data for expansion */ - zr36060_write(ptr, ZR060_MER, 0); - - /* setup the fixed jpeg tables - maybe variable, though - - * (see table init section above) */ - zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht), - zr36060_dht); - - /* Setup the Video Frontend */ - //zr36060_write(ptr, ZR060_VCR, ZR060_VCR_FIExt); - //this doesn't seem right and doesn't work... - zr36060_write(ptr, ZR060_VCR, ZR060_VCR_Range); - } - - /* Load the tables */ - zr36060_write(ptr, ZR060_LOAD, - ZR060_LOAD_SyncRst | ZR060_LOAD_Load); - zr36060_wait_end(ptr); - dprintk(2, "%s: Status after table preload: 0x%02x\n", ptr->name, - ptr->status); - - if (ptr->status & ZR060_CFSR_Busy) { - dprintk(1, KERN_ERR "%s: init aborted!\n", ptr->name); - return; // something is wrong, its timed out!!!! - } -} - -/* ========================================================================= - CODEC API FUNCTIONS - - this functions are accessed by the master via the API structure - ========================================================================= */ - -/* set compression/expansion mode and launches codec - - this should be the last call from the master before starting processing */ -static int -zr36060_set_mode (struct videocodec *codec, - int mode) -{ - struct zr36060 *ptr = (struct zr36060 *) codec->data; - - dprintk(2, "%s: set_mode %d call\n", ptr->name, mode); - - if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION)) - return -EINVAL; - - ptr->mode = mode; - zr36060_init(ptr); - - return 0; -} - -/* set picture size (norm is ignored as the codec doesn't know about it) */ -static int -zr36060_set_video (struct videocodec *codec, - struct tvnorm *norm, - struct vfe_settings *cap, - struct vfe_polarity *pol) -{ - struct zr36060 *ptr = (struct zr36060 *) codec->data; - u32 reg; - int size; - - dprintk(2, "%s: set_video %d/%d-%dx%d (%%%d) call\n", ptr->name, - cap->x, cap->y, cap->width, cap->height, cap->decimation); - - /* if () return -EINVAL; - * trust the master driver that it knows what it does - so - * we allow invalid startx/y and norm for now ... */ - ptr->width = cap->width / (cap->decimation & 0xff); - ptr->height = cap->height / (cap->decimation >> 8); - - zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst); - - /* Note that VSPol/HSPol bits in zr36060 have the opposite - * meaning of their zr360x7 counterparts with the same names - * N.b. for VSPol this is only true if FIVEdge = 0 (default, - * left unchanged here - in accordance with datasheet). - */ - reg = (!pol->vsync_pol ? ZR060_VPR_VSPol : 0) - | (!pol->hsync_pol ? ZR060_VPR_HSPol : 0) - | (pol->field_pol ? ZR060_VPR_FIPol : 0) - | (pol->blank_pol ? ZR060_VPR_BLPol : 0) - | (pol->subimg_pol ? ZR060_VPR_SImgPol : 0) - | (pol->poe_pol ? ZR060_VPR_PoePol : 0) - | (pol->pvalid_pol ? ZR060_VPR_PValPol : 0) - | (pol->vclk_pol ? ZR060_VPR_VCLKPol : 0); - zr36060_write(ptr, ZR060_VPR, reg); - - reg = 0; - switch (cap->decimation & 0xff) { - default: - case 1: - break; - - case 2: - reg |= ZR060_SR_HScale2; - break; - - case 4: - reg |= ZR060_SR_HScale4; - break; - } - - switch (cap->decimation >> 8) { - default: - case 1: - break; - - case 2: - reg |= ZR060_SR_VScale; - break; - } - zr36060_write(ptr, ZR060_SR, reg); - - zr36060_write(ptr, ZR060_BCR_Y, 0x00); - zr36060_write(ptr, ZR060_BCR_U, 0x80); - zr36060_write(ptr, ZR060_BCR_V, 0x80); - - /* sync generator */ - - reg = norm->Ht - 1; /* Vtotal */ - zr36060_write(ptr, ZR060_SGR_VTOTAL_HI, (reg >> 8) & 0xff); - zr36060_write(ptr, ZR060_SGR_VTOTAL_LO, (reg >> 0) & 0xff); - - reg = norm->Wt - 1; /* Htotal */ - zr36060_write(ptr, ZR060_SGR_HTOTAL_HI, (reg >> 8) & 0xff); - zr36060_write(ptr, ZR060_SGR_HTOTAL_LO, (reg >> 0) & 0xff); - - reg = 6 - 1; /* VsyncSize */ - zr36060_write(ptr, ZR060_SGR_VSYNC, reg); - - //reg = 30 - 1; /* HsyncSize */ -///*CP*/ reg = (zr->params.norm == 1 ? 57 : 68); - reg = 68; - zr36060_write(ptr, ZR060_SGR_HSYNC, reg); - - reg = norm->VStart - 1; /* BVstart */ - zr36060_write(ptr, ZR060_SGR_BVSTART, reg); - - reg += norm->Ha / 2; /* BVend */ - zr36060_write(ptr, ZR060_SGR_BVEND_HI, (reg >> 8) & 0xff); - zr36060_write(ptr, ZR060_SGR_BVEND_LO, (reg >> 0) & 0xff); - - reg = norm->HStart - 1; /* BHstart */ - zr36060_write(ptr, ZR060_SGR_BHSTART, reg); - - reg += norm->Wa; /* BHend */ - zr36060_write(ptr, ZR060_SGR_BHEND_HI, (reg >> 8) & 0xff); - zr36060_write(ptr, ZR060_SGR_BHEND_LO, (reg >> 0) & 0xff); - - /* active area */ - reg = cap->y + norm->VStart; /* Vstart */ - zr36060_write(ptr, ZR060_AAR_VSTART_HI, (reg >> 8) & 0xff); - zr36060_write(ptr, ZR060_AAR_VSTART_LO, (reg >> 0) & 0xff); - - reg += cap->height; /* Vend */ - zr36060_write(ptr, ZR060_AAR_VEND_HI, (reg >> 8) & 0xff); - zr36060_write(ptr, ZR060_AAR_VEND_LO, (reg >> 0) & 0xff); - - reg = cap->x + norm->HStart; /* Hstart */ - zr36060_write(ptr, ZR060_AAR_HSTART_HI, (reg >> 8) & 0xff); - zr36060_write(ptr, ZR060_AAR_HSTART_LO, (reg >> 0) & 0xff); - - reg += cap->width; /* Hend */ - zr36060_write(ptr, ZR060_AAR_HEND_HI, (reg >> 8) & 0xff); - zr36060_write(ptr, ZR060_AAR_HEND_LO, (reg >> 0) & 0xff); - - /* subimage area */ - reg = norm->VStart - 4; /* SVstart */ - zr36060_write(ptr, ZR060_SWR_VSTART_HI, (reg >> 8) & 0xff); - zr36060_write(ptr, ZR060_SWR_VSTART_LO, (reg >> 0) & 0xff); - - reg += norm->Ha / 2 + 8; /* SVend */ - zr36060_write(ptr, ZR060_SWR_VEND_HI, (reg >> 8) & 0xff); - zr36060_write(ptr, ZR060_SWR_VEND_LO, (reg >> 0) & 0xff); - - reg = norm->HStart /*+ 64 */ - 4; /* SHstart */ - zr36060_write(ptr, ZR060_SWR_HSTART_HI, (reg >> 8) & 0xff); - zr36060_write(ptr, ZR060_SWR_HSTART_LO, (reg >> 0) & 0xff); - - reg += norm->Wa + 8; /* SHend */ - zr36060_write(ptr, ZR060_SWR_HEND_HI, (reg >> 8) & 0xff); - zr36060_write(ptr, ZR060_SWR_HEND_LO, (reg >> 0) & 0xff); - - size = ptr->width * ptr->height; - /* Target compressed field size in bits: */ - size = size * 16; /* uncompressed size in bits */ - /* (Ronald) by default, quality = 100 is a compression - * ratio 1:2. Setting low_bitrate (insmod option) sets - * it to 1:4 (instead of 1:2, zr36060 max) as limit because the - * buz can't handle more at decimation=1... Use low_bitrate if - * you have a Buz, unless you know what you're doing */ - size = size * cap->quality / (low_bitrate ? 400 : 200); - /* Lower limit (arbitrary, 1 KB) */ - if (size < 8192) - size = 8192; - /* Upper limit: 7/8 of the code buffers */ - if (size > ptr->total_code_vol * 7) - size = ptr->total_code_vol * 7; - - ptr->real_code_vol = size >> 3; /* in bytes */ - - /* the MBCVR is the *maximum* block volume, according to the - * JPEG ISO specs, this shouldn't be used, since that allows - * for the best encoding quality. So set it to it's max value */ - reg = ptr->max_block_vol; - zr36060_write(ptr, ZR060_MBCVR, reg); - - return 0; -} - -/* additional control functions */ -static int -zr36060_control (struct videocodec *codec, - int type, - int size, - void *data) -{ - struct zr36060 *ptr = (struct zr36060 *) codec->data; - int *ival = (int *) data; - - dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type, - size); - - switch (type) { - case CODEC_G_STATUS: /* get last status */ - if (size != sizeof(int)) - return -EFAULT; - zr36060_read_status(ptr); - *ival = ptr->status; - break; - - case CODEC_G_CODEC_MODE: - if (size != sizeof(int)) - return -EFAULT; - *ival = CODEC_MODE_BJPG; - break; - - case CODEC_S_CODEC_MODE: - if (size != sizeof(int)) - return -EFAULT; - if (*ival != CODEC_MODE_BJPG) - return -EINVAL; - /* not needed, do nothing */ - return 0; - - case CODEC_G_VFE: - case CODEC_S_VFE: - /* not needed, do nothing */ - return 0; - - case CODEC_S_MMAP: - /* not available, give an error */ - return -ENXIO; - - case CODEC_G_JPEG_TDS_BYTE: /* get target volume in byte */ - if (size != sizeof(int)) - return -EFAULT; - *ival = ptr->total_code_vol; - break; - - case CODEC_S_JPEG_TDS_BYTE: /* get target volume in byte */ - if (size != sizeof(int)) - return -EFAULT; - ptr->total_code_vol = *ival; - ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3; - break; - - case CODEC_G_JPEG_SCALE: /* get scaling factor */ - if (size != sizeof(int)) - return -EFAULT; - *ival = zr36060_read_scalefactor(ptr); - break; - - case CODEC_S_JPEG_SCALE: /* set scaling factor */ - if (size != sizeof(int)) - return -EFAULT; - ptr->scalefact = *ival; - break; - - case CODEC_G_JPEG_APP_DATA: { /* get appn marker data */ - struct jpeg_app_marker *app = data; - - if (size != sizeof(struct jpeg_app_marker)) - return -EFAULT; - - *app = ptr->app; - break; - } - - case CODEC_S_JPEG_APP_DATA: { /* set appn marker data */ - struct jpeg_app_marker *app = data; - - if (size != sizeof(struct jpeg_app_marker)) - return -EFAULT; - - ptr->app = *app; - break; - } - - case CODEC_G_JPEG_COM_DATA: { /* get comment marker data */ - struct jpeg_com_marker *com = data; - - if (size != sizeof(struct jpeg_com_marker)) - return -EFAULT; - - *com = ptr->com; - break; - } - - case CODEC_S_JPEG_COM_DATA: { /* set comment marker data */ - struct jpeg_com_marker *com = data; - - if (size != sizeof(struct jpeg_com_marker)) - return -EFAULT; - - ptr->com = *com; - break; - } - - default: - return -EINVAL; - } - - return size; -} - -/* ========================================================================= - Exit and unregister function: - - Deinitializes Zoran's JPEG processor - ========================================================================= */ - -static int -zr36060_unset (struct videocodec *codec) -{ - struct zr36060 *ptr = codec->data; - - if (ptr) { - /* do wee need some codec deinit here, too ???? */ - - dprintk(1, "%s: finished codec #%d\n", ptr->name, - ptr->num); - kfree(ptr); - codec->data = NULL; - - zr36060_codecs--; - return 0; - } - - return -EFAULT; -} - -/* ========================================================================= - Setup and registry function: - - Initializes Zoran's JPEG processor - - Also sets pixel size, average code size, mode (compr./decompr.) - (the given size is determined by the processor with the video interface) - ========================================================================= */ - -static int -zr36060_setup (struct videocodec *codec) -{ - struct zr36060 *ptr; - int res; - - dprintk(2, "zr36060: initializing MJPEG subsystem #%d.\n", - zr36060_codecs); - - if (zr36060_codecs == MAX_CODECS) { - dprintk(1, - KERN_ERR "zr36060: Can't attach more codecs!\n"); - return -ENOSPC; - } - //mem structure init - codec->data = ptr = kzalloc(sizeof(struct zr36060), GFP_KERNEL); - if (NULL == ptr) { - dprintk(1, KERN_ERR "zr36060: Can't get enough memory!\n"); - return -ENOMEM; - } - - snprintf(ptr->name, sizeof(ptr->name), "zr36060[%d]", - zr36060_codecs); - ptr->num = zr36060_codecs++; - ptr->codec = codec; - - //testing - res = zr36060_basic_test(ptr); - if (res < 0) { - zr36060_unset(codec); - return res; - } - //final setup - memcpy(ptr->h_samp_ratio, zr36060_decimation_h, 8); - memcpy(ptr->v_samp_ratio, zr36060_decimation_v, 8); - - ptr->bitrate_ctrl = 0; /* 0 or 1 - fixed file size flag - * (what is the difference?) */ - ptr->mode = CODEC_DO_COMPRESSION; - ptr->width = 384; - ptr->height = 288; - ptr->total_code_vol = 16000; /* CHECKME */ - ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3; - ptr->max_block_vol = 240; /* CHECKME, was 120 is 240 */ - ptr->scalefact = 0x100; - ptr->dri = 1; /* CHECKME, was 8 is 1 */ - - /* by default, no COM or APP markers - app should set those */ - ptr->com.len = 0; - ptr->app.appn = 0; - ptr->app.len = 0; - - zr36060_init(ptr); - - dprintk(1, KERN_INFO "%s: codec attached and running\n", - ptr->name); - - return 0; -} - -static const struct videocodec zr36060_codec = { - .owner = THIS_MODULE, - .name = "zr36060", - .magic = 0L, // magic not used - .flags = - CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER | - CODEC_FLAG_DECODER | CODEC_FLAG_VFE, - .type = CODEC_TYPE_ZR36060, - .setup = zr36060_setup, // functionality - .unset = zr36060_unset, - .set_mode = zr36060_set_mode, - .set_video = zr36060_set_video, - .control = zr36060_control, - // others are not used -}; - -/* ========================================================================= - HOOK IN DRIVER AS KERNEL MODULE - ========================================================================= */ - -static int __init -zr36060_init_module (void) -{ - //dprintk(1, "zr36060 driver %s\n",ZR060_VERSION); - zr36060_codecs = 0; - return videocodec_register(&zr36060_codec); -} - -static void __exit -zr36060_cleanup_module (void) -{ - if (zr36060_codecs) { - dprintk(1, - "zr36060: something's wrong - %d codecs left somehow.\n", - zr36060_codecs); - } - - /* however, we can't just stay alive */ - videocodec_unregister(&zr36060_codec); -} - -module_init(zr36060_init_module); -module_exit(zr36060_cleanup_module); - -MODULE_AUTHOR("Laurent Pinchart "); -MODULE_DESCRIPTION("Driver module for ZR36060 jpeg processors " - ZR060_VERSION); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/media/zoran/zr36060.h b/drivers/staging/media/zoran/zr36060.h deleted file mode 100644 index 82911757ba78..000000000000 --- a/drivers/staging/media/zoran/zr36060.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Zoran ZR36060 basic configuration functions - header file - * - * Copyright (C) 2002 Laurent Pinchart - * - * $Id: zr36060.h,v 1.1.1.1.2.3 2003/01/14 21:18:47 rbultje Exp $ - * - * ------------------------------------------------------------------------ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * ------------------------------------------------------------------------ - */ - -#ifndef ZR36060_H -#define ZR36060_H - -#include "videocodec.h" - -/* data stored for each zoran jpeg codec chip */ -struct zr36060 { - char name[32]; - int num; - /* io datastructure */ - struct videocodec *codec; - // last coder status - __u8 status; - // actual coder setup - int mode; - - __u16 width; - __u16 height; - - __u16 bitrate_ctrl; - - __u32 total_code_vol; - __u32 real_code_vol; - __u16 max_block_vol; - - __u8 h_samp_ratio[8]; - __u8 v_samp_ratio[8]; - __u16 scalefact; - __u16 dri; - - /* app/com marker data */ - struct jpeg_app_marker app; - struct jpeg_com_marker com; -}; - -/* ZR36060 register addresses */ -#define ZR060_LOAD 0x000 -#define ZR060_CFSR 0x001 -#define ZR060_CIR 0x002 -#define ZR060_CMR 0x003 -#define ZR060_MBZ 0x004 -#define ZR060_MBCVR 0x005 -#define ZR060_MER 0x006 -#define ZR060_IMR 0x007 -#define ZR060_ISR 0x008 -#define ZR060_TCV_NET_HI 0x009 -#define ZR060_TCV_NET_MH 0x00a -#define ZR060_TCV_NET_ML 0x00b -#define ZR060_TCV_NET_LO 0x00c -#define ZR060_TCV_DATA_HI 0x00d -#define ZR060_TCV_DATA_MH 0x00e -#define ZR060_TCV_DATA_ML 0x00f -#define ZR060_TCV_DATA_LO 0x010 -#define ZR060_SF_HI 0x011 -#define ZR060_SF_LO 0x012 -#define ZR060_AF_HI 0x013 -#define ZR060_AF_M 0x014 -#define ZR060_AF_LO 0x015 -#define ZR060_ACV_HI 0x016 -#define ZR060_ACV_MH 0x017 -#define ZR060_ACV_ML 0x018 -#define ZR060_ACV_LO 0x019 -#define ZR060_ACT_HI 0x01a -#define ZR060_ACT_MH 0x01b -#define ZR060_ACT_ML 0x01c -#define ZR060_ACT_LO 0x01d -#define ZR060_ACV_TRUN_HI 0x01e -#define ZR060_ACV_TRUN_MH 0x01f -#define ZR060_ACV_TRUN_ML 0x020 -#define ZR060_ACV_TRUN_LO 0x021 -#define ZR060_IDR_DEV 0x022 -#define ZR060_IDR_REV 0x023 -#define ZR060_TCR_HI 0x024 -#define ZR060_TCR_LO 0x025 -#define ZR060_VCR 0x030 -#define ZR060_VPR 0x031 -#define ZR060_SR 0x032 -#define ZR060_BCR_Y 0x033 -#define ZR060_BCR_U 0x034 -#define ZR060_BCR_V 0x035 -#define ZR060_SGR_VTOTAL_HI 0x036 -#define ZR060_SGR_VTOTAL_LO 0x037 -#define ZR060_SGR_HTOTAL_HI 0x038 -#define ZR060_SGR_HTOTAL_LO 0x039 -#define ZR060_SGR_VSYNC 0x03a -#define ZR060_SGR_HSYNC 0x03b -#define ZR060_SGR_BVSTART 0x03c -#define ZR060_SGR_BHSTART 0x03d -#define ZR060_SGR_BVEND_HI 0x03e -#define ZR060_SGR_BVEND_LO 0x03f -#define ZR060_SGR_BHEND_HI 0x040 -#define ZR060_SGR_BHEND_LO 0x041 -#define ZR060_AAR_VSTART_HI 0x042 -#define ZR060_AAR_VSTART_LO 0x043 -#define ZR060_AAR_VEND_HI 0x044 -#define ZR060_AAR_VEND_LO 0x045 -#define ZR060_AAR_HSTART_HI 0x046 -#define ZR060_AAR_HSTART_LO 0x047 -#define ZR060_AAR_HEND_HI 0x048 -#define ZR060_AAR_HEND_LO 0x049 -#define ZR060_SWR_VSTART_HI 0x04a -#define ZR060_SWR_VSTART_LO 0x04b -#define ZR060_SWR_VEND_HI 0x04c -#define ZR060_SWR_VEND_LO 0x04d -#define ZR060_SWR_HSTART_HI 0x04e -#define ZR060_SWR_HSTART_LO 0x04f -#define ZR060_SWR_HEND_HI 0x050 -#define ZR060_SWR_HEND_LO 0x051 - -#define ZR060_SOF_IDX 0x060 -#define ZR060_SOS_IDX 0x07a -#define ZR060_DRI_IDX 0x0c0 -#define ZR060_DQT_IDX 0x0cc -#define ZR060_DHT_IDX 0x1d4 -#define ZR060_APP_IDX 0x380 -#define ZR060_COM_IDX 0x3c0 - -/* ZR36060 LOAD register bits */ - -#define ZR060_LOAD_Load (1 << 7) -#define ZR060_LOAD_SyncRst (1 << 0) - -/* ZR36060 Code FIFO Status register bits */ - -#define ZR060_CFSR_Busy (1 << 7) -#define ZR060_CFSR_CBusy (1 << 2) -#define ZR060_CFSR_CFIFO (3 << 0) - -/* ZR36060 Code Interface register */ - -#define ZR060_CIR_Code16 (1 << 7) -#define ZR060_CIR_Endian (1 << 6) -#define ZR060_CIR_CFIS (1 << 2) -#define ZR060_CIR_CodeMstr (1 << 0) - -/* ZR36060 Codec Mode register */ - -#define ZR060_CMR_Comp (1 << 7) -#define ZR060_CMR_ATP (1 << 6) -#define ZR060_CMR_Pass2 (1 << 5) -#define ZR060_CMR_TLM (1 << 4) -#define ZR060_CMR_BRB (1 << 2) -#define ZR060_CMR_FSF (1 << 1) - -/* ZR36060 Markers Enable register */ - -#define ZR060_MER_App (1 << 7) -#define ZR060_MER_Com (1 << 6) -#define ZR060_MER_DRI (1 << 5) -#define ZR060_MER_DQT (1 << 4) -#define ZR060_MER_DHT (1 << 3) - -/* ZR36060 Interrupt Mask register */ - -#define ZR060_IMR_EOAV (1 << 3) -#define ZR060_IMR_EOI (1 << 2) -#define ZR060_IMR_End (1 << 1) -#define ZR060_IMR_DataErr (1 << 0) - -/* ZR36060 Interrupt Status register */ - -#define ZR060_ISR_ProCnt (3 << 6) -#define ZR060_ISR_EOAV (1 << 3) -#define ZR060_ISR_EOI (1 << 2) -#define ZR060_ISR_End (1 << 1) -#define ZR060_ISR_DataErr (1 << 0) - -/* ZR36060 Video Control register */ - -#define ZR060_VCR_Video8 (1 << 7) -#define ZR060_VCR_Range (1 << 6) -#define ZR060_VCR_FIDet (1 << 3) -#define ZR060_VCR_FIVedge (1 << 2) -#define ZR060_VCR_FIExt (1 << 1) -#define ZR060_VCR_SyncMstr (1 << 0) - -/* ZR36060 Video Polarity register */ - -#define ZR060_VPR_VCLKPol (1 << 7) -#define ZR060_VPR_PValPol (1 << 6) -#define ZR060_VPR_PoePol (1 << 5) -#define ZR060_VPR_SImgPol (1 << 4) -#define ZR060_VPR_BLPol (1 << 3) -#define ZR060_VPR_FIPol (1 << 2) -#define ZR060_VPR_HSPol (1 << 1) -#define ZR060_VPR_VSPol (1 << 0) - -/* ZR36060 Scaling register */ - -#define ZR060_SR_VScale (1 << 2) -#define ZR060_SR_HScale2 (1 << 0) -#define ZR060_SR_HScale4 (2 << 0) - -#endif /*fndef ZR36060_H */ From e25ec9141114c7124eeba09385e272dd76fbe617 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 28 Mar 2019 01:23:54 -0400 Subject: [PATCH 209/218] media: v4l: Add definitions for missing 32-bit RGB formats The V4L2 API is missing the 32-bit RGB formats for the ABGR, XBGR, RGBA and RGBX component orders. Add them, using the same 4CCs as DRM. Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- .../media/uapi/v4l/pixfmt-packed-rgb.rst | 160 ++++++++++++++++++ include/uapi/linux/videodev2.h | 4 + 2 files changed, 164 insertions(+) diff --git a/Documentation/media/uapi/v4l/pixfmt-packed-rgb.rst b/Documentation/media/uapi/v4l/pixfmt-packed-rgb.rst index 4766a6f47222..ed0b541afe59 100644 --- a/Documentation/media/uapi/v4l/pixfmt-packed-rgb.rst +++ b/Documentation/media/uapi/v4l/pixfmt-packed-rgb.rst @@ -453,6 +453,166 @@ next to each other in memory. - r\ :sub:`1` - r\ :sub:`0` + - + - + - + - + - + - + - + - + * .. _V4L2-PIX-FMT-BGRA32: + + - ``V4L2_PIX_FMT_BGRA32`` + - 'RA24' + + - a\ :sub:`7` + - a\ :sub:`6` + - a\ :sub:`5` + - a\ :sub:`4` + - a\ :sub:`3` + - a\ :sub:`2` + - a\ :sub:`1` + - a\ :sub:`0` + + - b\ :sub:`7` + - b\ :sub:`6` + - b\ :sub:`5` + - b\ :sub:`4` + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + + - g\ :sub:`7` + - g\ :sub:`6` + - g\ :sub:`5` + - g\ :sub:`4` + - g\ :sub:`3` + - g\ :sub:`2` + - g\ :sub:`1` + - g\ :sub:`0` + + - r\ :sub:`7` + - r\ :sub:`6` + - r\ :sub:`5` + - r\ :sub:`4` + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + * .. _V4L2-PIX-FMT-BGRX32: + + - ``V4L2_PIX_FMT_BGRX32`` + - 'RX24' + + - + - + - + - + - + - + - + - + + - b\ :sub:`7` + - b\ :sub:`6` + - b\ :sub:`5` + - b\ :sub:`4` + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + + - g\ :sub:`7` + - g\ :sub:`6` + - g\ :sub:`5` + - g\ :sub:`4` + - g\ :sub:`3` + - g\ :sub:`2` + - g\ :sub:`1` + - g\ :sub:`0` + + - r\ :sub:`7` + - r\ :sub:`6` + - r\ :sub:`5` + - r\ :sub:`4` + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + * .. _V4L2-PIX-FMT-RGBA32: + + - ``V4L2_PIX_FMT_RGBA32`` + - 'AB24' + + - r\ :sub:`7` + - r\ :sub:`6` + - r\ :sub:`5` + - r\ :sub:`4` + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + + - g\ :sub:`7` + - g\ :sub:`6` + - g\ :sub:`5` + - g\ :sub:`4` + - g\ :sub:`3` + - g\ :sub:`2` + - g\ :sub:`1` + - g\ :sub:`0` + + - b\ :sub:`7` + - b\ :sub:`6` + - b\ :sub:`5` + - b\ :sub:`4` + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + + - a\ :sub:`7` + - a\ :sub:`6` + - a\ :sub:`5` + - a\ :sub:`4` + - a\ :sub:`3` + - a\ :sub:`2` + - a\ :sub:`1` + - a\ :sub:`0` + * .. _V4L2-PIX-FMT-RGBX32: + + - ``V4L2_PIX_FMT_RGBX32`` + - 'XB24' + + - r\ :sub:`7` + - r\ :sub:`6` + - r\ :sub:`5` + - r\ :sub:`4` + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + + - g\ :sub:`7` + - g\ :sub:`6` + - g\ :sub:`5` + - g\ :sub:`4` + - g\ :sub:`3` + - g\ :sub:`2` + - g\ :sub:`1` + - g\ :sub:`0` + + - b\ :sub:`7` + - b\ :sub:`6` + - b\ :sub:`5` + - b\ :sub:`4` + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + - - - diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 496e6453450c..00525503267d 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -528,7 +528,11 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B', 'G', 'R', '4') /* 32 BGR-8-8-8-8 */ #define V4L2_PIX_FMT_ABGR32 v4l2_fourcc('A', 'R', '2', '4') /* 32 BGRA-8-8-8-8 */ #define V4L2_PIX_FMT_XBGR32 v4l2_fourcc('X', 'R', '2', '4') /* 32 BGRX-8-8-8-8 */ +#define V4L2_PIX_FMT_BGRA32 v4l2_fourcc('R', 'A', '2', '4') /* 32 ABGR-8-8-8-8 */ +#define V4L2_PIX_FMT_BGRX32 v4l2_fourcc('R', 'X', '2', '4') /* 32 XBGR-8-8-8-8 */ #define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R', 'G', 'B', '4') /* 32 RGB-8-8-8-8 */ +#define V4L2_PIX_FMT_RGBA32 v4l2_fourcc('A', 'B', '2', '4') /* 32 RGBA-8-8-8-8 */ +#define V4L2_PIX_FMT_RGBX32 v4l2_fourcc('X', 'B', '2', '4') /* 32 RGBX-8-8-8-8 */ #define V4L2_PIX_FMT_ARGB32 v4l2_fourcc('B', 'A', '2', '4') /* 32 ARGB-8-8-8-8 */ #define V4L2_PIX_FMT_XRGB32 v4l2_fourcc('B', 'X', '2', '4') /* 32 XRGB-8-8-8-8 */ From 6c84f9b1d2900c80eea74e682637976fd25eb471 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 28 Mar 2019 01:23:54 -0400 Subject: [PATCH 210/218] media: v4l: Add definitions for missing 16-bit RGB4444 formats The V4L2 API is missing the 16-bit RGB4444 formats for the RGBA, RGBX, ABGR, XBGR, BGRA and BGRX component orders. Add them, using the same 4CCs as DRM. Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- .../media/uapi/v4l/pixfmt-packed-rgb.rst | 138 ++++++++++++++++++ include/uapi/linux/videodev2.h | 6 + 2 files changed, 144 insertions(+) diff --git a/Documentation/media/uapi/v4l/pixfmt-packed-rgb.rst b/Documentation/media/uapi/v4l/pixfmt-packed-rgb.rst index ed0b541afe59..ab2416787c5a 100644 --- a/Documentation/media/uapi/v4l/pixfmt-packed-rgb.rst +++ b/Documentation/media/uapi/v4l/pixfmt-packed-rgb.rst @@ -139,6 +139,144 @@ next to each other in memory. - r\ :sub:`1` - r\ :sub:`0` - + * .. _V4L2-PIX-FMT-RGBA444: + + - ``V4L2_PIX_FMT_RGBA444`` + - 'RA12' + + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + - a\ :sub:`3` + - a\ :sub:`2` + - a\ :sub:`1` + - a\ :sub:`0` + + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + - g\ :sub:`3` + - g\ :sub:`2` + - g\ :sub:`1` + - g\ :sub:`0` + - + * .. _V4L2-PIX-FMT-RGBX444: + + - ``V4L2_PIX_FMT_RGBX444`` + - 'RX12' + + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + - + - + - + - + + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + - g\ :sub:`3` + - g\ :sub:`2` + - g\ :sub:`1` + - g\ :sub:`0` + - + * .. _V4L2-PIX-FMT-ABGR444: + + - ``V4L2_PIX_FMT_ABGR444`` + - 'AB12' + + - g\ :sub:`3` + - g\ :sub:`2` + - g\ :sub:`1` + - g\ :sub:`0` + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + + - a\ :sub:`3` + - a\ :sub:`2` + - a\ :sub:`1` + - a\ :sub:`0` + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + - + * .. _V4L2-PIX-FMT-XBGR444: + + - ``V4L2_PIX_FMT_XBGR444`` + - 'XB12' + + - g\ :sub:`3` + - g\ :sub:`2` + - g\ :sub:`1` + - g\ :sub:`0` + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + + - + - + - + - + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + - + * .. _V4L2-PIX-FMT-BGRA444: + + - ``V4L2_PIX_FMT_BGRA444`` + - 'BA12' + + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + - a\ :sub:`3` + - a\ :sub:`2` + - a\ :sub:`1` + - a\ :sub:`0` + + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + - g\ :sub:`3` + - g\ :sub:`2` + - g\ :sub:`1` + - g\ :sub:`0` + - + * .. _V4L2-PIX-FMT-BGRX444: + + - ``V4L2_PIX_FMT_BGRX444`` + - 'BX12' + + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + - + - + - + - + + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + - g\ :sub:`3` + - g\ :sub:`2` + - g\ :sub:`1` + - g\ :sub:`0` + - * .. _V4L2-PIX-FMT-ARGB555: - ``V4L2_PIX_FMT_ARGB555`` diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 00525503267d..561eabdd027a 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -514,6 +514,12 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_RGB444 v4l2_fourcc('R', '4', '4', '4') /* 16 xxxxrrrr ggggbbbb */ #define V4L2_PIX_FMT_ARGB444 v4l2_fourcc('A', 'R', '1', '2') /* 16 aaaarrrr ggggbbbb */ #define V4L2_PIX_FMT_XRGB444 v4l2_fourcc('X', 'R', '1', '2') /* 16 xxxxrrrr ggggbbbb */ +#define V4L2_PIX_FMT_RGBA444 v4l2_fourcc('R', 'A', '1', '2') /* 16 rrrrgggg bbbbaaaa */ +#define V4L2_PIX_FMT_RGBX444 v4l2_fourcc('R', 'X', '1', '2') /* 16 rrrrgggg bbbbxxxx */ +#define V4L2_PIX_FMT_ABGR444 v4l2_fourcc('A', 'B', '1', '2') /* 16 aaaabbbb ggggrrrr */ +#define V4L2_PIX_FMT_XBGR444 v4l2_fourcc('X', 'B', '1', '2') /* 16 xxxxbbbb ggggrrrr */ +#define V4L2_PIX_FMT_BGRA444 v4l2_fourcc('B', 'A', '1', '2') /* 16 bbbbgggg rrrraaaa */ +#define V4L2_PIX_FMT_BGRX444 v4l2_fourcc('B', 'X', '1', '2') /* 16 bbbbgggg rrrrxxxx */ #define V4L2_PIX_FMT_RGB555 v4l2_fourcc('R', 'G', 'B', 'O') /* 16 RGB-5-5-5 */ #define V4L2_PIX_FMT_ARGB555 v4l2_fourcc('A', 'R', '1', '5') /* 16 ARGB-1-5-5-5 */ #define V4L2_PIX_FMT_XRGB555 v4l2_fourcc('X', 'R', '1', '5') /* 16 XRGB-1-5-5-5 */ From 8b65db13bf59ce0d3aeff4b3558f904e3d98b53a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 28 Mar 2019 01:23:54 -0400 Subject: [PATCH 211/218] media: v4l: Add definitions for missing 16-bit RGB555 formats The V4L2 API is missing the 16-bit RGB555 formats for the RGBA, RGBX, ABGR, XBGR, BGRA and BGRX component orders. Add them, using the same 4CCs as DRM. Signed-off-by: Laurent Pinchart Acked-by: Sakari Ailus Reviewed-by: Jacopo Mondi Signed-off-by: Mauro Carvalho Chehab --- .../media/uapi/v4l/pixfmt-packed-rgb.rst | 138 ++++++++++++++++++ include/uapi/linux/videodev2.h | 6 + 2 files changed, 144 insertions(+) diff --git a/Documentation/media/uapi/v4l/pixfmt-packed-rgb.rst b/Documentation/media/uapi/v4l/pixfmt-packed-rgb.rst index ab2416787c5a..738bb14c0ee2 100644 --- a/Documentation/media/uapi/v4l/pixfmt-packed-rgb.rst +++ b/Documentation/media/uapi/v4l/pixfmt-packed-rgb.rst @@ -323,6 +323,144 @@ next to each other in memory. - g\ :sub:`4` - g\ :sub:`3` - + * .. _V4L2-PIX-FMT-RGBA555: + + - ``V4L2_PIX_FMT_RGBA555`` + - 'RA15' + + - g\ :sub:`1` + - g\ :sub:`0` + - b\ :sub:`4` + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + - a + + - r\ :sub:`4` + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + - g\ :sub:`4` + - g\ :sub:`3` + - g\ :sub:`2` + - + * .. _V4L2-PIX-FMT-RGBX555: + + - ``V4L2_PIX_FMT_RGBX555`` + - 'RX15' + + - g\ :sub:`1` + - g\ :sub:`0` + - b\ :sub:`4` + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + - + + - r\ :sub:`4` + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + - g\ :sub:`4` + - g\ :sub:`3` + - g\ :sub:`2` + - + * .. _V4L2-PIX-FMT-ABGR555: + + - ``V4L2_PIX_FMT_ABGR555`` + - 'AB15' + + - g\ :sub:`2` + - g\ :sub:`1` + - g\ :sub:`0` + - r\ :sub:`4` + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + + - a + - b\ :sub:`4` + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + - g\ :sub:`4` + - g\ :sub:`3` + - + * .. _V4L2-PIX-FMT-XBGR555: + + - ``V4L2_PIX_FMT_XBGR555`` + - 'XB15' + + - g\ :sub:`2` + - g\ :sub:`1` + - g\ :sub:`0` + - r\ :sub:`4` + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + + - + - b\ :sub:`4` + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + - g\ :sub:`4` + - g\ :sub:`3` + - + * .. _V4L2-PIX-FMT-BGRA555: + + - ``V4L2_PIX_FMT_BGRA555`` + - 'BA15' + + - g\ :sub:`1` + - g\ :sub:`0` + - r\ :sub:`4` + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + - a + + - b\ :sub:`4` + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + - g\ :sub:`4` + - g\ :sub:`3` + - g\ :sub:`2` + - + * .. _V4L2-PIX-FMT-BGRX555: + + - ``V4L2_PIX_FMT_BGRX555`` + - 'BX15' + + - g\ :sub:`1` + - g\ :sub:`0` + - r\ :sub:`4` + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + - + + - b\ :sub:`4` + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + - g\ :sub:`4` + - g\ :sub:`3` + - g\ :sub:`2` + - * .. _V4L2-PIX-FMT-RGB565: - ``V4L2_PIX_FMT_RGB565`` diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 561eabdd027a..1050a75fb7ef 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -523,6 +523,12 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_RGB555 v4l2_fourcc('R', 'G', 'B', 'O') /* 16 RGB-5-5-5 */ #define V4L2_PIX_FMT_ARGB555 v4l2_fourcc('A', 'R', '1', '5') /* 16 ARGB-1-5-5-5 */ #define V4L2_PIX_FMT_XRGB555 v4l2_fourcc('X', 'R', '1', '5') /* 16 XRGB-1-5-5-5 */ +#define V4L2_PIX_FMT_RGBA555 v4l2_fourcc('R', 'A', '1', '5') /* 16 RGBA-5-5-5-1 */ +#define V4L2_PIX_FMT_RGBX555 v4l2_fourcc('R', 'X', '1', '5') /* 16 RGBX-5-5-5-1 */ +#define V4L2_PIX_FMT_ABGR555 v4l2_fourcc('A', 'B', '1', '5') /* 16 ABGR-1-5-5-5 */ +#define V4L2_PIX_FMT_XBGR555 v4l2_fourcc('X', 'B', '1', '5') /* 16 XBGR-1-5-5-5 */ +#define V4L2_PIX_FMT_BGRA555 v4l2_fourcc('B', 'A', '1', '5') /* 16 BGRA-5-5-5-1 */ +#define V4L2_PIX_FMT_BGRX555 v4l2_fourcc('B', 'X', '1', '5') /* 16 BGRX-5-5-5-1 */ #define V4L2_PIX_FMT_RGB565 v4l2_fourcc('R', 'G', 'B', 'P') /* 16 RGB-5-6-5 */ #define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R', 'G', 'B', 'Q') /* 16 RGB-5-5-5 BE */ #define V4L2_PIX_FMT_ARGB555X v4l2_fourcc_be('A', 'R', '1', '5') /* 16 ARGB-5-5-5 BE */ From 515c45650c9bfee14bfe0597eda933abc0e878d1 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 28 Mar 2019 01:31:32 -0400 Subject: [PATCH 212/218] media: vsp1: Add support for missing 32-bit RGB formats Add support for the V4L2_PIX_FMT_BGRA32, V4L2_PIX_FMT_BGRX32, V4L2_PIX_FMT_RGBA32 and V4L2_PIX_FMT_RGBX32 formats to the VSP driver. Signed-off-by: Laurent Pinchart Acked-by: Sakari Ailus Reviewed-by: Jacopo Mondi Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_pipe.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index 54ff539ffea0..9f08d85e89d7 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -68,6 +68,20 @@ static const struct vsp1_format_info vsp1_video_formats[] = { { V4L2_PIX_FMT_XBGR32, MEDIA_BUS_FMT_ARGB8888_1X32, VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS, 1, { 32, 0, 0 }, false, false, 1, 1, false }, + { V4L2_PIX_FMT_BGRA32, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_RGBA_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS, + 1, { 32, 0, 0 }, false, false, 1, 1, true }, + { V4L2_PIX_FMT_BGRX32, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_RGBA_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS, + 1, { 32, 0, 0 }, false, false, 1, 1, false }, + { V4L2_PIX_FMT_RGBA32, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_RGBA_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 1, { 32, 0, 0 }, false, false, 1, 1, true }, + { V4L2_PIX_FMT_RGBX32, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_RGBA_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 1, { 32, 0, 0 }, false, false, 1, 1, false }, { V4L2_PIX_FMT_ARGB32, MEDIA_BUS_FMT_ARGB8888_1X32, VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, From 4735c16b8bdd3051227ca9c617b94009e4614e21 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 28 Mar 2019 01:31:32 -0400 Subject: [PATCH 213/218] media: vsp1: Add support for missing 16-bit RGB444 formats Add support for the V4L2_PIX_FMT_RGBA444, V4L2_PIX_FMT_RGBX444, V4L2_PIX_FMT_ABGR444, V4L2_PIX_FMT_XBGR444, V4L2_PIX_FMT_BGRA444 and V4L2_PIX_FMT_BGRX444 formats to the VSP driver. Signed-off-by: Laurent Pinchart Acked-by: Sakari Ailus Reviewed-by: Jacopo Mondi Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_pipe.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index 9f08d85e89d7..4332c138ee22 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -42,6 +42,30 @@ static const struct vsp1_format_info vsp1_video_formats[] = { VI6_FMT_XRGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | VI6_RPF_DSWAP_P_WDS, 1, { 16, 0, 0 }, false, false, 1, 1, false }, + { V4L2_PIX_FMT_RGBA444, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_RGBA_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS, + 1, { 16, 0, 0 }, false, false, 1, 1, true }, + { V4L2_PIX_FMT_RGBX444, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_RGBX_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS, + 1, { 16, 0, 0 }, false, false, 1, 1, false }, + { V4L2_PIX_FMT_ABGR444, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_ABGR_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS, + 1, { 16, 0, 0 }, false, false, 1, 1, true }, + { V4L2_PIX_FMT_XBGR444, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_ABGR_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS, + 1, { 16, 0, 0 }, false, false, 1, 1, false }, + { V4L2_PIX_FMT_BGRA444, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_BGRA_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS, + 1, { 16, 0, 0 }, false, false, 1, 1, true }, + { V4L2_PIX_FMT_BGRX444, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_BGRA_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS, + 1, { 16, 0, 0 }, false, false, 1, 1, false }, { V4L2_PIX_FMT_ARGB555, MEDIA_BUS_FMT_ARGB8888_1X32, VI6_FMT_ARGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | VI6_RPF_DSWAP_P_WDS, From 7afa8db323e37b9174cf78a1c9ab0ae7a9f5e7dd Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 28 Mar 2019 01:31:32 -0400 Subject: [PATCH 214/218] media: vsp1: Add support for missing 16-bit RGB555 formats Add support for the V4L2_PIX_FMT_RGBA555, V4L2_PIX_FMT_RGBX555, V4L2_PIX_FMT_ABGR555, V4L2_PIX_FMT_XBGR555, V4L2_PIX_FMT_BGRA555 and V4L2_PIX_FMT_BGRX555 formats to the VSP driver. Signed-off-by: Laurent Pinchart Acked-by: Sakari Ailus Reviewed-by: Jacopo Mondi Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vsp1/vsp1_pipe.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index 4332c138ee22..f72ac01c21ea 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -74,6 +74,30 @@ static const struct vsp1_format_info vsp1_video_formats[] = { VI6_FMT_XRGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | VI6_RPF_DSWAP_P_WDS, 1, { 16, 0, 0 }, false, false, 1, 1, false }, + { V4L2_PIX_FMT_RGBA555, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_RGBA_5551, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS, + 1, { 16, 0, 0 }, false, false, 1, 1, true }, + { V4L2_PIX_FMT_RGBX555, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_RGBX_5551, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS, + 1, { 16, 0, 0 }, false, false, 1, 1, false }, + { V4L2_PIX_FMT_ABGR555, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_ABGR_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS, + 1, { 16, 0, 0 }, false, false, 1, 1, true }, + { V4L2_PIX_FMT_XBGR555, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_ABGR_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS, + 1, { 16, 0, 0 }, false, false, 1, 1, false }, + { V4L2_PIX_FMT_BGRA555, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_BGRA_5551, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS, + 1, { 16, 0, 0 }, false, false, 1, 1, true }, + { V4L2_PIX_FMT_BGRX555, MEDIA_BUS_FMT_ARGB8888_1X32, + VI6_FMT_BGRA_5551, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS, + 1, { 16, 0, 0 }, false, false, 1, 1, false }, { V4L2_PIX_FMT_RGB565, MEDIA_BUS_FMT_ARGB8888_1X32, VI6_FMT_RGB_565, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | VI6_RPF_DSWAP_P_WDS, From b5b5a27bee5884860798ffd0f08e611a3942064b Mon Sep 17 00:00:00 2001 From: Fabien Dessenne Date: Wed, 24 Apr 2019 09:25:44 -0400 Subject: [PATCH 215/218] media: stm32-dcmi: return appropriate error codes during probe During probe, return the provided errors value instead of -ENODEV. This allows the driver to be deferred probed if needed. Signed-off-by: Fabien Dessenne Acked-by: Hugues Fruchet Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/stm32/stm32-dcmi.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c index 906e71b19039..b9dad0accd1b 100644 --- a/drivers/media/platform/stm32/stm32-dcmi.c +++ b/drivers/media/platform/stm32/stm32-dcmi.c @@ -1672,7 +1672,7 @@ static int dcmi_probe(struct platform_device *pdev) dcmi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); if (IS_ERR(dcmi->rstc)) { dev_err(&pdev->dev, "Could not get reset control\n"); - return -ENODEV; + return PTR_ERR(dcmi->rstc); } /* Get bus characteristics from devicetree */ @@ -1687,7 +1687,7 @@ static int dcmi_probe(struct platform_device *pdev) of_node_put(np); if (ret) { dev_err(&pdev->dev, "Could not parse the endpoint\n"); - return -ENODEV; + return ret; } if (ep.bus_type == V4L2_MBUS_CSI2_DPHY) { @@ -1700,8 +1700,9 @@ static int dcmi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq <= 0) { - dev_err(&pdev->dev, "Could not get irq\n"); - return -ENODEV; + if (irq != -EPROBE_DEFER) + dev_err(&pdev->dev, "Could not get irq\n"); + return irq; } dcmi->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1721,12 +1722,13 @@ static int dcmi_probe(struct platform_device *pdev) dev_name(&pdev->dev), dcmi); if (ret) { dev_err(&pdev->dev, "Unable to request irq %d\n", irq); - return -ENODEV; + return ret; } mclk = devm_clk_get(&pdev->dev, "mclk"); if (IS_ERR(mclk)) { - dev_err(&pdev->dev, "Unable to get mclk\n"); + if (PTR_ERR(mclk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Unable to get mclk\n"); return PTR_ERR(mclk); } From b28cf7a9c8d5614e1e979bc6122d3ed8e64ad182 Mon Sep 17 00:00:00 2001 From: Eddie James Date: Wed, 24 Apr 2019 11:16:57 -0400 Subject: [PATCH 216/218] media: platform: Aspeed: Remove use of reset line The reset line is toggled by enabling the clocks, so it's not necessary to manually toggle the reset as well. Signed-off-by: Eddie James Reviewed-by: Joel Stanley Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/aspeed-video.c | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/drivers/media/platform/aspeed-video.c b/drivers/media/platform/aspeed-video.c index 692e08ef38c0..55c55a68b016 100644 --- a/drivers/media/platform/aspeed-video.c +++ b/drivers/media/platform/aspeed-video.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -208,7 +207,6 @@ struct aspeed_video { void __iomem *base; struct clk *eclk; struct clk *vclk; - struct reset_control *rst; struct device *dev; struct v4l2_ctrl_handler ctrl_handler; @@ -483,19 +481,10 @@ static void aspeed_video_enable_mode_detect(struct aspeed_video *video) aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_TRIG_MODE_DET); } -static void aspeed_video_reset(struct aspeed_video *video) -{ - /* Reset the engine */ - reset_control_assert(video->rst); - - /* Don't usleep here; function may be called in interrupt context */ - udelay(100); - reset_control_deassert(video->rst); -} - static void aspeed_video_off(struct aspeed_video *video) { - aspeed_video_reset(video); + /* Disable interrupts */ + aspeed_video_write(video, VE_INTERRUPT_CTRL, 0); /* Turn off the relevant clocks */ clk_disable_unprepare(video->vclk); @@ -507,8 +496,6 @@ static void aspeed_video_on(struct aspeed_video *video) /* Turn on the relevant clocks */ clk_prepare_enable(video->eclk); clk_prepare_enable(video->vclk); - - aspeed_video_reset(video); } static void aspeed_video_bufs_done(struct aspeed_video *video, @@ -1464,7 +1451,9 @@ static void aspeed_video_stop_streaming(struct vb2_queue *q) * Need to force stop any DMA and try and get HW into a good * state for future calls to start streaming again. */ - aspeed_video_reset(video); + aspeed_video_off(video); + aspeed_video_on(video); + aspeed_video_init_regs(video); aspeed_video_get_resolution(video); @@ -1619,12 +1608,6 @@ static int aspeed_video_init(struct aspeed_video *video) return PTR_ERR(video->vclk); } - video->rst = devm_reset_control_get_exclusive(dev, NULL); - if (IS_ERR(video->rst)) { - dev_err(dev, "Unable to get VE reset\n"); - return PTR_ERR(video->rst); - } - rc = of_reserved_mem_device_init(dev); if (rc) { dev_err(dev, "Unable to reserve memory\n"); From 54b021099e2d20db324f2581cc0f18f9b22aadfa Mon Sep 17 00:00:00 2001 From: Eddie James Date: Wed, 24 Apr 2019 11:16:58 -0400 Subject: [PATCH 217/218] media: platform: Aspeed: Make reserved memory optional Reserved memory doesn't need to be required; system memory would work fine. Signed-off-by: Eddie James Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/aspeed-video.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/media/platform/aspeed-video.c b/drivers/media/platform/aspeed-video.c index 55c55a68b016..8144fe36ad48 100644 --- a/drivers/media/platform/aspeed-video.c +++ b/drivers/media/platform/aspeed-video.c @@ -1608,11 +1608,7 @@ static int aspeed_video_init(struct aspeed_video *video) return PTR_ERR(video->vclk); } - rc = of_reserved_mem_device_init(dev); - if (rc) { - dev_err(dev, "Unable to reserve memory\n"); - return rc; - } + of_reserved_mem_device_init(dev); rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); if (rc) { From 0d672fffb447aa1699d76fdacd90dc31eeb66d97 Mon Sep 17 00:00:00 2001 From: Eddie James Date: Wed, 24 Apr 2019 11:16:59 -0400 Subject: [PATCH 218/218] media: dt-bindings: aspeed-video: Add missing memory-region property Missed documenting this property in the initial commit. Signed-off-by: Eddie James Reviewed-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/aspeed-video.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/media/aspeed-video.txt b/Documentation/devicetree/bindings/media/aspeed-video.txt index 78b464ae2672..ce2894506e1f 100644 --- a/Documentation/devicetree/bindings/media/aspeed-video.txt +++ b/Documentation/devicetree/bindings/media/aspeed-video.txt @@ -14,6 +14,11 @@ Required properties: the VE - interrupts: the interrupt associated with the VE on this platform +Optional properties: + - memory-region: + phandle to a memory region to allocate from, as defined in + Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt + Example: video-engine@1e700000 { @@ -23,4 +28,5 @@ video-engine@1e700000 { clock-names = "vclk", "eclk"; resets = <&syscon ASPEED_RESET_VIDEO>; interrupts = <7>; + memory-region = <&video_engine_memory>; };