From f28701cc24fcfd7f7b2fdd8b87e529b2034314d7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 13 May 2023 18:14:27 +0100 Subject: [PATCH 001/253] media: dvbdev: fix most coding style issues As we're doing several changes here, address coding style issues, as reported by checkpatch.pl. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvbdev.c | 157 +++++++++++++++----------------- 1 file changed, 74 insertions(+), 83 deletions(-) diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index a4b05e366ccc..fb81fa46d92e 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -61,21 +61,21 @@ static const char * const dnames[] = { #define DVB_MAX_IDS 4 static const u8 minor_type[] = { - [DVB_DEVICE_VIDEO] = 0, - [DVB_DEVICE_AUDIO] = 1, - [DVB_DEVICE_SEC] = 2, - [DVB_DEVICE_FRONTEND] = 3, - [DVB_DEVICE_DEMUX] = 4, - [DVB_DEVICE_DVR] = 5, - [DVB_DEVICE_CA] = 6, - [DVB_DEVICE_NET] = 7, - [DVB_DEVICE_OSD] = 8, + [DVB_DEVICE_VIDEO] = 0, + [DVB_DEVICE_AUDIO] = 1, + [DVB_DEVICE_SEC] = 2, + [DVB_DEVICE_FRONTEND] = 3, + [DVB_DEVICE_DEMUX] = 4, + [DVB_DEVICE_DVR] = 5, + [DVB_DEVICE_CA] = 6, + [DVB_DEVICE_NET] = 7, + [DVB_DEVICE_OSD] = 8, }; #define nums2minor(num, type, id) \ - (((num) << 6) | ((id) << 4) | minor_type[type]) + (((num) << 6) | ((id) << 4) | minor_type[type]) -#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64) +#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS * 64) #endif static struct class *dvb_class; @@ -112,9 +112,7 @@ fail: return -ENODEV; } - -static const struct file_operations dvb_device_fops = -{ +static const struct file_operations dvb_device_fops = { .owner = THIS_MODULE, .open = dvb_device_open, .llseek = noop_llseek, @@ -147,7 +145,6 @@ int dvb_generic_open(struct inode *inode, struct file *file) } EXPORT_SYMBOL(dvb_generic_open); - int dvb_generic_release(struct inode *inode, struct file *file) { struct dvb_device *dvbdev = file->private_data; @@ -155,11 +152,10 @@ int dvb_generic_release(struct inode *inode, struct file *file) if (!dvbdev) return -ENODEV; - if ((file->f_flags & O_ACCMODE) == O_RDONLY) { + if ((file->f_flags & O_ACCMODE) == O_RDONLY) dvbdev->readers++; - } else { + else dvbdev->writers++; - } dvbdev->users++; @@ -169,7 +165,6 @@ int dvb_generic_release(struct inode *inode, struct file *file) } EXPORT_SYMBOL(dvb_generic_release); - long dvb_generic_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -185,13 +180,13 @@ long dvb_generic_ioctl(struct file *file, } EXPORT_SYMBOL(dvb_generic_ioctl); - -static int dvbdev_get_free_id (struct dvb_adapter *adap, int type) +static int dvbdev_get_free_id(struct dvb_adapter *adap, int type) { u32 id = 0; while (id < DVB_MAX_IDS) { struct dvb_device *dev; + list_for_each_entry(dev, &adap->device_list, list_head) if (dev->type == type && dev->id == id) goto skip; @@ -245,7 +240,7 @@ static void dvb_media_device_free(struct dvb_device *dvbdev) #if defined(CONFIG_MEDIA_CONTROLLER_DVB) static int dvb_create_tsout_entity(struct dvb_device *dvbdev, - const char *name, int npads) + const char *name, int npads) { int i; @@ -387,7 +382,7 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev, static int dvb_register_media_device(struct dvb_device *dvbdev, int type, int minor, - unsigned demux_sink_pads) + unsigned int demux_sink_pads) { #if defined(CONFIG_MEDIA_CONTROLLER_DVB) struct media_link *link; @@ -462,7 +457,8 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, mutex_lock(&dvbdev_register_lock); - if ((id = dvbdev_get_free_id (adap, type)) < 0) { + id = dvbdev_get_free_id(adap, type); + if (id < 0) { mutex_unlock(&dvbdev_register_lock); *pdvbdev = NULL; pr_err("%s: couldn't find free device id\n", __func__); @@ -470,7 +466,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, } *pdvbdev = dvbdev = kzalloc(sizeof(*dvbdev), GFP_KERNEL); - if (!dvbdev){ + if (!dvbdev) { mutex_unlock(&dvbdev_register_lock); return -ENOMEM; } @@ -482,14 +478,13 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, */ list_for_each_entry(node, &dvbdevfops_list, list_head) { if (node->fops->owner == adap->module && - node->type == type && - node->template == template) { + node->type == type && node->template == template) { dvbdevfops = node->fops; break; } } - if (dvbdevfops == NULL) { + if (!dvbdevfops) { dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL); if (!dvbdevfops) { kfree(dvbdev); @@ -497,7 +492,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, return -ENOMEM; } - new_node = kzalloc(sizeof(struct dvbdevfops_node), GFP_KERNEL); + new_node = kzalloc(sizeof(*new_node), GFP_KERNEL); if (!new_node) { kfree(dvbdevfops); kfree(dvbdev); @@ -508,7 +503,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, new_node->fops = dvbdevfops; new_node->type = type; new_node->template = template; - list_add_tail (&new_node->list_head, &dvbdevfops_list); + list_add_tail(&new_node->list_head, &dvbdevfops_list); } memcpy(dvbdev, template, sizeof(struct dvb_device)); @@ -518,21 +513,21 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, dvbdev->adapter = adap; dvbdev->priv = priv; dvbdev->fops = dvbdevfops; - init_waitqueue_head (&dvbdev->wait_queue); + init_waitqueue_head(&dvbdev->wait_queue); dvbdevfops->owner = adap->module; - list_add_tail (&dvbdev->list_head, &adap->device_list); + list_add_tail(&dvbdev->list_head, &adap->device_list); down_write(&minor_rwsem); #ifdef CONFIG_DVB_DYNAMIC_MINORS for (minor = 0; minor < MAX_DVB_MINORS; minor++) - if (dvb_minors[minor] == NULL) + if (!dvb_minors[minor]) break; if (minor == MAX_DVB_MINORS) { if (new_node) { - list_del (&new_node->list_head); + list_del(&new_node->list_head); kfree(dvbdevfops); kfree(new_node); } - list_del (&dvbdev->list_head); + list_del(&dvbdev->list_head); kfree(dvbdev); up_write(&minor_rwsem); mutex_unlock(&dvbdev_register_lock); @@ -547,14 +542,14 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads); if (ret) { pr_err("%s: dvb_register_media_device failed to create the mediagraph\n", - __func__); + __func__); if (new_node) { - list_del (&new_node->list_head); + list_del(&new_node->list_head); kfree(dvbdevfops); kfree(new_node); } dvb_media_device_free(dvbdev); - list_del (&dvbdev->list_head); + list_del(&dvbdev->list_head); kfree(dvbdev); mutex_unlock(&dvbdev_register_lock); return ret; @@ -567,12 +562,12 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n", __func__, adap->num, dnames[type], id, PTR_ERR(clsdev)); if (new_node) { - list_del (&new_node->list_head); + list_del(&new_node->list_head); kfree(dvbdevfops); kfree(new_node); } dvb_media_device_free(dvbdev); - list_del (&dvbdev->list_head); + list_del(&dvbdev->list_head); kfree(dvbdev); mutex_unlock(&dvbdev_register_lock); return PTR_ERR(clsdev); @@ -586,7 +581,6 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, } EXPORT_SYMBOL(dvb_register_device); - void dvb_remove_device(struct dvb_device *dvbdev) { if (!dvbdev) @@ -601,19 +595,17 @@ void dvb_remove_device(struct dvb_device *dvbdev) device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor)); - list_del (&dvbdev->list_head); + list_del(&dvbdev->list_head); } EXPORT_SYMBOL(dvb_remove_device); - static void dvb_free_device(struct kref *ref) { struct dvb_device *dvbdev = container_of(ref, struct dvb_device, ref); - kfree (dvbdev); + kfree(dvbdev); } - struct dvb_device *dvb_device_get(struct dvb_device *dvbdev) { kref_get(&dvbdev->ref); @@ -621,14 +613,12 @@ struct dvb_device *dvb_device_get(struct dvb_device *dvbdev) } EXPORT_SYMBOL(dvb_device_get); - void dvb_device_put(struct dvb_device *dvbdev) { if (dvbdev) kref_put(&dvbdev->ref, dvb_free_device); } - void dvb_unregister_device(struct dvb_device *dvbdev) { dvb_remove_device(dvbdev); @@ -636,7 +626,6 @@ void dvb_unregister_device(struct dvb_device *dvbdev) } EXPORT_SYMBOL(dvb_unregister_device); - #ifdef CONFIG_MEDIA_CONTROLLER_DVB static int dvb_create_io_intf_links(struct dvb_adapter *adap, @@ -669,9 +658,9 @@ int dvb_create_media_graph(struct dvb_adapter *adap, struct media_entity *demux = NULL, *ca = NULL; struct media_link *link; struct media_interface *intf; - unsigned demux_pad = 0; - unsigned dvr_pad = 0; - unsigned ntuner = 0, ndemod = 0; + unsigned int demux_pad = 0; + unsigned int dvr_pad = 0; + unsigned int ntuner = 0, ndemod = 0; int ret, pad_source, pad_sink; static const char *connector_name = "Television"; @@ -795,18 +784,18 @@ int dvb_create_media_graph(struct dvb_adapter *adap, media_device_for_each_entity(entity, mdev) { if (entity->function == MEDIA_ENT_F_IO_DTV) { if (!strncmp(entity->name, DVR_TSOUT, - strlen(DVR_TSOUT))) { + strlen(DVR_TSOUT))) { ret = media_create_pad_link(demux, - ++dvr_pad, - entity, 0, 0); + ++dvr_pad, + entity, 0, 0); if (ret) return ret; } if (!strncmp(entity->name, DEMUX_TSOUT, - strlen(DEMUX_TSOUT))) { + strlen(DEMUX_TSOUT))) { ret = media_create_pad_link(demux, - ++demux_pad, - entity, 0, 0); + ++demux_pad, + entity, 0, 0); if (ret) return ret; } @@ -864,8 +853,10 @@ EXPORT_SYMBOL_GPL(dvb_create_media_graph); static int dvbdev_check_free_adapter_num(int num) { struct list_head *entry; + list_for_each(entry, &dvb_adapter_list) { struct dvb_adapter *adap; + adap = list_entry(entry, struct dvb_adapter, list_head); if (adap->num == num) return 0; @@ -873,7 +864,7 @@ static int dvbdev_check_free_adapter_num(int num) return 1; } -static int dvbdev_get_free_adapter_num (void) +static int dvbdev_get_free_adapter_num(void) { int num = 0; @@ -886,7 +877,6 @@ static int dvbdev_get_free_adapter_num (void) return -ENFILE; } - int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module, struct device *device, short *adapter_nums) @@ -913,8 +903,8 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, return -ENFILE; } - memset (adap, 0, sizeof(struct dvb_adapter)); - INIT_LIST_HEAD (&adap->device_list); + memset(adap, 0, sizeof(struct dvb_adapter)); + INIT_LIST_HEAD(&adap->device_list); pr_info("DVB: registering new adapter (%s)\n", name); @@ -924,13 +914,13 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, adap->device = device; adap->mfe_shared = 0; adap->mfe_dvbdev = NULL; - mutex_init (&adap->mfe_lock); + mutex_init(&adap->mfe_lock); #ifdef CONFIG_MEDIA_CONTROLLER_DVB mutex_init(&adap->mdev_lock); #endif - list_add_tail (&adap->list_head, &dvb_adapter_list); + list_add_tail(&adap->list_head, &dvb_adapter_list); mutex_unlock(&dvbdev_register_lock); @@ -938,25 +928,26 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, } EXPORT_SYMBOL(dvb_register_adapter); - int dvb_unregister_adapter(struct dvb_adapter *adap) { mutex_lock(&dvbdev_register_lock); - list_del (&adap->list_head); + list_del(&adap->list_head); mutex_unlock(&dvbdev_register_lock); return 0; } EXPORT_SYMBOL(dvb_unregister_adapter); -/* if the miracle happens and "generic_usercopy()" is included into - the kernel, then this can vanish. please don't make the mistake and - define this as video_usercopy(). this will introduce a dependency - to the v4l "videodev.o" module, which is unnecessary for some - cards (ie. the budget dvb-cards don't need the v4l module...) */ +/* + * if the miracle happens and "generic_usercopy()" is included into + * the kernel, then this can vanish. please don't make the mistake and + * define this as video_usercopy(). this will introduce a dependency + * to the v4l "videodev.o" module, which is unnecessary for some + * cards (ie. the budget dvb-cards don't need the v4l module...) + */ int dvb_usercopy(struct file *file, - unsigned int cmd, unsigned long arg, - int (*func)(struct file *file, - unsigned int cmd, void *arg)) + unsigned int cmd, unsigned long arg, + int (*func)(struct file *file, + unsigned int cmd, void *arg)) { char sbuf[128]; void *mbuf = NULL; @@ -970,7 +961,7 @@ int dvb_usercopy(struct file *file, * For this command, the pointer is actually an integer * argument. */ - parg = (void *) arg; + parg = (void *)arg; break; case _IOC_READ: /* some v4l ioctls are marked wrong ... */ case _IOC_WRITE: @@ -980,7 +971,7 @@ int dvb_usercopy(struct file *file, } else { /* too big to allocate from stack */ mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); - if (NULL == mbuf) + if (!mbuf) return -ENOMEM; parg = mbuf; } @@ -992,15 +983,15 @@ int dvb_usercopy(struct file *file, } /* call driver */ - if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD) + err = func(file, cmd, parg); + if (err == -ENOIOCTLCMD) err = -ENOTTY; if (err < 0) goto out; /* Copy results into user buffer */ - switch (_IOC_DIR(cmd)) - { + switch (_IOC_DIR(cmd)) { case _IOC_READ: case (_IOC_WRITE | _IOC_READ): if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) @@ -1080,19 +1071,20 @@ static char *dvb_devnode(const struct device *dev, umode_t *mode) dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id); } - static int __init init_dvbdev(void) { int retval; dev_t dev = MKDEV(DVB_MAJOR, 0); - if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) { + retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB"); + if (retval != 0) { pr_err("dvb-core: unable to get major %d\n", DVB_MAJOR); return retval; } cdev_init(&dvb_device_cdev, &dvb_device_fops); - if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) { + retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS); + if (retval != 0) { pr_err("dvb-core: unable register character device\n"); goto error; } @@ -1112,7 +1104,6 @@ error: return retval; } - static void __exit exit_dvbdev(void) { struct dvbdevfops_node *node, *next; @@ -1122,7 +1113,7 @@ static void __exit exit_dvbdev(void) unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS); list_for_each_entry_safe(node, next, &dvbdevfops_list, list_head) { - list_del (&node->list_head); + list_del(&node->list_head); kfree(node->fops); kfree(node); } From 633733f5c2aa66583450a107dd0f22786ac30400 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 3 Dec 2022 06:09:31 +0000 Subject: [PATCH 002/253] media: dvbdev.h: do some kernel-doc cleanups Some kernel-doc warnings in were introduced. A fixup patch addressed them was already merged, but Randy's approach from: https://lore.kernel.org/linux-media/20221203060931.19953-1-rdunlap@infradead.org Had some advantages, as it moves the @dvbdev to the right place inside dvb_remove_device() documentation and it makes clearer about what refcounter struct dvb_device refers to. So, apply the changes suggested by Randy. Suggested-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- include/media/dvbdev.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/media/dvbdev.h b/include/media/dvbdev.h index 8958e5e2fc5b..e5a00d126612 100644 --- a/include/media/dvbdev.h +++ b/include/media/dvbdev.h @@ -130,7 +130,7 @@ struct dvb_adapter { * struct dvb_device - represents a DVB device node * * @list_head: List head with all DVB devices - * @ref: reference counter + * @ref: reference count for this device * @fops: pointer to struct file_operations * @adapter: pointer to the adapter that holds this device node * @type: type of the device, as defined by &enum dvb_device_type. @@ -266,10 +266,10 @@ int dvb_register_device(struct dvb_adapter *adap, /** * dvb_remove_device - Remove a registered DVB device * + * @dvbdev: pointer to struct dvb_device + * * This does not free memory. dvb_free_device() will do that when * reference counter is empty - * - * @dvbdev: pointer to struct dvb_device */ void dvb_remove_device(struct dvb_device *dvbdev); From a41ef7869166c3705e858c0813d59cf844889265 Mon Sep 17 00:00:00 2001 From: Yu Zhe Date: Mon, 20 Mar 2023 07:08:28 +0000 Subject: [PATCH 003/253] media: c8sectpfe: dvb: remove unnecessary (void*) conversions Pointer variables of void * type do not require type cast. Link: https://lore.kernel.org/linux-media/20230320070828.13322-1-yuzhe@nfschina.com Signed-off-by: Yu Zhe Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c index 45ade7210d26..120830973d22 100644 --- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c +++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c @@ -135,7 +135,7 @@ static void channel_swdemux_tsklet(struct tasklet_struct *t) static int c8sectpfe_start_feed(struct dvb_demux_feed *dvbdmxfeed) { struct dvb_demux *demux = dvbdmxfeed->demux; - struct stdemux *stdemux = (struct stdemux *)demux->priv; + struct stdemux *stdemux = demux->priv; struct c8sectpfei *fei = stdemux->c8sectpfei; struct channel_info *channel; u32 tmp; @@ -256,7 +256,7 @@ static int c8sectpfe_stop_feed(struct dvb_demux_feed *dvbdmxfeed) { struct dvb_demux *demux = dvbdmxfeed->demux; - struct stdemux *stdemux = (struct stdemux *)demux->priv; + struct stdemux *stdemux = demux->priv; struct c8sectpfei *fei = stdemux->c8sectpfei; struct channel_info *channel; int idlereq; From 663e7460b123271c64be7024cadef86dbb4d8463 Mon Sep 17 00:00:00 2001 From: Yu Zhe Date: Mon, 20 Mar 2023 06:40:39 +0000 Subject: [PATCH 004/253] media: dvb-usb: remove unnecessary (void*) conversions Pointer variables of void * type do not require type cast. Link: https://lore.kernel.org/linux-media/20230320064039.5670-1-yuzhe@nfschina.com Signed-off-by: Yu Zhe Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/af9005-fe.c | 3 +-- drivers/media/usb/dvb-usb/az6027.c | 34 +++++++++++++------------- drivers/media/usb/dvb-usb/dtt200u-fe.c | 2 +- drivers/media/usb/dvb-usb/dw2102.c | 20 ++++++--------- drivers/media/usb/dvb-usb/opera1.c | 3 +-- drivers/media/usb/dvb-usb/pctv452e.c | 20 +++++++-------- 6 files changed, 38 insertions(+), 44 deletions(-) diff --git a/drivers/media/usb/dvb-usb/af9005-fe.c b/drivers/media/usb/dvb-usb/af9005-fe.c index 9d6fa0556d7b..404e56b32145 100644 --- a/drivers/media/usb/dvb-usb/af9005-fe.c +++ b/drivers/media/usb/dvb-usb/af9005-fe.c @@ -1412,8 +1412,7 @@ static int af9005_fe_get_frontend(struct dvb_frontend *fe, static void af9005_fe_release(struct dvb_frontend *fe) { - struct af9005_fe_state *state = - (struct af9005_fe_state *)fe->demodulator_priv; + struct af9005_fe_state *state = fe->demodulator_priv; kfree(state); } diff --git a/drivers/media/usb/dvb-usb/az6027.c b/drivers/media/usb/dvb-usb/az6027.c index a31c6f82f4e9..2bc27710427d 100644 --- a/drivers/media/usb/dvb-usb/az6027.c +++ b/drivers/media/usb/dvb-usb/az6027.c @@ -407,8 +407,8 @@ static int az6027_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + struct dvb_usb_device *d = ca->data; + struct az6027_device_state *state = d->priv; int ret; u8 req; @@ -449,8 +449,8 @@ static int az6027_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, int address, u8 value) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + struct dvb_usb_device *d = ca->data; + struct az6027_device_state *state = d->priv; int ret; u8 req; @@ -480,8 +480,8 @@ static int az6027_ci_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + struct dvb_usb_device *d = ca->data; + struct az6027_device_state *state = d->priv; int ret; u8 req; @@ -526,8 +526,8 @@ static int az6027_ci_write_cam_control(struct dvb_ca_en50221 *ca, u8 address, u8 value) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + struct dvb_usb_device *d = ca->data; + struct az6027_device_state *state = d->priv; int ret; u8 req; @@ -557,7 +557,7 @@ failed: static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct dvb_usb_device *d = ca->data; int ret; u8 req; @@ -588,8 +588,8 @@ static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot) static int az6027_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + struct dvb_usb_device *d = ca->data; + struct az6027_device_state *state = d->priv; int ret, i; u8 req; @@ -644,8 +644,8 @@ static int az6027_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) static int az6027_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + struct dvb_usb_device *d = ca->data; + struct az6027_device_state *state = d->priv; int ret; u8 req; @@ -673,8 +673,8 @@ failed: static int az6027_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + struct dvb_usb_device *d = ca->data; + struct az6027_device_state *state = d->priv; int ret; u8 req; u16 value; @@ -719,7 +719,7 @@ static void az6027_ci_uninit(struct dvb_usb_device *d) if (NULL == d) return; - state = (struct az6027_device_state *)d->priv; + state = d->priv; if (NULL == state) return; @@ -735,7 +735,7 @@ static void az6027_ci_uninit(struct dvb_usb_device *d) static int az6027_ci_init(struct dvb_usb_adapter *a) { struct dvb_usb_device *d = a->dev; - struct az6027_device_state *state = (struct az6027_device_state *)d->priv; + struct az6027_device_state *state = d->priv; int ret; deb_info("%s", __func__); diff --git a/drivers/media/usb/dvb-usb/dtt200u-fe.c b/drivers/media/usb/dvb-usb/dtt200u-fe.c index 9f83560ba63d..586afe22d817 100644 --- a/drivers/media/usb/dvb-usb/dtt200u-fe.c +++ b/drivers/media/usb/dvb-usb/dtt200u-fe.c @@ -195,7 +195,7 @@ static int dtt200u_fe_get_frontend(struct dvb_frontend* fe, static void dtt200u_fe_release(struct dvb_frontend* fe) { - struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv; + struct dtt200u_fe_state *state = fe->demodulator_priv; kfree(state); } diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 8747960e6146..2a048499468b 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -903,7 +903,7 @@ static int su3000_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) static int su3000_power_ctrl(struct dvb_usb_device *d, int i) { - struct dw2102_state *state = (struct dw2102_state *)d->priv; + struct dw2102_state *state = d->priv; int ret = 0; info("%s: %d, initialized %d", __func__, i, state->initialized); @@ -978,8 +978,7 @@ static int dw210x_set_voltage(struct dvb_frontend *fe, .len = 2, }; - struct dvb_usb_adapter *udev_adap = - (struct dvb_usb_adapter *)(fe->dvb->priv); + struct dvb_usb_adapter *udev_adap = fe->dvb->priv; if (voltage == SEC_VOLTAGE_18) msg.buf = command_18v; else if (voltage == SEC_VOLTAGE_13) @@ -993,9 +992,8 @@ static int dw210x_set_voltage(struct dvb_frontend *fe, static int s660_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) { - struct dvb_usb_adapter *d = - (struct dvb_usb_adapter *)(fe->dvb->priv); - struct dw2102_state *st = (struct dw2102_state *)d->dev->priv; + struct dvb_usb_adapter *d = fe->dvb->priv; + struct dw2102_state *st = d->dev->priv; dw210x_set_voltage(fe, voltage); if (st->old_set_voltage) @@ -1014,8 +1012,7 @@ static void dw210x_led_ctrl(struct dvb_frontend *fe, int offon) .buf = led_off, .len = 1 }; - struct dvb_usb_adapter *udev_adap = - (struct dvb_usb_adapter *)(fe->dvb->priv); + struct dvb_usb_adapter *udev_adap = fe->dvb->priv; if (offon) msg.buf = led_on; @@ -1025,9 +1022,8 @@ static void dw210x_led_ctrl(struct dvb_frontend *fe, int offon) static int tt_s2_4600_read_status(struct dvb_frontend *fe, enum fe_status *status) { - struct dvb_usb_adapter *d = - (struct dvb_usb_adapter *)(fe->dvb->priv); - struct dw2102_state *st = (struct dw2102_state *)d->dev->priv; + struct dvb_usb_adapter *d = fe->dvb->priv; + struct dw2102_state *st = d->dev->priv; int ret; ret = st->fe_read_status(fe, status); @@ -2576,7 +2572,7 @@ static int dw2102_probe(struct usb_interface *intf, static void dw2102_disconnect(struct usb_interface *intf) { struct dvb_usb_device *d = usb_get_intfdata(intf); - struct dw2102_state *st = (struct dw2102_state *)d->priv; + struct dw2102_state *st = d->priv; struct i2c_client *client; /* remove I2C client for tuner */ diff --git a/drivers/media/usb/dvb-usb/opera1.c b/drivers/media/usb/dvb-usb/opera1.c index 0da86f58aff6..98b2177667d2 100644 --- a/drivers/media/usb/dvb-usb/opera1.c +++ b/drivers/media/usb/dvb-usb/opera1.c @@ -172,8 +172,7 @@ static int opera1_set_voltage(struct dvb_frontend *fe, struct i2c_msg msg[] = { {.addr = ADDR_B600_VOLTAGE_13V,.flags = 0,.buf = command_13v,.len = 1}, }; - struct dvb_usb_adapter *udev_adap = - (struct dvb_usb_adapter *)(fe->dvb->priv); + struct dvb_usb_adapter *udev_adap = fe->dvb->priv; if (voltage == SEC_VOLTAGE_18) { msg[0].addr = ADDR_B601_VOLTAGE_18V; msg[0].buf = command_18v; diff --git a/drivers/media/usb/dvb-usb/pctv452e.c b/drivers/media/usb/dvb-usb/pctv452e.c index da42c989e071..2aab49003493 100644 --- a/drivers/media/usb/dvb-usb/pctv452e.c +++ b/drivers/media/usb/dvb-usb/pctv452e.c @@ -108,7 +108,7 @@ struct pctv452e_state { static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len) { - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; + struct pctv452e_state *state = d->priv; u8 *buf; u8 id; unsigned int rlen; @@ -159,8 +159,8 @@ static int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; + struct dvb_usb_device *d = ca->data; + struct pctv452e_state *state = d->priv; int ret; mutex_lock(&state->ca_mutex); @@ -292,8 +292,8 @@ static int tt3650_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) static int tt3650_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; + struct dvb_usb_device *d = ca->data; + struct pctv452e_state *state = d->priv; u8 buf[1]; int ret; @@ -361,7 +361,7 @@ static void tt3650_ci_uninit(struct dvb_usb_device *d) if (NULL == d) return; - state = (struct pctv452e_state *)d->priv; + state = d->priv; if (NULL == state) return; @@ -379,7 +379,7 @@ static void tt3650_ci_uninit(struct dvb_usb_device *d) static int tt3650_ci_init(struct dvb_usb_adapter *a) { struct dvb_usb_device *d = a->dev; - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; + struct pctv452e_state *state = d->priv; int ret; ci_dbg("%s", __func__); @@ -417,7 +417,7 @@ static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr, const u8 *snd_buf, u8 snd_len, u8 *rcv_buf, u8 rcv_len) { - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; + struct pctv452e_state *state = d->priv; u8 *buf; u8 id; int ret; @@ -516,7 +516,7 @@ static u32 pctv452e_i2c_func(struct i2c_adapter *adapter) static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i) { - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; + struct pctv452e_state *state = d->priv; u8 *b0, *rx; int ret; @@ -567,7 +567,7 @@ ret: static int pctv452e_rc_query(struct dvb_usb_device *d) { - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; + struct pctv452e_state *state = d->priv; u8 *b, *rx; int ret, i; u8 id; From b37d9c995aef9487040d07326c9e7e560cf23396 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 13 May 2023 08:04:32 +0100 Subject: [PATCH 005/253] media: dw2102: return -EIO instead of -1 for mac address read errors The dvb-usb core function only checks if the returned value is zero, so it doesn't actually matter the error code. Still, returning -1 as an error condition is something that we don't do upstream. So, change the logic to return -EIO in case of I2C transfer failures. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/dw2102.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 2a048499468b..970b84c3f0b5 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -830,7 +830,7 @@ static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) for (i = 0; i < 256; i++) { if (dw210x_op_rw(d->udev, 0xb6, 0xa0 , i, ibuf, 2, DW210X_READ_MSG) < 0) { err("read eeprom failed."); - return -1; + return -EIO; } else { eepromline[i%16] = ibuf[0]; eeprom[i] = ibuf[0]; @@ -869,7 +869,7 @@ static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) ret = s6x0_i2c_transfer(&d->i2c_adap, msg, 2); if (ret != 2) { err("read eeprom failed."); - return -1; + return -EIO; } else { eepromline[i % 16] = ibuf[0]; eeprom[i] = ibuf[0]; @@ -946,7 +946,7 @@ static int su3000_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) for (i = 0; i < 6; i++) { obuf[1] = 0xf0 + i; if (i2c_transfer(&d->i2c_adap, msg, 2) != 2) - return -1; + return -EIO; else mac[i] = ibuf[0]; } From 1825788e2a96764ae9ad4641191b2aebec6d2b84 Mon Sep 17 00:00:00 2001 From: Athanasios Oikonomou Date: Wed, 11 Jan 2023 19:46:08 +0000 Subject: [PATCH 006/253] media: dvb: add missing DVB-S2X FEC parameter values This commit is adding the missing short FEC Missed on commit 6508a50fe84f9858e8b59b53dce3847aaeeab744 More info: https://dvb.org/wp-content/uploads/2021/02/A083-2r2_DVB-S2X_Draft-EN-302-307-2-v131_Feb_2021.pdf Table 1: S2X System configurations and application areas Please note that 128APSK, 256APSK and 256APSK-L and FEC 29/45, 31/45 are still missing from enums. Link: https://lore.kernel.org/linux-media/20230111194608.1853-1-athoik@gmail.com Cc: Robert Schlabbach Cc: Tom Richardson Signed-off-by: Athanasios Oikonomou Signed-off-by: Mauro Carvalho Chehab --- include/uapi/linux/dvb/frontend.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/uapi/linux/dvb/frontend.h b/include/uapi/linux/dvb/frontend.h index 326f6a53f1f2..7e0983b987c2 100644 --- a/include/uapi/linux/dvb/frontend.h +++ b/include/uapi/linux/dvb/frontend.h @@ -296,6 +296,10 @@ enum fe_spectral_inversion { * @FEC_28_45: Forward Error Correction Code 28/45 * @FEC_32_45: Forward Error Correction Code 32/45 * @FEC_77_90: Forward Error Correction Code 77/90 + * @FEC_11_45: Forward Error Correction Code 11/45 + * @FEC_4_15: Forward Error Correction Code 4/15 + * @FEC_14_45: Forward Error Correction Code 14/45 + * @FEC_7_15: Forward Error Correction Code 7/15 * * Please note that not all FEC types are supported by a given standard. */ @@ -329,6 +333,10 @@ enum fe_code_rate { FEC_28_45, FEC_32_45, FEC_77_90, + FEC_11_45, + FEC_4_15, + FEC_14_45, + FEC_7_15, }; /** From 2a3f9d4def27c5b30563d11c548ac606ab0066ac Mon Sep 17 00:00:00 2001 From: Athanasios Oikonomou Date: Tue, 10 Jan 2023 07:14:21 +0000 Subject: [PATCH 007/253] media: dvb: bump DVB API version Bump the DVB API version in order userspace to be aware of the changes recently implemented in enumerations for DVB-S2(X) and DVB-C2. Related: commit 6508a50fe84f ("media: dvb: add DVB-C2 and DVB-S2X parameter values") Link: https://lore.kernel.org/linux-media/20230110071421.31498-1-athoik@gmail.com Cc: Robert Schlabbach Signed-off-by: Athanasios Oikonomou Signed-off-by: Mauro Carvalho Chehab --- include/uapi/linux/dvb/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/uapi/linux/dvb/version.h b/include/uapi/linux/dvb/version.h index 1a8cd038aa0b..20bc874de321 100644 --- a/include/uapi/linux/dvb/version.h +++ b/include/uapi/linux/dvb/version.h @@ -10,6 +10,6 @@ #define _DVBVERSION_H_ #define DVB_API_VERSION 5 -#define DVB_API_VERSION_MINOR 11 +#define DVB_API_VERSION_MINOR 12 #endif /*_DVBVERSION_H_*/ From 8bc27fa5d7763d376a992a1638475987ed4807e7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 15 May 2023 06:43:43 +0100 Subject: [PATCH 008/253] docs: uapi: media: ignore new DVB-S2X FEC values Some new FEC values was added to support DVB-S2X. They're properly documented, but its addition adds some extra warnings to htmldocs build. So, add them to the ignore list. Fixes: 1825788e2a96 ("media: dvb: add missing DVB-S2X FEC parameter values") Reported-by: Stephen Rothwell Signed-off-by: Mauro Carvalho Chehab --- Documentation/userspace-api/media/frontend.h.rst.exceptions | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/userspace-api/media/frontend.h.rst.exceptions b/Documentation/userspace-api/media/frontend.h.rst.exceptions index 8b73fee11a79..dcaf5740de7e 100644 --- a/Documentation/userspace-api/media/frontend.h.rst.exceptions +++ b/Documentation/userspace-api/media/frontend.h.rst.exceptions @@ -142,6 +142,10 @@ ignore symbol FEC_26_45 ignore symbol FEC_28_45 ignore symbol FEC_32_45 ignore symbol FEC_77_90 +ignore symbol FEC_11_45 +ignore symbol FEC_4_15 +ignore symbol FEC_14_45 +ignore symbol FEC_7_15 ignore symbol TRANSMISSION_MODE_AUTO ignore symbol TRANSMISSION_MODE_1K From 7e3d507ab040c0f21f680c6e23d8432623867b3c Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 18 Apr 2023 10:00:35 +0200 Subject: [PATCH 009/253] dt-bindings: display: tegra: add Tegra20 VIP VIP is the parallel video capture component within the video input subsystem of Tegra20 (and other Tegra chips, apparently). Signed-off-by: Luca Ceresoli Reviewed-by: Krzysztof Kozlowski Reviewed-by: Dmitry Osipenko Signed-off-by: Hans Verkuil --- .../display/tegra/nvidia,tegra20-vip.yaml | 41 +++++++++++++++++++ MAINTAINERS | 2 + 2 files changed, 43 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vip.yaml diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vip.yaml b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vip.yaml new file mode 100644 index 000000000000..14294edb8d8c --- /dev/null +++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vip.yaml @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/tegra/nvidia,tegra20-vip.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NVIDIA Tegra VIP (parallel video capture) controller + +maintainers: + - Luca Ceresoli + +properties: + compatible: + enum: + - nvidia,tegra20-vip + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: + Port receiving the video stream from the sensor + + port@1: + $ref: /schemas/graph.yaml#/properties/port + description: + Port sending the video stream to the VI + + required: + - port@0 + - port@1 + +unevaluatedProperties: false + +required: + - compatible + - ports + +# see nvidia,tegra20-vi.yaml for an example diff --git a/MAINTAINERS b/MAINTAINERS index e0ad886d3163..2b080e17105b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20817,10 +20817,12 @@ TEGRA VIDEO DRIVER M: Thierry Reding M: Jonathan Hunter M: Sowjanya Komatineni +M: Luca Ceresoli L: linux-media@vger.kernel.org L: linux-tegra@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.yaml +F: Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vip.yaml F: drivers/staging/media/tegra-video/ TEGRA XUSB PADCTL DRIVER From f17aa778ac36298a8b5648984de6f1b8c8d87705 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 18 Apr 2023 10:00:36 +0200 Subject: [PATCH 010/253] dt-bindings: display: tegra: vi: add 'vip' property and example The Tegra20 VI peripheral can receive parallel input from the VIP parallel input module. Add it to the allowed properties and augment the existing nvidia,tegra20-vi example to show a 'vip' property. Signed-off-by: Luca Ceresoli Reviewed-by: Rob Herring Signed-off-by: Hans Verkuil --- .../display/tegra/nvidia,tegra20-vi.yaml | 59 +++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 60 insertions(+) diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vi.yaml b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vi.yaml index a42bf33d1e7d..2181855a0920 100644 --- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vi.yaml +++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vi.yaml @@ -73,6 +73,18 @@ properties: avdd-dsi-csi-supply: description: DSI/CSI power supply. Must supply 1.2 V. + vip: + $ref: /schemas/display/tegra/nvidia,tegra20-vip.yaml + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + description: + Input from the VIP (parallel input capture) module + patternProperties: "^csi@[0-9a-f]+$": type: object @@ -108,6 +120,22 @@ examples: #include #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + camera@48 { + compatible = "aptina,mt9v111"; + reg = <0x48>; + clocks = <&camera_clk>; + + port { + mt9v111_out: endpoint { + remote-endpoint = <&vi_vip_in>; + }; + }; + }; + }; + vi@54080000 { compatible = "nvidia,tegra20-vi"; reg = <0x54080000 0x00040000>; @@ -115,6 +143,37 @@ examples: clocks = <&tegra_car TEGRA20_CLK_VI>; resets = <&tegra_car 100>; reset-names = "vi"; + + vip { + compatible = "nvidia,tegra20-vip"; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + vi_vip_in: endpoint { + remote-endpoint = <&mt9v111_out>; + }; + }; + port@1 { + reg = <1>; + vi_vip_out: endpoint { + remote-endpoint = <&vi_in>; + }; + }; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + vi_in: endpoint { + remote-endpoint = <&vi_vip_out>; + }; + }; + }; }; - | diff --git a/MAINTAINERS b/MAINTAINERS index 2b080e17105b..3d44daf1ac15 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20822,6 +20822,7 @@ L: linux-media@vger.kernel.org L: linux-tegra@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.yaml +F: Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vi.yaml F: Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vip.yaml F: drivers/staging/media/tegra-video/ From b48ece9bb81b2a0e84dfd08432c4f5cdb81f84c0 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 18 Apr 2023 10:00:37 +0200 Subject: [PATCH 011/253] staging: media: tegra-video: improve documentation of tegra_video_format fields Some fields are irrelevant for Tegra20/VIP. Add a note to clarify that. Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Osipenko Signed-off-by: Hans Verkuil --- drivers/staging/media/tegra-video/vi.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/media/tegra-video/vi.h b/drivers/staging/media/tegra-video/vi.h index a68e2c02c7b0..5396bf53ab75 100644 --- a/drivers/staging/media/tegra-video/vi.h +++ b/drivers/staging/media/tegra-video/vi.h @@ -260,11 +260,11 @@ enum tegra_image_dt { /** * struct tegra_video_format - Tegra video format description * - * @img_dt: image data type - * @bit_width: format width in bits per component + * @img_dt: MIPI CSI-2 data type (for CSI-2 only) + * @bit_width: format width in bits per component (for CSI/Tegra210 only) * @code: media bus format code * @bpp: bytes per pixel (when stored in memory) - * @img_fmt: image format + * @img_fmt: image format (for CSI/Tegra210 only) * @fourcc: V4L2 pixel format FCC identifier */ struct tegra_video_format { From 2f229d40490534e76ab06c4b3a5627ae08620997 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 18 Apr 2023 10:00:38 +0200 Subject: [PATCH 012/253] staging: media: tegra-video: document tegra_channel_get_remote_source_subdev Clarify what this function does. Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Osipenko Signed-off-by: Hans Verkuil --- drivers/staging/media/tegra-video/vi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 2f1aff7e8717..0b2d6dcb44b7 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -164,6 +164,9 @@ tegra_channel_get_remote_csi_subdev(struct tegra_vi_channel *chan) return media_entity_to_v4l2_subdev(pad->entity); } +/* + * Walk up the chain until the initial source (e.g. image sensor) + */ struct v4l2_subdev * tegra_channel_get_remote_source_subdev(struct tegra_vi_channel *chan) { From 6309986d7e42f68d6d13eccd81dfd7f3e2c3d92b Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 18 Apr 2023 10:00:39 +0200 Subject: [PATCH 013/253] staging: media: tegra-video: fix typos in comment Add "skip" in "so we can *skip* the current channel" or it doesn't make sense. Also add articles where appropriate to fix English grammar. Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Osipenko Signed-off-by: Hans Verkuil --- drivers/staging/media/tegra-video/vi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 0b2d6dcb44b7..ddf683be506f 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -1861,10 +1861,10 @@ static int tegra_vi_graph_init(struct tegra_vi *vi) * Walk the links to parse the full graph. Each channel will have * one endpoint of the composite node. Start by parsing the * composite node and parse the remote entities in turn. - * Each channel will register v4l2 async notifier to make the graph - * independent between the channels so we can the current channel + * Each channel will register a v4l2 async notifier to make the graph + * independent between the channels so we can skip the current channel * in case of something wrong during graph parsing and continue with - * next channels. + * the next channels. */ list_for_each_entry(chan, &vi->vi_chans, list) { struct fwnode_handle *ep, *remote; From 40ecb38e5c961174f86bfb4d5b1d2ae821cc45c2 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 18 Apr 2023 10:00:40 +0200 Subject: [PATCH 014/253] staging: media: tegra-video: improve error messages tegra_vi_channels_alloc() can primarily fail for two reasons: 1. "ports" node not found 2. port_num > vi->soc->vi_max_channels Case 1 prints nothing, case 2 has a dev_err(). The caller [tegra_vi_init()] has a generic dev_err() on any failure. This mean that in case 2 we print two messages, and in case 1 we only print a generic message. Remove the generic message and add a specific message when case 1 happens, so that we always have one specific message without even increasing the number of dev_dbg*() calls. Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Osipenko Signed-off-by: Hans Verkuil --- drivers/staging/media/tegra-video/vi.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index ddf683be506f..be27a93ebe2a 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -1363,7 +1363,7 @@ static int tegra_vi_channels_alloc(struct tegra_vi *vi) ports = of_get_child_by_name(node, "ports"); if (!ports) - return -ENODEV; + return dev_err_probe(vi->dev, -ENODEV, "%pOF: missing 'ports' node\n", node); for_each_child_of_node(ports, port) { if (!of_node_name_eq(port, "port")) @@ -1923,11 +1923,8 @@ static int tegra_vi_init(struct host1x_client *client) ret = tegra_vi_tpg_channels_alloc(vi); else ret = tegra_vi_channels_alloc(vi); - if (ret < 0) { - dev_err(vi->dev, - "failed to allocate vi channels: %d\n", ret); + if (ret < 0) goto free_chans; - } ret = tegra_vi_channels_init(vi); if (ret < 0) From 26b44232f581b2baa8a2e767b52db33a9c7e839b Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 18 Apr 2023 10:00:41 +0200 Subject: [PATCH 015/253] staging: media: tegra-video: slightly simplify cleanup on errors of_node_put(node) does nothing if node == NULL, so it can be moved to the cleanup section at the bottom. Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Osipenko Signed-off-by: Hans Verkuil --- drivers/staging/media/tegra-video/vi.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index be27a93ebe2a..8deeeeedfd73 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -1354,7 +1354,7 @@ static int tegra_vi_channels_alloc(struct tegra_vi *vi) struct device_node *node = vi->dev->of_node; struct device_node *ep = NULL; struct device_node *ports; - struct device_node *port; + struct device_node *port = NULL; unsigned int port_num; struct device_node *parent; struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = 0 }; @@ -1377,7 +1377,6 @@ static int tegra_vi_channels_alloc(struct tegra_vi *vi) dev_err(vi->dev, "invalid port num %d for %pOF\n", port_num, port); ret = -EINVAL; - of_node_put(port); goto cleanup; } @@ -1400,13 +1399,12 @@ static int tegra_vi_channels_alloc(struct tegra_vi *vi) lanes = v4l2_ep.bus.mipi_csi2.num_data_lanes; ret = tegra_vi_channel_alloc(vi, port_num, port, lanes); - if (ret < 0) { - of_node_put(port); + if (ret < 0) goto cleanup; - } } cleanup: + of_node_put(port); of_node_put(ports); return ret; } From 983d22f6deb16aca1727ac3713a539650ef37e81 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 18 Apr 2023 10:00:42 +0200 Subject: [PATCH 016/253] staging: media: tegra-video: move private struct declaration to C file struct tegra_vi_graph_entity is an internal implementation detail of the VI module. Move its declaration from vi.h to vi.c. Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Osipenko Signed-off-by: Hans Verkuil --- drivers/staging/media/tegra-video/vi.c | 13 +++++++++++++ drivers/staging/media/tegra-video/vi.h | 13 ------------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 8deeeeedfd73..db0f0e415b4f 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -32,6 +32,19 @@ #define MAX_CID_CONTROLS 1 +/** + * struct tegra_vi_graph_entity - Entity in the video graph + * + * @asd: subdev asynchronous registration information + * @entity: media entity from the corresponding V4L2 subdev + * @subdev: V4L2 subdev + */ +struct tegra_vi_graph_entity { + struct v4l2_async_subdev asd; + struct media_entity *entity; + struct v4l2_subdev *subdev; +}; + static const struct tegra_video_format tegra_default_format = { .img_dt = TEGRA_IMAGE_DT_RAW10, .bit_width = 10, diff --git a/drivers/staging/media/tegra-video/vi.h b/drivers/staging/media/tegra-video/vi.h index 5396bf53ab75..9959cbe02ca0 100644 --- a/drivers/staging/media/tegra-video/vi.h +++ b/drivers/staging/media/tegra-video/vi.h @@ -98,19 +98,6 @@ struct tegra_vi { struct list_head vi_chans; }; -/** - * struct tegra_vi_graph_entity - Entity in the video graph - * - * @asd: subdev asynchronous registration information - * @entity: media entity from the corresponding V4L2 subdev - * @subdev: V4L2 subdev - */ -struct tegra_vi_graph_entity { - struct v4l2_async_subdev asd; - struct media_entity *entity; - struct v4l2_subdev *subdev; -}; - /** * struct tegra_vi_channel - Tegra video channel * From 44977bdc157f4619e919ea448f51ef247ab44f57 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 18 Apr 2023 10:00:43 +0200 Subject: [PATCH 017/253] staging: media: tegra-video: move tegra210_csi_soc to C file This declaration is used only in csi.c, no need to export it elsewhere. Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Osipenko Signed-off-by: Hans Verkuil --- drivers/staging/media/tegra-video/csi.c | 4 ++++ drivers/staging/media/tegra-video/csi.h | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c index 36ca639622c9..37b661b58cc2 100644 --- a/drivers/staging/media/tegra-video/csi.c +++ b/drivers/staging/media/tegra-video/csi.c @@ -786,6 +786,10 @@ static int tegra_csi_remove(struct platform_device *pdev) return 0; } +#if defined(CONFIG_ARCH_TEGRA_210_SOC) +extern const struct tegra_csi_soc tegra210_csi_soc; +#endif + static const struct of_device_id tegra_csi_of_id_table[] = { #if defined(CONFIG_ARCH_TEGRA_210_SOC) { .compatible = "nvidia,tegra210-csi", .data = &tegra210_csi_soc }, diff --git a/drivers/staging/media/tegra-video/csi.h b/drivers/staging/media/tegra-video/csi.h index 6960ea2e3d36..3e6e5ee1bb1e 100644 --- a/drivers/staging/media/tegra-video/csi.h +++ b/drivers/staging/media/tegra-video/csi.h @@ -151,10 +151,6 @@ struct tegra_csi { struct list_head csi_chans; }; -#if defined(CONFIG_ARCH_TEGRA_210_SOC) -extern const struct tegra_csi_soc tegra210_csi_soc; -#endif - void tegra_csi_error_recover(struct v4l2_subdev *subdev); void tegra_csi_calc_settle_time(struct tegra_csi_channel *csi_chan, u8 csi_port_num, From 21bd264c1c2608388387f7dcf6916091c9a023e9 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 18 Apr 2023 10:00:44 +0200 Subject: [PATCH 018/253] staging: media: tegra-video: remove unneeded include There is only a pointer reference to struct tegra_vi in video.h, thus vi.h is not needed. Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Osipenko Signed-off-by: Hans Verkuil --- drivers/staging/media/tegra-video/video.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/media/tegra-video/video.h b/drivers/staging/media/tegra-video/video.h index fadaf2189dc9..1e9be1474a9c 100644 --- a/drivers/staging/media/tegra-video/video.h +++ b/drivers/staging/media/tegra-video/video.h @@ -12,7 +12,6 @@ #include #include "vi.h" -#include "csi.h" struct tegra_video_device { struct v4l2_device v4l2_dev; From c973880dfbe2b1cf85276c2e6f4fc3478d24d649 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 18 Apr 2023 10:00:45 +0200 Subject: [PATCH 019/253] staging: media: tegra-video: Kconfig: allow TPG only on Tegra210 We are about to add support for the Tegra20 parallel video capture, which has no TPG. In preparation for that, limit the VIDEO_TEGRA_TPG option to Tegra210 which is the only implementation currently provided by this driver. Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Osipenko Signed-off-by: Hans Verkuil --- drivers/staging/media/tegra-video/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/media/tegra-video/Kconfig b/drivers/staging/media/tegra-video/Kconfig index df1b2cff2417..c53441822fdf 100644 --- a/drivers/staging/media/tegra-video/Kconfig +++ b/drivers/staging/media/tegra-video/Kconfig @@ -15,5 +15,6 @@ config VIDEO_TEGRA config VIDEO_TEGRA_TPG bool "NVIDIA Tegra VI driver TPG mode" depends on VIDEO_TEGRA + depends on ARCH_TEGRA_210_SOC help Say yes here to enable Tegra internal TPG mode From 1a3ea975d794181056157412183e4c23ea87353b Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 18 Apr 2023 10:00:46 +0200 Subject: [PATCH 020/253] staging: media: tegra-video: move tegra_channel_fmt_align to a per-soc op tegra_channel_fmt_align() takes care of the size constraints, alignment and rounding requirements of the Tegra210 VI peripheral. Tegra20 has different constraints. In preparation for adding Tegra20 support, move this function to a new op in the soc-specific `struct tegra_vi_ops` . Also move to tegra210.c the T210-specific defines used in the moved code. No functional changes. Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Osipenko Signed-off-by: Hans Verkuil --- drivers/staging/media/tegra-video/tegra210.c | 36 ++++++++++++++++++ drivers/staging/media/tegra-video/vi.c | 40 +++----------------- drivers/staging/media/tegra-video/vi.h | 9 ++--- 3 files changed, 44 insertions(+), 41 deletions(-) diff --git a/drivers/staging/media/tegra-video/tegra210.c b/drivers/staging/media/tegra-video/tegra210.c index d58370a84737..d19ff6b49ae8 100644 --- a/drivers/staging/media/tegra-video/tegra210.c +++ b/drivers/staging/media/tegra-video/tegra210.c @@ -17,6 +17,13 @@ #include "csi.h" #include "vi.h" +#define TEGRA210_MIN_WIDTH 32U +#define TEGRA210_MAX_WIDTH 32768U +#define TEGRA210_MIN_HEIGHT 32U +#define TEGRA210_MAX_HEIGHT 32768U + +#define SURFACE_ALIGN_BYTES 64 + #define TEGRA_VI_SYNCPT_WAIT_TIMEOUT msecs_to_jiffies(200) /* Tegra210 VI registers */ @@ -172,6 +179,34 @@ static u32 vi_csi_read(struct tegra_vi_channel *chan, u8 portno, /* * Tegra210 VI channel capture operations */ +static void tegra210_fmt_align(struct v4l2_pix_format *pix, unsigned int bpp) +{ + unsigned int min_bpl; + unsigned int max_bpl; + unsigned int bpl; + + /* + * The transfer alignment requirements are expressed in bytes. + * Clamp the requested width and height to the limits. + */ + pix->width = clamp(pix->width, TEGRA210_MIN_WIDTH, TEGRA210_MAX_WIDTH); + pix->height = clamp(pix->height, TEGRA210_MIN_HEIGHT, TEGRA210_MAX_HEIGHT); + + /* Clamp the requested bytes per line value. If the maximum bytes per + * line value is zero, the module doesn't support user configurable + * line sizes. Override the requested value with the minimum in that + * case. + */ + min_bpl = pix->width * bpp; + max_bpl = rounddown(TEGRA210_MAX_WIDTH, SURFACE_ALIGN_BYTES); + bpl = roundup(pix->bytesperline, SURFACE_ALIGN_BYTES); + + pix->bytesperline = clamp(bpl, min_bpl, max_bpl); + pix->sizeimage = pix->bytesperline * pix->height; + if (pix->pixelformat == V4L2_PIX_FMT_NV16) + pix->sizeimage *= 2; +} + static int tegra_channel_capture_setup(struct tegra_vi_channel *chan, u8 portno) { @@ -718,6 +753,7 @@ static const struct tegra_video_format tegra210_video_formats[] = { /* Tegra210 VI operations */ static const struct tegra_vi_ops tegra210_vi_ops = { + .vi_fmt_align = tegra210_fmt_align, .vi_start_streaming = tegra210_vi_start_streaming, .vi_stop_streaming = tegra210_vi_stop_streaming, }; diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index db0f0e415b4f..238119791947 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -473,36 +473,6 @@ static int tegra_channel_get_format(struct file *file, void *fh, return 0; } -static void tegra_channel_fmt_align(struct tegra_vi_channel *chan, - struct v4l2_pix_format *pix, - unsigned int bpp) -{ - unsigned int min_bpl; - unsigned int max_bpl; - unsigned int bpl; - - /* - * The transfer alignment requirements are expressed in bytes. - * Clamp the requested width and height to the limits. - */ - pix->width = clamp(pix->width, TEGRA_MIN_WIDTH, TEGRA_MAX_WIDTH); - pix->height = clamp(pix->height, TEGRA_MIN_HEIGHT, TEGRA_MAX_HEIGHT); - - /* Clamp the requested bytes per line value. If the maximum bytes per - * line value is zero, the module doesn't support user configurable - * line sizes. Override the requested value with the minimum in that - * case. - */ - min_bpl = pix->width * bpp; - max_bpl = rounddown(TEGRA_MAX_WIDTH, SURFACE_ALIGN_BYTES); - bpl = roundup(pix->bytesperline, SURFACE_ALIGN_BYTES); - - pix->bytesperline = clamp(bpl, min_bpl, max_bpl); - pix->sizeimage = pix->bytesperline * pix->height; - if (pix->pixelformat == V4L2_PIX_FMT_NV16) - pix->sizeimage *= 2; -} - static int __tegra_channel_try_format(struct tegra_vi_channel *chan, struct v4l2_pix_format *pix) { @@ -579,7 +549,7 @@ static int __tegra_channel_try_format(struct tegra_vi_channel *chan, return ret; v4l2_fill_pix_format(pix, &fmt.format); - tegra_channel_fmt_align(chan, pix, fmtinfo->bpp); + chan->vi->ops->vi_fmt_align(pix, fmtinfo->bpp); __v4l2_subdev_state_free(sd_state); @@ -632,7 +602,7 @@ static int tegra_channel_set_format(struct file *file, void *fh, return ret; v4l2_fill_pix_format(pix, &fmt.format); - tegra_channel_fmt_align(chan, pix, fmtinfo->bpp); + chan->vi->ops->vi_fmt_align(pix, fmtinfo->bpp); chan->format = *pix; chan->fmtinfo = fmtinfo; @@ -668,7 +638,7 @@ static int tegra_channel_set_subdev_active_fmt(struct tegra_vi_channel *chan) chan->format.bytesperline = chan->format.width * chan->fmtinfo->bpp; chan->format.sizeimage = chan->format.bytesperline * chan->format.height; - tegra_channel_fmt_align(chan, &chan->format, chan->fmtinfo->bpp); + chan->vi->ops->vi_fmt_align(&chan->format, chan->fmtinfo->bpp); tegra_channel_update_gangports(chan); return 0; @@ -837,7 +807,7 @@ static int tegra_channel_s_dv_timings(struct file *file, void *fh, chan->format.height = bt->height; chan->format.bytesperline = bt->width * chan->fmtinfo->bpp; chan->format.sizeimage = chan->format.bytesperline * bt->height; - tegra_channel_fmt_align(chan, &chan->format, chan->fmtinfo->bpp); + chan->vi->ops->vi_fmt_align(&chan->format, chan->fmtinfo->bpp); tegra_channel_update_gangports(chan); return 0; @@ -1240,7 +1210,7 @@ static int tegra_channel_init(struct tegra_vi_channel *chan) chan->format.height = TEGRA_DEF_HEIGHT; chan->format.bytesperline = TEGRA_DEF_WIDTH * chan->fmtinfo->bpp; chan->format.sizeimage = chan->format.bytesperline * TEGRA_DEF_HEIGHT; - tegra_channel_fmt_align(chan, &chan->format, chan->fmtinfo->bpp); + vi->ops->vi_fmt_align(&chan->format, chan->fmtinfo->bpp); ret = tegra_channel_host1x_syncpt_init(chan); if (ret) diff --git a/drivers/staging/media/tegra-video/vi.h b/drivers/staging/media/tegra-video/vi.h index 9959cbe02ca0..213955c7545d 100644 --- a/drivers/staging/media/tegra-video/vi.h +++ b/drivers/staging/media/tegra-video/vi.h @@ -25,17 +25,11 @@ #define V4L2_CID_TEGRA_SYNCPT_TIMEOUT_RETRY (V4L2_CTRL_CLASS_CAMERA | 0x1001) -#define TEGRA_MIN_WIDTH 32U -#define TEGRA_MAX_WIDTH 32768U -#define TEGRA_MIN_HEIGHT 32U -#define TEGRA_MAX_HEIGHT 32768U - #define TEGRA_DEF_WIDTH 1920 #define TEGRA_DEF_HEIGHT 1080 #define TEGRA_IMAGE_FORMAT_DEF 32 #define MAX_FORMAT_NUM 64 -#define SURFACE_ALIGN_BYTES 64 enum tegra_vi_pg_mode { TEGRA_VI_PG_DISABLED = 0, @@ -45,6 +39,8 @@ enum tegra_vi_pg_mode { /** * struct tegra_vi_ops - Tegra VI operations + * @vi_fmt_align: modify `pix` to fit the hardware alignment + * requirements and fill image geometry * @vi_start_streaming: starts media pipeline, subdevice streaming, sets up * VI for capture and runs capture start and capture finish * kthreads for capturing frames to buffer and returns them back. @@ -52,6 +48,7 @@ enum tegra_vi_pg_mode { * back any queued buffers. */ struct tegra_vi_ops { + void (*vi_fmt_align)(struct v4l2_pix_format *pix, unsigned int bpp); int (*vi_start_streaming)(struct vb2_queue *vq, u32 count); void (*vi_stop_streaming)(struct vb2_queue *vq); }; From aabec712ce0e5ca2e47904dbc4326de614dc0bbf Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 18 Apr 2023 10:00:47 +0200 Subject: [PATCH 021/253] staging: media: tegra-video: move default format to soc-specific data The tegra_default_format in vi.c is specific to Tegra210 CSI. In preparation for adding Tegra20 VIP support, move the default format to a new field in the soc-specific `struct tegra_vi_soc`. Instead of an entire format struct, only store a pointer to an item in the existing format array. No functional changes. The format pointed to is the same that used to be in vi.c. Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Osipenko Signed-off-by: Hans Verkuil --- drivers/staging/media/tegra-video/tegra210.c | 2 ++ drivers/staging/media/tegra-video/vi.c | 13 ++----------- drivers/staging/media/tegra-video/vi.h | 2 ++ 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/staging/media/tegra-video/tegra210.c b/drivers/staging/media/tegra-video/tegra210.c index d19ff6b49ae8..b4fcd4e93b8c 100644 --- a/drivers/staging/media/tegra-video/tegra210.c +++ b/drivers/staging/media/tegra-video/tegra210.c @@ -766,8 +766,10 @@ const struct tegra_vi_soc tegra210_vi_soc = { .hw_revision = 3, .vi_max_channels = 6, #if IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG) + .default_video_format = &tegra210_video_formats[0], .vi_max_clk_hz = 499200000, #else + .default_video_format = &tegra210_video_formats[4], .vi_max_clk_hz = 998400000, #endif }; diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 238119791947..2ef53ccb4627 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -45,15 +45,6 @@ struct tegra_vi_graph_entity { struct v4l2_subdev *subdev; }; -static const struct tegra_video_format tegra_default_format = { - .img_dt = TEGRA_IMAGE_DT_RAW10, - .bit_width = 10, - .code = MEDIA_BUS_FMT_SRGGB10_1X10, - .bpp = 2, - .img_fmt = TEGRA_IMAGE_FORMAT_DEF, - .fourcc = V4L2_PIX_FMT_SRGGB10, -}; - static inline struct tegra_vi * host1x_client_to_vi(struct host1x_client *client) { @@ -1105,7 +1096,7 @@ static int vi_fmts_bitmap_init(struct tegra_vi_channel *chan) * there are no matched formats. */ if (!match_code) { - match_code = tegra_default_format.code; + match_code = chan->vi->soc->default_video_format->code; index = tegra_get_format_idx_by_code(chan->vi, match_code, 0); if (WARN_ON(index < 0)) return -EINVAL; @@ -1202,7 +1193,7 @@ static int tegra_channel_init(struct tegra_vi_channel *chan) init_waitqueue_head(&chan->done_wait); /* initialize the video format */ - chan->fmtinfo = &tegra_default_format; + chan->fmtinfo = chan->vi->soc->default_video_format; chan->format.pixelformat = chan->fmtinfo->fourcc; chan->format.colorspace = V4L2_COLORSPACE_SRGB; chan->format.field = V4L2_FIELD_NONE; diff --git a/drivers/staging/media/tegra-video/vi.h b/drivers/staging/media/tegra-video/vi.h index 213955c7545d..b424c967c6f2 100644 --- a/drivers/staging/media/tegra-video/vi.h +++ b/drivers/staging/media/tegra-video/vi.h @@ -58,6 +58,7 @@ struct tegra_vi_ops { * * @video_formats: supported video formats * @nformats: total video formats + * @default_video_format: default video format (pointer to a @video_formats item) * @ops: vi operations * @hw_revision: VI hw_revision * @vi_max_channels: supported max streaming channels @@ -66,6 +67,7 @@ struct tegra_vi_ops { struct tegra_vi_soc { const struct tegra_video_format *video_formats; const unsigned int nformats; + const struct tegra_video_format *default_video_format; const struct tegra_vi_ops *ops; u32 hw_revision; unsigned int vi_max_channels; From 3bc46d752eab89ff2ddbd49cba931cf49d9c5dfb Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 18 Apr 2023 10:00:48 +0200 Subject: [PATCH 022/253] staging: media: tegra-video: move MIPI calibration calls from VI to CSI The CSI module does not handle all the MIPI lane calibration procedure, leaving a small part of it to the VI module. In doing this, tegra_channel_enable_stream() (vi.c) manipulates the private data of the upstream subdev casting it to struct 'tegra_csi_channel', which will be wrong after introducing a VIP (parallel video input) channel. This prevents adding support for the VIP module. It also breaks the logical isolation between modules. Since the lane calibration requirement does not exist in the parallel input module, moving the calibration function to a per-module op is not optimal. Instead move the calibration procedure in the CSI module, together with the rest of the calibration procedures. After this change, tegra_channel_enable_stream() just calls v4l2_subdev_call() to ask for a stream start/stop to the CSI module, which in turn knows all the CSI-specific details to implement it. Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Osipenko Signed-off-by: Hans Verkuil --- drivers/staging/media/tegra-video/csi.c | 44 ++++++++++++++++++++ drivers/staging/media/tegra-video/vi.c | 54 ++----------------------- 2 files changed, 48 insertions(+), 50 deletions(-) diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c index 37b661b58cc2..052172017b3b 100644 --- a/drivers/staging/media/tegra-video/csi.c +++ b/drivers/staging/media/tegra-video/csi.c @@ -328,12 +328,42 @@ static int tegra_csi_enable_stream(struct v4l2_subdev *subdev) } csi_chan->pg_mode = chan->pg_mode; + + /* + * Tegra CSI receiver can detect the first LP to HS transition. + * So, start the CSI stream-on prior to sensor stream-on and + * vice-versa for stream-off. + */ ret = csi->ops->csi_start_streaming(csi_chan); if (ret < 0) goto finish_calibration; + if (csi_chan->mipi) { + struct v4l2_subdev *src_subdev; + /* + * TRM has incorrectly documented to wait for done status from + * calibration logic after CSI interface power on. + * As per the design, calibration results are latched and applied + * to the pads only when the link is in LP11 state which will happen + * during the sensor stream-on. + * CSI subdev stream-on triggers start of MIPI pads calibration. + * Wait for calibration to finish here after sensor subdev stream-on. + */ + src_subdev = tegra_channel_get_remote_source_subdev(chan); + ret = v4l2_subdev_call(src_subdev, video, s_stream, true); + + if (ret < 0 && ret != -ENOIOCTLCMD) + goto disable_csi_stream; + + err = tegra_mipi_finish_calibration(csi_chan->mipi); + if (err < 0) + dev_warn(csi->dev, "MIPI calibration failed: %d\n", err); + } + return 0; +disable_csi_stream: + csi->ops->csi_stop_streaming(csi_chan); finish_calibration: if (csi_chan->mipi) tegra_mipi_finish_calibration(csi_chan->mipi); @@ -352,10 +382,24 @@ rpm_put: static int tegra_csi_disable_stream(struct v4l2_subdev *subdev) { + struct tegra_vi_channel *chan = v4l2_get_subdev_hostdata(subdev); struct tegra_csi_channel *csi_chan = to_csi_chan(subdev); struct tegra_csi *csi = csi_chan->csi; int err; + /* + * Stream-off subdevices in reverse order to stream-on. + * Remote source subdev in TPG mode is same as CSI subdev. + */ + if (csi_chan->mipi) { + struct v4l2_subdev *src_subdev; + + src_subdev = tegra_channel_get_remote_source_subdev(chan); + err = v4l2_subdev_call(src_subdev, video, s_stream, false); + if (err < 0 && err != -ENOIOCTLCMD) + dev_err_probe(csi->dev, err, "source subdev stream off failed\n"); + } + csi->ops->csi_stop_streaming(csi_chan); if (csi_chan->mipi) { diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 2ef53ccb4627..7e47de75b170 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -197,49 +197,15 @@ tegra_channel_get_remote_source_subdev(struct tegra_vi_channel *chan) static int tegra_channel_enable_stream(struct tegra_vi_channel *chan) { - struct v4l2_subdev *csi_subdev, *src_subdev; - struct tegra_csi_channel *csi_chan; - int ret, err; + struct v4l2_subdev *subdev; + int ret; - /* - * Tegra CSI receiver can detect the first LP to HS transition. - * So, start the CSI stream-on prior to sensor stream-on and - * vice-versa for stream-off. - */ - csi_subdev = tegra_channel_get_remote_csi_subdev(chan); - ret = v4l2_subdev_call(csi_subdev, video, s_stream, true); + subdev = tegra_channel_get_remote_csi_subdev(chan); + ret = v4l2_subdev_call(subdev, video, s_stream, true); if (ret < 0 && ret != -ENOIOCTLCMD) return ret; - if (IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG)) - return 0; - - csi_chan = v4l2_get_subdevdata(csi_subdev); - /* - * TRM has incorrectly documented to wait for done status from - * calibration logic after CSI interface power on. - * As per the design, calibration results are latched and applied - * to the pads only when the link is in LP11 state which will happen - * during the sensor stream-on. - * CSI subdev stream-on triggers start of MIPI pads calibration. - * Wait for calibration to finish here after sensor subdev stream-on. - */ - src_subdev = tegra_channel_get_remote_source_subdev(chan); - ret = v4l2_subdev_call(src_subdev, video, s_stream, true); - err = tegra_mipi_finish_calibration(csi_chan->mipi); - - if (ret < 0 && ret != -ENOIOCTLCMD) - goto err_disable_csi_stream; - - if (err < 0) - dev_warn(csi_chan->csi->dev, - "MIPI calibration failed: %d\n", err); - return 0; - -err_disable_csi_stream: - v4l2_subdev_call(csi_subdev, video, s_stream, false); - return ret; } static int tegra_channel_disable_stream(struct tegra_vi_channel *chan) @@ -247,18 +213,6 @@ static int tegra_channel_disable_stream(struct tegra_vi_channel *chan) struct v4l2_subdev *subdev; int ret; - /* - * Stream-off subdevices in reverse order to stream-on. - * Remote source subdev in TPG mode is same as CSI subdev. - */ - subdev = tegra_channel_get_remote_source_subdev(chan); - ret = v4l2_subdev_call(subdev, video, s_stream, false); - if (ret < 0 && ret != -ENOIOCTLCMD) - return ret; - - if (IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG)) - return 0; - subdev = tegra_channel_get_remote_csi_subdev(chan); ret = v4l2_subdev_call(subdev, video, s_stream, false); if (ret < 0 && ret != -ENOIOCTLCMD) From ef9435a5b4066e6935b922702446b555565898c9 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 18 Apr 2023 10:00:49 +0200 Subject: [PATCH 023/253] staging: media: tegra-video: add a per-soc enable/disable op The Tegra20 VI needs an additional operation to enable the VI, add an operation for that. Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Osipenko Signed-off-by: Hans Verkuil --- drivers/staging/media/tegra-video/vi.c | 7 +++++++ drivers/staging/media/tegra-video/vi.h | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 7e47de75b170..ffce0022f8eb 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -1952,6 +1952,9 @@ static int tegra_vi_probe(struct platform_device *pdev) vi->client.ops = &vi_client_ops; vi->client.dev = &pdev->dev; + if (vi->ops->vi_enable) + vi->ops->vi_enable(vi, true); + ret = host1x_client_register(&vi->client); if (ret < 0) { dev_err(&pdev->dev, @@ -1962,6 +1965,8 @@ static int tegra_vi_probe(struct platform_device *pdev) return 0; rpm_disable: + if (vi->ops->vi_enable) + vi->ops->vi_enable(vi, false); pm_runtime_disable(&pdev->dev); return ret; } @@ -1972,6 +1977,8 @@ static int tegra_vi_remove(struct platform_device *pdev) host1x_client_unregister(&vi->client); + if (vi->ops->vi_enable) + vi->ops->vi_enable(vi, false); pm_runtime_disable(&pdev->dev); return 0; diff --git a/drivers/staging/media/tegra-video/vi.h b/drivers/staging/media/tegra-video/vi.h index b424c967c6f2..886b10e7d723 100644 --- a/drivers/staging/media/tegra-video/vi.h +++ b/drivers/staging/media/tegra-video/vi.h @@ -37,8 +37,11 @@ enum tegra_vi_pg_mode { TEGRA_VI_PG_PATCH, }; +struct tegra_vi; + /** * struct tegra_vi_ops - Tegra VI operations + * @vi_enable: soc-specific operations needed to enable/disable the VI peripheral * @vi_fmt_align: modify `pix` to fit the hardware alignment * requirements and fill image geometry * @vi_start_streaming: starts media pipeline, subdevice streaming, sets up @@ -48,6 +51,7 @@ enum tegra_vi_pg_mode { * back any queued buffers. */ struct tegra_vi_ops { + int (*vi_enable)(struct tegra_vi *vi, bool on); void (*vi_fmt_align)(struct v4l2_pix_format *pix, unsigned int bpp); int (*vi_start_streaming)(struct vb2_queue *vq, u32 count); void (*vi_stop_streaming)(struct vb2_queue *vq); From 89a0f667cb20c53dd9164d72a565a146af0fd11e Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 18 Apr 2023 10:00:50 +0200 Subject: [PATCH 024/253] staging: media: tegra-video: move syncpt init/free to a per-soc op tegra_channel_host1x_syncpt_init() gets the host1x syncpts needed for the Tegra210 implementation, and tegra_channel_host1x_syncpts_free() puts them. Tegra20 needs to get and put a different syncpt. In preparation for adding Tegra20 support, move these functions to new ops in the soc-specific `struct tegra_vi_ops` . No functional changes. Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Osipenko Signed-off-by: Hans Verkuil --- drivers/staging/media/tegra-video/tegra210.c | 52 ++++++++++++++++++++ drivers/staging/media/tegra-video/vi.c | 52 ++------------------ drivers/staging/media/tegra-video/vi.h | 5 ++ 3 files changed, 60 insertions(+), 49 deletions(-) diff --git a/drivers/staging/media/tegra-video/tegra210.c b/drivers/staging/media/tegra-video/tegra210.c index b4fcd4e93b8c..da99f19a39e7 100644 --- a/drivers/staging/media/tegra-video/tegra210.c +++ b/drivers/staging/media/tegra-video/tegra210.c @@ -179,6 +179,56 @@ static u32 vi_csi_read(struct tegra_vi_channel *chan, u8 portno, /* * Tegra210 VI channel capture operations */ + +static int tegra210_channel_host1x_syncpt_init(struct tegra_vi_channel *chan) +{ + struct tegra_vi *vi = chan->vi; + unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED; + struct host1x_syncpt *fs_sp; + struct host1x_syncpt *mw_sp; + int ret, i; + + for (i = 0; i < chan->numgangports; i++) { + fs_sp = host1x_syncpt_request(&vi->client, flags); + if (!fs_sp) { + dev_err(vi->dev, "failed to request frame start syncpoint\n"); + ret = -ENOMEM; + goto free_syncpts; + } + + mw_sp = host1x_syncpt_request(&vi->client, flags); + if (!mw_sp) { + dev_err(vi->dev, "failed to request memory ack syncpoint\n"); + host1x_syncpt_put(fs_sp); + ret = -ENOMEM; + goto free_syncpts; + } + + chan->frame_start_sp[i] = fs_sp; + chan->mw_ack_sp[i] = mw_sp; + spin_lock_init(&chan->sp_incr_lock[i]); + } + + return 0; + +free_syncpts: + for (i = 0; i < chan->numgangports; i++) { + host1x_syncpt_put(chan->mw_ack_sp[i]); + host1x_syncpt_put(chan->frame_start_sp[i]); + } + return ret; +} + +static void tegra210_channel_host1x_syncpt_free(struct tegra_vi_channel *chan) +{ + int i; + + for (i = 0; i < chan->numgangports; i++) { + host1x_syncpt_put(chan->mw_ack_sp[i]); + host1x_syncpt_put(chan->frame_start_sp[i]); + } +} + static void tegra210_fmt_align(struct v4l2_pix_format *pix, unsigned int bpp) { unsigned int min_bpl; @@ -753,6 +803,8 @@ static const struct tegra_video_format tegra210_video_formats[] = { /* Tegra210 VI operations */ static const struct tegra_vi_ops tegra210_vi_ops = { + .channel_host1x_syncpt_init = tegra210_channel_host1x_syncpt_init, + .channel_host1x_syncpt_free = tegra210_channel_host1x_syncpt_free, .vi_fmt_align = tegra210_fmt_align, .vi_start_streaming = tegra210_vi_start_streaming, .vi_stop_streaming = tegra210_vi_stop_streaming, diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index ffce0022f8eb..caad1764575d 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -1064,21 +1064,11 @@ static int vi_fmts_bitmap_init(struct tegra_vi_channel *chan) return 0; } -static void tegra_channel_host1x_syncpts_free(struct tegra_vi_channel *chan) -{ - int i; - - for (i = 0; i < chan->numgangports; i++) { - host1x_syncpt_put(chan->mw_ack_sp[i]); - host1x_syncpt_put(chan->frame_start_sp[i]); - } -} - static void tegra_channel_cleanup(struct tegra_vi_channel *chan) { v4l2_ctrl_handler_free(&chan->ctrl_handler); media_entity_cleanup(&chan->video.entity); - tegra_channel_host1x_syncpts_free(chan); + chan->vi->ops->channel_host1x_syncpt_free(chan); mutex_destroy(&chan->video_lock); } @@ -1096,42 +1086,6 @@ void tegra_channels_cleanup(struct tegra_vi *vi) } } -static int tegra_channel_host1x_syncpt_init(struct tegra_vi_channel *chan) -{ - struct tegra_vi *vi = chan->vi; - unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED; - struct host1x_syncpt *fs_sp; - struct host1x_syncpt *mw_sp; - int ret, i; - - for (i = 0; i < chan->numgangports; i++) { - fs_sp = host1x_syncpt_request(&vi->client, flags); - if (!fs_sp) { - dev_err(vi->dev, "failed to request frame start syncpoint\n"); - ret = -ENOMEM; - goto free_syncpts; - } - - mw_sp = host1x_syncpt_request(&vi->client, flags); - if (!mw_sp) { - dev_err(vi->dev, "failed to request memory ack syncpoint\n"); - host1x_syncpt_put(fs_sp); - ret = -ENOMEM; - goto free_syncpts; - } - - chan->frame_start_sp[i] = fs_sp; - chan->mw_ack_sp[i] = mw_sp; - spin_lock_init(&chan->sp_incr_lock[i]); - } - - return 0; - -free_syncpts: - tegra_channel_host1x_syncpts_free(chan); - return ret; -} - static int tegra_channel_init(struct tegra_vi_channel *chan) { struct tegra_vi *vi = chan->vi; @@ -1157,7 +1111,7 @@ static int tegra_channel_init(struct tegra_vi_channel *chan) chan->format.sizeimage = chan->format.bytesperline * TEGRA_DEF_HEIGHT; vi->ops->vi_fmt_align(&chan->format, chan->fmtinfo->bpp); - ret = tegra_channel_host1x_syncpt_init(chan); + ret = vi->ops->channel_host1x_syncpt_init(chan); if (ret) return ret; @@ -1220,7 +1174,7 @@ free_v4l2_ctrl_hdl: cleanup_media: media_entity_cleanup(&chan->video.entity); free_syncpts: - tegra_channel_host1x_syncpts_free(chan); + vi->ops->channel_host1x_syncpt_free(chan); return ret; } diff --git a/drivers/staging/media/tegra-video/vi.h b/drivers/staging/media/tegra-video/vi.h index 886b10e7d723..dfb5870b1411 100644 --- a/drivers/staging/media/tegra-video/vi.h +++ b/drivers/staging/media/tegra-video/vi.h @@ -38,10 +38,13 @@ enum tegra_vi_pg_mode { }; struct tegra_vi; +struct tegra_vi_channel; /** * struct tegra_vi_ops - Tegra VI operations * @vi_enable: soc-specific operations needed to enable/disable the VI peripheral + * @channel_host1x_syncpt_init: initialize synchronization points + * @channel_host1x_syncpt_free: free all synchronization points * @vi_fmt_align: modify `pix` to fit the hardware alignment * requirements and fill image geometry * @vi_start_streaming: starts media pipeline, subdevice streaming, sets up @@ -52,6 +55,8 @@ struct tegra_vi; */ struct tegra_vi_ops { int (*vi_enable)(struct tegra_vi *vi, bool on); + int (*channel_host1x_syncpt_init)(struct tegra_vi_channel *chan); + void (*channel_host1x_syncpt_free)(struct tegra_vi_channel *chan); void (*vi_fmt_align)(struct v4l2_pix_format *pix, unsigned int bpp); int (*vi_start_streaming)(struct vb2_queue *vq, u32 count); void (*vi_stop_streaming)(struct vb2_queue *vq); From 4cbd8479cd2ea6d36597ad7c16860a074d804f85 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 18 Apr 2023 10:00:51 +0200 Subject: [PATCH 025/253] staging: media: tegra-video: add syncpts for Tegra20 to struct tegra_vi In preparation to implement Tegra20 parallel video capture, add a variable to hold the required syncpt and document all the syncpt variables. Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Osipenko Signed-off-by: Hans Verkuil --- drivers/staging/media/tegra-video/vi.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/tegra-video/vi.h b/drivers/staging/media/tegra-video/vi.h index dfb5870b1411..02f940f2e2eb 100644 --- a/drivers/staging/media/tegra-video/vi.h +++ b/drivers/staging/media/tegra-video/vi.h @@ -117,11 +117,13 @@ struct tegra_vi { * @vi: Tegra video input device structure * @frame_start_sp: host1x syncpoint pointer to synchronize programmed capture * start condition with hardware frame start events through host1x - * syncpoint counters. + * syncpoint counters. (Tegra210) * @mw_ack_sp: host1x syncpoint pointer to synchronize programmed memory write * ack trigger condition with hardware memory write done at end of - * frame through host1x syncpoint counters. + * frame through host1x syncpoint counters (On Tegra20 used for the + * OUT_1 syncpt) * @sp_incr_lock: protects cpu syncpoint increment. + * @next_out_sp_idx: next expected value for mw_ack_sp[0], i.e. OUT_1 (Tegra20) * * @kthread_start_capture: kthread to start capture of single frame when * vb buffer is available. This thread programs VI CSI hardware @@ -175,6 +177,7 @@ struct tegra_vi_channel { struct host1x_syncpt *mw_ack_sp[GANG_PORTS_MAX]; /* protects the cpu syncpoint increment */ spinlock_t sp_incr_lock[GANG_PORTS_MAX]; + u32 next_out_sp_idx; struct task_struct *kthread_start_capture; wait_queue_head_t start_wait; From b4e2572267a1e91ba6e4813b4d71517cccccdbea Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 18 Apr 2023 10:00:52 +0200 Subject: [PATCH 026/253] staging: media: tegra-video: add hooks for planar YUV and H/V flip Tegra20 supports planar YUV422 capture, which can be implemented by writing U and V base address registers in addition to the "main" base buffer address register. It also supports H and V flip, which among others requires to write the start address (i.e. the 1st offset to write, at the end of the buffer or line) in more registers for Y and, for planar formats, U and V. Add minimal hooks in VI to allow per-SoC optional support to those features: - variables in struct tegra_vi for the U and V buffer base offsets - variables in struct tegra_vi for the Y, U and V buffer start offsets - an optional per-soc VI operation to compute those values on queue setup Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Osipenko Signed-off-by: Hans Verkuil --- drivers/staging/media/tegra-video/vi.c | 4 ++++ drivers/staging/media/tegra-video/vi.h | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index caad1764575d..0d02468aba2c 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -102,6 +102,7 @@ tegra_get_format_by_fourcc(struct tegra_vi *vi, u32 fourcc) /* * videobuf2 queue operations */ + static int tegra_channel_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, @@ -117,6 +118,9 @@ static int tegra_channel_queue_setup(struct vb2_queue *vq, sizes[0] = chan->format.sizeimage; alloc_devs[0] = chan->vi->dev; + if (chan->vi->ops->channel_queue_setup) + chan->vi->ops->channel_queue_setup(chan); + return 0; } diff --git a/drivers/staging/media/tegra-video/vi.h b/drivers/staging/media/tegra-video/vi.h index 02f940f2e2eb..cadf80b742a8 100644 --- a/drivers/staging/media/tegra-video/vi.h +++ b/drivers/staging/media/tegra-video/vi.h @@ -47,6 +47,7 @@ struct tegra_vi_channel; * @channel_host1x_syncpt_free: free all synchronization points * @vi_fmt_align: modify `pix` to fit the hardware alignment * requirements and fill image geometry + * @channel_queue_setup: additional operations at the end of vb2_ops::queue_setup * @vi_start_streaming: starts media pipeline, subdevice streaming, sets up * VI for capture and runs capture start and capture finish * kthreads for capturing frames to buffer and returns them back. @@ -58,6 +59,7 @@ struct tegra_vi_ops { int (*channel_host1x_syncpt_init)(struct tegra_vi_channel *chan); void (*channel_host1x_syncpt_free)(struct tegra_vi_channel *chan); void (*vi_fmt_align)(struct v4l2_pix_format *pix, unsigned int bpp); + void (*channel_queue_setup)(struct tegra_vi_channel *chan); int (*vi_start_streaming)(struct vb2_queue *vq, u32 count); void (*vi_stop_streaming)(struct vb2_queue *vq); }; @@ -148,6 +150,12 @@ struct tegra_vi { * @queue: vb2 buffers queue * @sequence: V4L2 buffers sequence number * + * @addr_offset_u: U plane base address, relative to buffer base address (only for planar) + * @addr_offset_v: V plane base address, relative to buffer base address (only for planar) + * @start_offset: 1st Y byte to write, relative to buffer base address (for H/V flip) + * @start_offset_u: 1st U byte to write, relative to buffer base address (for H/V flip) + * @start_offset_v: 1st V byte to write, relative to buffer base address (for H/V flip) + * * @capture: list of queued buffers for capture * @start_lock: protects the capture queued list * @done: list of capture done queued buffers @@ -189,6 +197,12 @@ struct tegra_vi_channel { struct vb2_queue queue; u32 sequence; + unsigned int addr_offset_u; + unsigned int addr_offset_v; + unsigned int start_offset; + unsigned int start_offset_u; + unsigned int start_offset_v; + struct list_head capture; /* protects the capture queued list */ spinlock_t start_lock; From eeb036ab9ca90bcc0abf917a14983fb8a66b7a28 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 18 Apr 2023 10:00:53 +0200 Subject: [PATCH 027/253] staging: media: tegra-video: add H/V flip controls Tegra20 can do horizontal and vertical image flip, but Tegra210 cannot (either the hardware, or this driver). In preparation to adding Tegra20 support, add a flag in struct tegra_vi_soc so the generic vi.c code knows whether the flip controls should be added or not. Also provide a generic implementation that simply sets two flags in the channel struct. The Tegra20 implementation will enable flipping at stream start based on those flags. Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Osipenko Signed-off-by: Hans Verkuil --- drivers/staging/media/tegra-video/vi.c | 14 +++++++++++++- drivers/staging/media/tegra-video/vi.h | 8 ++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 0d02468aba2c..428872a105e2 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -30,7 +30,7 @@ #include "vi.h" #include "video.h" -#define MAX_CID_CONTROLS 1 +#define MAX_CID_CONTROLS 3 /** * struct tegra_vi_graph_entity - Entity in the video graph @@ -912,6 +912,12 @@ static int vi_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_TEGRA_SYNCPT_TIMEOUT_RETRY: chan->syncpt_timeout_retry = ctrl->val; break; + case V4L2_CID_HFLIP: + chan->hflip = ctrl->val; + break; + case V4L2_CID_VFLIP: + chan->vflip = ctrl->val; + break; default: return -EINVAL; } @@ -983,6 +989,12 @@ static int tegra_channel_setup_ctrl_handler(struct tegra_vi_channel *chan) v4l2_ctrl_handler_free(&chan->ctrl_handler); return ret; } + + if (chan->vi->soc->has_h_v_flip) { + v4l2_ctrl_new_std(&chan->ctrl_handler, &vi_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0); + v4l2_ctrl_new_std(&chan->ctrl_handler, &vi_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0); + } + #endif /* setup the controls */ diff --git a/drivers/staging/media/tegra-video/vi.h b/drivers/staging/media/tegra-video/vi.h index cadf80b742a8..778c0ec475ab 100644 --- a/drivers/staging/media/tegra-video/vi.h +++ b/drivers/staging/media/tegra-video/vi.h @@ -74,6 +74,7 @@ struct tegra_vi_ops { * @hw_revision: VI hw_revision * @vi_max_channels: supported max streaming channels * @vi_max_clk_hz: VI clock max frequency + * @has_h_v_flip: the chip can do H and V flip, and the driver implements it */ struct tegra_vi_soc { const struct tegra_video_format *video_formats; @@ -83,6 +84,7 @@ struct tegra_vi_soc { u32 hw_revision; unsigned int vi_max_channels; unsigned int vi_max_clk_hz; + bool has_h_v_flip:1; }; /** @@ -172,6 +174,9 @@ struct tegra_vi { * @tpg_fmts_bitmap: a bitmap for supported TPG formats * @pg_mode: test pattern generator mode (disabled/direct/patch) * @notifier: V4L2 asynchronous subdevs notifier + * + * @hflip: Horizontal flip is enabled + * @vflip: Vertical flip is enabled */ struct tegra_vi_channel { struct list_head list; @@ -222,6 +227,9 @@ struct tegra_vi_channel { enum tegra_vi_pg_mode pg_mode; struct v4l2_async_notifier notifier; + + bool hflip:1; + bool vflip:1; }; /** From e740d199cf0ff1e53ddc2ab067c0a09b55845d68 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 18 Apr 2023 10:00:54 +0200 Subject: [PATCH 028/253] staging: media: tegra-video: add support for Tegra20 parallel input The VI peripheral of Tegra supports capturing from MIPI CSI-2 or parallel video (called VIP in the docs). The staging tegra-video driver currently implements MIPI CSI-2 video capture for Tegra210. Add support for parallel video capture (VIP) on Tegra20. With the generalizations added to the VI driver in previous commits, this is only a matter of adding the vip.c and tegra20.c implementations and registering them. Unfortunately there was no documentation available for the VI or VIP peripherals of Tegra20 (or any other Tegra chips). This implementation has been based entirely on the code from a vendor kernel based on Linux 3.1 and massively adapted to fit into the tegra-video driver. Parts of this code is definitely non-optimal to say the least (especially tegra20_vi_enable() and the single-frame capture logic), but it was impossible to improve it. Signed-off-by: Luca Ceresoli Reviewed-by: Dmitry Osipenko Signed-off-by: Hans Verkuil [hverkuil: fix host1x_client_unregister usage: it's now a void func] --- drivers/staging/media/tegra-video/Makefile | 2 + drivers/staging/media/tegra-video/tegra20.c | 661 ++++++++++++++++++++ drivers/staging/media/tegra-video/vi.c | 3 + drivers/staging/media/tegra-video/vi.h | 3 + drivers/staging/media/tegra-video/video.c | 5 + drivers/staging/media/tegra-video/video.h | 1 + drivers/staging/media/tegra-video/vip.c | 287 +++++++++ drivers/staging/media/tegra-video/vip.h | 68 ++ 8 files changed, 1030 insertions(+) create mode 100644 drivers/staging/media/tegra-video/tegra20.c create mode 100644 drivers/staging/media/tegra-video/vip.c create mode 100644 drivers/staging/media/tegra-video/vip.h diff --git a/drivers/staging/media/tegra-video/Makefile b/drivers/staging/media/tegra-video/Makefile index dfa2ef8f99ef..6c7552e05109 100644 --- a/drivers/staging/media/tegra-video/Makefile +++ b/drivers/staging/media/tegra-video/Makefile @@ -2,7 +2,9 @@ tegra-video-objs := \ video.o \ vi.o \ + vip.o \ csi.o +tegra-video-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20.o tegra-video-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210.o obj-$(CONFIG_VIDEO_TEGRA) += tegra-video.o diff --git a/drivers/staging/media/tegra-video/tegra20.c b/drivers/staging/media/tegra-video/tegra20.c new file mode 100644 index 000000000000..c25286772603 --- /dev/null +++ b/drivers/staging/media/tegra-video/tegra20.c @@ -0,0 +1,661 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Tegra20-specific VI implementation + * + * Copyright (C) 2023 SKIDATA GmbH + * Author: Luca Ceresoli + */ + +/* + * This source file contains Tegra20 supported video formats, + * VI and VIP SoC specific data, operations and registers accessors. + */ + +#include +#include +#include +#include +#include +#include + +#include "vip.h" +#include "vi.h" + +#define TEGRA_VI_SYNCPT_WAIT_TIMEOUT msecs_to_jiffies(200) + +/* This are just good-sense numbers. The actual min/max is not documented. */ +#define TEGRA20_MIN_WIDTH 32U +#define TEGRA20_MIN_HEIGHT 32U +#define TEGRA20_MAX_WIDTH 2048U +#define TEGRA20_MAX_HEIGHT 2048U + +/* -------------------------------------------------------------------------- + * Registers + */ + +#define TEGRA_VI_CONT_SYNCPT_OUT_1 0x0060 +#define VI_CONT_SYNCPT_OUT_1_CONTINUOUS_SYNCPT BIT(8) +#define VI_CONT_SYNCPT_OUT_1_SYNCPT_IDX_SFT 0 + +#define TEGRA_VI_VI_INPUT_CONTROL 0x0088 +#define VI_INPUT_FIELD_DETECT BIT(27) +#define VI_INPUT_BT656 BIT(25) +#define VI_INPUT_YUV_INPUT_FORMAT_SFT 8 /* bits [9:8] */ +#define VI_INPUT_YUV_INPUT_FORMAT_UYVY (0 << VI_INPUT_YUV_INPUT_FORMAT_SFT) +#define VI_INPUT_YUV_INPUT_FORMAT_VYUY (1 << VI_INPUT_YUV_INPUT_FORMAT_SFT) +#define VI_INPUT_YUV_INPUT_FORMAT_YUYV (2 << VI_INPUT_YUV_INPUT_FORMAT_SFT) +#define VI_INPUT_YUV_INPUT_FORMAT_YVYU (3 << VI_INPUT_YUV_INPUT_FORMAT_SFT) +#define VI_INPUT_INPUT_FORMAT_SFT 2 /* bits [5:2] */ +#define VI_INPUT_INPUT_FORMAT_YUV422 (0 << VI_INPUT_INPUT_FORMAT_SFT) +#define VI_INPUT_VIP_INPUT_ENABLE BIT(1) + +#define TEGRA_VI_VI_CORE_CONTROL 0x008c +#define VI_VI_CORE_CONTROL_PLANAR_CONV_IN_SEL_EXT BIT(31) +#define VI_VI_CORE_CONTROL_CSC_INPUT_SEL_EXT BIT(30) +#define VI_VI_CORE_CONTROL_INPUT_TO_ALT_MUX_SFT 27 +#define VI_VI_CORE_CONTROL_INPUT_TO_CORE_EXT_SFT 24 +#define VI_VI_CORE_CONTROL_OUTPUT_TO_ISP_EXT_SFT 21 +#define VI_VI_CORE_CONTROL_ISP_HOST_STALL_OFF BIT(20) +#define VI_VI_CORE_CONTROL_V_DOWNSCALING BIT(19) +#define VI_VI_CORE_CONTROL_V_AVERAGING BIT(18) +#define VI_VI_CORE_CONTROL_H_DOWNSCALING BIT(17) +#define VI_VI_CORE_CONTROL_H_AVERAGING BIT(16) +#define VI_VI_CORE_CONTROL_CSC_INPUT_SEL BIT(11) +#define VI_VI_CORE_CONTROL_PLANAR_CONV_INPUT_SEL BIT(10) +#define VI_VI_CORE_CONTROL_INPUT_TO_CORE_SFT 8 +#define VI_VI_CORE_CONTROL_ISP_DOWNSAMPLE_SFT 5 +#define VI_VI_CORE_CONTROL_OUTPUT_TO_EPP_SFT 2 +#define VI_VI_CORE_CONTROL_OUTPUT_TO_ISP_SFT 0 + +#define TEGRA_VI_VI_FIRST_OUTPUT_CONTROL 0x0090 +#define VI_OUTPUT_FORMAT_EXT BIT(22) +#define VI_OUTPUT_V_DIRECTION BIT(20) +#define VI_OUTPUT_H_DIRECTION BIT(19) +#define VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT 17 +#define VI_OUTPUT_YUV_OUTPUT_FORMAT_UYVY (0 << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT) +#define VI_OUTPUT_YUV_OUTPUT_FORMAT_VYUY (1 << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT) +#define VI_OUTPUT_YUV_OUTPUT_FORMAT_YUYV (2 << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT) +#define VI_OUTPUT_YUV_OUTPUT_FORMAT_YVYU (3 << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT) +#define VI_OUTPUT_OUTPUT_BYTE_SWAP BIT(16) +#define VI_OUTPUT_LAST_PIXEL_DUPLICATION BIT(8) +#define VI_OUTPUT_OUTPUT_FORMAT_SFT 0 +#define VI_OUTPUT_OUTPUT_FORMAT_YUV422POST (3 << VI_OUTPUT_OUTPUT_FORMAT_SFT) +#define VI_OUTPUT_OUTPUT_FORMAT_YUV420PLANAR (6 << VI_OUTPUT_OUTPUT_FORMAT_SFT) + +#define TEGRA_VI_VIP_H_ACTIVE 0x00a4 +#define VI_VIP_H_ACTIVE_PERIOD_SFT 16 /* active pixels/line, must be even */ +#define VI_VIP_H_ACTIVE_START_SFT 0 + +#define TEGRA_VI_VIP_V_ACTIVE 0x00a8 +#define VI_VIP_V_ACTIVE_PERIOD_SFT 16 /* active lines */ +#define VI_VIP_V_ACTIVE_START_SFT 0 + +#define TEGRA_VI_VB0_START_ADDRESS_FIRST 0x00c4 +#define TEGRA_VI_VB0_BASE_ADDRESS_FIRST 0x00c8 +#define TEGRA_VI_VB0_START_ADDRESS_U 0x00cc +#define TEGRA_VI_VB0_BASE_ADDRESS_U 0x00d0 +#define TEGRA_VI_VB0_START_ADDRESS_V 0x00d4 +#define TEGRA_VI_VB0_BASE_ADDRESS_V 0x00d8 + +#define TEGRA_VI_FIRST_OUTPUT_FRAME_SIZE 0x00e0 +#define VI_FIRST_OUTPUT_FRAME_HEIGHT_SFT 16 +#define VI_FIRST_OUTPUT_FRAME_WIDTH_SFT 0 + +#define TEGRA_VI_VB0_COUNT_FIRST 0x00e4 + +#define TEGRA_VI_VB0_SIZE_FIRST 0x00e8 +#define VI_VB0_SIZE_FIRST_V_SFT 16 +#define VI_VB0_SIZE_FIRST_H_SFT 0 + +#define TEGRA_VI_VB0_BUFFER_STRIDE_FIRST 0x00ec +#define VI_VB0_BUFFER_STRIDE_FIRST_CHROMA_SFT 30 +#define VI_VB0_BUFFER_STRIDE_FIRST_LUMA_SFT 0 + +#define TEGRA_VI_H_LPF_CONTROL 0x0108 +#define VI_H_LPF_CONTROL_CHROMA_SFT 16 +#define VI_H_LPF_CONTROL_LUMA_SFT 0 + +#define TEGRA_VI_H_DOWNSCALE_CONTROL 0x010c +#define TEGRA_VI_V_DOWNSCALE_CONTROL 0x0110 + +#define TEGRA_VI_VIP_INPUT_STATUS 0x0144 + +#define TEGRA_VI_VI_DATA_INPUT_CONTROL 0x0168 +#define VI_DATA_INPUT_SFT 0 /* [11:0] = mask pin inputs to VI core */ + +#define TEGRA_VI_PIN_INPUT_ENABLE 0x016c +#define VI_PIN_INPUT_VSYNC BIT(14) +#define VI_PIN_INPUT_HSYNC BIT(13) +#define VI_PIN_INPUT_VD_SFT 0 /* [11:0] = data bin N input enable */ + +#define TEGRA_VI_PIN_INVERSION 0x0174 +#define VI_PIN_INVERSION_VSYNC_ACTIVE_HIGH BIT(1) +#define VI_PIN_INVERSION_HSYNC_ACTIVE_HIGH BIT(0) + +#define TEGRA_VI_CAMERA_CONTROL 0x01a0 +#define VI_CAMERA_CONTROL_STOP_CAPTURE BIT(2) +#define VI_CAMERA_CONTROL_TEST_MODE BIT(1) +#define VI_CAMERA_CONTROL_VIP_ENABLE BIT(0) + +#define TEGRA_VI_VI_ENABLE 0x01a4 +#define VI_VI_ENABLE_SW_FLOW_CONTROL_OUT1 BIT(1) +#define VI_VI_ENABLE_FIRST_OUTPUT_TO_MEM_DISABLE BIT(0) + +#define TEGRA_VI_VI_RAISE 0x01ac +#define VI_VI_RAISE_ON_EDGE BIT(0) + +/* -------------------------------------------------------------------------- + * VI + */ + +static void tegra20_vi_write(struct tegra_vi_channel *chan, unsigned int addr, u32 val) +{ + writel(val, chan->vi->iomem + addr); +} + +/* + * Get the main input format (YUV/RGB...) and the YUV variant as values to + * be written into registers for the current VI input mbus code. + */ +static void tegra20_vi_get_input_formats(struct tegra_vi_channel *chan, + unsigned int *main_input_format, + unsigned int *yuv_input_format) +{ + unsigned int input_mbus_code = chan->fmtinfo->code; + + (*main_input_format) = VI_INPUT_INPUT_FORMAT_YUV422; + + switch (input_mbus_code) { + case MEDIA_BUS_FMT_UYVY8_2X8: + (*yuv_input_format) = VI_INPUT_YUV_INPUT_FORMAT_UYVY; + break; + case MEDIA_BUS_FMT_VYUY8_2X8: + (*yuv_input_format) = VI_INPUT_YUV_INPUT_FORMAT_VYUY; + break; + case MEDIA_BUS_FMT_YUYV8_2X8: + (*yuv_input_format) = VI_INPUT_YUV_INPUT_FORMAT_YUYV; + break; + case MEDIA_BUS_FMT_YVYU8_2X8: + (*yuv_input_format) = VI_INPUT_YUV_INPUT_FORMAT_YVYU; + break; + } +} + +/* + * Get the main output format (YUV/RGB...) and the YUV variant as values to + * be written into registers for the current VI output pixel format. + */ +static void tegra20_vi_get_output_formats(struct tegra_vi_channel *chan, + unsigned int *main_output_format, + unsigned int *yuv_output_format) +{ + u32 output_fourcc = chan->format.pixelformat; + + /* Default to YUV422 non-planar (U8Y8V8Y8) after downscaling */ + (*main_output_format) = VI_OUTPUT_OUTPUT_FORMAT_YUV422POST; + (*yuv_output_format) = VI_OUTPUT_YUV_OUTPUT_FORMAT_UYVY; + + switch (output_fourcc) { + case V4L2_PIX_FMT_UYVY: + (*yuv_output_format) = VI_OUTPUT_YUV_OUTPUT_FORMAT_UYVY; + break; + case V4L2_PIX_FMT_VYUY: + (*yuv_output_format) = VI_OUTPUT_YUV_OUTPUT_FORMAT_VYUY; + break; + case V4L2_PIX_FMT_YUYV: + (*yuv_output_format) = VI_OUTPUT_YUV_OUTPUT_FORMAT_YUYV; + break; + case V4L2_PIX_FMT_YVYU: + (*yuv_output_format) = VI_OUTPUT_YUV_OUTPUT_FORMAT_YVYU; + break; + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + (*main_output_format) = VI_OUTPUT_OUTPUT_FORMAT_YUV420PLANAR; + break; + } +} + +/* + * Make the VI accessible (needed on Tegra20). + * + * This function writes an unknown bit into an unknown register. The code + * comes from a downstream 3.1 kernel that has a working VIP driver for + * Tegra20, and removing it makes the VI completely unaccessible. It should + * be rewritten and possibly moved elsewhere, but the appropriate location + * and implementation is unknown due to a total lack of documentation. + */ +static int tegra20_vi_enable(struct tegra_vi *vi, bool on) +{ + /* from arch/arm/mach-tegra/iomap.h */ + const phys_addr_t TEGRA_APB_MISC_BASE = 0x70000000; + const unsigned long reg_offset = 0x42c; + void __iomem *apb_misc; + u32 val; + + apb_misc = ioremap(TEGRA_APB_MISC_BASE, PAGE_SIZE); + if (!apb_misc) + apb_misc = ERR_PTR(-ENOENT); + if (IS_ERR(apb_misc)) + return dev_err_probe(vi->dev, PTR_ERR(apb_misc), "cannot access APB_MISC"); + + val = readl(apb_misc + reg_offset); + val &= ~BIT(0); + val |= on ? BIT(0) : 0; + writel(val, apb_misc + reg_offset); + iounmap(apb_misc); + + return 0; +} + +static int tegra20_channel_host1x_syncpt_init(struct tegra_vi_channel *chan) +{ + struct tegra_vi *vi = chan->vi; + struct host1x_syncpt *out_sp; + + out_sp = host1x_syncpt_request(&vi->client, HOST1X_SYNCPT_CLIENT_MANAGED); + if (!out_sp) + return dev_err_probe(vi->dev, -ENOMEM, "failed to request syncpoint\n"); + + chan->mw_ack_sp[0] = out_sp; + + return 0; +} + +static void tegra20_channel_host1x_syncpt_free(struct tegra_vi_channel *chan) +{ + host1x_syncpt_put(chan->mw_ack_sp[0]); +} + +static void tegra20_fmt_align(struct v4l2_pix_format *pix, unsigned int bpp) +{ + pix->width = clamp(pix->width, TEGRA20_MIN_WIDTH, TEGRA20_MAX_WIDTH); + pix->height = clamp(pix->height, TEGRA20_MIN_HEIGHT, TEGRA20_MAX_HEIGHT); + + switch (pix->pixelformat) { + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_VYUY: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_YVYU: + pix->bytesperline = roundup(pix->width, 2) * 2; + pix->sizeimage = roundup(pix->width, 2) * 2 * pix->height; + break; + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + pix->bytesperline = roundup(pix->width, 8); + pix->sizeimage = roundup(pix->width, 8) * pix->height * 3 / 2; + break; + } +} + +/* + * Compute buffer offsets once per stream so that + * tegra20_channel_vi_buffer_setup() only has to do very simple maths for + * each buffer. + */ +static void tegra20_channel_queue_setup(struct tegra_vi_channel *chan) +{ + unsigned int stride = chan->format.bytesperline; + unsigned int height = chan->format.height; + + chan->start_offset = 0; + + switch (chan->format.pixelformat) { + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_VYUY: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_YVYU: + if (chan->vflip) + chan->start_offset += stride * (height - 1); + if (chan->hflip) + chan->start_offset += stride - 1; + break; + + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + chan->addr_offset_u = stride * height; + chan->addr_offset_v = chan->addr_offset_u + stride * height / 4; + + /* For YVU420, we swap the locations of the U and V planes. */ + if (chan->format.pixelformat == V4L2_PIX_FMT_YVU420) { + unsigned long temp; + + temp = chan->addr_offset_u; + chan->addr_offset_u = chan->addr_offset_v; + chan->addr_offset_v = temp; + } + + chan->start_offset_u = chan->addr_offset_u; + chan->start_offset_v = chan->addr_offset_v; + + if (chan->vflip) { + chan->start_offset += stride * (height - 1); + chan->start_offset_u += (stride / 2) * ((height / 2) - 1); + chan->start_offset_v += (stride / 2) * ((height / 2) - 1); + } + if (chan->hflip) { + chan->start_offset += stride - 1; + chan->start_offset_u += (stride / 2) - 1; + chan->start_offset_v += (stride / 2) - 1; + } + break; + } +} + +static void release_buffer(struct tegra_vi_channel *chan, + struct tegra_channel_buffer *buf, + enum vb2_buffer_state state) +{ + struct vb2_v4l2_buffer *vb = &buf->buf; + + vb->sequence = chan->sequence++; + vb->field = V4L2_FIELD_NONE; + vb->vb2_buf.timestamp = ktime_get_ns(); + vb2_buffer_done(&vb->vb2_buf, state); +} + +static void tegra20_channel_vi_buffer_setup(struct tegra_vi_channel *chan, + struct tegra_channel_buffer *buf) +{ + dma_addr_t base = buf->addr; + + switch (chan->fmtinfo->fourcc) { + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS_U, base + chan->addr_offset_u); + tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS_U, base + chan->start_offset_u); + tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS_V, base + chan->addr_offset_v); + tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS_V, base + chan->start_offset_v); + fallthrough; + + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_VYUY: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_YVYU: + tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS_FIRST, base); + tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS_FIRST, base + chan->start_offset); + break; + } +} + +static int tegra20_channel_capture_frame(struct tegra_vi_channel *chan, + struct tegra_channel_buffer *buf) +{ + int err; + + chan->next_out_sp_idx++; + + tegra20_channel_vi_buffer_setup(chan, buf); + + tegra20_vi_write(chan, TEGRA_VI_CAMERA_CONTROL, VI_CAMERA_CONTROL_VIP_ENABLE); + + /* Wait for syncpt counter to reach frame start event threshold */ + err = host1x_syncpt_wait(chan->mw_ack_sp[0], chan->next_out_sp_idx, + TEGRA_VI_SYNCPT_WAIT_TIMEOUT, NULL); + if (err) { + host1x_syncpt_incr(chan->mw_ack_sp[0]); + dev_err_ratelimited(&chan->video.dev, "frame start syncpt timeout: %d\n", err); + release_buffer(chan, buf, VB2_BUF_STATE_ERROR); + return err; + } + + tegra20_vi_write(chan, TEGRA_VI_CAMERA_CONTROL, + VI_CAMERA_CONTROL_STOP_CAPTURE | VI_CAMERA_CONTROL_VIP_ENABLE); + + release_buffer(chan, buf, VB2_BUF_STATE_DONE); + + return 0; +} + +static int tegra20_chan_capture_kthread_start(void *data) +{ + struct tegra_vi_channel *chan = data; + struct tegra_channel_buffer *buf; + unsigned int retries = 0; + int err = 0; + + while (1) { + /* + * Source is not streaming if error is non-zero. + * So, do not dequeue buffers on error and let the thread sleep + * till kthread stop signal is received. + */ + wait_event_interruptible(chan->start_wait, + kthread_should_stop() || + (!list_empty(&chan->capture) && !err)); + + if (kthread_should_stop()) + break; + + /* dequeue the buffer and start capture */ + spin_lock(&chan->start_lock); + if (list_empty(&chan->capture)) { + spin_unlock(&chan->start_lock); + continue; + } + + buf = list_first_entry(&chan->capture, struct tegra_channel_buffer, queue); + list_del_init(&buf->queue); + spin_unlock(&chan->start_lock); + + err = tegra20_channel_capture_frame(chan, buf); + if (!err) { + retries = 0; + continue; + } + + if (retries++ > chan->syncpt_timeout_retry) + vb2_queue_error(&chan->queue); + else + err = 0; + } + + return 0; +} + +static void tegra20_camera_capture_setup(struct tegra_vi_channel *chan) +{ + u32 output_fourcc = chan->format.pixelformat; + int width = chan->format.width; + int height = chan->format.height; + int stride_l = chan->format.bytesperline; + int stride_c = (output_fourcc == V4L2_PIX_FMT_YUV420 || + output_fourcc == V4L2_PIX_FMT_YVU420) ? 1 : 0; + int main_output_format; + int yuv_output_format; + + tegra20_vi_get_output_formats(chan, &main_output_format, &yuv_output_format); + + /* + * Set up low pass filter. Use 0x240 for chromaticity and 0x240 + * for luminance, which is the default and means not to touch + * anything. + */ + tegra20_vi_write(chan, TEGRA_VI_H_LPF_CONTROL, + 0x0240 << VI_H_LPF_CONTROL_LUMA_SFT | + 0x0240 << VI_H_LPF_CONTROL_CHROMA_SFT); + + /* Set up raise-on-edge, so we get an interrupt on end of frame. */ + tegra20_vi_write(chan, TEGRA_VI_VI_RAISE, VI_VI_RAISE_ON_EDGE); + + tegra20_vi_write(chan, TEGRA_VI_VI_FIRST_OUTPUT_CONTROL, + (chan->vflip ? VI_OUTPUT_V_DIRECTION : 0) | + (chan->hflip ? VI_OUTPUT_H_DIRECTION : 0) | + yuv_output_format << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT | + main_output_format << VI_OUTPUT_OUTPUT_FORMAT_SFT); + + /* Set up frame size */ + tegra20_vi_write(chan, TEGRA_VI_FIRST_OUTPUT_FRAME_SIZE, + height << VI_FIRST_OUTPUT_FRAME_HEIGHT_SFT | + width << VI_FIRST_OUTPUT_FRAME_WIDTH_SFT); + + /* First output memory enabled */ + tegra20_vi_write(chan, TEGRA_VI_VI_ENABLE, 0); + + /* Set the number of frames in the buffer */ + tegra20_vi_write(chan, TEGRA_VI_VB0_COUNT_FIRST, 1); + + /* Set up buffer frame size */ + tegra20_vi_write(chan, TEGRA_VI_VB0_SIZE_FIRST, + height << VI_VB0_SIZE_FIRST_V_SFT | + width << VI_VB0_SIZE_FIRST_H_SFT); + + tegra20_vi_write(chan, TEGRA_VI_VB0_BUFFER_STRIDE_FIRST, + stride_l << VI_VB0_BUFFER_STRIDE_FIRST_LUMA_SFT | + stride_c << VI_VB0_BUFFER_STRIDE_FIRST_CHROMA_SFT); + + tegra20_vi_write(chan, TEGRA_VI_VI_ENABLE, 0); +} + +static int tegra20_vi_start_streaming(struct vb2_queue *vq, u32 count) +{ + struct tegra_vi_channel *chan = vb2_get_drv_priv(vq); + struct media_pipeline *pipe = &chan->video.pipe; + int err; + + chan->next_out_sp_idx = host1x_syncpt_read(chan->mw_ack_sp[0]); + + err = video_device_pipeline_start(&chan->video, pipe); + if (err) + goto error_pipeline_start; + + tegra20_camera_capture_setup(chan); + + err = tegra_channel_set_stream(chan, true); + if (err) + goto error_set_stream; + + chan->sequence = 0; + + chan->kthread_start_capture = kthread_run(tegra20_chan_capture_kthread_start, + chan, "%s:0", chan->video.name); + if (IS_ERR(chan->kthread_start_capture)) { + err = PTR_ERR(chan->kthread_start_capture); + chan->kthread_start_capture = NULL; + dev_err_probe(&chan->video.dev, err, "failed to run capture kthread\n"); + goto error_kthread_start; + } + + return 0; + +error_kthread_start: + tegra_channel_set_stream(chan, false); +error_set_stream: + video_device_pipeline_stop(&chan->video); +error_pipeline_start: + tegra_channel_release_buffers(chan, VB2_BUF_STATE_QUEUED); + + return err; +} + +static void tegra20_vi_stop_streaming(struct vb2_queue *vq) +{ + struct tegra_vi_channel *chan = vb2_get_drv_priv(vq); + + if (chan->kthread_start_capture) { + kthread_stop(chan->kthread_start_capture); + chan->kthread_start_capture = NULL; + } + + tegra_channel_release_buffers(chan, VB2_BUF_STATE_ERROR); + tegra_channel_set_stream(chan, false); + video_device_pipeline_stop(&chan->video); +} + +static const struct tegra_vi_ops tegra20_vi_ops = { + .vi_enable = tegra20_vi_enable, + .channel_host1x_syncpt_init = tegra20_channel_host1x_syncpt_init, + .channel_host1x_syncpt_free = tegra20_channel_host1x_syncpt_free, + .vi_fmt_align = tegra20_fmt_align, + .channel_queue_setup = tegra20_channel_queue_setup, + .vi_start_streaming = tegra20_vi_start_streaming, + .vi_stop_streaming = tegra20_vi_stop_streaming, +}; + +#define TEGRA20_VIDEO_FMT(MBUS_CODE, BPP, FOURCC) \ +{ \ + .code = MEDIA_BUS_FMT_##MBUS_CODE, \ + .bpp = BPP, \ + .fourcc = V4L2_PIX_FMT_##FOURCC, \ +} + +static const struct tegra_video_format tegra20_video_formats[] = { + TEGRA20_VIDEO_FMT(UYVY8_2X8, 2, UYVY), + TEGRA20_VIDEO_FMT(VYUY8_2X8, 2, VYUY), + TEGRA20_VIDEO_FMT(YUYV8_2X8, 2, YUYV), + TEGRA20_VIDEO_FMT(YVYU8_2X8, 2, YVYU), + TEGRA20_VIDEO_FMT(UYVY8_2X8, 1, YUV420), + TEGRA20_VIDEO_FMT(UYVY8_2X8, 1, YVU420), +}; + +const struct tegra_vi_soc tegra20_vi_soc = { + .video_formats = tegra20_video_formats, + .nformats = ARRAY_SIZE(tegra20_video_formats), + .default_video_format = &tegra20_video_formats[0], + .ops = &tegra20_vi_ops, + .vi_max_channels = 1, /* parallel input (VIP) */ + .vi_max_clk_hz = 150000000, + .has_h_v_flip = true, +}; + +/* -------------------------------------------------------------------------- + * VIP + */ + +/* + * VIP-specific configuration for stream start. + * + * Whatever is common among VIP and CSI is done by the VI component (see + * tegra20_vi_start_streaming()). Here we do what is VIP-specific. + */ +static int tegra20_vip_start_streaming(struct tegra_vip_channel *vip_chan) +{ + struct tegra_vi_channel *vi_chan = v4l2_get_subdev_hostdata(&vip_chan->subdev); + int width = vi_chan->format.width; + int height = vi_chan->format.height; + + unsigned int main_input_format; + unsigned int yuv_input_format; + + tegra20_vi_get_input_formats(vi_chan, &main_input_format, &yuv_input_format); + + tegra20_vi_write(vi_chan, TEGRA_VI_VI_CORE_CONTROL, 0); + + tegra20_vi_write(vi_chan, TEGRA_VI_VI_INPUT_CONTROL, + VI_INPUT_VIP_INPUT_ENABLE | main_input_format | yuv_input_format); + + tegra20_vi_write(vi_chan, TEGRA_VI_V_DOWNSCALE_CONTROL, 0); + tegra20_vi_write(vi_chan, TEGRA_VI_H_DOWNSCALE_CONTROL, 0); + + tegra20_vi_write(vi_chan, TEGRA_VI_VIP_V_ACTIVE, height << VI_VIP_V_ACTIVE_PERIOD_SFT); + tegra20_vi_write(vi_chan, TEGRA_VI_VIP_H_ACTIVE, + roundup(width, 2) << VI_VIP_H_ACTIVE_PERIOD_SFT); + + /* + * For VIP, D9..D2 is mapped to the video decoder's P7..P0. + * Disable/mask out the other Dn wires. When not in BT656 + * mode we also need the V/H sync. + */ + tegra20_vi_write(vi_chan, TEGRA_VI_PIN_INPUT_ENABLE, + GENMASK(9, 2) << VI_PIN_INPUT_VD_SFT | + VI_PIN_INPUT_HSYNC | VI_PIN_INPUT_VSYNC); + tegra20_vi_write(vi_chan, TEGRA_VI_VI_DATA_INPUT_CONTROL, + GENMASK(9, 2) << VI_DATA_INPUT_SFT); + tegra20_vi_write(vi_chan, TEGRA_VI_PIN_INVERSION, 0); + + tegra20_vi_write(vi_chan, TEGRA_VI_CONT_SYNCPT_OUT_1, + VI_CONT_SYNCPT_OUT_1_CONTINUOUS_SYNCPT | + host1x_syncpt_id(vi_chan->mw_ack_sp[0]) + << VI_CONT_SYNCPT_OUT_1_SYNCPT_IDX_SFT); + + tegra20_vi_write(vi_chan, TEGRA_VI_CAMERA_CONTROL, VI_CAMERA_CONTROL_STOP_CAPTURE); + + return 0; +} + +static const struct tegra_vip_ops tegra20_vip_ops = { + .vip_start_streaming = tegra20_vip_start_streaming, +}; + +const struct tegra_vip_soc tegra20_vip_soc = { + .ops = &tegra20_vip_ops, +}; diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 428872a105e2..79284c3b6cae 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -1955,6 +1955,9 @@ static int tegra_vi_remove(struct platform_device *pdev) } static const struct of_device_id tegra_vi_of_id_table[] = { +#if defined(CONFIG_ARCH_TEGRA_2x_SOC) + { .compatible = "nvidia,tegra20-vi", .data = &tegra20_vi_soc }, +#endif #if defined(CONFIG_ARCH_TEGRA_210_SOC) { .compatible = "nvidia,tegra210-vi", .data = &tegra210_vi_soc }, #endif diff --git a/drivers/staging/media/tegra-video/vi.h b/drivers/staging/media/tegra-video/vi.h index 778c0ec475ab..1e6a5caa7082 100644 --- a/drivers/staging/media/tegra-video/vi.h +++ b/drivers/staging/media/tegra-video/vi.h @@ -296,6 +296,9 @@ struct tegra_video_format { u32 fourcc; }; +#if defined(CONFIG_ARCH_TEGRA_2x_SOC) +extern const struct tegra_vi_soc tegra20_vi_soc; +#endif #if defined(CONFIG_ARCH_TEGRA_210_SOC) extern const struct tegra_vi_soc tegra210_vi_soc; #endif diff --git a/drivers/staging/media/tegra-video/video.c b/drivers/staging/media/tegra-video/video.c index d966b319553f..074ad0dc56ca 100644 --- a/drivers/staging/media/tegra-video/video.c +++ b/drivers/staging/media/tegra-video/video.c @@ -123,6 +123,10 @@ static int host1x_video_remove(struct host1x_device *dev) } static const struct of_device_id host1x_video_subdevs[] = { +#if defined(CONFIG_ARCH_TEGRA_2x_SOC) + { .compatible = "nvidia,tegra20-vip", }, + { .compatible = "nvidia,tegra20-vi", }, +#endif #if defined(CONFIG_ARCH_TEGRA_210_SOC) { .compatible = "nvidia,tegra210-csi", }, { .compatible = "nvidia,tegra210-vi", }, @@ -141,6 +145,7 @@ static struct host1x_driver host1x_video_driver = { static struct platform_driver * const drivers[] = { &tegra_csi_driver, + &tegra_vip_driver, &tegra_vi_driver, }; diff --git a/drivers/staging/media/tegra-video/video.h b/drivers/staging/media/tegra-video/video.h index 1e9be1474a9c..7275affa6558 100644 --- a/drivers/staging/media/tegra-video/video.h +++ b/drivers/staging/media/tegra-video/video.h @@ -24,5 +24,6 @@ int tegra_v4l2_nodes_setup_tpg(struct tegra_video_device *vid); void tegra_v4l2_nodes_cleanup_tpg(struct tegra_video_device *vid); extern struct platform_driver tegra_vi_driver; +extern struct platform_driver tegra_vip_driver; extern struct platform_driver tegra_csi_driver; #endif diff --git a/drivers/staging/media/tegra-video/vip.c b/drivers/staging/media/tegra-video/vip.c new file mode 100644 index 000000000000..a1ab886acc18 --- /dev/null +++ b/drivers/staging/media/tegra-video/vip.c @@ -0,0 +1,287 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Parallel video capture module (VIP) for the Tegra VI. + * + * This file implements the VIP-specific infrastructure. + * + * Copyright (C) 2023 SKIDATA GmbH + * Author: Luca Ceresoli + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "vip.h" + +static inline struct tegra_vip *host1x_client_to_vip(struct host1x_client *client) +{ + return container_of(client, struct tegra_vip, client); +} + +static inline struct tegra_vip_channel *subdev_to_vip_channel(struct v4l2_subdev *subdev) +{ + return container_of(subdev, struct tegra_vip_channel, subdev); +} + +static inline struct tegra_vip *vip_channel_to_vip(struct tegra_vip_channel *chan) +{ + return container_of(chan, struct tegra_vip, chan); +} + +/* Find the previous subdev in the pipeline (i.e. the one connected to our sink pad) */ +static struct v4l2_subdev *tegra_vip_channel_get_prev_subdev(struct tegra_vip_channel *chan) +{ + struct media_pad *remote_pad; + + remote_pad = media_pad_remote_pad_first(&chan->pads[TEGRA_VIP_PAD_SINK]); + if (!remote_pad) + return NULL; + + return media_entity_to_v4l2_subdev(remote_pad->entity); +} + +static int tegra_vip_enable_stream(struct v4l2_subdev *subdev) +{ + struct tegra_vip_channel *vip_chan = subdev_to_vip_channel(subdev); + struct tegra_vip *vip = vip_channel_to_vip(vip_chan); + struct v4l2_subdev *prev_subdev = tegra_vip_channel_get_prev_subdev(vip_chan); + int err; + + err = pm_runtime_resume_and_get(vip->dev); + if (err) + return dev_err_probe(vip->dev, err, "failed to get runtime PM\n"); + + err = vip->soc->ops->vip_start_streaming(vip_chan); + if (err < 0) + goto err_start_streaming; + + err = v4l2_subdev_call(prev_subdev, video, s_stream, true); + if (err < 0 && err != -ENOIOCTLCMD) + goto err_prev_subdev_start_stream; + + return 0; + +err_prev_subdev_start_stream: +err_start_streaming: + pm_runtime_put(vip->dev); + return err; +} + +static int tegra_vip_disable_stream(struct v4l2_subdev *subdev) +{ + struct tegra_vip_channel *vip_chan = subdev_to_vip_channel(subdev); + struct tegra_vip *vip = vip_channel_to_vip(vip_chan); + struct v4l2_subdev *prev_subdev = tegra_vip_channel_get_prev_subdev(vip_chan); + + v4l2_subdev_call(prev_subdev, video, s_stream, false); + + pm_runtime_put(vip->dev); + + return 0; +} + +static int tegra_vip_s_stream(struct v4l2_subdev *subdev, int enable) +{ + int err; + + if (enable) + err = tegra_vip_enable_stream(subdev); + else + err = tegra_vip_disable_stream(subdev); + + return err; +} + +static const struct v4l2_subdev_video_ops tegra_vip_video_ops = { + .s_stream = tegra_vip_s_stream, +}; + +static const struct v4l2_subdev_ops tegra_vip_ops = { + .video = &tegra_vip_video_ops, +}; + +static int tegra_vip_channel_of_parse(struct tegra_vip *vip) +{ + struct device *dev = vip->dev; + struct device_node *np = dev->of_node; + struct v4l2_fwnode_endpoint v4l2_ep = { + .bus_type = V4L2_MBUS_PARALLEL + }; + struct fwnode_handle *fwh; + struct device_node *ep; + unsigned int num_pads; + int err; + + dev_dbg(dev, "Parsing %pOF", np); + + ep = of_graph_get_endpoint_by_regs(np, 0, 0); + if (!ep) { + err = -EINVAL; + dev_err_probe(dev, err, "%pOF: error getting endpoint node\n", np); + goto err_node_put; + } + + fwh = of_fwnode_handle(ep); + err = v4l2_fwnode_endpoint_parse(fwh, &v4l2_ep); + of_node_put(ep); + if (err) { + dev_err_probe(dev, err, "%pOF: failed to parse v4l2 endpoint\n", np); + goto err_node_put; + } + + num_pads = of_graph_get_endpoint_count(np); + if (num_pads != TEGRA_VIP_PADS_NUM) { + err = -EINVAL; + dev_err_probe(dev, err, "%pOF: need 2 pads, got %d\n", np, num_pads); + goto err_node_put; + } + + vip->chan.of_node = of_node_get(np); + vip->chan.pads[TEGRA_VIP_PAD_SINK].flags = MEDIA_PAD_FL_SINK; + vip->chan.pads[TEGRA_VIP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; + + return 0; + +err_node_put: + of_node_put(np); + return err; +} + +static int tegra_vip_channel_init(struct tegra_vip *vip) +{ + struct v4l2_subdev *subdev; + int err; + + subdev = &vip->chan.subdev; + v4l2_subdev_init(subdev, &tegra_vip_ops); + subdev->dev = vip->dev; + snprintf(subdev->name, V4L2_SUBDEV_NAME_SIZE, "%s", + kbasename(vip->chan.of_node->full_name)); + + v4l2_set_subdevdata(subdev, &vip->chan); + subdev->fwnode = of_fwnode_handle(vip->chan.of_node); + subdev->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; + + err = media_entity_pads_init(&subdev->entity, TEGRA_VIP_PADS_NUM, vip->chan.pads); + if (err) + return dev_err_probe(vip->dev, err, "failed to initialize media entity\n"); + + err = v4l2_async_register_subdev(subdev); + if (err) { + dev_err_probe(vip->dev, err, "failed to register subdev\n"); + goto err_register_subdev; + } + + return 0; + +err_register_subdev: + media_entity_cleanup(&subdev->entity); + return err; +} + +static int tegra_vip_init(struct host1x_client *client) +{ + struct tegra_vip *vip = host1x_client_to_vip(client); + int err; + + err = tegra_vip_channel_of_parse(vip); + if (err) + return err; + + err = tegra_vip_channel_init(vip); + if (err) + goto err_init; + + return 0; + +err_init: + of_node_put(vip->chan.of_node); + return err; +} + +static int tegra_vip_exit(struct host1x_client *client) +{ + struct tegra_vip *vip = host1x_client_to_vip(client); + struct v4l2_subdev *subdev = &vip->chan.subdev; + + v4l2_async_unregister_subdev(subdev); + media_entity_cleanup(&subdev->entity); + of_node_put(vip->chan.of_node); + + return 0; +} + +static const struct host1x_client_ops vip_client_ops = { + .init = tegra_vip_init, + .exit = tegra_vip_exit, +}; + +static int tegra_vip_probe(struct platform_device *pdev) +{ + struct tegra_vip *vip; + int err; + + dev_dbg(&pdev->dev, "Probing VIP \"%s\" from %pOF\n", pdev->name, pdev->dev.of_node); + + vip = devm_kzalloc(&pdev->dev, sizeof(*vip), GFP_KERNEL); + if (!vip) + return -ENOMEM; + + vip->soc = of_device_get_match_data(&pdev->dev); + + vip->dev = &pdev->dev; + platform_set_drvdata(pdev, vip); + + /* initialize host1x interface */ + INIT_LIST_HEAD(&vip->client.list); + vip->client.ops = &vip_client_ops; + vip->client.dev = &pdev->dev; + + err = host1x_client_register(&vip->client); + if (err) + return dev_err_probe(&pdev->dev, err, "failed to register host1x client\n"); + + pm_runtime_enable(&pdev->dev); + + return 0; +} + +static int tegra_vip_remove(struct platform_device *pdev) +{ + struct tegra_vip *vip = platform_get_drvdata(pdev); + + host1x_client_unregister(&vip->client); + + pm_runtime_disable(&pdev->dev); + + return 0; +} + +#if defined(CONFIG_ARCH_TEGRA_2x_SOC) +extern const struct tegra_vip_soc tegra20_vip_soc; +#endif + +static const struct of_device_id tegra_vip_of_id_table[] = { +#if defined(CONFIG_ARCH_TEGRA_2x_SOC) + { .compatible = "nvidia,tegra20-vip", .data = &tegra20_vip_soc }, +#endif + { } +}; +MODULE_DEVICE_TABLE(of, tegra_vip_of_id_table); + +struct platform_driver tegra_vip_driver = { + .driver = { + .name = "tegra-vip", + .of_match_table = tegra_vip_of_id_table, + }, + .probe = tegra_vip_probe, + .remove = tegra_vip_remove, +}; diff --git a/drivers/staging/media/tegra-video/vip.h b/drivers/staging/media/tegra-video/vip.h new file mode 100644 index 000000000000..32ceaaccbba2 --- /dev/null +++ b/drivers/staging/media/tegra-video/vip.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2023 SKIDATA GmbH + * Author: Luca Ceresoli + */ + +#ifndef __TEGRA_VIP_H__ +#define __TEGRA_VIP_H__ + +#include +#include +#include + +enum { + TEGRA_VIP_PAD_SINK, + TEGRA_VIP_PAD_SOURCE, + TEGRA_VIP_PADS_NUM, +}; + +struct tegra_vip; + +/** + * struct tegra_vip_channel - Tegra VIP (parallel video capture) channel + * + * @subdev: V4L2 subdevice associated with this channel + * @pads: media pads for the subdevice entity + * @of_node: vip device tree node + */ +struct tegra_vip_channel { + struct v4l2_subdev subdev; + struct media_pad pads[TEGRA_VIP_PADS_NUM]; + struct device_node *of_node; +}; + +/** + * struct tegra_vip_ops - Tegra VIP operations + * + * @vip_start_streaming: programs vip hardware to enable streaming. + */ +struct tegra_vip_ops { + int (*vip_start_streaming)(struct tegra_vip_channel *vip_chan); +}; + +/** + * struct tegra_vip_soc - NVIDIA Tegra VIP SoC structure + * + * @ops: vip hardware operations + */ +struct tegra_vip_soc { + const struct tegra_vip_ops *ops; +}; + +/** + * struct tegra_vip - NVIDIA Tegra VIP device structure + * + * @dev: device struct + * @client: host1x_client struct + * @soc: pointer to SoC data structure + * @chan: the VIP channel + */ +struct tegra_vip { + struct device *dev; + struct host1x_client client; + const struct tegra_vip_soc *soc; + struct tegra_vip_channel chan; +}; + +#endif From e5f29bb9c4350dd9692f3b98eb8538dbbebccbaf Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Wed, 23 Nov 2022 10:50:22 +0000 Subject: [PATCH 029/253] media: platform: rzg2l-cru: rzg2l-csi2: Enclose the macro in parentheses Fix the below error reported by checkpatch: ERROR: Macros with complex values should be enclosed in parentheses CSIDPHYSKW0_UTIL_DL1_SKW_ADJ(1) | \ CSIDPHYSKW0_UTIL_DL2_SKW_ADJ(1) | \ CSIDPHYSKW0_UTIL_DL3_SKW_ADJ(1) Signed-off-by: Lad Prabhakar Signed-off-by: Hans Verkuil --- drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c index 30dad7383654..d6489c62b081 100644 --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c @@ -81,10 +81,10 @@ #define CSIDPHYSKW0_UTIL_DL1_SKW_ADJ(x) (((x) & 0x3) << 4) #define CSIDPHYSKW0_UTIL_DL2_SKW_ADJ(x) (((x) & 0x3) << 8) #define CSIDPHYSKW0_UTIL_DL3_SKW_ADJ(x) (((x) & 0x3) << 12) -#define CSIDPHYSKW0_DEFAULT_SKW CSIDPHYSKW0_UTIL_DL0_SKW_ADJ(1) | \ - CSIDPHYSKW0_UTIL_DL1_SKW_ADJ(1) | \ - CSIDPHYSKW0_UTIL_DL2_SKW_ADJ(1) | \ - CSIDPHYSKW0_UTIL_DL3_SKW_ADJ(1) +#define CSIDPHYSKW0_DEFAULT_SKW (CSIDPHYSKW0_UTIL_DL0_SKW_ADJ(1) | \ + CSIDPHYSKW0_UTIL_DL1_SKW_ADJ(1) | \ + CSIDPHYSKW0_UTIL_DL2_SKW_ADJ(1) | \ + CSIDPHYSKW0_UTIL_DL3_SKW_ADJ(1)) #define VSRSTS_RETRIES 20 From b8ed1ceb4a2653a2d5529b3afb79343d77efb3ce Mon Sep 17 00:00:00 2001 From: Deepak R Varma Date: Sat, 11 Feb 2023 16:39:50 +0530 Subject: [PATCH 030/253] media: platform: mtk-mdp3: release node reference before returning The iterator for_each_child_of_node() increments the refcount of the child node it is processing. Release such a reference when the loop needs to break due to an error during its execution. Issue identified using for_each_child.cocci Coccinelle semantic patch. Signed-off-by: Deepak R Varma Signed-off-by: Hans Verkuil --- .../media/platform/mediatek/mdp3/mtk-mdp3-comp.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c index 19a4a085f73a..a605e80c7dc3 100644 --- a/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c +++ b/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c @@ -1035,6 +1035,7 @@ static int mdp_comp_sub_create(struct mdp_dev *mdp) { struct device *dev = &mdp->pdev->dev; struct device_node *node, *parent; + int ret = 0; parent = dev->of_node->parent; @@ -1060,16 +1061,22 @@ static int mdp_comp_sub_create(struct mdp_dev *mdp) dev_err(dev, "Fail to get sub comp. id: type %d alias %d\n", type, alias_id); - return -EINVAL; + ret = -EINVAL; + goto err_free_node; } mdp_comp_alias_id[type]++; comp = mdp_comp_create(mdp, node, id); - if (IS_ERR(comp)) - return PTR_ERR(comp); + if (IS_ERR(comp)) { + ret = PTR_ERR(comp); + goto err_free_node; + } } + return ret; - return 0; +err_free_node: + of_node_put(node); + return ret; } void mdp_comp_destroy(struct mdp_dev *mdp) From fdaca63186f59fc664b346c45b76576624b48e57 Mon Sep 17 00:00:00 2001 From: Daniil Dulov Date: Tue, 14 Mar 2023 10:04:49 -0700 Subject: [PATCH 031/253] media: usb: Check az6007_read() return value If az6007_read() returns error, there is no sence to continue. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: 3af2f4f15a61 ("[media] az6007: Change the az6007 read/write routine parameter") Signed-off-by: Daniil Dulov Signed-off-by: Hans Verkuil --- drivers/media/usb/dvb-usb-v2/az6007.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/dvb-usb-v2/az6007.c b/drivers/media/usb/dvb-usb-v2/az6007.c index 62ee09f28a0b..7524c90f5da6 100644 --- a/drivers/media/usb/dvb-usb-v2/az6007.c +++ b/drivers/media/usb/dvb-usb-v2/az6007.c @@ -202,7 +202,8 @@ static int az6007_rc_query(struct dvb_usb_device *d) unsigned code; enum rc_proto proto; - az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10); + if (az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10) < 0) + return -EIO; if (st->data[1] == 0x44) return 0; From 59cea5a3e519c5c7d26878364d576c12f77d4f78 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Thu, 23 Mar 2023 14:17:04 +0100 Subject: [PATCH 032/253] media: verisilicon: Simplify error handling in tile_buffer_reallocate() Rework allocation errors cases handling to simply it by removing useless tests. Signed-off-by: Benjamin Gaignard Reported-by: Markus Elfring Signed-off-by: Hans Verkuil --- .../media/platform/verisilicon/hantro_hevc.c | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/media/platform/verisilicon/hantro_hevc.c b/drivers/media/platform/verisilicon/hantro_hevc.c index 9383fb7081f6..2c14330bc562 100644 --- a/drivers/media/platform/verisilicon/hantro_hevc.c +++ b/drivers/media/platform/verisilicon/hantro_hevc.c @@ -109,7 +109,7 @@ static int tile_buffer_reallocate(struct hantro_ctx *ctx) &hevc_dec->tile_filter.dma, GFP_KERNEL); if (!hevc_dec->tile_filter.cpu) - goto err_free_tile_buffers; + return -ENOMEM; hevc_dec->tile_filter.size = size; size = (VERT_SAO_RAM_SIZE * height64 * (num_tile_cols - 1) * ctx->bit_depth) / 8; @@ -125,13 +125,20 @@ static int tile_buffer_reallocate(struct hantro_ctx *ctx) &hevc_dec->tile_bsd.dma, GFP_KERNEL); if (!hevc_dec->tile_bsd.cpu) - goto err_free_tile_buffers; + goto err_free_sao_buffers; hevc_dec->tile_bsd.size = size; hevc_dec->num_tile_cols_allocated = num_tile_cols; return 0; +err_free_sao_buffers: + if (hevc_dec->tile_sao.cpu) + dma_free_coherent(vpu->dev, hevc_dec->tile_sao.size, + hevc_dec->tile_sao.cpu, + hevc_dec->tile_sao.dma); + hevc_dec->tile_sao.cpu = NULL; + err_free_tile_buffers: if (hevc_dec->tile_filter.cpu) dma_free_coherent(vpu->dev, hevc_dec->tile_filter.size, @@ -139,18 +146,6 @@ err_free_tile_buffers: hevc_dec->tile_filter.dma); hevc_dec->tile_filter.cpu = NULL; - if (hevc_dec->tile_sao.cpu) - dma_free_coherent(vpu->dev, hevc_dec->tile_sao.size, - hevc_dec->tile_sao.cpu, - hevc_dec->tile_sao.dma); - hevc_dec->tile_sao.cpu = NULL; - - if (hevc_dec->tile_bsd.cpu) - dma_free_coherent(vpu->dev, hevc_dec->tile_bsd.size, - hevc_dec->tile_bsd.cpu, - hevc_dec->tile_bsd.dma); - hevc_dec->tile_bsd.cpu = NULL; - return -ENOMEM; } From 8111496ceb52870157e663d747c71f5520ec9c94 Mon Sep 17 00:00:00 2001 From: Angel Alberto Carretero Date: Wed, 12 Apr 2023 19:51:01 +0200 Subject: [PATCH 033/253] media: imx: utils: Enclose IMX_BUS_FMTS macro in parenthesis Conform to kernel coding style by wrapping macro in parenthesis. Issue found by checkpatch. Signed-off-by: Angel Alberto Carretero Signed-off-by: Hans Verkuil --- drivers/staging/media/imx/imx-media-utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/imx/imx-media-utils.c b/drivers/staging/media/imx/imx-media-utils.c index 2d712eda2c5d..064dc562bc96 100644 --- a/drivers/staging/media/imx/imx-media-utils.c +++ b/drivers/staging/media/imx/imx-media-utils.c @@ -7,7 +7,7 @@ #include #include "imx-media.h" -#define IMX_BUS_FMTS(fmt...) (const u32[]) {fmt, 0} +#define IMX_BUS_FMTS(fmt...) ((const u32[]) {fmt, 0}) /* * List of supported pixel formats for the subdevs. From 668ee1a3a1870381225002c246972419b98e4253 Mon Sep 17 00:00:00 2001 From: Ming Qian Date: Fri, 14 Apr 2023 09:55:42 +0800 Subject: [PATCH 034/253] media: amphion: drop repeated codec data for vc1l format For format V4L2_PIX_FMT_VC1_ANNEX_L, the codec data is replaced with startcode, and then driver drop it, otherwise it may led to decoding error. It's amphion vpu's limitation Driver has dropped the first codec data, but need to drop the repeated codec data too. Fixes: e670f5d672ef ("media: amphion: only insert the first sequence startcode for vc1l format") Signed-off-by: Ming Qian Tested-by: xiahong.bao Signed-off-by: Hans Verkuil --- drivers/media/platform/amphion/vpu_malone.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/amphion/vpu_malone.c b/drivers/media/platform/amphion/vpu_malone.c index ef44bff9fbaf..e96994437429 100644 --- a/drivers/media/platform/amphion/vpu_malone.c +++ b/drivers/media/platform/amphion/vpu_malone.c @@ -1344,6 +1344,8 @@ static int vpu_malone_insert_scode_vc1_l_seq(struct malone_scode_t *scode) int size = 0; u8 rcv_seqhdr[MALONE_VC1_RCV_SEQ_HEADER_LEN]; + if (vpu_vb_is_codecconfig(to_vb2_v4l2_buffer(scode->vb))) + scode->need_data = 0; if (scode->inst->total_input_count) return 0; scode->need_data = 0; From e1d2ccc2cdd6333584aa3d5386dc667d0837c48f Mon Sep 17 00:00:00 2001 From: Ming Qian Date: Fri, 14 Apr 2023 09:55:43 +0800 Subject: [PATCH 035/253] media: amphion: drop repeated codec data for vc1g format For format V4L2_PIX_FMT_VC1_ANNEX_G, the separate codec data is required only once. The repeated codec data may introduce some decoding error. so drop the repeated codec data. It's amphion vpu's limitation Fixes: e670f5d672ef ("media: amphion: only insert the first sequence startcode for vc1l format") Signed-off-by: Ming Qian Tested-by: xiahong.bao Signed-off-by: Hans Verkuil --- drivers/media/platform/amphion/vpu_malone.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/media/platform/amphion/vpu_malone.c b/drivers/media/platform/amphion/vpu_malone.c index e96994437429..c1d6606ad7e5 100644 --- a/drivers/media/platform/amphion/vpu_malone.c +++ b/drivers/media/platform/amphion/vpu_malone.c @@ -1313,6 +1313,15 @@ static int vpu_malone_insert_scode_pic(struct malone_scode_t *scode, u32 codec_i return sizeof(hdr); } +static int vpu_malone_insert_scode_vc1_g_seq(struct malone_scode_t *scode) +{ + if (!scode->inst->total_input_count) + return 0; + if (vpu_vb_is_codecconfig(to_vb2_v4l2_buffer(scode->vb))) + scode->need_data = 0; + return 0; +} + static int vpu_malone_insert_scode_vc1_g_pic(struct malone_scode_t *scode) { struct vb2_v4l2_buffer *vbuf; @@ -1460,6 +1469,7 @@ static const struct malone_scode_handler scode_handlers[] = { }, { .pixelformat = V4L2_PIX_FMT_VC1_ANNEX_G, + .insert_scode_seq = vpu_malone_insert_scode_vc1_g_seq, .insert_scode_pic = vpu_malone_insert_scode_vc1_g_pic, }, { From f0b4a2c037c0ab1affdf0937aee84314ab9c4fee Mon Sep 17 00:00:00 2001 From: Max Staudt Date: Fri, 14 Apr 2023 16:24:19 +0900 Subject: [PATCH 036/253] media: vivid: Extend FPS rates offered by simulated webcam This adds an option for higher frame rates from a simulated webcam. Currently, vivid emulates (amongst other things) a webcam with somewhat limited bandwidth - higher resolutions deliver fewer frames per second. $ yavta --enum-formats -c /dev/video0 Device /dev/video0 opened. Device `vivid' on `platform:vivid-000' (driver 'vivid') supports video, capture, without mplanes. - Available formats: Format 0: YUYV (56595559) Type: Video capture (1) Name: YUYV 4:2:2 Frame size: 320x180 (1/1, 1/2, 1/4, 1/5, 1/10, 2/25, 1/15, 1/25, 1/30, 1/40, 1/50, 1/60) Frame size: 640x360 (1/1, 1/2, 1/4, 1/5, 1/10, 2/25, 1/15, 1/25, 1/30, 1/40) Frame size: 640x480 (1/1, 1/2, 1/4, 1/5, 1/10, 2/25, 1/15, 1/25) Frame size: 1280x720 (1/1, 1/2, 1/4, 1/5, 1/10, 2/25) Frame size: 1920x1080 (1/1, 1/2, 1/4, 1/5) Frame size: 3840x2160 (1/1, 1/2) In some test cases, it is useful to allow for higher frame rates, as configurations such as 720p@30 FPS have become commonplace now. This patch allows: 0- 719p - 120fps 720-1079p - 60fps 1080-2159p - 30fps 2160p - 15fps $ yavta --enum-formats -c /dev/video0 Device /dev/video0 opened. Device `vivid' on `platform:vivid-000' (driver 'vivid') supports video, capture, without mplanes. - Available formats: Format 0: YUYV (56595559) Type: Video capture (1) Name: YUYV 4:2:2 Frame size: 320x180 (1/1, 1/2, 1/4, 1/5, 1/10, 2/25, 1/15, 1/25, 1/30, 1/40, 1/50, 1/60, 1/120) Frame size: 640x360 (1/1, 1/2, 1/4, 1/5, 1/10, 2/25, 1/15, 1/25, 1/30, 1/40, 1/50, 1/60, 1/120) Frame size: 640x480 (1/1, 1/2, 1/4, 1/5, 1/10, 2/25, 1/15, 1/25, 1/30, 1/40, 1/50, 1/60, 1/120) Frame size: 1280x720 (1/1, 1/2, 1/4, 1/5, 1/10, 2/25, 1/15, 1/25, 1/30, 1/40, 1/50, 1/60) Frame size: 1920x1080 (1/1, 1/2, 1/4, 1/5, 1/10, 2/25, 1/15, 1/25, 1/30) Frame size: 3840x2160 (1/1, 1/2, 1/4, 1/5, 1/10, 2/25, 1/15) Passes: v4l2-compliance 1.25.0-5039 from v4l-utils git ccc08732823f Signed-off-by: Max Staudt Reviewed-by: Ricardo Ribalda Signed-off-by: Hans Verkuil [hverkuil: unsigned -> unsigned int] --- .../media/test-drivers/vivid/vivid-vid-cap.c | 49 +++++++++++++------ 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/drivers/media/test-drivers/vivid/vivid-vid-cap.c b/drivers/media/test-drivers/vivid/vivid-vid-cap.c index 801286dc1448..3a06df35a2d7 100644 --- a/drivers/media/test-drivers/vivid/vivid-vid-cap.c +++ b/drivers/media/test-drivers/vivid/vivid-vid-cap.c @@ -21,13 +21,8 @@ #include "vivid-kthread-cap.h" #include "vivid-vid-cap.h" -/* The number of discrete webcam framesizes */ -#define VIVID_WEBCAM_SIZES 6 -/* The number of discrete webcam frameintervals */ -#define VIVID_WEBCAM_IVALS (VIVID_WEBCAM_SIZES * 2) - /* Sizes must be in increasing order */ -static const struct v4l2_frmsize_discrete webcam_sizes[VIVID_WEBCAM_SIZES] = { +static const struct v4l2_frmsize_discrete webcam_sizes[] = { { 320, 180 }, { 640, 360 }, { 640, 480 }, @@ -40,21 +35,43 @@ static const struct v4l2_frmsize_discrete webcam_sizes[VIVID_WEBCAM_SIZES] = { * Intervals must be in increasing order and there must be twice as many * elements in this array as there are in webcam_sizes. */ -static const struct v4l2_fract webcam_intervals[VIVID_WEBCAM_IVALS] = { +static const struct v4l2_fract webcam_intervals[] = { { 1, 1 }, { 1, 2 }, { 1, 4 }, { 1, 5 }, { 1, 10 }, { 2, 25 }, - { 1, 15 }, + { 1, 15 }, /* 7 - maximum for 2160p */ { 1, 25 }, - { 1, 30 }, + { 1, 30 }, /* 9 - maximum for 1080p */ { 1, 40 }, { 1, 50 }, - { 1, 60 }, + { 1, 60 }, /* 12 - maximum for 720p */ + { 1, 120 }, }; +/* Limit maximum FPS rates for high resolutions */ +#define IVAL_COUNT_720P 12 /* 720p and up is limited to 60 fps */ +#define IVAL_COUNT_1080P 9 /* 1080p and up is limited to 30 fps */ +#define IVAL_COUNT_2160P 7 /* 2160p and up is limited to 15 fps */ + +static inline unsigned int webcam_ival_count(const struct vivid_dev *dev, + unsigned int frmsize_idx) +{ + if (webcam_sizes[frmsize_idx].height >= 2160) + return IVAL_COUNT_2160P; + + if (webcam_sizes[frmsize_idx].height >= 1080) + return IVAL_COUNT_1080P; + + if (webcam_sizes[frmsize_idx].height >= 720) + return IVAL_COUNT_720P; + + /* For low resolutions, allow all FPS rates */ + return ARRAY_SIZE(webcam_intervals); +} + static int vid_cap_queue_setup(struct vb2_queue *vq, unsigned *nbuffers, unsigned *nplanes, unsigned sizes[], struct device *alloc_devs[]) @@ -560,7 +577,7 @@ int vivid_try_fmt_vid_cap(struct file *file, void *priv, if (vivid_is_webcam(dev)) { const struct v4l2_frmsize_discrete *sz = v4l2_find_nearest_size(webcam_sizes, - VIVID_WEBCAM_SIZES, width, + ARRAY_SIZE(webcam_sizes), width, height, mp->width, mp->height); w = sz->width; @@ -736,14 +753,16 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv, compose->height /= factor; } } else if (vivid_is_webcam(dev)) { + unsigned int ival_sz = webcam_ival_count(dev, dev->webcam_size_idx); + /* Guaranteed to be a match */ for (i = 0; i < ARRAY_SIZE(webcam_sizes); i++) if (webcam_sizes[i].width == mp->width && webcam_sizes[i].height == mp->height) break; dev->webcam_size_idx = i; - if (dev->webcam_ival_idx >= 2 * (VIVID_WEBCAM_SIZES - i)) - dev->webcam_ival_idx = 2 * (VIVID_WEBCAM_SIZES - i) - 1; + if (dev->webcam_ival_idx >= ival_sz) + dev->webcam_ival_idx = ival_sz - 1; vivid_update_format_cap(dev, false); } else { struct v4l2_rect r = { 0, 0, mp->width, mp->height }; @@ -1636,7 +1655,7 @@ int vidioc_enum_frameintervals(struct file *file, void *priv, break; if (i == ARRAY_SIZE(webcam_sizes)) return -EINVAL; - if (fival->index >= 2 * (VIVID_WEBCAM_SIZES - i)) + if (fival->index >= webcam_ival_count(dev, i)) return -EINVAL; fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; fival->discrete = webcam_intervals[fival->index]; @@ -1663,7 +1682,7 @@ int vivid_vid_cap_s_parm(struct file *file, void *priv, struct v4l2_streamparm *parm) { struct vivid_dev *dev = video_drvdata(file); - unsigned ival_sz = 2 * (VIVID_WEBCAM_SIZES - dev->webcam_size_idx); + unsigned int ival_sz = webcam_ival_count(dev, dev->webcam_size_idx); struct v4l2_fract tpf; unsigned i; From 56b5c3e67b0f9af3f45cf393be048ee8d8a92694 Mon Sep 17 00:00:00 2001 From: Yunfei Dong Date: Mon, 17 Apr 2023 16:17:40 +0800 Subject: [PATCH 037/253] media: v4l2-mem2mem: add lock to protect parameter num_rdy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Getting below error when using KCSAN to check the driver. Adding lock to protect parameter num_rdy when getting the value with function: v4l2_m2m_num_src_bufs_ready/v4l2_m2m_num_dst_bufs_ready. kworker/u16:3: [name:report&]BUG: KCSAN: data-race in v4l2_m2m_buf_queue kworker/u16:3: [name:report&] kworker/u16:3: [name:report&]read-write to 0xffffff8105f35b94 of 1 bytes by task 20865 on cpu 7: kworker/u16:3:  v4l2_m2m_buf_queue+0xd8/0x10c Signed-off-by: Pina Chen Signed-off-by: Yunfei Dong Signed-off-by: Hans Verkuil --- include/media/v4l2-mem2mem.h | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h index bb9de6a899e0..d6c8eb2b5201 100644 --- a/include/media/v4l2-mem2mem.h +++ b/include/media/v4l2-mem2mem.h @@ -593,7 +593,14 @@ void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, static inline unsigned int v4l2_m2m_num_src_bufs_ready(struct v4l2_m2m_ctx *m2m_ctx) { - return m2m_ctx->out_q_ctx.num_rdy; + unsigned int num_buf_rdy; + unsigned long flags; + + spin_lock_irqsave(&m2m_ctx->out_q_ctx.rdy_spinlock, flags); + num_buf_rdy = m2m_ctx->out_q_ctx.num_rdy; + spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags); + + return num_buf_rdy; } /** @@ -605,7 +612,14 @@ unsigned int v4l2_m2m_num_src_bufs_ready(struct v4l2_m2m_ctx *m2m_ctx) static inline unsigned int v4l2_m2m_num_dst_bufs_ready(struct v4l2_m2m_ctx *m2m_ctx) { - return m2m_ctx->cap_q_ctx.num_rdy; + unsigned int num_buf_rdy; + unsigned long flags; + + spin_lock_irqsave(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags); + num_buf_rdy = m2m_ctx->cap_q_ctx.num_rdy; + spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags); + + return num_buf_rdy; } /** From 4a35700018065a3f40b9d5dd84829f7086594c9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= Date: Tue, 18 Apr 2023 17:50:52 -0400 Subject: [PATCH 038/253] Revert "media: mediatek: vcodec: Fix bitstream crop information error" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit cd61f3c6794bea2b717fe6083ca2ad189db75418. That commit's purpose was to prevent the padding from being decoded when userspace didn't set a selection, relying on the default one. However, as described in the Step 6 of the Initialization procedure for the Memory-to-Memory Stateful Video Encoder Interface [1]: "Set the visible resolution for the stream metadata via VIDIOC_S_SELECTION() on the OUTPUT queue if it is desired to be different than the full OUTPUT resolution." And from the Note: "To avoid encoding the padding, the client needs to explicitly configure this selection target" Hence the behavior in the original commit doesn't follow the interface and needs to be reverted. This fixes the following v4l2-compliance failure observed on mt8192-asurada-spherion: fail: v4l2-test-formats.cpp(924): sel.r.width != fmt.g_width() test VIDIOC_S_FMT: FAIL [1] https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/dev-encoder.html#initialization Signed-off-by: Nícolas F. R. A. Prado Tested-by: AngeloGioacchino Del Regno Signed-off-by: Hans Verkuil --- drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c index db65e77bd373..9ff439a50f53 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c @@ -505,13 +505,13 @@ static int vidioc_venc_s_fmt_out(struct file *file, void *priv, f->fmt.pix.pixelformat = fmt->fourcc; } - q_data->visible_width = f->fmt.pix_mp.width; - q_data->visible_height = f->fmt.pix_mp.height; - q_data->fmt = fmt; - ret = vidioc_try_fmt_out(ctx, f, q_data->fmt); + ret = vidioc_try_fmt_out(ctx, f, fmt); if (ret) return ret; + q_data->fmt = fmt; + q_data->visible_width = f->fmt.pix_mp.width; + q_data->visible_height = f->fmt.pix_mp.height; q_data->coded_width = f->fmt.pix_mp.width; q_data->coded_height = f->fmt.pix_mp.height; From b2aa8ac6f97e26d788948fb60dcc5625c9633f4e Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Tue, 25 Apr 2023 15:25:46 +0200 Subject: [PATCH 039/253] media: common: saa7146: Avoid a leak in vmalloc_to_sg() Commit in Fixes turned a BUG() into a "normal" memory allocation failure. While at it, it introduced a memory leak. So fix it. Also update the comment on top of the function to reflect what has been change by the commit in Fixes. Fixes: 40e986c99624 ("media: common: saa7146: replace BUG_ON by WARN_ON") Signed-off-by: Christophe JAILLET Signed-off-by: Hans Verkuil --- drivers/media/common/saa7146/saa7146_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/common/saa7146/saa7146_core.c b/drivers/media/common/saa7146/saa7146_core.c index bcb957883044..27c53eed8fe3 100644 --- a/drivers/media/common/saa7146/saa7146_core.c +++ b/drivers/media/common/saa7146/saa7146_core.c @@ -133,8 +133,8 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop) ****************************************************************************/ /* this is videobuf_vmalloc_to_sg() from videobuf-dma-sg.c - make sure virt has been allocated with vmalloc_32(), otherwise the BUG() - may be triggered on highmem machines */ + make sure virt has been allocated with vmalloc_32(), otherwise return NULL + on highmem machines */ static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages) { struct scatterlist *sglist; @@ -150,7 +150,7 @@ static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages) if (NULL == pg) goto err; if (WARN_ON(PageHighMem(pg))) - return NULL; + goto err; sg_set_page(&sglist[i], pg, PAGE_SIZE, 0); } return sglist; From 8217af0984f962e64a756488d5e33c0cf57b327c Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 1 May 2023 11:39:14 +0100 Subject: [PATCH 040/253] media: MAINTAINERS: Add myself as Venus reviewer I'd like to be looped in on changes to venus so that I can help ensure no obvious regressions creep in. I'm happy to run some simple tests for venus on the hardware I have access to - db410c - db820 - rb3 - rb5 and one of rb1 / rb2 in the future when they are delivered. Signed-off-by: Bryan O'Donoghue Reviewed-by: Javier Martinez Canillas Signed-off-by: Hans Verkuil --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 3d44daf1ac15..a2878f5f59f3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17535,6 +17535,7 @@ F: drivers/thermal/qcom/ QUALCOMM VENUS VIDEO ACCELERATOR DRIVER M: Stanimir Varbanov M: Vikash Garodia +R: Bryan O'Donoghue L: linux-media@vger.kernel.org L: linux-arm-msm@vger.kernel.org S: Maintained From 3f6375a2d1956739c6c8ffa3a862c9278d346940 Mon Sep 17 00:00:00 2001 From: Daniel Lundberg Pedersen Date: Mon, 1 May 2023 16:57:06 +0200 Subject: [PATCH 041/253] media: videodev2.h: Fix p_s32 and p_s64 pointer types Use the intended pointer types for p_s32 and p_64 in the union of the struct v4l2_ext_control. Fixes: e77eb66342c7 ("videodev2.h: add p_s32 and p_s64 pointers") Signed-off-by: Daniel Lundberg Pedersen Signed-off-by: Hans Verkuil --- include/uapi/linux/videodev2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index aee75eb9e686..9e7cf1d36945 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -1807,8 +1807,8 @@ struct v4l2_ext_control { __u8 __user *p_u8; __u16 __user *p_u16; __u32 __user *p_u32; - __u32 __user *p_s32; - __u32 __user *p_s64; + __s32 __user *p_s32; + __s64 __user *p_s64; struct v4l2_area __user *p_area; struct v4l2_ctrl_h264_sps __user *p_h264_sps; struct v4l2_ctrl_h264_pps *p_h264_pps; From f93ff8b7dd0c713feccfe7215651febb6de5bf68 Mon Sep 17 00:00:00 2001 From: Daniel Lundberg Pedersen Date: Mon, 1 May 2023 16:57:07 +0200 Subject: [PATCH 042/253] media: docs: vidioc-g-ext-ctrls.rst: Update p_s32 and p_s64 types The pointer types of p_s32 and p_s64 in v4l2_ext_control has been updated, match the change in documentation. Signed-off-by: Daniel Lundberg Pedersen Signed-off-by: Hans Verkuil --- Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst index 5292d5e1a91f..6d85ec6a19b4 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst @@ -185,12 +185,12 @@ still cause this situation. - ``p_u32`` - A pointer to a matrix control of unsigned 32-bit values. Valid if this control is of type ``V4L2_CTRL_TYPE_U32``. - * - __u32 * + * - __s32 * - ``p_s32`` - A pointer to a matrix control of signed 32-bit values. Valid if this control is of type ``V4L2_CTRL_TYPE_INTEGER`` and ``V4L2_CTRL_FLAG_HAS_PAYLOAD`` is set. - * - __u32 * + * - __s64 * - ``p_s64`` - A pointer to a matrix control of signed 64-bit values. Valid if this control is of type ``V4L2_CTRL_TYPE_INTEGER64`` and From e75d25a0c9bea52d50894e3d72c9ab486f165ac9 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Tue, 2 May 2023 16:09:02 +0200 Subject: [PATCH 043/253] media: staging: media: imx6-mipi-csi2: Add log_status core callback This prints all register values. Signed-off-by: Alexander Stein Signed-off-by: Hans Verkuil --- drivers/staging/media/imx/imx6-mipi-csi2.c | 45 ++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c index c07994ea6e96..ab565b4e29ec 100644 --- a/drivers/staging/media/imx/imx6-mipi-csi2.c +++ b/drivers/staging/media/imx/imx6-mipi-csi2.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -564,6 +565,49 @@ static int csi2_registered(struct v4l2_subdev *sd) V4L2_FIELD_NONE, NULL); } +/* --------------- CORE OPS --------------- */ + +static int csi2_log_status(struct v4l2_subdev *sd) +{ + struct csi2_dev *csi2 = sd_to_dev(sd); + + v4l2_info(sd, "-----MIPI CSI status-----\n"); + v4l2_info(sd, "VERSION: 0x%x\n", + readl(csi2->base + CSI2_VERSION)); + v4l2_info(sd, "N_LANES: 0x%x\n", + readl(csi2->base + CSI2_N_LANES)); + v4l2_info(sd, "PHY_SHUTDOWNZ: 0x%x\n", + readl(csi2->base + CSI2_PHY_SHUTDOWNZ)); + v4l2_info(sd, "DPHY_RSTZ: 0x%x\n", + readl(csi2->base + CSI2_DPHY_RSTZ)); + v4l2_info(sd, "RESETN: 0x%x\n", + readl(csi2->base + CSI2_RESETN)); + v4l2_info(sd, "PHY_STATE: 0x%x\n", + readl(csi2->base + CSI2_PHY_STATE)); + v4l2_info(sd, "DATA_IDS_1: 0x%x\n", + readl(csi2->base + CSI2_DATA_IDS_1)); + v4l2_info(sd, "DATA_IDS_2: 0x%x\n", + readl(csi2->base + CSI2_DATA_IDS_2)); + v4l2_info(sd, "ERR1: 0x%x\n", + readl(csi2->base + CSI2_ERR1)); + v4l2_info(sd, "ERR2: 0x%x\n", + readl(csi2->base + CSI2_ERR2)); + v4l2_info(sd, "MSK1: 0x%x\n", + readl(csi2->base + CSI2_MSK1)); + v4l2_info(sd, "MSK2: 0x%x\n", + readl(csi2->base + CSI2_MSK2)); + v4l2_info(sd, "PHY_TST_CTRL0: 0x%x\n", + readl(csi2->base + CSI2_PHY_TST_CTRL0)); + v4l2_info(sd, "PHY_TST_CTRL1: 0x%x\n", + readl(csi2->base + CSI2_PHY_TST_CTRL1)); + + return 0; +} + +static const struct v4l2_subdev_core_ops csi2_core_ops = { + .log_status = csi2_log_status, +}; + static const struct media_entity_operations csi2_entity_ops = { .link_setup = csi2_link_setup, .link_validate = v4l2_subdev_link_validate, @@ -581,6 +625,7 @@ static const struct v4l2_subdev_pad_ops csi2_pad_ops = { }; static const struct v4l2_subdev_ops csi2_subdev_ops = { + .core = &csi2_core_ops, .video = &csi2_video_ops, .pad = &csi2_pad_ops, }; From 076b6289b2c12d76fab248659896682830fa7766 Mon Sep 17 00:00:00 2001 From: Ming Qian Date: Sat, 6 May 2023 16:47:35 +0800 Subject: [PATCH 044/253] media: amphion: initiate a drain of the capture queue in dynamic resolution change The last buffer from before the change must be marked with the V4L2_BUF_FLAG_LAST flag, similarly to the Drain sequence above. initiate a drain of the capture queue in dynamic resolution change Fixes: 6de8d628df6e ("media: amphion: add v4l2 m2m vpu decoder stateful driver") Signed-off-by: Ming Qian Signed-off-by: Hans Verkuil --- drivers/media/platform/amphion/vdec.c | 7 ++++--- drivers/media/platform/amphion/venc.c | 4 ++-- drivers/media/platform/amphion/vpu_v4l2.c | 5 +++-- drivers/media/platform/amphion/vpu_v4l2.h | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/amphion/vdec.c b/drivers/media/platform/amphion/vdec.c index 3fa1a74a2e20..6515f3cdb7a7 100644 --- a/drivers/media/platform/amphion/vdec.c +++ b/drivers/media/platform/amphion/vdec.c @@ -279,6 +279,7 @@ static void vdec_handle_resolution_change(struct vpu_inst *inst) vdec->source_change--; vpu_notify_source_change(inst); + vpu_set_last_buffer_dequeued(inst, false); } static int vdec_update_state(struct vpu_inst *inst, enum vpu_codec_state state, u32 force) @@ -314,7 +315,7 @@ static void vdec_set_last_buffer_dequeued(struct vpu_inst *inst) return; if (vdec->eos_received) { - if (!vpu_set_last_buffer_dequeued(inst)) { + if (!vpu_set_last_buffer_dequeued(inst, true)) { vdec->eos_received--; vdec_update_state(inst, VPU_CODEC_STATE_DRAIN, 0); } @@ -569,7 +570,7 @@ static int vdec_drain(struct vpu_inst *inst) return 0; if (!vdec->params.frame_count) { - vpu_set_last_buffer_dequeued(inst); + vpu_set_last_buffer_dequeued(inst, true); return 0; } @@ -608,7 +609,7 @@ static int vdec_cmd_stop(struct vpu_inst *inst) vpu_trace(inst->dev, "[%d]\n", inst->id); if (inst->state == VPU_CODEC_STATE_DEINIT) { - vpu_set_last_buffer_dequeued(inst); + vpu_set_last_buffer_dequeued(inst, true); } else { vdec->drain = 1; vdec_drain(inst); diff --git a/drivers/media/platform/amphion/venc.c b/drivers/media/platform/amphion/venc.c index e6e8fe45fc7c..58480e2755ec 100644 --- a/drivers/media/platform/amphion/venc.c +++ b/drivers/media/platform/amphion/venc.c @@ -458,7 +458,7 @@ static int venc_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd vpu_inst_lock(inst); if (cmd->cmd == V4L2_ENC_CMD_STOP) { if (inst->state == VPU_CODEC_STATE_DEINIT) - vpu_set_last_buffer_dequeued(inst); + vpu_set_last_buffer_dequeued(inst, true); else venc_request_eos(inst); } @@ -878,7 +878,7 @@ static void venc_set_last_buffer_dequeued(struct vpu_inst *inst) struct venc_t *venc = inst->priv; if (venc->stopped && list_empty(&venc->frames)) - vpu_set_last_buffer_dequeued(inst); + vpu_set_last_buffer_dequeued(inst, true); } static void venc_stop_done(struct vpu_inst *inst) diff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 6773b885597c..810e93d2c954 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -100,7 +100,7 @@ int vpu_notify_source_change(struct vpu_inst *inst) return 0; } -int vpu_set_last_buffer_dequeued(struct vpu_inst *inst) +int vpu_set_last_buffer_dequeued(struct vpu_inst *inst, bool eos) { struct vb2_queue *q; @@ -116,7 +116,8 @@ int vpu_set_last_buffer_dequeued(struct vpu_inst *inst) vpu_trace(inst->dev, "last buffer dequeued\n"); q->last_buffer_dequeued = true; wake_up(&q->done_wq); - vpu_notify_eos(inst); + if (eos) + vpu_notify_eos(inst); return 0; } diff --git a/drivers/media/platform/amphion/vpu_v4l2.h b/drivers/media/platform/amphion/vpu_v4l2.h index ef5de6b66e47..60f43056a7a2 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.h +++ b/drivers/media/platform/amphion/vpu_v4l2.h @@ -27,7 +27,7 @@ struct vb2_v4l2_buffer *vpu_find_buf_by_idx(struct vpu_inst *inst, u32 type, u32 void vpu_v4l2_set_error(struct vpu_inst *inst); int vpu_notify_eos(struct vpu_inst *inst); int vpu_notify_source_change(struct vpu_inst *inst); -int vpu_set_last_buffer_dequeued(struct vpu_inst *inst); +int vpu_set_last_buffer_dequeued(struct vpu_inst *inst, bool eos); void vpu_vb2_buffers_return(struct vpu_inst *inst, unsigned int type, enum vb2_buffer_state state); int vpu_get_num_buffers(struct vpu_inst *inst, u32 type); bool vpu_is_source_empty(struct vpu_inst *inst); From 7f7ac101236bd020681f122089b611eca8e507ac Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Mon, 8 May 2023 06:13:39 +0200 Subject: [PATCH 045/253] media: stk1160: Simplify the build config definition Commit dfb9f94e8e5e ("[media] stk1160: Build as a module if SND is m and audio support is selected") had to introduce some complex config dependency handling to compile for all combinations of configs VIDEO_STK1160 and VIDEO_STK1160_AC97. Later, commit e36e6b5f26c1 ("[media] stk1160: Remove stk1160-mixer and setup internal AC97 codec automatically") removes the config VIDEO_STK1160_AC97, which renders the previous dependency handling unnecessary. The commit already simplified the dependency of the remaining config VIDEO_STK1160, but it misses the opportunity to merge VIDEO_STK1160 and VIDEO_STK1160_COMMON. So, do that now and simplify the build config definition of the STK1160 USB video capture support. Signed-off-by: Lukas Bulwahn Signed-off-by: Hans Verkuil --- drivers/media/usb/stk1160/Kconfig | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/media/usb/stk1160/Kconfig b/drivers/media/usb/stk1160/Kconfig index 4f50fb7db7b9..bf7c16baa9f8 100644 --- a/drivers/media/usb/stk1160/Kconfig +++ b/drivers/media/usb/stk1160/Kconfig @@ -1,8 +1,9 @@ # SPDX-License-Identifier: GPL-2.0-only -config VIDEO_STK1160_COMMON +config VIDEO_STK1160 tristate "STK1160 USB video capture support" depends on VIDEO_DEV && I2C - + select VIDEOBUF2_VMALLOC + select VIDEO_SAA711X help This is a video4linux driver for STK1160 based video capture devices. @@ -12,10 +13,3 @@ config VIDEO_STK1160_COMMON This driver only provides support for video capture. For audio capture, you need to select the snd-usb-audio driver (i.e. CONFIG_SND_USB_AUDIO). - -config VIDEO_STK1160 - tristate - depends on VIDEO_STK1160_COMMON - default y - select VIDEOBUF2_VMALLOC - select VIDEO_SAA711X From eff540df5f80667eadf7a4a117b8a7655a47c7ea Mon Sep 17 00:00:00 2001 From: Su Hui Date: Tue, 9 May 2023 15:40:01 +0800 Subject: [PATCH 046/253] media: usb: remove unnecessary (void*) conversions No need cast (void*) to (struct dvb_usb_device *) or (struct filter_info *). Signed-off-by: Su Hui Signed-off-by: Hans Verkuil [hverkuil: drop the obsolete dvb-usb/az6027.c and dvb-usb/pctv452e.c changes] --- drivers/media/usb/dvb-usb-v2/az6007.c | 16 ++++++++-------- drivers/media/usb/ttusb-dec/ttusb_dec.c | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/az6007.c b/drivers/media/usb/dvb-usb-v2/az6007.c index 7524c90f5da6..2dcbb49d66da 100644 --- a/drivers/media/usb/dvb-usb-v2/az6007.c +++ b/drivers/media/usb/dvb-usb-v2/az6007.c @@ -249,7 +249,7 @@ static int az6007_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct dvb_usb_device *d = ca->data; struct az6007_device_state *state = d_to_priv(d); int ret; @@ -291,7 +291,7 @@ static int az6007_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, int address, u8 value) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct dvb_usb_device *d = ca->data; struct az6007_device_state *state = d_to_priv(d); int ret; @@ -322,7 +322,7 @@ static int az6007_ci_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct dvb_usb_device *d = ca->data; struct az6007_device_state *state = d_to_priv(d); int ret; @@ -368,7 +368,7 @@ static int az6007_ci_write_cam_control(struct dvb_ca_en50221 *ca, u8 address, u8 value) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct dvb_usb_device *d = ca->data; struct az6007_device_state *state = d_to_priv(d); int ret; @@ -399,7 +399,7 @@ failed: static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct dvb_usb_device *d = ca->data; int ret; u8 req; @@ -430,7 +430,7 @@ static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot) static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct dvb_usb_device *d = ca->data; struct az6007_device_state *state = d_to_priv(d); int ret, i; @@ -486,7 +486,7 @@ static int az6007_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) static int az6007_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct dvb_usb_device *d = ca->data; struct az6007_device_state *state = d_to_priv(d); int ret; @@ -515,7 +515,7 @@ failed: static int az6007_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; + struct dvb_usb_device *d = ca->data; struct az6007_device_state *state = d_to_priv(d); int ret; u8 req; diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c index c4474d4c44e2..79faa2560613 100644 --- a/drivers/media/usb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c @@ -1128,7 +1128,7 @@ static int ttusb_dec_stop_sec_feed(struct dvb_demux_feed *dvbdmxfeed) { struct ttusb_dec *dec = dvbdmxfeed->demux->priv; u8 b0[] = { 0x00, 0x00 }; - struct filter_info *finfo = (struct filter_info *)dvbdmxfeed->priv; + struct filter_info *finfo = dvbdmxfeed->priv; unsigned long flags; b0[1] = finfo->stream_id; From afa8516c86fe153e8eb7daba41d6f46c64783b20 Mon Sep 17 00:00:00 2001 From: Su Hui Date: Wed, 10 May 2023 09:29:44 +0800 Subject: [PATCH 047/253] media: platform: Remove unnecessary (void*) conversions No need cast (void*) to (struct stdemux *),(struct hva_h264_ctx *) or (struct hva_h264_task *). Signed-off-by: Su Hui Signed-off-by: Hans Verkuil --- drivers/media/platform/st/sti/hva/hva-h264.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/st/sti/hva/hva-h264.c b/drivers/media/platform/st/sti/hva/hva-h264.c index 98cb00d2d868..196e631fa4b8 100644 --- a/drivers/media/platform/st/sti/hva/hva-h264.c +++ b/drivers/media/platform/st/sti/hva/hva-h264.c @@ -591,7 +591,7 @@ static int hva_h264_prepare_task(struct hva_ctx *pctx, { struct hva_dev *hva = ctx_to_hdev(pctx); struct device *dev = ctx_to_dev(pctx); - struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv; + struct hva_h264_ctx *ctx = pctx->priv; struct hva_buffer *seq_info = ctx->seq_info; struct hva_buffer *fwd_ref_frame = ctx->ref_frame; struct hva_buffer *loc_rec_frame = ctx->rec_frame; @@ -984,7 +984,7 @@ err: static int hva_h264_close(struct hva_ctx *pctx) { - struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv; + struct hva_h264_ctx *ctx = pctx->priv; struct device *dev = ctx_to_dev(pctx); if (ctx->seq_info) @@ -1007,8 +1007,8 @@ static int hva_h264_close(struct hva_ctx *pctx) static int hva_h264_encode(struct hva_ctx *pctx, struct hva_frame *frame, struct hva_stream *stream) { - struct hva_h264_ctx *ctx = (struct hva_h264_ctx *)pctx->priv; - struct hva_h264_task *task = (struct hva_h264_task *)ctx->task->vaddr; + struct hva_h264_ctx *ctx = pctx->priv; + struct hva_h264_task *task = ctx->task->vaddr; u32 stuffing_bytes = 0; int ret = 0; From 17ae8136549f512e3fbc78cb78402df6a211cfb5 Mon Sep 17 00:00:00 2001 From: Su Hui Date: Fri, 12 May 2023 09:41:59 +0800 Subject: [PATCH 048/253] media: pci: remove unnecessary (void*) conversions No need cast (void*) to (struct dst_state *), (struct cx18_stream *), (struct saa7164_port *) or (struct budget *). Signed-off-by: Su Hui Signed-off-by: Hans Verkuil --- drivers/media/pci/bt8xx/dst_ca.c | 2 +- drivers/media/pci/cx18/cx18-dvb.c | 4 ++-- drivers/media/pci/saa7164/saa7164-dvb.c | 4 ++-- drivers/media/pci/ttpci/budget-core.c | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/media/pci/bt8xx/dst_ca.c b/drivers/media/pci/bt8xx/dst_ca.c index 85fcdc59f0d1..d234a0f404d6 100644 --- a/drivers/media/pci/bt8xx/dst_ca.c +++ b/drivers/media/pci/bt8xx/dst_ca.c @@ -534,7 +534,7 @@ static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioct mutex_lock(&dst_ca_mutex); dvbdev = file->private_data; - state = (struct dst_state *)dvbdev->priv; + state = dvbdev->priv; p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL); p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL); p_ca_caps = kmalloc(sizeof (struct ca_caps), GFP_KERNEL); diff --git a/drivers/media/pci/cx18/cx18-dvb.c b/drivers/media/pci/cx18/cx18-dvb.c index 33e5a5b5fab4..cf82360a503d 100644 --- a/drivers/media/pci/cx18/cx18-dvb.c +++ b/drivers/media/pci/cx18/cx18-dvb.c @@ -234,7 +234,7 @@ static int dvb_register(struct cx18_stream *stream); static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - struct cx18_stream *stream = (struct cx18_stream *) demux->priv; + struct cx18_stream *stream = demux->priv; struct cx18 *cx; int ret; u32 v; @@ -305,7 +305,7 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - struct cx18_stream *stream = (struct cx18_stream *)demux->priv; + struct cx18_stream *stream = demux->priv; struct cx18 *cx; int ret = -EINVAL; diff --git a/drivers/media/pci/saa7164/saa7164-dvb.c b/drivers/media/pci/saa7164/saa7164-dvb.c index 24421c116b0b..3eb749db1ca7 100644 --- a/drivers/media/pci/saa7164/saa7164-dvb.c +++ b/drivers/media/pci/saa7164/saa7164-dvb.c @@ -280,7 +280,7 @@ out: static int saa7164_dvb_start_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - struct saa7164_port *port = (struct saa7164_port *) demux->priv; + struct saa7164_port *port = demux->priv; struct saa7164_dvb *dvb = &port->dvb; struct saa7164_dev *dev = port->dev; int ret = 0; @@ -307,7 +307,7 @@ static int saa7164_dvb_start_feed(struct dvb_demux_feed *feed) static int saa7164_dvb_stop_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - struct saa7164_port *port = (struct saa7164_port *) demux->priv; + struct saa7164_port *port = demux->priv; struct saa7164_dvb *dvb = &port->dvb; struct saa7164_dev *dev = port->dev; int ret = 0; diff --git a/drivers/media/pci/ttpci/budget-core.c b/drivers/media/pci/ttpci/budget-core.c index 5d5796f24469..710595987522 100644 --- a/drivers/media/pci/ttpci/budget-core.c +++ b/drivers/media/pci/ttpci/budget-core.c @@ -308,7 +308,7 @@ int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr, static int budget_start_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - struct budget *budget = (struct budget *) demux->priv; + struct budget *budget = demux->priv; int status = 0; dprintk(2, "budget: %p\n", budget); @@ -327,7 +327,7 @@ static int budget_start_feed(struct dvb_demux_feed *feed) static int budget_stop_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - struct budget *budget = (struct budget *) demux->priv; + struct budget *budget = demux->priv; int status = 0; dprintk(2, "budget: %p\n", budget); From c82d4d9353b02bf531ff43654863e7497a1caebe Mon Sep 17 00:00:00 2001 From: Atin Bainada Date: Thu, 18 May 2023 09:17:47 +0000 Subject: [PATCH 049/253] media: av7110: Remove unnecessary (void*) conversions No need cast (void*) to (struct dvb_demux_feed *) or (struct av7110 *). Signed-off-by: Atin Bainada Signed-off-by: Hans Verkuil --- drivers/staging/media/av7110/av7110_av.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/av7110/av7110_av.c b/drivers/staging/media/av7110/av7110_av.c index a5c5bebad306..00dd6a7fea64 100644 --- a/drivers/staging/media/av7110/av7110_av.c +++ b/drivers/staging/media/av7110/av7110_av.c @@ -78,7 +78,7 @@ static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, s int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len) { - struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) p2t->priv; + struct dvb_demux_feed *dvbdmxfeed = p2t->priv; if (!(dvbdmxfeed->ts_type & TS_PACKET)) return 0; @@ -837,7 +837,7 @@ static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, s int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t len) { struct dvb_demux *demux = feed->demux; - struct av7110 *av7110 = (struct av7110 *) demux->priv; + struct av7110 *av7110 = demux->priv; dprintk(2, "av7110:%p, \n", av7110); From 26ae58f65e64fa7ba61d64bae752e59e08380c6a Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 18 May 2023 15:36:49 +0200 Subject: [PATCH 050/253] media: videodev2.h: Fix struct v4l2_input tuner index comment VIDIOC_ENUMINPUT documentation describes the tuner field of struct v4l2_input as index: Documentation/userspace-api/media/v4l/vidioc-enuminput.rst " * - __u32 - ``tuner`` - Capture devices can have zero or more tuners (RF demodulators). When the ``type`` is set to ``V4L2_INPUT_TYPE_TUNER`` this is an RF connector and this field identifies the tuner. It corresponds to struct :c:type:`v4l2_tuner` field ``index``. For details on tuners see :ref:`tuner`. " Drivers I could find also use the 'tuner' field as an index, e.g.: drivers/media/pci/bt8xx/bttv-driver.c bttv_enum_input() drivers/media/usb/go7007/go7007-v4l2.c vidioc_enum_input() However, the UAPI comment claims this field is 'enum v4l2_tuner_type': include/uapi/linux/videodev2.h This field being 'enum v4l2_tuner_type' is unlikely as it seems to be never used that way in drivers, and documentation confirms it. It seem this comment got in accidentally in the commit which this patch fixes. Fix the UAPI comment to stop confusion. This was pointed out by Dmitry while reviewing VIDIOC_ENUMINPUT support for strace. Fixes: 6016af82eafc ("[media] v4l2: use __u32 rather than enums in ioctl() structs") Signed-off-by: Marek Vasut Signed-off-by: Hans Verkuil --- include/uapi/linux/videodev2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 9e7cf1d36945..5d8bd754c69f 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -1720,7 +1720,7 @@ struct v4l2_input { __u8 name[32]; /* Label */ __u32 type; /* Type of input */ __u32 audioset; /* Associated audios (bitfield) */ - __u32 tuner; /* enum v4l2_tuner_type */ + __u32 tuner; /* Tuner index */ v4l2_std_id std; __u32 status; __u32 capabilities; From d5b7eb477c286f6ceccbb38704136eea0e6b09ca Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Fri, 19 May 2023 00:52:35 +0300 Subject: [PATCH 051/253] media: camss: set VFE bpl_alignment to 16 for sdm845 and sm8250 From the experiments with camera sensors using SGRBG10_1X10/3280x2464 and SRGGB10_1X10/3280x2464 formats, it becomes clear that on sdm845 and sm8250 VFE outputs the lines padded to a length multiple of 16 bytes. As in the current driver the value of the bpl_alignment is set to 8 bytes, the frames captured in formats with the bytes-per-line value being not a multiple of 16 get corrupted. Set the bpl_alignment of the camss video output device to 16 for sdm845 and sm8250 to fix that. Signed-off-by: Andrey Konovalov Tested-by: Bryan O'Donoghue Acked-by: Bryan O'Donoghue Signed-off-by: Hans Verkuil --- drivers/media/platform/qcom/camss/camss-vfe.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index e0832f3f4f25..06c95568e5af 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -1541,7 +1541,11 @@ int msm_vfe_register_entities(struct vfe_device *vfe, } video_out->ops = &vfe->video_ops; - video_out->bpl_alignment = 8; + if (vfe->camss->version == CAMSS_845 || + vfe->camss->version == CAMSS_8250) + video_out->bpl_alignment = 16; + else + video_out->bpl_alignment = 8; video_out->line_based = 0; if (i == VFE_LINE_PIX) { video_out->bpl_alignment = 16; From da4ede4b7fd6aa341b69e3a9d2517b8df5e744fd Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 20 May 2023 16:41:42 -0700 Subject: [PATCH 052/253] media: mtk-jpeg: move data/code inside CONFIG_OF blocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lots of data and functions here are not needed when CONFIG_OF is not set, so move them inside #ifdef CONFIG_OF blocks to prevent the warnings. ../drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c:1645:29: warning: ‘mtk_jpeg_clocks’ defined but not used [-Wunused-variable] 1645 | static struct clk_bulk_data mtk_jpeg_clocks[] = { ../drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c:1640:29: warning: ‘mt8173_jpeg_dec_clocks’ defined but not used [-Wunused-variable] 1640 | static struct clk_bulk_data mt8173_jpeg_dec_clocks[] = { ../drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c:1481:20: warning: ‘mtk_jpeg_dec_irq’ defined but not used [-Wunused-function] 1481 | static irqreturn_t mtk_jpeg_dec_irq(int irq, void *priv) ../drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c:1461:20: warning: ‘mtk_jpeg_enc_irq’ defined but not used [-Wunused-function] 1461 | static irqreturn_t mtk_jpeg_enc_irq(int irq, void *priv) ../drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c:1180:13: warning: ‘mtk_jpegdec_worker’ defined but not used [-Wunused-function] 1180 | static void mtk_jpegdec_worker(struct work_struct *work) ../drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c:986:13: warning: ‘mtk_jpegenc_worker’ defined but not used [-Wunused-function] 986 | static void mtk_jpegenc_worker(struct work_struct *work) ../drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c:79:28: warning: ‘mtk_jpeg_dec_formats’ defined but not used [-Wunused-variable] 79 | static struct mtk_jpeg_fmt mtk_jpeg_dec_formats[] = { ../drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c:31:28: warning: ‘mtk_jpeg_enc_formats’ defined but not used [-Wunused-variable] 31 | static struct mtk_jpeg_fmt mtk_jpeg_enc_formats[] = { ../drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c:1222:20: warning: ‘mtk_jpeg_enc_done’ defined but not used [-Wunused-function] 1222 | static irqreturn_t mtk_jpeg_enc_done(struct mtk_jpeg_dev *jpeg) ../drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c:1072:12: warning: ‘mtk_jpegdec_set_hw_param’ defined but not used [-Wunused-function] 1072 | static int mtk_jpegdec_set_hw_param(struct mtk_jpeg_ctx *ctx, ../drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c:1060:12: warning: ‘mtk_jpegdec_put_hw’ defined but not used [-Wunused-function] 1060 | static int mtk_jpegdec_put_hw(struct mtk_jpeg_dev *jpeg, int hw_id) ../drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c:1038:12: warning: ‘mtk_jpegdec_get_hw’ defined but not used [-Wunused-function] 1038 | static int mtk_jpegdec_get_hw(struct mtk_jpeg_ctx *ctx) ../drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c:977:12: warning: ‘mtk_jpegenc_put_hw’ defined but not used [-Wunused-function] 977 | static int mtk_jpegenc_put_hw(struct mtk_jpeg_dev *jpeg, int hw_id) ../drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c:963:12: warning: ‘mtk_jpegenc_set_hw_param’ defined but not used [-Wunused-function] 963 | static int mtk_jpegenc_set_hw_param(struct mtk_jpeg_ctx *ctx, ../drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c:941:12: warning: ‘mtk_jpegenc_get_hw’ defined but not used [-Wunused-function] 941 | static int mtk_jpegenc_get_hw(struct mtk_jpeg_ctx *ctx) Signed-off-by: Randy Dunlap Reported-by: kernel test robot Link: https://lore.kernel.org/linux-media/202305042146.j4ZxuvpM-lkp@intel.com/ Cc: Bin Liu Cc: oushixiong Cc: Mauro Carvalho Chehab Cc: Hans Verkuil Cc: linux-media@vger.kernel.org Signed-off-by: Hans Verkuil --- .../platform/mediatek/jpeg/mtk_jpeg_core.c | 828 +++++++++--------- 1 file changed, 415 insertions(+), 413 deletions(-) diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c index 0051f372a66c..4768156181c9 100644 --- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c +++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c @@ -28,6 +28,7 @@ #include "mtk_jpeg_core.h" #include "mtk_jpeg_dec_parse.h" +#if defined(CONFIG_OF) static struct mtk_jpeg_fmt mtk_jpeg_enc_formats[] = { { .fourcc = V4L2_PIX_FMT_JPEG, @@ -101,6 +102,7 @@ static struct mtk_jpeg_fmt mtk_jpeg_dec_formats[] = { .flags = MTK_JPEG_FMT_FLAG_CAPTURE, }, }; +#endif #define MTK_JPEG_ENC_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_enc_formats) #define MTK_JPEG_DEC_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_dec_formats) @@ -936,148 +938,6 @@ static int mtk_jpeg_set_dec_dst(struct mtk_jpeg_ctx *ctx, return 0; } -static int mtk_jpegenc_get_hw(struct mtk_jpeg_ctx *ctx) -{ - struct mtk_jpegenc_comp_dev *comp_jpeg; - struct mtk_jpeg_dev *jpeg = ctx->jpeg; - unsigned long flags; - int hw_id = -1; - int i; - - spin_lock_irqsave(&jpeg->hw_lock, flags); - for (i = 0; i < MTK_JPEGENC_HW_MAX; i++) { - comp_jpeg = jpeg->enc_hw_dev[i]; - if (comp_jpeg->hw_state == MTK_JPEG_HW_IDLE) { - hw_id = i; - comp_jpeg->hw_state = MTK_JPEG_HW_BUSY; - break; - } - } - spin_unlock_irqrestore(&jpeg->hw_lock, flags); - - return hw_id; -} - -static int mtk_jpegenc_set_hw_param(struct mtk_jpeg_ctx *ctx, - int hw_id, - struct vb2_v4l2_buffer *src_buf, - struct vb2_v4l2_buffer *dst_buf) -{ - struct mtk_jpegenc_comp_dev *jpeg = ctx->jpeg->enc_hw_dev[hw_id]; - - jpeg->hw_param.curr_ctx = ctx; - jpeg->hw_param.src_buffer = src_buf; - jpeg->hw_param.dst_buffer = dst_buf; - - return 0; -} - -static int mtk_jpegenc_put_hw(struct mtk_jpeg_dev *jpeg, int hw_id) -{ - unsigned long flags; - - spin_lock_irqsave(&jpeg->hw_lock, flags); - jpeg->enc_hw_dev[hw_id]->hw_state = MTK_JPEG_HW_IDLE; - spin_unlock_irqrestore(&jpeg->hw_lock, flags); - - return 0; -} - -static void mtk_jpegenc_worker(struct work_struct *work) -{ - struct mtk_jpegenc_comp_dev *comp_jpeg[MTK_JPEGENC_HW_MAX]; - enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR; - struct mtk_jpeg_src_buf *jpeg_dst_buf; - struct vb2_v4l2_buffer *src_buf, *dst_buf; - int ret, i, hw_id = 0; - unsigned long flags; - - struct mtk_jpeg_ctx *ctx = container_of(work, - struct mtk_jpeg_ctx, - jpeg_work); - struct mtk_jpeg_dev *jpeg = ctx->jpeg; - - for (i = 0; i < MTK_JPEGENC_HW_MAX; i++) - comp_jpeg[i] = jpeg->enc_hw_dev[i]; - i = 0; - -retry_select: - hw_id = mtk_jpegenc_get_hw(ctx); - if (hw_id < 0) { - ret = wait_event_interruptible(jpeg->hw_wq, - atomic_read(&jpeg->hw_rdy) > 0); - if (ret != 0 || (i++ > MTK_JPEG_MAX_RETRY_TIME)) { - dev_err(jpeg->dev, "%s : %d, all HW are busy\n", - __func__, __LINE__); - v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); - return; - } - - goto retry_select; - } - - atomic_dec(&jpeg->hw_rdy); - src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); - if (!src_buf) - goto getbuf_fail; - - dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); - if (!dst_buf) - goto getbuf_fail; - - v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true); - - mtk_jpegenc_set_hw_param(ctx, hw_id, src_buf, dst_buf); - ret = pm_runtime_get_sync(comp_jpeg[hw_id]->dev); - if (ret < 0) { - dev_err(jpeg->dev, "%s : %d, pm_runtime_get_sync fail !!!\n", - __func__, __LINE__); - goto enc_end; - } - - ret = clk_prepare_enable(comp_jpeg[hw_id]->venc_clk.clks->clk); - if (ret) { - dev_err(jpeg->dev, "%s : %d, jpegenc clk_prepare_enable fail\n", - __func__, __LINE__); - goto enc_end; - } - - v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); - v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); - - schedule_delayed_work(&comp_jpeg[hw_id]->job_timeout_work, - msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC)); - - spin_lock_irqsave(&comp_jpeg[hw_id]->hw_lock, flags); - jpeg_dst_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buf->vb2_buf); - jpeg_dst_buf->curr_ctx = ctx; - jpeg_dst_buf->frame_num = ctx->total_frame_num; - ctx->total_frame_num++; - mtk_jpeg_enc_reset(comp_jpeg[hw_id]->reg_base); - mtk_jpeg_set_enc_dst(ctx, - comp_jpeg[hw_id]->reg_base, - &dst_buf->vb2_buf); - mtk_jpeg_set_enc_src(ctx, - comp_jpeg[hw_id]->reg_base, - &src_buf->vb2_buf); - mtk_jpeg_set_enc_params(ctx, comp_jpeg[hw_id]->reg_base); - mtk_jpeg_enc_start(comp_jpeg[hw_id]->reg_base); - v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); - spin_unlock_irqrestore(&comp_jpeg[hw_id]->hw_lock, flags); - - return; - -enc_end: - v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); - v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); - v4l2_m2m_buf_done(src_buf, buf_state); - v4l2_m2m_buf_done(dst_buf, buf_state); -getbuf_fail: - atomic_inc(&jpeg->hw_rdy); - mtk_jpegenc_put_hw(jpeg, hw_id); - v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); -} - static void mtk_jpeg_enc_device_run(void *priv) { struct mtk_jpeg_ctx *ctx = priv; @@ -1128,173 +988,6 @@ static void mtk_jpeg_multicore_enc_device_run(void *priv) queue_work(jpeg->workqueue, &ctx->jpeg_work); } -static int mtk_jpegdec_get_hw(struct mtk_jpeg_ctx *ctx) -{ - struct mtk_jpegdec_comp_dev *comp_jpeg; - struct mtk_jpeg_dev *jpeg = ctx->jpeg; - unsigned long flags; - int hw_id = -1; - int i; - - spin_lock_irqsave(&jpeg->hw_lock, flags); - for (i = 0; i < MTK_JPEGDEC_HW_MAX; i++) { - comp_jpeg = jpeg->dec_hw_dev[i]; - if (comp_jpeg->hw_state == MTK_JPEG_HW_IDLE) { - hw_id = i; - comp_jpeg->hw_state = MTK_JPEG_HW_BUSY; - break; - } - } - spin_unlock_irqrestore(&jpeg->hw_lock, flags); - - return hw_id; -} - -static int mtk_jpegdec_put_hw(struct mtk_jpeg_dev *jpeg, int hw_id) -{ - unsigned long flags; - - spin_lock_irqsave(&jpeg->hw_lock, flags); - jpeg->dec_hw_dev[hw_id]->hw_state = - MTK_JPEG_HW_IDLE; - spin_unlock_irqrestore(&jpeg->hw_lock, flags); - - return 0; -} - -static int mtk_jpegdec_set_hw_param(struct mtk_jpeg_ctx *ctx, - int hw_id, - struct vb2_v4l2_buffer *src_buf, - struct vb2_v4l2_buffer *dst_buf) -{ - struct mtk_jpegdec_comp_dev *jpeg = - ctx->jpeg->dec_hw_dev[hw_id]; - - jpeg->hw_param.curr_ctx = ctx; - jpeg->hw_param.src_buffer = src_buf; - jpeg->hw_param.dst_buffer = dst_buf; - - return 0; -} - -static void mtk_jpegdec_worker(struct work_struct *work) -{ - struct mtk_jpeg_ctx *ctx = container_of(work, struct mtk_jpeg_ctx, - jpeg_work); - struct mtk_jpegdec_comp_dev *comp_jpeg[MTK_JPEGDEC_HW_MAX]; - enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR; - struct mtk_jpeg_src_buf *jpeg_src_buf, *jpeg_dst_buf; - struct vb2_v4l2_buffer *src_buf, *dst_buf; - struct mtk_jpeg_dev *jpeg = ctx->jpeg; - int ret, i, hw_id = 0; - struct mtk_jpeg_bs bs; - struct mtk_jpeg_fb fb; - unsigned long flags; - - for (i = 0; i < MTK_JPEGDEC_HW_MAX; i++) - comp_jpeg[i] = jpeg->dec_hw_dev[i]; - i = 0; - -retry_select: - hw_id = mtk_jpegdec_get_hw(ctx); - if (hw_id < 0) { - ret = wait_event_interruptible_timeout(jpeg->hw_wq, - atomic_read(&jpeg->hw_rdy) > 0, - MTK_JPEG_HW_TIMEOUT_MSEC); - if (ret != 0 || (i++ > MTK_JPEG_MAX_RETRY_TIME)) { - dev_err(jpeg->dev, "%s : %d, all HW are busy\n", - __func__, __LINE__); - v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); - return; - } - - goto retry_select; - } - - atomic_dec(&jpeg->hw_rdy); - src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); - if (!src_buf) - goto getbuf_fail; - - dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); - if (!dst_buf) - goto getbuf_fail; - - v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true); - jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf); - jpeg_dst_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buf->vb2_buf); - - if (mtk_jpeg_check_resolution_change(ctx, - &jpeg_src_buf->dec_param)) { - mtk_jpeg_queue_src_chg_event(ctx); - ctx->state = MTK_JPEG_SOURCE_CHANGE; - goto getbuf_fail; - } - - jpeg_src_buf->curr_ctx = ctx; - jpeg_src_buf->frame_num = ctx->total_frame_num; - jpeg_dst_buf->curr_ctx = ctx; - jpeg_dst_buf->frame_num = ctx->total_frame_num; - - mtk_jpegdec_set_hw_param(ctx, hw_id, src_buf, dst_buf); - ret = pm_runtime_get_sync(comp_jpeg[hw_id]->dev); - if (ret < 0) { - dev_err(jpeg->dev, "%s : %d, pm_runtime_get_sync fail !!!\n", - __func__, __LINE__); - goto dec_end; - } - - ret = clk_prepare_enable(comp_jpeg[hw_id]->jdec_clk.clks->clk); - if (ret) { - dev_err(jpeg->dev, "%s : %d, jpegdec clk_prepare_enable fail\n", - __func__, __LINE__); - goto clk_end; - } - - v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); - v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); - - schedule_delayed_work(&comp_jpeg[hw_id]->job_timeout_work, - msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC)); - - mtk_jpeg_set_dec_src(ctx, &src_buf->vb2_buf, &bs); - if (mtk_jpeg_set_dec_dst(ctx, - &jpeg_src_buf->dec_param, - &dst_buf->vb2_buf, &fb)) { - dev_err(jpeg->dev, "%s : %d, mtk_jpeg_set_dec_dst fail\n", - __func__, __LINE__); - goto setdst_end; - } - - spin_lock_irqsave(&comp_jpeg[hw_id]->hw_lock, flags); - ctx->total_frame_num++; - mtk_jpeg_dec_reset(comp_jpeg[hw_id]->reg_base); - mtk_jpeg_dec_set_config(comp_jpeg[hw_id]->reg_base, - &jpeg_src_buf->dec_param, - jpeg_src_buf->bs_size, - &bs, - &fb); - mtk_jpeg_dec_start(comp_jpeg[hw_id]->reg_base); - v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); - spin_unlock_irqrestore(&comp_jpeg[hw_id]->hw_lock, flags); - - return; - -setdst_end: - clk_disable_unprepare(comp_jpeg[hw_id]->jdec_clk.clks->clk); -clk_end: - pm_runtime_put(comp_jpeg[hw_id]->dev); -dec_end: - v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); - v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); - v4l2_m2m_buf_done(src_buf, buf_state); - v4l2_m2m_buf_done(dst_buf, buf_state); -getbuf_fail: - atomic_inc(&jpeg->hw_rdy); - mtk_jpegdec_put_hw(jpeg, hw_id); - v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); -} - static void mtk_jpeg_multicore_dec_device_run(void *priv) { struct mtk_jpeg_ctx *ctx = priv; @@ -1430,101 +1123,6 @@ static void mtk_jpeg_clk_off(struct mtk_jpeg_dev *jpeg) jpeg->variant->clks); } -static irqreturn_t mtk_jpeg_enc_done(struct mtk_jpeg_dev *jpeg) -{ - struct mtk_jpeg_ctx *ctx; - struct vb2_v4l2_buffer *src_buf, *dst_buf; - enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR; - u32 result_size; - - ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); - if (!ctx) { - v4l2_err(&jpeg->v4l2_dev, "Context is NULL\n"); - return IRQ_HANDLED; - } - - src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); - dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); - - result_size = mtk_jpeg_enc_get_file_size(jpeg->reg_base); - vb2_set_plane_payload(&dst_buf->vb2_buf, 0, result_size); - - buf_state = VB2_BUF_STATE_DONE; - - v4l2_m2m_buf_done(src_buf, buf_state); - v4l2_m2m_buf_done(dst_buf, buf_state); - v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); - pm_runtime_put(ctx->jpeg->dev); - return IRQ_HANDLED; -} - -static irqreturn_t mtk_jpeg_enc_irq(int irq, void *priv) -{ - struct mtk_jpeg_dev *jpeg = priv; - u32 irq_status; - irqreturn_t ret = IRQ_NONE; - - cancel_delayed_work(&jpeg->job_timeout_work); - - irq_status = readl(jpeg->reg_base + JPEG_ENC_INT_STS) & - JPEG_ENC_INT_STATUS_MASK_ALLIRQ; - if (irq_status) - writel(0, jpeg->reg_base + JPEG_ENC_INT_STS); - - if (!(irq_status & JPEG_ENC_INT_STATUS_DONE)) - return ret; - - ret = mtk_jpeg_enc_done(jpeg); - return ret; -} - -static irqreturn_t mtk_jpeg_dec_irq(int irq, void *priv) -{ - struct mtk_jpeg_dev *jpeg = priv; - struct mtk_jpeg_ctx *ctx; - struct vb2_v4l2_buffer *src_buf, *dst_buf; - struct mtk_jpeg_src_buf *jpeg_src_buf; - enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR; - u32 dec_irq_ret; - u32 dec_ret; - int i; - - cancel_delayed_work(&jpeg->job_timeout_work); - - dec_ret = mtk_jpeg_dec_get_int_status(jpeg->reg_base); - dec_irq_ret = mtk_jpeg_dec_enum_result(dec_ret); - ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); - if (!ctx) { - v4l2_err(&jpeg->v4l2_dev, "Context is NULL\n"); - return IRQ_HANDLED; - } - - src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); - dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); - jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf); - - if (dec_irq_ret >= MTK_JPEG_DEC_RESULT_UNDERFLOW) - mtk_jpeg_dec_reset(jpeg->reg_base); - - if (dec_irq_ret != MTK_JPEG_DEC_RESULT_EOF_DONE) { - dev_err(jpeg->dev, "decode failed\n"); - goto dec_end; - } - - for (i = 0; i < dst_buf->vb2_buf.num_planes; i++) - vb2_set_plane_payload(&dst_buf->vb2_buf, i, - jpeg_src_buf->dec_param.comp_size[i]); - - buf_state = VB2_BUF_STATE_DONE; - -dec_end: - v4l2_m2m_buf_done(src_buf, buf_state); - v4l2_m2m_buf_done(dst_buf, buf_state); - v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); - pm_runtime_put(ctx->jpeg->dev); - return IRQ_HANDLED; -} - static void mtk_jpeg_set_default_params(struct mtk_jpeg_ctx *ctx) { struct mtk_jpeg_q_data *q = &ctx->out_q; @@ -1637,15 +1235,6 @@ static const struct v4l2_file_operations mtk_jpeg_fops = { .mmap = v4l2_m2m_fop_mmap, }; -static struct clk_bulk_data mt8173_jpeg_dec_clocks[] = { - { .id = "jpgdec-smi" }, - { .id = "jpgdec" }, -}; - -static struct clk_bulk_data mtk_jpeg_clocks[] = { - { .id = "jpgenc" }, -}; - static void mtk_jpeg_job_timeout_work(struct work_struct *work) { struct mtk_jpeg_dev *jpeg = container_of(work, struct mtk_jpeg_dev, @@ -1867,6 +1456,419 @@ static const struct dev_pm_ops mtk_jpeg_pm_ops = { }; #if defined(CONFIG_OF) +static int mtk_jpegenc_get_hw(struct mtk_jpeg_ctx *ctx) +{ + struct mtk_jpegenc_comp_dev *comp_jpeg; + struct mtk_jpeg_dev *jpeg = ctx->jpeg; + unsigned long flags; + int hw_id = -1; + int i; + + spin_lock_irqsave(&jpeg->hw_lock, flags); + for (i = 0; i < MTK_JPEGENC_HW_MAX; i++) { + comp_jpeg = jpeg->enc_hw_dev[i]; + if (comp_jpeg->hw_state == MTK_JPEG_HW_IDLE) { + hw_id = i; + comp_jpeg->hw_state = MTK_JPEG_HW_BUSY; + break; + } + } + spin_unlock_irqrestore(&jpeg->hw_lock, flags); + + return hw_id; +} + +static int mtk_jpegenc_set_hw_param(struct mtk_jpeg_ctx *ctx, + int hw_id, + struct vb2_v4l2_buffer *src_buf, + struct vb2_v4l2_buffer *dst_buf) +{ + struct mtk_jpegenc_comp_dev *jpeg = ctx->jpeg->enc_hw_dev[hw_id]; + + jpeg->hw_param.curr_ctx = ctx; + jpeg->hw_param.src_buffer = src_buf; + jpeg->hw_param.dst_buffer = dst_buf; + + return 0; +} + +static int mtk_jpegenc_put_hw(struct mtk_jpeg_dev *jpeg, int hw_id) +{ + unsigned long flags; + + spin_lock_irqsave(&jpeg->hw_lock, flags); + jpeg->enc_hw_dev[hw_id]->hw_state = MTK_JPEG_HW_IDLE; + spin_unlock_irqrestore(&jpeg->hw_lock, flags); + + return 0; +} + +static int mtk_jpegdec_get_hw(struct mtk_jpeg_ctx *ctx) +{ + struct mtk_jpegdec_comp_dev *comp_jpeg; + struct mtk_jpeg_dev *jpeg = ctx->jpeg; + unsigned long flags; + int hw_id = -1; + int i; + + spin_lock_irqsave(&jpeg->hw_lock, flags); + for (i = 0; i < MTK_JPEGDEC_HW_MAX; i++) { + comp_jpeg = jpeg->dec_hw_dev[i]; + if (comp_jpeg->hw_state == MTK_JPEG_HW_IDLE) { + hw_id = i; + comp_jpeg->hw_state = MTK_JPEG_HW_BUSY; + break; + } + } + spin_unlock_irqrestore(&jpeg->hw_lock, flags); + + return hw_id; +} + +static int mtk_jpegdec_put_hw(struct mtk_jpeg_dev *jpeg, int hw_id) +{ + unsigned long flags; + + spin_lock_irqsave(&jpeg->hw_lock, flags); + jpeg->dec_hw_dev[hw_id]->hw_state = + MTK_JPEG_HW_IDLE; + spin_unlock_irqrestore(&jpeg->hw_lock, flags); + + return 0; +} + +static int mtk_jpegdec_set_hw_param(struct mtk_jpeg_ctx *ctx, + int hw_id, + struct vb2_v4l2_buffer *src_buf, + struct vb2_v4l2_buffer *dst_buf) +{ + struct mtk_jpegdec_comp_dev *jpeg = + ctx->jpeg->dec_hw_dev[hw_id]; + + jpeg->hw_param.curr_ctx = ctx; + jpeg->hw_param.src_buffer = src_buf; + jpeg->hw_param.dst_buffer = dst_buf; + + return 0; +} + +static irqreturn_t mtk_jpeg_enc_done(struct mtk_jpeg_dev *jpeg) +{ + struct mtk_jpeg_ctx *ctx; + struct vb2_v4l2_buffer *src_buf, *dst_buf; + enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR; + u32 result_size; + + ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); + if (!ctx) { + v4l2_err(&jpeg->v4l2_dev, "Context is NULL\n"); + return IRQ_HANDLED; + } + + src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + + result_size = mtk_jpeg_enc_get_file_size(jpeg->reg_base); + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, result_size); + + buf_state = VB2_BUF_STATE_DONE; + + v4l2_m2m_buf_done(src_buf, buf_state); + v4l2_m2m_buf_done(dst_buf, buf_state); + v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); + pm_runtime_put(ctx->jpeg->dev); + return IRQ_HANDLED; +} + +static void mtk_jpegenc_worker(struct work_struct *work) +{ + struct mtk_jpegenc_comp_dev *comp_jpeg[MTK_JPEGENC_HW_MAX]; + enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR; + struct mtk_jpeg_src_buf *jpeg_dst_buf; + struct vb2_v4l2_buffer *src_buf, *dst_buf; + int ret, i, hw_id = 0; + unsigned long flags; + + struct mtk_jpeg_ctx *ctx = container_of(work, + struct mtk_jpeg_ctx, + jpeg_work); + struct mtk_jpeg_dev *jpeg = ctx->jpeg; + + for (i = 0; i < MTK_JPEGENC_HW_MAX; i++) + comp_jpeg[i] = jpeg->enc_hw_dev[i]; + i = 0; + +retry_select: + hw_id = mtk_jpegenc_get_hw(ctx); + if (hw_id < 0) { + ret = wait_event_interruptible(jpeg->hw_wq, + atomic_read(&jpeg->hw_rdy) > 0); + if (ret != 0 || (i++ > MTK_JPEG_MAX_RETRY_TIME)) { + dev_err(jpeg->dev, "%s : %d, all HW are busy\n", + __func__, __LINE__); + v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); + return; + } + + goto retry_select; + } + + atomic_dec(&jpeg->hw_rdy); + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + if (!src_buf) + goto getbuf_fail; + + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); + if (!dst_buf) + goto getbuf_fail; + + v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true); + + mtk_jpegenc_set_hw_param(ctx, hw_id, src_buf, dst_buf); + ret = pm_runtime_get_sync(comp_jpeg[hw_id]->dev); + if (ret < 0) { + dev_err(jpeg->dev, "%s : %d, pm_runtime_get_sync fail !!!\n", + __func__, __LINE__); + goto enc_end; + } + + ret = clk_prepare_enable(comp_jpeg[hw_id]->venc_clk.clks->clk); + if (ret) { + dev_err(jpeg->dev, "%s : %d, jpegenc clk_prepare_enable fail\n", + __func__, __LINE__); + goto enc_end; + } + + v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + + schedule_delayed_work(&comp_jpeg[hw_id]->job_timeout_work, + msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC)); + + spin_lock_irqsave(&comp_jpeg[hw_id]->hw_lock, flags); + jpeg_dst_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buf->vb2_buf); + jpeg_dst_buf->curr_ctx = ctx; + jpeg_dst_buf->frame_num = ctx->total_frame_num; + ctx->total_frame_num++; + mtk_jpeg_enc_reset(comp_jpeg[hw_id]->reg_base); + mtk_jpeg_set_enc_dst(ctx, + comp_jpeg[hw_id]->reg_base, + &dst_buf->vb2_buf); + mtk_jpeg_set_enc_src(ctx, + comp_jpeg[hw_id]->reg_base, + &src_buf->vb2_buf); + mtk_jpeg_set_enc_params(ctx, comp_jpeg[hw_id]->reg_base); + mtk_jpeg_enc_start(comp_jpeg[hw_id]->reg_base); + v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); + spin_unlock_irqrestore(&comp_jpeg[hw_id]->hw_lock, flags); + + return; + +enc_end: + v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + v4l2_m2m_buf_done(src_buf, buf_state); + v4l2_m2m_buf_done(dst_buf, buf_state); +getbuf_fail: + atomic_inc(&jpeg->hw_rdy); + mtk_jpegenc_put_hw(jpeg, hw_id); + v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); +} + +static void mtk_jpegdec_worker(struct work_struct *work) +{ + struct mtk_jpeg_ctx *ctx = container_of(work, struct mtk_jpeg_ctx, + jpeg_work); + struct mtk_jpegdec_comp_dev *comp_jpeg[MTK_JPEGDEC_HW_MAX]; + enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR; + struct mtk_jpeg_src_buf *jpeg_src_buf, *jpeg_dst_buf; + struct vb2_v4l2_buffer *src_buf, *dst_buf; + struct mtk_jpeg_dev *jpeg = ctx->jpeg; + int ret, i, hw_id = 0; + struct mtk_jpeg_bs bs; + struct mtk_jpeg_fb fb; + unsigned long flags; + + for (i = 0; i < MTK_JPEGDEC_HW_MAX; i++) + comp_jpeg[i] = jpeg->dec_hw_dev[i]; + i = 0; + +retry_select: + hw_id = mtk_jpegdec_get_hw(ctx); + if (hw_id < 0) { + ret = wait_event_interruptible_timeout(jpeg->hw_wq, + atomic_read(&jpeg->hw_rdy) > 0, + MTK_JPEG_HW_TIMEOUT_MSEC); + if (ret != 0 || (i++ > MTK_JPEG_MAX_RETRY_TIME)) { + dev_err(jpeg->dev, "%s : %d, all HW are busy\n", + __func__, __LINE__); + v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); + return; + } + + goto retry_select; + } + + atomic_dec(&jpeg->hw_rdy); + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + if (!src_buf) + goto getbuf_fail; + + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); + if (!dst_buf) + goto getbuf_fail; + + v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true); + jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf); + jpeg_dst_buf = mtk_jpeg_vb2_to_srcbuf(&dst_buf->vb2_buf); + + if (mtk_jpeg_check_resolution_change(ctx, + &jpeg_src_buf->dec_param)) { + mtk_jpeg_queue_src_chg_event(ctx); + ctx->state = MTK_JPEG_SOURCE_CHANGE; + goto getbuf_fail; + } + + jpeg_src_buf->curr_ctx = ctx; + jpeg_src_buf->frame_num = ctx->total_frame_num; + jpeg_dst_buf->curr_ctx = ctx; + jpeg_dst_buf->frame_num = ctx->total_frame_num; + + mtk_jpegdec_set_hw_param(ctx, hw_id, src_buf, dst_buf); + ret = pm_runtime_get_sync(comp_jpeg[hw_id]->dev); + if (ret < 0) { + dev_err(jpeg->dev, "%s : %d, pm_runtime_get_sync fail !!!\n", + __func__, __LINE__); + goto dec_end; + } + + ret = clk_prepare_enable(comp_jpeg[hw_id]->jdec_clk.clks->clk); + if (ret) { + dev_err(jpeg->dev, "%s : %d, jpegdec clk_prepare_enable fail\n", + __func__, __LINE__); + goto clk_end; + } + + v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + + schedule_delayed_work(&comp_jpeg[hw_id]->job_timeout_work, + msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC)); + + mtk_jpeg_set_dec_src(ctx, &src_buf->vb2_buf, &bs); + if (mtk_jpeg_set_dec_dst(ctx, + &jpeg_src_buf->dec_param, + &dst_buf->vb2_buf, &fb)) { + dev_err(jpeg->dev, "%s : %d, mtk_jpeg_set_dec_dst fail\n", + __func__, __LINE__); + goto setdst_end; + } + + spin_lock_irqsave(&comp_jpeg[hw_id]->hw_lock, flags); + ctx->total_frame_num++; + mtk_jpeg_dec_reset(comp_jpeg[hw_id]->reg_base); + mtk_jpeg_dec_set_config(comp_jpeg[hw_id]->reg_base, + &jpeg_src_buf->dec_param, + jpeg_src_buf->bs_size, + &bs, + &fb); + mtk_jpeg_dec_start(comp_jpeg[hw_id]->reg_base); + v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); + spin_unlock_irqrestore(&comp_jpeg[hw_id]->hw_lock, flags); + + return; + +setdst_end: + clk_disable_unprepare(comp_jpeg[hw_id]->jdec_clk.clks->clk); +clk_end: + pm_runtime_put(comp_jpeg[hw_id]->dev); +dec_end: + v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + v4l2_m2m_buf_done(src_buf, buf_state); + v4l2_m2m_buf_done(dst_buf, buf_state); +getbuf_fail: + atomic_inc(&jpeg->hw_rdy); + mtk_jpegdec_put_hw(jpeg, hw_id); + v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); +} + +static irqreturn_t mtk_jpeg_enc_irq(int irq, void *priv) +{ + struct mtk_jpeg_dev *jpeg = priv; + u32 irq_status; + irqreturn_t ret = IRQ_NONE; + + cancel_delayed_work(&jpeg->job_timeout_work); + + irq_status = readl(jpeg->reg_base + JPEG_ENC_INT_STS) & + JPEG_ENC_INT_STATUS_MASK_ALLIRQ; + if (irq_status) + writel(0, jpeg->reg_base + JPEG_ENC_INT_STS); + + if (!(irq_status & JPEG_ENC_INT_STATUS_DONE)) + return ret; + + ret = mtk_jpeg_enc_done(jpeg); + return ret; +} + +static irqreturn_t mtk_jpeg_dec_irq(int irq, void *priv) +{ + struct mtk_jpeg_dev *jpeg = priv; + struct mtk_jpeg_ctx *ctx; + struct vb2_v4l2_buffer *src_buf, *dst_buf; + struct mtk_jpeg_src_buf *jpeg_src_buf; + enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR; + u32 dec_irq_ret; + u32 dec_ret; + int i; + + cancel_delayed_work(&jpeg->job_timeout_work); + + dec_ret = mtk_jpeg_dec_get_int_status(jpeg->reg_base); + dec_irq_ret = mtk_jpeg_dec_enum_result(dec_ret); + ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); + if (!ctx) { + v4l2_err(&jpeg->v4l2_dev, "Context is NULL\n"); + return IRQ_HANDLED; + } + + src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf); + + if (dec_irq_ret >= MTK_JPEG_DEC_RESULT_UNDERFLOW) + mtk_jpeg_dec_reset(jpeg->reg_base); + + if (dec_irq_ret != MTK_JPEG_DEC_RESULT_EOF_DONE) { + dev_err(jpeg->dev, "decode failed\n"); + goto dec_end; + } + + for (i = 0; i < dst_buf->vb2_buf.num_planes; i++) + vb2_set_plane_payload(&dst_buf->vb2_buf, i, + jpeg_src_buf->dec_param.comp_size[i]); + + buf_state = VB2_BUF_STATE_DONE; + +dec_end: + v4l2_m2m_buf_done(src_buf, buf_state); + v4l2_m2m_buf_done(dst_buf, buf_state); + v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx); + pm_runtime_put(ctx->jpeg->dev); + return IRQ_HANDLED; +} + +static struct clk_bulk_data mtk_jpeg_clocks[] = { + { .id = "jpgenc" }, +}; + +static struct clk_bulk_data mt8173_jpeg_dec_clocks[] = { + { .id = "jpgdec-smi" }, + { .id = "jpgdec" }, +}; + static const struct mtk_jpeg_variant mt8173_jpeg_drvdata = { .clks = mt8173_jpeg_dec_clocks, .num_clks = ARRAY_SIZE(mt8173_jpeg_dec_clocks), From 6f489a966fbeb0da63d45c2c66a8957eab604bf6 Mon Sep 17 00:00:00 2001 From: Duoming Zhou Date: Tue, 23 May 2023 07:59:32 +0800 Subject: [PATCH 053/253] media: usb: siano: Fix warning due to null work_func_t function pointer The previous commit ebad8e731c1c ("media: usb: siano: Fix use after free bugs caused by do_submit_urb") adds cancel_work_sync() in smsusb_stop_streaming(). But smsusb_stop_streaming() may be called, even if the work_struct surb->wq has not been initialized. As a result, the warning will occur. One of the processes that could lead to warning is shown below: smsusb_probe() smsusb_init_device() if (!dev->in_ep || !dev->out_ep || align < 0) { smsusb_term_device(intf); smsusb_stop_streaming() cancel_work_sync(&dev->surbs[i].wq); __cancel_work_timer() __flush_work() if (WARN_ON(!work->func)) // work->func is null The log reported by syzbot is shown below: WARNING: CPU: 0 PID: 897 at kernel/workqueue.c:3066 __flush_work+0x798/0xa80 kernel/workqueue.c:3063 Modules linked in: CPU: 0 PID: 897 Comm: kworker/0:2 Not tainted 6.2.0-rc1-syzkaller #0 RIP: 0010:__flush_work+0x798/0xa80 kernel/workqueue.c:3066 ... RSP: 0018:ffffc9000464ebf8 EFLAGS: 00010246 RAX: 1ffff11002dbb420 RBX: 0000000000000021 RCX: 1ffffffff204fa4e RDX: dffffc0000000000 RSI: 0000000000000001 RDI: ffff888016dda0e8 RBP: ffffc9000464ed98 R08: 0000000000000001 R09: ffffffff90253b2f R10: 0000000000000001 R11: 0000000000000000 R12: ffff888016dda0e8 R13: ffff888016dda0e8 R14: ffff888016dda100 R15: 0000000000000001 FS: 0000000000000000(0000) GS:ffff8880b9a00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007ffd4331efe8 CR3: 000000000b48e000 CR4: 00000000003506f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: __cancel_work_timer+0x315/0x460 kernel/workqueue.c:3160 smsusb_stop_streaming drivers/media/usb/siano/smsusb.c:182 [inline] smsusb_term_device+0xda/0x2d0 drivers/media/usb/siano/smsusb.c:344 smsusb_init_device+0x400/0x9ce drivers/media/usb/siano/smsusb.c:419 smsusb_probe+0xbbd/0xc55 drivers/media/usb/siano/smsusb.c:567 ... This patch adds check before cancel_work_sync(). If surb->wq has not been initialized, the cancel_work_sync() will not be executed. Reported-by: syzbot+27b0b464864741b18b99@syzkaller.appspotmail.com Fixes: ebad8e731c1c ("media: usb: siano: Fix use after free bugs caused by do_submit_urb") Signed-off-by: Duoming Zhou Signed-off-by: Hans Verkuil --- drivers/media/usb/siano/smsusb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c index 6f443c542c6d..640737d3b8ae 100644 --- a/drivers/media/usb/siano/smsusb.c +++ b/drivers/media/usb/siano/smsusb.c @@ -179,7 +179,8 @@ static void smsusb_stop_streaming(struct smsusb_device_t *dev) for (i = 0; i < MAX_URBS; i++) { usb_kill_urb(&dev->surbs[i].urb); - cancel_work_sync(&dev->surbs[i].wq); + if (dev->surbs[i].wq.func) + cancel_work_sync(&dev->surbs[i].wq); if (dev->surbs[i].cb) { smscore_putbuffer(dev->coredev, dev->surbs[i].cb); From bf950e1f3030ab310cdbc386e0ad3e531bc32de4 Mon Sep 17 00:00:00 2001 From: Michael Tretter Date: Tue, 23 May 2023 11:03:09 +0200 Subject: [PATCH 054/253] media: rockchip: rga: use v4l2_m2m_buf_copy_metadata The v4l2_m2m_buf_copy_metadata function correctly copies the metadata of the buffer. Use that function instead of open-coding the metadata copy. Signed-off-by: Michael Tretter Signed-off-by: Hans Verkuil --- drivers/media/platform/rockchip/rga/rga.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c index 67dcf22e5ba3..e4b8ce9ab3c6 100644 --- a/drivers/media/platform/rockchip/rga/rga.c +++ b/drivers/media/platform/rockchip/rga/rga.c @@ -76,10 +76,7 @@ static irqreturn_t rga_isr(int irq, void *prv) WARN_ON(!src); WARN_ON(!dst); - dst->timecode = src->timecode; - dst->vb2_buf.timestamp = src->vb2_buf.timestamp; - dst->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; - dst->flags |= src->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; + v4l2_m2m_buf_copy_metadata(src, dst, true); v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE); v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE); From ecdbab337da1c72a8bb9e2162a271943e3559a52 Mon Sep 17 00:00:00 2001 From: Fei Shao Date: Mon, 15 May 2023 14:16:10 +0800 Subject: [PATCH 055/253] media: mediatek: vcodec: mtk_vcodec_dec_hw: Use devm_pm_runtime_enable() Convert pm_runtime_enable() to the managed version, and clean up error handling and unnecessary .remove() callback accordingly. Signed-off-by: Fei Shao Reviewed-by: Alexandre Mergnat Suggested-by: Chen-Yu Tsai Signed-off-by: Hans Verkuil --- .../mediatek/vcodec/mtk_vcodec_dec_hw.c | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_hw.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_hw.c index b753bf54ebd9..e1cb2f8dca33 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_hw.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_hw.c @@ -148,20 +148,21 @@ static int mtk_vdec_hw_probe(struct platform_device *pdev) ret = mtk_vcodec_init_dec_clk(pdev, &subdev_dev->pm); if (ret) return ret; - pm_runtime_enable(&pdev->dev); + + ret = devm_pm_runtime_enable(&pdev->dev); + if (ret) + return ret; of_id = of_match_device(mtk_vdec_hw_match, dev); if (!of_id) { dev_err(dev, "Can't get vdec subdev id.\n"); - ret = -EINVAL; - goto err; + return -EINVAL; } hw_idx = (enum mtk_vdec_hw_id)(uintptr_t)of_id->data; if (hw_idx >= MTK_VDEC_HW_MAX) { dev_err(dev, "Hardware index %d not correct.\n", hw_idx); - ret = -EINVAL; - goto err; + return -EINVAL; } main_dev->subdev_dev[hw_idx] = subdev_dev; @@ -173,36 +174,25 @@ static int mtk_vdec_hw_probe(struct platform_device *pdev) if (IS_SUPPORT_VDEC_HW_IRQ(hw_idx)) { ret = mtk_vdec_hw_init_irq(subdev_dev); if (ret) - goto err; + return ret; } subdev_dev->reg_base[VDEC_HW_MISC] = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR((__force void *)subdev_dev->reg_base[VDEC_HW_MISC])) { ret = PTR_ERR((__force void *)subdev_dev->reg_base[VDEC_HW_MISC]); - goto err; + return ret; } if (!main_dev->subdev_prob_done) main_dev->subdev_prob_done = mtk_vdec_hw_prob_done; platform_set_drvdata(pdev, subdev_dev); - return 0; -err: - pm_runtime_disable(subdev_dev->pm.dev); - return ret; -} - -static int mtk_vdec_hw_remove(struct platform_device *pdev) -{ - pm_runtime_disable(&pdev->dev); - return 0; } static struct platform_driver mtk_vdec_driver = { .probe = mtk_vdec_hw_probe, - .remove = mtk_vdec_hw_remove, .driver = { .name = "mtk-vdec-comp", .of_match_table = mtk_vdec_hw_match, From e01c3ec7d60c3ede6f7a58ac6a8bb031f8c245f8 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Fri, 5 May 2023 14:06:17 +0800 Subject: [PATCH 056/253] media: nxp: remove unneeded semicolon No functional modification involved. ./drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c:226:2-3: Unneeded semicolon. Reported-by: Abaci Robot Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=4868 Signed-off-by: Jiapeng Chong Reviewed-by: Laurent Pinchart Signed-off-by: Hans Verkuil --- drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c index b5ffde46f31b..f7447b2f4d77 100644 --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c @@ -223,7 +223,7 @@ static int mxc_isi_crossbar_init_cfg(struct v4l2_subdev *sd, route->sink_pad = i; route->source_pad = i + xbar->num_sinks; route->flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE; - }; + } routing.num_routes = xbar->num_sources; routing.routes = routes; From 72a6127e9305ccf517ca962533c90c75bac39a57 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 23 May 2023 17:16:00 +0200 Subject: [PATCH 057/253] media: Add common header file with JPEG marker definitions When compile-testing on mips/RB532 with W=1: arch/mips/include/asm/mach-rc32434/rb.h:13: note: this is the location of the previous definition 13 | #define RST (1 << 15) | drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_parse.c:15: warning: "RST" redefined 15 | #define RST 0xd0 | drivers/media/platform/renesas/rcar_jpu.c:77: warning: "RST" redefined 77 | #define RST 0xd0 | "RST" is indeed a name too short to be conflict-free. Fix this by creating a common header file, containing definitions for all JPEG markers used, prefixed by "JPEG_MARKER_", based on the existing private definitions in the Samsung S5P JPEG driver, and convert all affected drivers. Reported-by: kernel test robot Link: https://lore.kernel.org/oe-kbuild-all/202304152346.hJOPxPRh-lkp@intel.com/ Link: https://lore.kernel.org/oe-kbuild-all/202304150059.bHUyuriy-lkp@intel.com/ Signed-off-by: Geert Uytterhoeven Acked-by: Andrzej Pietrasiewicz (s5p-jpeg) Reviewed-by: Laurent Pinchart Signed-off-by: Hans Verkuil --- .../mediatek/jpeg/mtk_jpeg_dec_parse.c | 17 ++---- drivers/media/platform/renesas/rcar_jpu.c | 55 +++++++++---------- .../platform/samsung/s5p-jpeg/jpeg-core.h | 12 +--- include/media/jpeg.h | 20 +++++++ 4 files changed, 52 insertions(+), 52 deletions(-) create mode 100644 include/media/jpeg.h diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_parse.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_parse.c index b95c45791c29..bb9cdc9e0e90 100644 --- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_parse.c +++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_parse.c @@ -7,15 +7,10 @@ #include #include +#include #include "mtk_jpeg_dec_parse.h" -#define TEM 0x01 -#define SOF0 0xc0 -#define RST 0xd0 -#define SOI 0xd8 -#define EOI 0xd9 - struct mtk_jpeg_stream { u8 *addr; u32 size; @@ -83,7 +78,7 @@ static bool mtk_jpeg_do_parse(struct mtk_jpeg_dec_param *param, u8 *src_addr_va, length = 0; switch (byte) { - case SOF0: + case JPEG_MARKER_SOF0: /* length */ if (read_word_be(&stream, &word)) break; @@ -123,10 +118,10 @@ static bool mtk_jpeg_do_parse(struct mtk_jpeg_dec_param *param, u8 *src_addr_va, notfound = !(i == param->comp_num); break; - case RST ... RST + 7: - case SOI: - case EOI: - case TEM: + case JPEG_MARKER_RST ... JPEG_MARKER_RST + 7: + case JPEG_MARKER_SOI: + case JPEG_MARKER_EOI: + case JPEG_MARKER_TEM: break; default: if (read_word_be(&stream, &word)) diff --git a/drivers/media/platform/renesas/rcar_jpu.c b/drivers/media/platform/renesas/rcar_jpu.c index e7f604807825..2b8cb50f54de 100644 --- a/drivers/media/platform/renesas/rcar_jpu.c +++ b/drivers/media/platform/renesas/rcar_jpu.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -71,19 +72,6 @@ #define JPU_JPEG_DEFAULT_422_PIX_FMT V4L2_PIX_FMT_NV16M #define JPU_JPEG_DEFAULT_420_PIX_FMT V4L2_PIX_FMT_NV12M -/* JPEG markers */ -#define TEM 0x01 -#define SOF0 0xc0 -#define RST 0xd0 -#define SOI 0xd8 -#define EOI 0xd9 -#define DHP 0xde -#define DHT 0xc4 -#define COM 0xfe -#define DQT 0xdb -#define DRI 0xdd -#define APP0 0xe0 - #define JPU_RESET_TIMEOUT 100 /* ms */ #define JPU_JOB_TIMEOUT 300 /* ms */ #define JPU_MAX_QUALITY 4 @@ -330,26 +318,32 @@ static const u8 zigzag[] = { * Huffman tables; Padding with 0xff (33.3.27 R01UH0501EJ0100 Rev.1.00) */ #define JPU_JPEG_HDR_BLOB { \ - 0xff, SOI, 0xff, DQT, 0x00, JPU_JPEG_QTBL_SIZE + 0x3, JPU_JPEG_LUM, \ - [JPU_JPEG_QTBL_LUM_OFFSET ... \ + 0xff, JPEG_MARKER_SOI, 0xff, JPEG_MARKER_DQT, 0x00, \ + JPU_JPEG_QTBL_SIZE + 0x3, JPU_JPEG_LUM, \ + [JPU_JPEG_QTBL_LUM_OFFSET ... \ JPU_JPEG_QTBL_LUM_OFFSET + JPU_JPEG_QTBL_SIZE - 1] = 0x00, \ - 0xff, DQT, 0x00, JPU_JPEG_QTBL_SIZE + 0x3, JPU_JPEG_CHR, \ + 0xff, JPEG_MARKER_DQT, 0x00, JPU_JPEG_QTBL_SIZE + 0x3, JPU_JPEG_CHR, \ [JPU_JPEG_QTBL_CHR_OFFSET ... JPU_JPEG_QTBL_CHR_OFFSET + \ - JPU_JPEG_QTBL_SIZE - 1] = 0x00, 0xff, SOF0, 0x00, 0x11, 0x08, \ + JPU_JPEG_QTBL_SIZE - 1] = 0x00, \ + 0xff, JPEG_MARKER_SOF0, 0x00, 0x11, 0x08, \ [JPU_JPEG_HEIGHT_OFFSET ... JPU_JPEG_HEIGHT_OFFSET + 1] = 0x00, \ [JPU_JPEG_WIDTH_OFFSET ... JPU_JPEG_WIDTH_OFFSET + 1] = 0x00, \ 0x03, 0x01, [JPU_JPEG_SUBS_OFFSET] = 0x00, JPU_JPEG_LUM, \ 0x02, 0x11, JPU_JPEG_CHR, 0x03, 0x11, JPU_JPEG_CHR, \ - 0xff, DHT, 0x00, JPU_JPEG_HDCTBL_SIZE + 0x3, JPU_JPEG_LUM|JPU_JPEG_DC, \ + 0xff, JPEG_MARKER_DHT, 0x00, JPU_JPEG_HDCTBL_SIZE + 0x3, \ + JPU_JPEG_LUM | JPU_JPEG_DC, \ [JPU_JPEG_HDCTBL_LUM_OFFSET ... \ JPU_JPEG_HDCTBL_LUM_OFFSET + JPU_JPEG_HDCTBL_SIZE - 1] = 0x00, \ - 0xff, DHT, 0x00, JPU_JPEG_HACTBL_SIZE + 0x3, JPU_JPEG_LUM|JPU_JPEG_AC, \ + 0xff, JPEG_MARKER_DHT, 0x00, JPU_JPEG_HACTBL_SIZE + 0x3, \ + JPU_JPEG_LUM | JPU_JPEG_AC, \ [JPU_JPEG_HACTBL_LUM_OFFSET ... \ JPU_JPEG_HACTBL_LUM_OFFSET + JPU_JPEG_HACTBL_SIZE - 1] = 0x00, \ - 0xff, DHT, 0x00, JPU_JPEG_HDCTBL_SIZE + 0x3, JPU_JPEG_CHR|JPU_JPEG_DC, \ + 0xff, JPEG_MARKER_DHT, 0x00, JPU_JPEG_HDCTBL_SIZE + 0x3, \ + JPU_JPEG_CHR | JPU_JPEG_DC, \ [JPU_JPEG_HDCTBL_CHR_OFFSET ... \ JPU_JPEG_HDCTBL_CHR_OFFSET + JPU_JPEG_HDCTBL_SIZE - 1] = 0x00, \ - 0xff, DHT, 0x00, JPU_JPEG_HACTBL_SIZE + 0x3, JPU_JPEG_CHR|JPU_JPEG_AC, \ + 0xff, JPEG_MARKER_DHT, 0x00, JPU_JPEG_HACTBL_SIZE + 0x3, \ + JPU_JPEG_CHR | JPU_JPEG_AC, \ [JPU_JPEG_HACTBL_CHR_OFFSET ... \ JPU_JPEG_HACTBL_CHR_OFFSET + JPU_JPEG_HACTBL_SIZE - 1] = 0x00, \ [JPU_JPEG_PADDING_OFFSET ... JPU_JPEG_HDR_SIZE - 1] = 0xff \ @@ -613,7 +607,8 @@ static u8 jpu_parse_hdr(void *buffer, unsigned long size, unsigned int *width, * basic size check and EOI - we don't want to let JPU cross * buffer bounds in any case. Hope it's stopping by EOI. */ - if (size < JPU_JPEG_MIN_SIZE || *(u8 *)(buffer + size - 1) != EOI) + if (size < JPU_JPEG_MIN_SIZE || + *(u8 *)(buffer + size - 1) != JPEG_MARKER_EOI) return 0; for (;;) { @@ -624,14 +619,14 @@ static u8 jpu_parse_hdr(void *buffer, unsigned long size, unsigned int *width, c = get_byte(&jpeg_buffer); while (c == 0xff || c == 0); - if (!soi && c == SOI) { + if (!soi && c == JPEG_MARKER_SOI) { soi = true; continue; - } else if (soi != (c != SOI)) + } else if (soi != (c != JPEG_MARKER_SOI)) return 0; switch (c) { - case SOF0: /* SOF0: baseline JPEG */ + case JPEG_MARKER_SOF0: /* SOF0: baseline JPEG */ skip(&jpeg_buffer, 3); /* segment length and bpp */ if (get_word_be(&jpeg_buffer, height) || get_word_be(&jpeg_buffer, width) || @@ -640,11 +635,11 @@ static u8 jpu_parse_hdr(void *buffer, unsigned long size, unsigned int *width, skip(&jpeg_buffer, 1); return get_byte(&jpeg_buffer); - case DHT: - case DQT: - case COM: - case DRI: - case APP0 ... APP0 + 0x0f: + case JPEG_MARKER_DHT: + case JPEG_MARKER_DQT: + case JPEG_MARKER_COM: + case JPEG_MARKER_DRI: + case JPEG_MARKER_APP0 ... JPEG_MARKER_APP0 + 0x0f: if (get_word_be(&jpeg_buffer, &word)) return 0; skip(&jpeg_buffer, (long)word - 2); diff --git a/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.h b/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.h index 5570c79f122f..4b665a3b630f 100644 --- a/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.h +++ b/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.h @@ -11,6 +11,7 @@ #define JPEG_CORE_H_ #include +#include #include #include #include @@ -36,17 +37,6 @@ #define EXYNOS3250_IRQ_TIMEOUT 0x10000000 -/* a selection of JPEG markers */ -#define JPEG_MARKER_TEM 0x01 -#define JPEG_MARKER_SOF0 0xc0 -#define JPEG_MARKER_DHT 0xc4 -#define JPEG_MARKER_RST 0xd0 -#define JPEG_MARKER_SOI 0xd8 -#define JPEG_MARKER_EOI 0xd9 -#define JPEG_MARKER_SOS 0xda -#define JPEG_MARKER_DQT 0xdb -#define JPEG_MARKER_DHP 0xde - /* Flags that indicate a format can be used for capture/output */ #define SJPEG_FMT_FLAG_ENC_CAPTURE (1 << 0) #define SJPEG_FMT_FLAG_ENC_OUTPUT (1 << 1) diff --git a/include/media/jpeg.h b/include/media/jpeg.h new file mode 100644 index 000000000000..a01e142e99a7 --- /dev/null +++ b/include/media/jpeg.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _MEDIA_JPEG_H_ +#define _MEDIA_JPEG_H_ + +/* JPEG markers */ +#define JPEG_MARKER_TEM 0x01 +#define JPEG_MARKER_SOF0 0xc0 +#define JPEG_MARKER_DHT 0xc4 +#define JPEG_MARKER_RST 0xd0 +#define JPEG_MARKER_SOI 0xd8 +#define JPEG_MARKER_EOI 0xd9 +#define JPEG_MARKER_SOS 0xda +#define JPEG_MARKER_DQT 0xdb +#define JPEG_MARKER_DRI 0xdd +#define JPEG_MARKER_DHP 0xde +#define JPEG_MARKER_APP0 0xe0 +#define JPEG_MARKER_COM 0xfe + +#endif /* _MEDIA_JPEG_H_ */ From aaeb31c00e61f6bdc2e4a3c2c491c5455ed3f7b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sun, 14 May 2023 14:04:07 +0200 Subject: [PATCH 058/253] media: Switch i2c drivers back to use .probe() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After commit b8a1a4cd5a98 ("i2c: Provide a temporary .probe_new() call-back type"), all drivers being converted to .probe_new() and then commit 03c835f498b5 ("i2c: Switch .probe() to not take an id parameter") convert back to (the new) .probe() to be able to eventually drop .probe_new() from struct i2c_driver. Signed-off-by: Uwe Kleine-König Signed-off-by: Hans Verkuil --- drivers/media/cec/i2c/ch7322.c | 2 +- drivers/media/dvb-frontends/a8293.c | 2 +- drivers/media/dvb-frontends/af9013.c | 2 +- drivers/media/dvb-frontends/af9033.c | 2 +- drivers/media/dvb-frontends/au8522_decoder.c | 2 +- drivers/media/dvb-frontends/cxd2099.c | 2 +- drivers/media/dvb-frontends/cxd2820r_core.c | 2 +- drivers/media/dvb-frontends/dvb-pll.c | 2 +- drivers/media/dvb-frontends/helene.c | 2 +- drivers/media/dvb-frontends/lgdt3306a.c | 2 +- drivers/media/dvb-frontends/lgdt330x.c | 2 +- drivers/media/dvb-frontends/m88ds3103.c | 2 +- drivers/media/dvb-frontends/mn88443x.c | 2 +- drivers/media/dvb-frontends/mn88472.c | 2 +- drivers/media/dvb-frontends/mn88473.c | 2 +- drivers/media/dvb-frontends/mxl692.c | 2 +- drivers/media/dvb-frontends/rtl2830.c | 2 +- drivers/media/dvb-frontends/rtl2832.c | 2 +- drivers/media/dvb-frontends/si2165.c | 2 +- drivers/media/dvb-frontends/si2168.c | 2 +- drivers/media/dvb-frontends/sp2.c | 2 +- drivers/media/dvb-frontends/stv090x.c | 2 +- drivers/media/dvb-frontends/stv6110x.c | 2 +- drivers/media/dvb-frontends/tc90522.c | 2 +- drivers/media/dvb-frontends/tda10071.c | 2 +- drivers/media/dvb-frontends/ts2020.c | 2 +- drivers/media/i2c/ad5820.c | 2 +- drivers/media/i2c/adp1653.c | 2 +- drivers/media/i2c/adv7170.c | 2 +- drivers/media/i2c/adv7175.c | 2 +- drivers/media/i2c/adv7180.c | 2 +- drivers/media/i2c/adv7183.c | 2 +- drivers/media/i2c/adv7343.c | 2 +- drivers/media/i2c/adv7393.c | 2 +- drivers/media/i2c/adv748x/adv748x-core.c | 2 +- drivers/media/i2c/adv7511-v4l2.c | 2 +- drivers/media/i2c/adv7604.c | 2 +- drivers/media/i2c/adv7842.c | 2 +- drivers/media/i2c/ak7375.c | 2 +- drivers/media/i2c/ak881x.c | 2 +- drivers/media/i2c/ar0521.c | 2 +- drivers/media/i2c/bt819.c | 2 +- drivers/media/i2c/bt856.c | 2 +- drivers/media/i2c/bt866.c | 2 +- drivers/media/i2c/ccs/ccs-core.c | 2 +- drivers/media/i2c/cs3308.c | 2 +- drivers/media/i2c/cs5345.c | 2 +- drivers/media/i2c/cs53l32a.c | 2 +- drivers/media/i2c/cx25840/cx25840-core.c | 2 +- drivers/media/i2c/dw9714.c | 2 +- drivers/media/i2c/dw9768.c | 2 +- drivers/media/i2c/dw9807-vcm.c | 2 +- drivers/media/i2c/et8ek8/et8ek8_driver.c | 2 +- drivers/media/i2c/hi556.c | 2 +- drivers/media/i2c/hi846.c | 2 +- drivers/media/i2c/hi847.c | 2 +- drivers/media/i2c/imx208.c | 2 +- drivers/media/i2c/imx214.c | 2 +- drivers/media/i2c/imx219.c | 2 +- drivers/media/i2c/imx258.c | 2 +- drivers/media/i2c/imx274.c | 2 +- drivers/media/i2c/imx290.c | 4 ++-- drivers/media/i2c/imx296.c | 2 +- drivers/media/i2c/imx319.c | 2 +- drivers/media/i2c/imx334.c | 2 +- drivers/media/i2c/imx335.c | 2 +- drivers/media/i2c/imx355.c | 2 +- drivers/media/i2c/imx412.c | 2 +- drivers/media/i2c/imx415.c | 2 +- drivers/media/i2c/ir-kbd-i2c.c | 2 +- drivers/media/i2c/isl7998x.c | 2 +- drivers/media/i2c/ks0127.c | 2 +- drivers/media/i2c/lm3560.c | 2 +- drivers/media/i2c/lm3646.c | 2 +- drivers/media/i2c/m52790.c | 2 +- drivers/media/i2c/max2175.c | 2 +- drivers/media/i2c/max9286.c | 2 +- drivers/media/i2c/ml86v7667.c | 2 +- drivers/media/i2c/msp3400-driver.c | 2 +- drivers/media/i2c/mt9m001.c | 2 +- drivers/media/i2c/mt9m111.c | 2 +- drivers/media/i2c/mt9p031.c | 2 +- drivers/media/i2c/mt9t112.c | 2 +- drivers/media/i2c/mt9v011.c | 2 +- drivers/media/i2c/mt9v032.c | 2 +- drivers/media/i2c/mt9v111.c | 2 +- drivers/media/i2c/og01a1b.c | 2 +- drivers/media/i2c/ov02a10.c | 4 ++-- drivers/media/i2c/ov08d10.c | 2 +- drivers/media/i2c/ov08x40.c | 2 +- drivers/media/i2c/ov13858.c | 2 +- drivers/media/i2c/ov13b10.c | 2 +- drivers/media/i2c/ov2640.c | 2 +- drivers/media/i2c/ov2659.c | 2 +- drivers/media/i2c/ov2680.c | 2 +- drivers/media/i2c/ov2685.c | 4 ++-- drivers/media/i2c/ov2740.c | 2 +- drivers/media/i2c/ov4689.c | 2 +- drivers/media/i2c/ov5640.c | 2 +- drivers/media/i2c/ov5645.c | 2 +- drivers/media/i2c/ov5647.c | 2 +- drivers/media/i2c/ov5648.c | 4 ++-- drivers/media/i2c/ov5670.c | 2 +- drivers/media/i2c/ov5675.c | 2 +- drivers/media/i2c/ov5693.c | 2 +- drivers/media/i2c/ov5695.c | 4 ++-- drivers/media/i2c/ov6650.c | 2 +- drivers/media/i2c/ov7251.c | 2 +- drivers/media/i2c/ov7640.c | 2 +- drivers/media/i2c/ov7670.c | 2 +- drivers/media/i2c/ov772x.c | 2 +- drivers/media/i2c/ov7740.c | 2 +- drivers/media/i2c/ov8856.c | 2 +- drivers/media/i2c/ov8858.c | 4 ++-- drivers/media/i2c/ov8865.c | 4 ++-- drivers/media/i2c/ov9282.c | 2 +- drivers/media/i2c/ov9640.c | 2 +- drivers/media/i2c/ov9650.c | 2 +- drivers/media/i2c/ov9734.c | 2 +- drivers/media/i2c/rdacm20.c | 2 +- drivers/media/i2c/rdacm21.c | 2 +- drivers/media/i2c/rj54n1cb0c.c | 2 +- drivers/media/i2c/s5c73m3/s5c73m3-core.c | 2 +- drivers/media/i2c/s5k5baf.c | 2 +- drivers/media/i2c/s5k6a3.c | 2 +- drivers/media/i2c/saa6588.c | 2 +- drivers/media/i2c/saa6752hs.c | 2 +- drivers/media/i2c/saa7110.c | 2 +- drivers/media/i2c/saa7115.c | 2 +- drivers/media/i2c/saa7127.c | 2 +- drivers/media/i2c/saa717x.c | 2 +- drivers/media/i2c/saa7185.c | 2 +- drivers/media/i2c/sony-btf-mpx.c | 2 +- drivers/media/i2c/st-mipid02.c | 2 +- drivers/media/i2c/st-vgxy61.c | 2 +- drivers/media/i2c/tc358743.c | 2 +- drivers/media/i2c/tc358746.c | 2 +- drivers/media/i2c/tda1997x.c | 2 +- drivers/media/i2c/tda7432.c | 2 +- drivers/media/i2c/tda9840.c | 2 +- drivers/media/i2c/tea6415c.c | 2 +- drivers/media/i2c/tea6420.c | 2 +- drivers/media/i2c/ths7303.c | 2 +- drivers/media/i2c/ths8200.c | 2 +- drivers/media/i2c/tlv320aic23b.c | 2 +- drivers/media/i2c/tvaudio.c | 2 +- drivers/media/i2c/tvp514x.c | 2 +- drivers/media/i2c/tvp5150.c | 2 +- drivers/media/i2c/tvp7002.c | 2 +- drivers/media/i2c/tw2804.c | 2 +- drivers/media/i2c/tw9903.c | 2 +- drivers/media/i2c/tw9906.c | 2 +- drivers/media/i2c/tw9910.c | 2 +- drivers/media/i2c/uda1342.c | 2 +- drivers/media/i2c/upd64031a.c | 2 +- drivers/media/i2c/upd64083.c | 2 +- drivers/media/i2c/video-i2c.c | 2 +- drivers/media/i2c/vp27smpx.c | 2 +- drivers/media/i2c/vpx3220.c | 2 +- drivers/media/i2c/wm8739.c | 2 +- drivers/media/i2c/wm8775.c | 2 +- drivers/media/radio/radio-tea5764.c | 2 +- drivers/media/radio/saa7706h.c | 2 +- drivers/media/radio/si470x/radio-si470x-i2c.c | 2 +- drivers/media/radio/si4713/si4713.c | 2 +- drivers/media/radio/tef6862.c | 2 +- drivers/media/test-drivers/vidtv/vidtv_demod.c | 2 +- drivers/media/test-drivers/vidtv/vidtv_tuner.c | 2 +- drivers/media/tuners/e4000.c | 2 +- drivers/media/tuners/fc2580.c | 2 +- drivers/media/tuners/m88rs6000t.c | 2 +- drivers/media/tuners/mt2060.c | 2 +- drivers/media/tuners/mxl301rf.c | 2 +- drivers/media/tuners/qm1d1b0004.c | 2 +- drivers/media/tuners/qm1d1c0042.c | 2 +- drivers/media/tuners/si2157.c | 2 +- drivers/media/tuners/tda18212.c | 2 +- drivers/media/tuners/tda18250.c | 2 +- drivers/media/tuners/tua9001.c | 2 +- drivers/media/usb/go7007/s2250-board.c | 2 +- drivers/media/v4l2-core/tuner-core.c | 2 +- 181 files changed, 188 insertions(+), 188 deletions(-) diff --git a/drivers/media/cec/i2c/ch7322.c b/drivers/media/cec/i2c/ch7322.c index 34fad7123704..439c15bc9e44 100644 --- a/drivers/media/cec/i2c/ch7322.c +++ b/drivers/media/cec/i2c/ch7322.c @@ -591,7 +591,7 @@ static struct i2c_driver ch7322_i2c_driver = { .name = "ch7322", .of_match_table = of_match_ptr(ch7322_of_match), }, - .probe_new = ch7322_probe, + .probe = ch7322_probe, .remove = ch7322_remove, }; diff --git a/drivers/media/dvb-frontends/a8293.c b/drivers/media/dvb-frontends/a8293.c index cca7cbdd4c7c..f39887c04978 100644 --- a/drivers/media/dvb-frontends/a8293.c +++ b/drivers/media/dvb-frontends/a8293.c @@ -266,7 +266,7 @@ static struct i2c_driver a8293_driver = { .name = "a8293", .suppress_bind_attrs = true, }, - .probe_new = a8293_probe, + .probe = a8293_probe, .remove = a8293_remove, .id_table = a8293_id_table, }; diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c index 206758a73ae2..a829c89792a4 100644 --- a/drivers/media/dvb-frontends/af9013.c +++ b/drivers/media/dvb-frontends/af9013.c @@ -1563,7 +1563,7 @@ static struct i2c_driver af9013_driver = { .name = "af9013", .suppress_bind_attrs = true, }, - .probe_new = af9013_probe, + .probe = af9013_probe, .remove = af9013_remove, .id_table = af9013_id_table, }; diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c index a30773f62006..49b7b04a7899 100644 --- a/drivers/media/dvb-frontends/af9033.c +++ b/drivers/media/dvb-frontends/af9033.c @@ -1183,7 +1183,7 @@ static struct i2c_driver af9033_driver = { .name = "af9033", .suppress_bind_attrs = true, }, - .probe_new = af9033_probe, + .probe = af9033_probe, .remove = af9033_remove, .id_table = af9033_id_table, }; diff --git a/drivers/media/dvb-frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c index 0f748cf46089..acc27376c246 100644 --- a/drivers/media/dvb-frontends/au8522_decoder.c +++ b/drivers/media/dvb-frontends/au8522_decoder.c @@ -776,7 +776,7 @@ static struct i2c_driver au8522_driver = { .driver = { .name = "au8522", }, - .probe_new = au8522_probe, + .probe = au8522_probe, .remove = au8522_remove, .id_table = au8522_id, }; diff --git a/drivers/media/dvb-frontends/cxd2099.c b/drivers/media/dvb-frontends/cxd2099.c index c0967ad95220..3f3b85743666 100644 --- a/drivers/media/dvb-frontends/cxd2099.c +++ b/drivers/media/dvb-frontends/cxd2099.c @@ -681,7 +681,7 @@ static struct i2c_driver cxd2099_driver = { .driver = { .name = "cxd2099", }, - .probe_new = cxd2099_probe, + .probe = cxd2099_probe, .remove = cxd2099_remove, .id_table = cxd2099_id, }; diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c index 47aa40967171..d7ee294c6833 100644 --- a/drivers/media/dvb-frontends/cxd2820r_core.c +++ b/drivers/media/dvb-frontends/cxd2820r_core.c @@ -733,7 +733,7 @@ static struct i2c_driver cxd2820r_driver = { .name = "cxd2820r", .suppress_bind_attrs = true, }, - .probe_new = cxd2820r_probe, + .probe = cxd2820r_probe, .remove = cxd2820r_remove, .id_table = cxd2820r_id_table, }; diff --git a/drivers/media/dvb-frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c index e35e00db7dbb..90cb41eacf98 100644 --- a/drivers/media/dvb-frontends/dvb-pll.c +++ b/drivers/media/dvb-frontends/dvb-pll.c @@ -942,7 +942,7 @@ static struct i2c_driver dvb_pll_driver = { .driver = { .name = "dvb_pll", }, - .probe_new = dvb_pll_probe, + .probe = dvb_pll_probe, .remove = dvb_pll_remove, .id_table = dvb_pll_id, }; diff --git a/drivers/media/dvb-frontends/helene.c b/drivers/media/dvb-frontends/helene.c index e4bbf6a51a2b..68c1a3e0e2ba 100644 --- a/drivers/media/dvb-frontends/helene.c +++ b/drivers/media/dvb-frontends/helene.c @@ -1110,7 +1110,7 @@ static struct i2c_driver helene_driver = { .driver = { .name = "helene", }, - .probe_new = helene_probe, + .probe = helene_probe, .id_table = helene_id, }; module_i2c_driver(helene_driver); diff --git a/drivers/media/dvb-frontends/lgdt3306a.c b/drivers/media/dvb-frontends/lgdt3306a.c index 6bf723b5ffad..70258884126b 100644 --- a/drivers/media/dvb-frontends/lgdt3306a.c +++ b/drivers/media/dvb-frontends/lgdt3306a.c @@ -2249,7 +2249,7 @@ static struct i2c_driver lgdt3306a_driver = { .name = "lgdt3306a", .suppress_bind_attrs = true, }, - .probe_new = lgdt3306a_probe, + .probe = lgdt3306a_probe, .remove = lgdt3306a_remove, .id_table = lgdt3306a_id_table, }; diff --git a/drivers/media/dvb-frontends/lgdt330x.c b/drivers/media/dvb-frontends/lgdt330x.c index 1d6932d8e497..83565209c3b1 100644 --- a/drivers/media/dvb-frontends/lgdt330x.c +++ b/drivers/media/dvb-frontends/lgdt330x.c @@ -993,7 +993,7 @@ static struct i2c_driver lgdt330x_driver = { .name = "lgdt330x", .suppress_bind_attrs = true, }, - .probe_new = lgdt330x_probe, + .probe = lgdt330x_probe, .remove = lgdt330x_remove, .id_table = lgdt330x_id_table, }; diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c index f26508b217ee..cf49ac56a37e 100644 --- a/drivers/media/dvb-frontends/m88ds3103.c +++ b/drivers/media/dvb-frontends/m88ds3103.c @@ -1941,7 +1941,7 @@ static struct i2c_driver m88ds3103_driver = { .name = "m88ds3103", .suppress_bind_attrs = true, }, - .probe_new = m88ds3103_probe, + .probe = m88ds3103_probe, .remove = m88ds3103_remove, .id_table = m88ds3103_id_table, }; diff --git a/drivers/media/dvb-frontends/mn88443x.c b/drivers/media/dvb-frontends/mn88443x.c index 0782f8377eb2..2ce5692bc22c 100644 --- a/drivers/media/dvb-frontends/mn88443x.c +++ b/drivers/media/dvb-frontends/mn88443x.c @@ -800,7 +800,7 @@ static struct i2c_driver mn88443x_driver = { .name = "mn88443x", .of_match_table = mn88443x_of_match, }, - .probe_new = mn88443x_probe, + .probe = mn88443x_probe, .remove = mn88443x_remove, .id_table = mn88443x_i2c_id, }; diff --git a/drivers/media/dvb-frontends/mn88472.c b/drivers/media/dvb-frontends/mn88472.c index 4a71f1c6371a..73d1e52de569 100644 --- a/drivers/media/dvb-frontends/mn88472.c +++ b/drivers/media/dvb-frontends/mn88472.c @@ -718,7 +718,7 @@ static struct i2c_driver mn88472_driver = { .name = "mn88472", .suppress_bind_attrs = true, }, - .probe_new = mn88472_probe, + .probe = mn88472_probe, .remove = mn88472_remove, .id_table = mn88472_id_table, }; diff --git a/drivers/media/dvb-frontends/mn88473.c b/drivers/media/dvb-frontends/mn88473.c index 205b14ae584e..eb50591c0e7a 100644 --- a/drivers/media/dvb-frontends/mn88473.c +++ b/drivers/media/dvb-frontends/mn88473.c @@ -753,7 +753,7 @@ static struct i2c_driver mn88473_driver = { .name = "mn88473", .suppress_bind_attrs = true, }, - .probe_new = mn88473_probe, + .probe = mn88473_probe, .remove = mn88473_remove, .id_table = mn88473_id_table, }; diff --git a/drivers/media/dvb-frontends/mxl692.c b/drivers/media/dvb-frontends/mxl692.c index 9858e11943a0..2a31bde2630f 100644 --- a/drivers/media/dvb-frontends/mxl692.c +++ b/drivers/media/dvb-frontends/mxl692.c @@ -1355,7 +1355,7 @@ static struct i2c_driver mxl692_driver = { .driver = { .name = "mxl692", }, - .probe_new = mxl692_probe, + .probe = mxl692_probe, .remove = mxl692_remove, .id_table = mxl692_id_table, }; diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index db3254950147..35c969fd2cb5 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -886,7 +886,7 @@ static struct i2c_driver rtl2830_driver = { .name = "rtl2830", .suppress_bind_attrs = true, }, - .probe_new = rtl2830_probe, + .probe = rtl2830_probe, .remove = rtl2830_remove, .id_table = rtl2830_id_table, }; diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 900d4db8b922..601cf45c3935 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -1135,7 +1135,7 @@ static struct i2c_driver rtl2832_driver = { .name = "rtl2832", .suppress_bind_attrs = true, }, - .probe_new = rtl2832_probe, + .probe = rtl2832_probe, .remove = rtl2832_remove, .id_table = rtl2832_id_table, }; diff --git a/drivers/media/dvb-frontends/si2165.c b/drivers/media/dvb-frontends/si2165.c index cc07e965c34c..72810efd1a96 100644 --- a/drivers/media/dvb-frontends/si2165.c +++ b/drivers/media/dvb-frontends/si2165.c @@ -1292,7 +1292,7 @@ static struct i2c_driver si2165_driver = { .driver = { .name = "si2165", }, - .probe_new = si2165_probe, + .probe = si2165_probe, .remove = si2165_remove, .id_table = si2165_id_table, }; diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c index 2a0e108c5eb0..dae1f2153e8b 100644 --- a/drivers/media/dvb-frontends/si2168.c +++ b/drivers/media/dvb-frontends/si2168.c @@ -798,7 +798,7 @@ static struct i2c_driver si2168_driver = { .name = "si2168", .suppress_bind_attrs = true, }, - .probe_new = si2168_probe, + .probe = si2168_probe, .remove = si2168_remove, .id_table = si2168_id_table, }; diff --git a/drivers/media/dvb-frontends/sp2.c b/drivers/media/dvb-frontends/sp2.c index 3395f6b5b948..4d7d0b8b51b4 100644 --- a/drivers/media/dvb-frontends/sp2.c +++ b/drivers/media/dvb-frontends/sp2.c @@ -416,7 +416,7 @@ static struct i2c_driver sp2_driver = { .driver = { .name = "sp2", }, - .probe_new = sp2_probe, + .probe = sp2_probe, .remove = sp2_remove, .id_table = sp2_id, }; diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c index 9bde0ad6f26e..a07dc5fdeb3d 100644 --- a/drivers/media/dvb-frontends/stv090x.c +++ b/drivers/media/dvb-frontends/stv090x.c @@ -5084,7 +5084,7 @@ static struct i2c_driver stv090x_driver = { .name = "stv090x", .suppress_bind_attrs = true, }, - .probe_new = stv090x_probe, + .probe = stv090x_probe, .remove = stv090x_remove, .id_table = stv090x_id_table, }; diff --git a/drivers/media/dvb-frontends/stv6110x.c b/drivers/media/dvb-frontends/stv6110x.c index b2f456116c60..11653f846c12 100644 --- a/drivers/media/dvb-frontends/stv6110x.c +++ b/drivers/media/dvb-frontends/stv6110x.c @@ -480,7 +480,7 @@ static struct i2c_driver stv6110x_driver = { .name = "stv6110x", .suppress_bind_attrs = true, }, - .probe_new = stv6110x_probe, + .probe = stv6110x_probe, .remove = stv6110x_remove, .id_table = stv6110x_id_table, }; diff --git a/drivers/media/dvb-frontends/tc90522.c b/drivers/media/dvb-frontends/tc90522.c index 77a991bf4713..879f028f9682 100644 --- a/drivers/media/dvb-frontends/tc90522.c +++ b/drivers/media/dvb-frontends/tc90522.c @@ -840,7 +840,7 @@ static struct i2c_driver tc90522_driver = { .driver = { .name = "tc90522", }, - .probe_new = tc90522_probe, + .probe = tc90522_probe, .remove = tc90522_remove, .id_table = tc90522_id, }; diff --git a/drivers/media/dvb-frontends/tda10071.c b/drivers/media/dvb-frontends/tda10071.c index c8e5617d08c0..6640851d8bbc 100644 --- a/drivers/media/dvb-frontends/tda10071.c +++ b/drivers/media/dvb-frontends/tda10071.c @@ -1240,7 +1240,7 @@ static struct i2c_driver tda10071_driver = { .name = "tda10071", .suppress_bind_attrs = true, }, - .probe_new = tda10071_probe, + .probe = tda10071_probe, .remove = tda10071_remove, .id_table = tda10071_id_table, }; diff --git a/drivers/media/dvb-frontends/ts2020.c b/drivers/media/dvb-frontends/ts2020.c index c28fee7509cd..f5b60f827697 100644 --- a/drivers/media/dvb-frontends/ts2020.c +++ b/drivers/media/dvb-frontends/ts2020.c @@ -720,7 +720,7 @@ static struct i2c_driver ts2020_driver = { .driver = { .name = "ts2020", }, - .probe_new = ts2020_probe, + .probe = ts2020_probe, .remove = ts2020_remove, .id_table = ts2020_id_table, }; diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c index 44c26af49071..5f605b9be3b1 100644 --- a/drivers/media/i2c/ad5820.c +++ b/drivers/media/i2c/ad5820.c @@ -370,7 +370,7 @@ static struct i2c_driver ad5820_i2c_driver = { .pm = &ad5820_pm, .of_match_table = ad5820_of_table, }, - .probe_new = ad5820_probe, + .probe = ad5820_probe, .remove = ad5820_remove, .id_table = ad5820_id_table, }; diff --git a/drivers/media/i2c/adp1653.c b/drivers/media/i2c/adp1653.c index a61a77de6eee..98ca417b8004 100644 --- a/drivers/media/i2c/adp1653.c +++ b/drivers/media/i2c/adp1653.c @@ -535,7 +535,7 @@ static struct i2c_driver adp1653_i2c_driver = { .name = ADP1653_NAME, .pm = &adp1653_pm_ops, }, - .probe_new = adp1653_probe, + .probe = adp1653_probe, .remove = adp1653_remove, .id_table = adp1653_id_table, }; diff --git a/drivers/media/i2c/adv7170.c b/drivers/media/i2c/adv7170.c index aa0f80e299b3..4a2b9fd9e2da 100644 --- a/drivers/media/i2c/adv7170.c +++ b/drivers/media/i2c/adv7170.c @@ -387,7 +387,7 @@ static struct i2c_driver adv7170_driver = { .driver = { .name = "adv7170", }, - .probe_new = adv7170_probe, + .probe = adv7170_probe, .remove = adv7170_remove, .id_table = adv7170_id, }; diff --git a/drivers/media/i2c/adv7175.c b/drivers/media/i2c/adv7175.c index d9bea2b9ec33..e454cba4b026 100644 --- a/drivers/media/i2c/adv7175.c +++ b/drivers/media/i2c/adv7175.c @@ -442,7 +442,7 @@ static struct i2c_driver adv7175_driver = { .driver = { .name = "adv7175", }, - .probe_new = adv7175_probe, + .probe = adv7175_probe, .remove = adv7175_remove, .id_table = adv7175_id, }; diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index a22402b7acff..99ba925e8ec8 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -1610,7 +1610,7 @@ static struct i2c_driver adv7180_driver = { .pm = ADV7180_PM_OPS, .of_match_table = of_match_ptr(adv7180_of_id), }, - .probe_new = adv7180_probe, + .probe = adv7180_probe, .remove = adv7180_remove, .id_table = adv7180_id, }; diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c index 98b63d79d33d..3659feafac69 100644 --- a/drivers/media/i2c/adv7183.c +++ b/drivers/media/i2c/adv7183.c @@ -631,7 +631,7 @@ static struct i2c_driver adv7183_driver = { .driver = { .name = "adv7183", }, - .probe_new = adv7183_probe, + .probe = adv7183_probe, .remove = adv7183_remove, .id_table = adv7183_id, }; diff --git a/drivers/media/i2c/adv7343.c b/drivers/media/i2c/adv7343.c index 7e84869d2434..ff21cd4744d3 100644 --- a/drivers/media/i2c/adv7343.c +++ b/drivers/media/i2c/adv7343.c @@ -521,7 +521,7 @@ static struct i2c_driver adv7343_driver = { .of_match_table = of_match_ptr(adv7343_of_match), .name = "adv7343", }, - .probe_new = adv7343_probe, + .probe = adv7343_probe, .remove = adv7343_remove, .id_table = adv7343_id, }; diff --git a/drivers/media/i2c/adv7393.c b/drivers/media/i2c/adv7393.c index 61e916cbe651..7638af455cef 100644 --- a/drivers/media/i2c/adv7393.c +++ b/drivers/media/i2c/adv7393.c @@ -455,7 +455,7 @@ static struct i2c_driver adv7393_driver = { .driver = { .name = "adv7393", }, - .probe_new = adv7393_probe, + .probe = adv7393_probe, .remove = adv7393_remove, .id_table = adv7393_id, }; diff --git a/drivers/media/i2c/adv748x/adv748x-core.c b/drivers/media/i2c/adv748x/adv748x-core.c index 4498d78a2357..3eb6d5e8f082 100644 --- a/drivers/media/i2c/adv748x/adv748x-core.c +++ b/drivers/media/i2c/adv748x/adv748x-core.c @@ -847,7 +847,7 @@ static struct i2c_driver adv748x_driver = { .of_match_table = adv748x_of_table, .pm = &adv748x_pm_ops, }, - .probe_new = adv748x_probe, + .probe = adv748x_probe, .remove = adv748x_remove, }; diff --git a/drivers/media/i2c/adv7511-v4l2.c b/drivers/media/i2c/adv7511-v4l2.c index 3999fa524cab..a9183d9282fd 100644 --- a/drivers/media/i2c/adv7511-v4l2.c +++ b/drivers/media/i2c/adv7511-v4l2.c @@ -1957,7 +1957,7 @@ static struct i2c_driver adv7511_driver = { .driver = { .name = "adv7511-v4l2", }, - .probe_new = adv7511_probe, + .probe = adv7511_probe, .remove = adv7511_remove, .id_table = adv7511_id, }; diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 3d0898c4175e..b202a85fbeaa 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -3689,7 +3689,7 @@ static struct i2c_driver adv76xx_driver = { .name = "adv7604", .of_match_table = of_match_ptr(adv76xx_of_id), }, - .probe_new = adv76xx_probe, + .probe = adv76xx_probe, .remove = adv76xx_remove, .id_table = adv76xx_i2c_id, }; diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index cb8655574119..c1664a3620c8 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c @@ -3619,7 +3619,7 @@ static struct i2c_driver adv7842_driver = { .driver = { .name = "adv7842", }, - .probe_new = adv7842_probe, + .probe = adv7842_probe, .remove = adv7842_remove, .id_table = adv7842_id, }; diff --git a/drivers/media/i2c/ak7375.c b/drivers/media/i2c/ak7375.c index e7cec45bc271..463b51d46320 100644 --- a/drivers/media/i2c/ak7375.c +++ b/drivers/media/i2c/ak7375.c @@ -306,7 +306,7 @@ static struct i2c_driver ak7375_i2c_driver = { .pm = &ak7375_pm_ops, .of_match_table = ak7375_of_table, }, - .probe_new = ak7375_probe, + .probe = ak7375_probe, .remove = ak7375_remove, }; module_i2c_driver(ak7375_i2c_driver); diff --git a/drivers/media/i2c/ak881x.c b/drivers/media/i2c/ak881x.c index 7c9ab76e2448..ce840adc2aa7 100644 --- a/drivers/media/i2c/ak881x.c +++ b/drivers/media/i2c/ak881x.c @@ -314,7 +314,7 @@ static struct i2c_driver ak881x_i2c_driver = { .driver = { .name = "ak881x", }, - .probe_new = ak881x_probe, + .probe = ak881x_probe, .remove = ak881x_remove, .id_table = ak881x_id, }; diff --git a/drivers/media/i2c/ar0521.c b/drivers/media/i2c/ar0521.c index 77f597571167..a4e39871e8f7 100644 --- a/drivers/media/i2c/ar0521.c +++ b/drivers/media/i2c/ar0521.c @@ -1198,7 +1198,7 @@ static struct i2c_driver ar0521_i2c_driver = { .pm = &ar0521_pm_ops, .of_match_table = ar0521_dt_ids, }, - .probe_new = ar0521_probe, + .probe = ar0521_probe, .remove = ar0521_remove, }; diff --git a/drivers/media/i2c/bt819.c b/drivers/media/i2c/bt819.c index 39f8a5361166..b4a25cc996dc 100644 --- a/drivers/media/i2c/bt819.c +++ b/drivers/media/i2c/bt819.c @@ -468,7 +468,7 @@ static struct i2c_driver bt819_driver = { .driver = { .name = "bt819", }, - .probe_new = bt819_probe, + .probe = bt819_probe, .remove = bt819_remove, .id_table = bt819_id, }; diff --git a/drivers/media/i2c/bt856.c b/drivers/media/i2c/bt856.c index d1d397b15b85..814acbd6a5a8 100644 --- a/drivers/media/i2c/bt856.c +++ b/drivers/media/i2c/bt856.c @@ -239,7 +239,7 @@ static struct i2c_driver bt856_driver = { .driver = { .name = "bt856", }, - .probe_new = bt856_probe, + .probe = bt856_probe, .remove = bt856_remove, .id_table = bt856_id, }; diff --git a/drivers/media/i2c/bt866.c b/drivers/media/i2c/bt866.c index d632d9a07f04..dada059cbce4 100644 --- a/drivers/media/i2c/bt866.c +++ b/drivers/media/i2c/bt866.c @@ -206,7 +206,7 @@ static struct i2c_driver bt866_driver = { .driver = { .name = "bt866", }, - .probe_new = bt866_probe, + .probe = bt866_probe, .remove = bt866_remove, .id_table = bt866_id, }; diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index 559a415fd827..49e0d9a09530 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -3731,7 +3731,7 @@ static struct i2c_driver ccs_i2c_driver = { .name = CCS_NAME, .pm = &ccs_pm_ops, }, - .probe_new = ccs_probe, + .probe = ccs_probe, .remove = ccs_remove, }; diff --git a/drivers/media/i2c/cs3308.c b/drivers/media/i2c/cs3308.c index a0b66c04fe25..61afa3d799d2 100644 --- a/drivers/media/i2c/cs3308.c +++ b/drivers/media/i2c/cs3308.c @@ -118,7 +118,7 @@ static struct i2c_driver cs3308_driver = { .driver = { .name = "cs3308", }, - .probe_new = cs3308_probe, + .probe = cs3308_probe, .remove = cs3308_remove, .id_table = cs3308_id, }; diff --git a/drivers/media/i2c/cs5345.c b/drivers/media/i2c/cs5345.c index ac4b5632fc46..3019a132e079 100644 --- a/drivers/media/i2c/cs5345.c +++ b/drivers/media/i2c/cs5345.c @@ -198,7 +198,7 @@ static struct i2c_driver cs5345_driver = { .driver = { .name = "cs5345", }, - .probe_new = cs5345_probe, + .probe = cs5345_probe, .remove = cs5345_remove, .id_table = cs5345_id, }; diff --git a/drivers/media/i2c/cs53l32a.c b/drivers/media/i2c/cs53l32a.c index 670f89de32d4..82881b79e730 100644 --- a/drivers/media/i2c/cs53l32a.c +++ b/drivers/media/i2c/cs53l32a.c @@ -209,7 +209,7 @@ static struct i2c_driver cs53l32a_driver = { .driver = { .name = "cs53l32a", }, - .probe_new = cs53l32a_probe, + .probe = cs53l32a_probe, .remove = cs53l32a_remove, .id_table = cs53l32a_id, }; diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c index 46cf422270b2..5aec25289062 100644 --- a/drivers/media/i2c/cx25840/cx25840-core.c +++ b/drivers/media/i2c/cx25840/cx25840-core.c @@ -6045,7 +6045,7 @@ static struct i2c_driver cx25840_driver = { .driver = { .name = "cx25840", }, - .probe_new = cx25840_probe, + .probe = cx25840_probe, .remove = cx25840_remove, .id_table = cx25840_id, }; diff --git a/drivers/media/i2c/dw9714.c b/drivers/media/i2c/dw9714.c index af59687383aa..cc09b32ede60 100644 --- a/drivers/media/i2c/dw9714.c +++ b/drivers/media/i2c/dw9714.c @@ -299,7 +299,7 @@ static struct i2c_driver dw9714_i2c_driver = { .pm = &dw9714_pm_ops, .of_match_table = dw9714_of_table, }, - .probe_new = dw9714_probe, + .probe = dw9714_probe, .remove = dw9714_remove, .id_table = dw9714_id_table, }; diff --git a/drivers/media/i2c/dw9768.c b/drivers/media/i2c/dw9768.c index 83a3ee275bbe..daabbece8c7e 100644 --- a/drivers/media/i2c/dw9768.c +++ b/drivers/media/i2c/dw9768.c @@ -549,7 +549,7 @@ static struct i2c_driver dw9768_i2c_driver = { .pm = &dw9768_pm_ops, .of_match_table = dw9768_of_table, }, - .probe_new = dw9768_probe, + .probe = dw9768_probe, .remove = dw9768_remove, }; module_i2c_driver(dw9768_i2c_driver); diff --git a/drivers/media/i2c/dw9807-vcm.c b/drivers/media/i2c/dw9807-vcm.c index 3599720db7e9..4148009e0e01 100644 --- a/drivers/media/i2c/dw9807-vcm.c +++ b/drivers/media/i2c/dw9807-vcm.c @@ -310,7 +310,7 @@ static struct i2c_driver dw9807_i2c_driver = { .pm = &dw9807_pm_ops, .of_match_table = dw9807_of_table, }, - .probe_new = dw9807_probe, + .probe = dw9807_probe, .remove = dw9807_remove, }; diff --git a/drivers/media/i2c/et8ek8/et8ek8_driver.c b/drivers/media/i2c/et8ek8/et8ek8_driver.c index ff9bb9fc97dd..d6fc843f9368 100644 --- a/drivers/media/i2c/et8ek8/et8ek8_driver.c +++ b/drivers/media/i2c/et8ek8/et8ek8_driver.c @@ -1501,7 +1501,7 @@ static struct i2c_driver et8ek8_i2c_driver = { .pm = &et8ek8_pm_ops, .of_match_table = et8ek8_of_table, }, - .probe_new = et8ek8_probe, + .probe = et8ek8_probe, .remove = __exit_p(et8ek8_remove), .id_table = et8ek8_id_table, }; diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c index 7daefab35cf0..50e78f5b058c 100644 --- a/drivers/media/i2c/hi556.c +++ b/drivers/media/i2c/hi556.c @@ -1350,7 +1350,7 @@ static struct i2c_driver hi556_i2c_driver = { .pm = &hi556_pm_ops, .acpi_match_table = ACPI_PTR(hi556_acpi_ids), }, - .probe_new = hi556_probe, + .probe = hi556_probe, .remove = hi556_remove, .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; diff --git a/drivers/media/i2c/hi846.c b/drivers/media/i2c/hi846.c index 306dc35e925f..5283a09fd359 100644 --- a/drivers/media/i2c/hi846.c +++ b/drivers/media/i2c/hi846.c @@ -2189,7 +2189,7 @@ static struct i2c_driver hi846_i2c_driver = { .pm = &hi846_pm_ops, .of_match_table = hi846_of_match, }, - .probe_new = hi846_probe, + .probe = hi846_probe, .remove = hi846_remove, }; diff --git a/drivers/media/i2c/hi847.c b/drivers/media/i2c/hi847.c index 5a82b15a9513..7cdce392e137 100644 --- a/drivers/media/i2c/hi847.c +++ b/drivers/media/i2c/hi847.c @@ -2999,7 +2999,7 @@ static struct i2c_driver hi847_i2c_driver = { .pm = &hi847_pm_ops, .acpi_match_table = ACPI_PTR(hi847_acpi_ids), }, - .probe_new = hi847_probe, + .probe = hi847_probe, .remove = hi847_remove, }; diff --git a/drivers/media/i2c/imx208.c b/drivers/media/i2c/imx208.c index 64c70ebf9869..3e870fa9ff79 100644 --- a/drivers/media/i2c/imx208.c +++ b/drivers/media/i2c/imx208.c @@ -1100,7 +1100,7 @@ static struct i2c_driver imx208_i2c_driver = { .pm = &imx208_pm_ops, .acpi_match_table = ACPI_PTR(imx208_acpi_ids), }, - .probe_new = imx208_probe, + .probe = imx208_probe, .remove = imx208_remove, .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c index 710c9fb515fd..2f9c8582f940 100644 --- a/drivers/media/i2c/imx214.c +++ b/drivers/media/i2c/imx214.c @@ -1112,7 +1112,7 @@ static struct i2c_driver imx214_i2c_driver = { .pm = &imx214_pm_ops, .name = "imx214", }, - .probe_new = imx214_probe, + .probe = imx214_probe, .remove = imx214_remove, }; diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c index f9471c9e3a74..d737d5e9a4a6 100644 --- a/drivers/media/i2c/imx219.c +++ b/drivers/media/i2c/imx219.c @@ -1583,7 +1583,7 @@ static struct i2c_driver imx219_i2c_driver = { .of_match_table = imx219_dt_ids, .pm = &imx219_pm_ops, }, - .probe_new = imx219_probe, + .probe = imx219_probe, .remove = imx219_remove, }; diff --git a/drivers/media/i2c/imx258.c b/drivers/media/i2c/imx258.c index 85d73b186111..e196565e846e 100644 --- a/drivers/media/i2c/imx258.c +++ b/drivers/media/i2c/imx258.c @@ -1395,7 +1395,7 @@ static struct i2c_driver imx258_i2c_driver = { .acpi_match_table = ACPI_PTR(imx258_acpi_ids), .of_match_table = imx258_dt_ids, }, - .probe_new = imx258_probe, + .probe = imx258_probe, .remove = imx258_remove, }; diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c index 9219f3c9594b..f33b692e6951 100644 --- a/drivers/media/i2c/imx274.c +++ b/drivers/media/i2c/imx274.c @@ -2168,7 +2168,7 @@ static struct i2c_driver imx274_i2c_driver = { .pm = &imx274_pm_ops, .of_match_table = imx274_of_id_table, }, - .probe_new = imx274_probe, + .probe = imx274_probe, .remove = imx274_remove, .id_table = imx274_id, }; diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c index 5ea25b7acc55..b3f832e9d7e1 100644 --- a/drivers/media/i2c/imx290.c +++ b/drivers/media/i2c/imx290.c @@ -1716,10 +1716,10 @@ static const struct of_device_id imx290_of_match[] = { MODULE_DEVICE_TABLE(of, imx290_of_match); static struct i2c_driver imx290_i2c_driver = { - .probe_new = imx290_probe, + .probe = imx290_probe, .remove = imx290_remove, .driver = { - .name = "imx290", + .name = "imx290", .pm = pm_ptr(&imx290_pm_ops), .of_match_table = imx290_of_match, }, diff --git a/drivers/media/i2c/imx296.c b/drivers/media/i2c/imx296.c index 4f22c0515ef8..70c129833601 100644 --- a/drivers/media/i2c/imx296.c +++ b/drivers/media/i2c/imx296.c @@ -1152,7 +1152,7 @@ static struct i2c_driver imx296_i2c_driver = { .name = "imx296", .pm = &imx296_pm_ops }, - .probe_new = imx296_probe, + .probe = imx296_probe, .remove = imx296_remove, }; diff --git a/drivers/media/i2c/imx319.c b/drivers/media/i2c/imx319.c index 45b1b61b2880..a2140848d0d6 100644 --- a/drivers/media/i2c/imx319.c +++ b/drivers/media/i2c/imx319.c @@ -2558,7 +2558,7 @@ static struct i2c_driver imx319_i2c_driver = { .pm = &imx319_pm_ops, .acpi_match_table = ACPI_PTR(imx319_acpi_ids), }, - .probe_new = imx319_probe, + .probe = imx319_probe, .remove = imx319_remove, .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; diff --git a/drivers/media/i2c/imx334.c b/drivers/media/i2c/imx334.c index 309c706114d2..bd79ebfe41ec 100644 --- a/drivers/media/i2c/imx334.c +++ b/drivers/media/i2c/imx334.c @@ -1382,7 +1382,7 @@ static const struct of_device_id imx334_of_match[] = { MODULE_DEVICE_TABLE(of, imx334_of_match); static struct i2c_driver imx334_driver = { - .probe_new = imx334_probe, + .probe = imx334_probe, .remove = imx334_remove, .driver = { .name = "imx334", diff --git a/drivers/media/i2c/imx335.c b/drivers/media/i2c/imx335.c index 078ede2b7a00..482a0b7f040a 100644 --- a/drivers/media/i2c/imx335.c +++ b/drivers/media/i2c/imx335.c @@ -1112,7 +1112,7 @@ static const struct of_device_id imx335_of_match[] = { MODULE_DEVICE_TABLE(of, imx335_of_match); static struct i2c_driver imx335_driver = { - .probe_new = imx335_probe, + .probe = imx335_probe, .remove = imx335_remove, .driver = { .name = "imx335", diff --git a/drivers/media/i2c/imx355.c b/drivers/media/i2c/imx355.c index 25d4dbb6041e..6571a98b1e9e 100644 --- a/drivers/media/i2c/imx355.c +++ b/drivers/media/i2c/imx355.c @@ -1845,7 +1845,7 @@ static struct i2c_driver imx355_i2c_driver = { .pm = &imx355_pm_ops, .acpi_match_table = ACPI_PTR(imx355_acpi_ids), }, - .probe_new = imx355_probe, + .probe = imx355_probe, .remove = imx355_remove, }; module_i2c_driver(imx355_i2c_driver); diff --git a/drivers/media/i2c/imx412.c b/drivers/media/i2c/imx412.c index e1e986dc8856..c7e862ae4040 100644 --- a/drivers/media/i2c/imx412.c +++ b/drivers/media/i2c/imx412.c @@ -1293,7 +1293,7 @@ static const struct of_device_id imx412_of_match[] = { MODULE_DEVICE_TABLE(of, imx412_of_match); static struct i2c_driver imx412_driver = { - .probe_new = imx412_probe, + .probe = imx412_probe, .remove = imx412_remove, .driver = { .name = "imx412", diff --git a/drivers/media/i2c/imx415.c b/drivers/media/i2c/imx415.c index d90392df98c7..4b5d1ee9cc6b 100644 --- a/drivers/media/i2c/imx415.c +++ b/drivers/media/i2c/imx415.c @@ -1283,7 +1283,7 @@ static const struct of_device_id imx415_of_match[] = { MODULE_DEVICE_TABLE(of, imx415_of_match); static struct i2c_driver imx415_driver = { - .probe_new = imx415_probe, + .probe = imx415_probe, .remove = imx415_remove, .driver = { .name = "imx415", diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c index 51921068931d..b37a2aaf8ac0 100644 --- a/drivers/media/i2c/ir-kbd-i2c.c +++ b/drivers/media/i2c/ir-kbd-i2c.c @@ -988,7 +988,7 @@ static struct i2c_driver ir_kbd_driver = { .driver = { .name = "ir-kbd-i2c", }, - .probe_new = ir_probe, + .probe = ir_probe, .remove = ir_remove, .id_table = ir_kbd_id, }; diff --git a/drivers/media/i2c/isl7998x.c b/drivers/media/i2c/isl7998x.c index ae7af2cc94f5..92e49d95363d 100644 --- a/drivers/media/i2c/isl7998x.c +++ b/drivers/media/i2c/isl7998x.c @@ -1614,7 +1614,7 @@ static struct i2c_driver isl7998x_i2c_driver = { .of_match_table = of_match_ptr(isl7998x_of_match), .pm = &isl7998x_pm_ops, }, - .probe_new = isl7998x_probe, + .probe = isl7998x_probe, .remove = isl7998x_remove, .id_table = isl7998x_id, }; diff --git a/drivers/media/i2c/ks0127.c b/drivers/media/i2c/ks0127.c index 0d86f2db7ad2..5c583f57e3f3 100644 --- a/drivers/media/i2c/ks0127.c +++ b/drivers/media/i2c/ks0127.c @@ -696,7 +696,7 @@ static struct i2c_driver ks0127_driver = { .driver = { .name = "ks0127", }, - .probe_new = ks0127_probe, + .probe = ks0127_probe, .remove = ks0127_remove, .id_table = ks0127_id, }; diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c index 5ef613604be7..05283ac68f2d 100644 --- a/drivers/media/i2c/lm3560.c +++ b/drivers/media/i2c/lm3560.c @@ -467,7 +467,7 @@ static struct i2c_driver lm3560_i2c_driver = { .name = LM3560_NAME, .pm = NULL, }, - .probe_new = lm3560_probe, + .probe = lm3560_probe, .remove = lm3560_remove, .id_table = lm3560_id_table, }; diff --git a/drivers/media/i2c/lm3646.c b/drivers/media/i2c/lm3646.c index 2a0cf74d2bed..fab3a7e05f92 100644 --- a/drivers/media/i2c/lm3646.c +++ b/drivers/media/i2c/lm3646.c @@ -396,7 +396,7 @@ static struct i2c_driver lm3646_i2c_driver = { .driver = { .name = LM3646_NAME, }, - .probe_new = lm3646_probe, + .probe = lm3646_probe, .remove = lm3646_remove, .id_table = lm3646_id_table, }; diff --git a/drivers/media/i2c/m52790.c b/drivers/media/i2c/m52790.c index 0e6507ab7e08..f8a69142aae9 100644 --- a/drivers/media/i2c/m52790.c +++ b/drivers/media/i2c/m52790.c @@ -172,7 +172,7 @@ static struct i2c_driver m52790_driver = { .driver = { .name = "m52790", }, - .probe_new = m52790_probe, + .probe = m52790_probe, .remove = m52790_remove, .id_table = m52790_id, }; diff --git a/drivers/media/i2c/max2175.c b/drivers/media/i2c/max2175.c index 1019020f3a37..70c2a2948fd4 100644 --- a/drivers/media/i2c/max2175.c +++ b/drivers/media/i2c/max2175.c @@ -1429,7 +1429,7 @@ static struct i2c_driver max2175_driver = { .name = DRIVER_NAME, .of_match_table = max2175_of_ids, }, - .probe_new = max2175_probe, + .probe = max2175_probe, .remove = max2175_remove, .id_table = max2175_id, }; diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c index 13a986b88588..88c58e0c49aa 100644 --- a/drivers/media/i2c/max9286.c +++ b/drivers/media/i2c/max9286.c @@ -1716,7 +1716,7 @@ static struct i2c_driver max9286_i2c_driver = { .name = "max9286", .of_match_table = of_match_ptr(max9286_dt_ids), }, - .probe_new = max9286_probe, + .probe = max9286_probe, .remove = max9286_remove, }; diff --git a/drivers/media/i2c/ml86v7667.c b/drivers/media/i2c/ml86v7667.c index dbd2f0bd3651..5b72d4434224 100644 --- a/drivers/media/i2c/ml86v7667.c +++ b/drivers/media/i2c/ml86v7667.c @@ -433,7 +433,7 @@ static struct i2c_driver ml86v7667_i2c_driver = { .driver = { .name = DRV_NAME, }, - .probe_new = ml86v7667_probe, + .probe = ml86v7667_probe, .remove = ml86v7667_remove, .id_table = ml86v7667_id, }; diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c index 12032e28b428..bec76801487a 100644 --- a/drivers/media/i2c/msp3400-driver.c +++ b/drivers/media/i2c/msp3400-driver.c @@ -892,7 +892,7 @@ static struct i2c_driver msp_driver = { .name = "msp3400", .pm = &msp3400_pm_ops, }, - .probe_new = msp_probe, + .probe = msp_probe, .remove = msp_remove, .id_table = msp_id, }; diff --git a/drivers/media/i2c/mt9m001.c b/drivers/media/i2c/mt9m001.c index ebf9cf1e1bce..ce9568e8391c 100644 --- a/drivers/media/i2c/mt9m001.c +++ b/drivers/media/i2c/mt9m001.c @@ -877,7 +877,7 @@ static struct i2c_driver mt9m001_i2c_driver = { .pm = &mt9m001_pm_ops, .of_match_table = mt9m001_of_match, }, - .probe_new = mt9m001_probe, + .probe = mt9m001_probe, .remove = mt9m001_remove, .id_table = mt9m001_id, }; diff --git a/drivers/media/i2c/mt9m111.c b/drivers/media/i2c/mt9m111.c index f5fe272d1205..2878d328fc01 100644 --- a/drivers/media/i2c/mt9m111.c +++ b/drivers/media/i2c/mt9m111.c @@ -1384,7 +1384,7 @@ static struct i2c_driver mt9m111_i2c_driver = { .name = "mt9m111", .of_match_table = of_match_ptr(mt9m111_of_match), }, - .probe_new = mt9m111_probe, + .probe = mt9m111_probe, .remove = mt9m111_remove, .id_table = mt9m111_id, }; diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index 9e023a4b9bd1..348f1e1098fb 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -1248,7 +1248,7 @@ static struct i2c_driver mt9p031_i2c_driver = { .of_match_table = of_match_ptr(mt9p031_of_match), .name = "mt9p031", }, - .probe_new = mt9p031_probe, + .probe = mt9p031_probe, .remove = mt9p031_remove, .id_table = mt9p031_id, }; diff --git a/drivers/media/i2c/mt9t112.c b/drivers/media/i2c/mt9t112.c index a82f056787b8..93f34b767027 100644 --- a/drivers/media/i2c/mt9t112.c +++ b/drivers/media/i2c/mt9t112.c @@ -1119,7 +1119,7 @@ static struct i2c_driver mt9t112_i2c_driver = { .driver = { .name = "mt9t112", }, - .probe_new = mt9t112_probe, + .probe = mt9t112_probe, .remove = mt9t112_remove, .id_table = mt9t112_id, }; diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c index c54c7fbf0963..774861ba7747 100644 --- a/drivers/media/i2c/mt9v011.c +++ b/drivers/media/i2c/mt9v011.c @@ -585,7 +585,7 @@ static struct i2c_driver mt9v011_driver = { .driver = { .name = "mt9v011", }, - .probe_new = mt9v011_probe, + .probe = mt9v011_probe, .remove = mt9v011_remove, .id_table = mt9v011_id, }; diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 7cfd4ebdd2e6..00e7bc6e3235 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -1296,7 +1296,7 @@ static struct i2c_driver mt9v032_driver = { .name = "mt9v032", .of_match_table = of_match_ptr(mt9v032_of_match), }, - .probe_new = mt9v032_probe, + .probe = mt9v032_probe, .remove = mt9v032_remove, .id_table = mt9v032_id, }; diff --git a/drivers/media/i2c/mt9v111.c b/drivers/media/i2c/mt9v111.c index 46d91cd0870c..1f7edc0f5b1a 100644 --- a/drivers/media/i2c/mt9v111.c +++ b/drivers/media/i2c/mt9v111.c @@ -1265,7 +1265,7 @@ static struct i2c_driver mt9v111_driver = { .name = "mt9v111", .of_match_table = mt9v111_of_match, }, - .probe_new = mt9v111_probe, + .probe = mt9v111_probe, .remove = mt9v111_remove, }; diff --git a/drivers/media/i2c/og01a1b.c b/drivers/media/i2c/og01a1b.c index 35663c10fcd9..b5948759342e 100644 --- a/drivers/media/i2c/og01a1b.c +++ b/drivers/media/i2c/og01a1b.c @@ -1115,7 +1115,7 @@ static struct i2c_driver og01a1b_i2c_driver = { .pm = &og01a1b_pm_ops, .acpi_match_table = ACPI_PTR(og01a1b_acpi_ids), }, - .probe_new = og01a1b_probe, + .probe = og01a1b_probe, .remove = og01a1b_remove, }; diff --git a/drivers/media/i2c/ov02a10.c b/drivers/media/i2c/ov02a10.c index 2c1eb724d8e5..741d977a76f3 100644 --- a/drivers/media/i2c/ov02a10.c +++ b/drivers/media/i2c/ov02a10.c @@ -1002,8 +1002,8 @@ static struct i2c_driver ov02a10_i2c_driver = { .pm = &ov02a10_pm_ops, .of_match_table = ov02a10_of_match, }, - .probe_new = &ov02a10_probe, - .remove = &ov02a10_remove, + .probe = ov02a10_probe, + .remove = ov02a10_remove, }; module_i2c_driver(ov02a10_i2c_driver); diff --git a/drivers/media/i2c/ov08d10.c b/drivers/media/i2c/ov08d10.c index a39e086a51c5..7d55d4ca24de 100644 --- a/drivers/media/i2c/ov08d10.c +++ b/drivers/media/i2c/ov08d10.c @@ -1520,7 +1520,7 @@ static struct i2c_driver ov08d10_i2c_driver = { .pm = &ov08d10_pm_ops, .acpi_match_table = ACPI_PTR(ov08d10_acpi_ids), }, - .probe_new = ov08d10_probe, + .probe = ov08d10_probe, .remove = ov08d10_remove, }; diff --git a/drivers/media/i2c/ov08x40.c b/drivers/media/i2c/ov08x40.c index 72ae7fba94eb..77bcdcd0824c 100644 --- a/drivers/media/i2c/ov08x40.c +++ b/drivers/media/i2c/ov08x40.c @@ -3313,7 +3313,7 @@ static struct i2c_driver ov08x40_i2c_driver = { .pm = &ov08x40_pm_ops, .acpi_match_table = ACPI_PTR(ov08x40_acpi_ids), }, - .probe_new = ov08x40_probe, + .probe = ov08x40_probe, .remove = ov08x40_remove, }; diff --git a/drivers/media/i2c/ov13858.c b/drivers/media/i2c/ov13858.c index 69a7a2c590db..3db3e64fa3ff 100644 --- a/drivers/media/i2c/ov13858.c +++ b/drivers/media/i2c/ov13858.c @@ -1806,7 +1806,7 @@ static struct i2c_driver ov13858_i2c_driver = { .pm = &ov13858_pm_ops, .acpi_match_table = ACPI_PTR(ov13858_acpi_ids), }, - .probe_new = ov13858_probe, + .probe = ov13858_probe, .remove = ov13858_remove, .id_table = ov13858_id_table, }; diff --git a/drivers/media/i2c/ov13b10.c b/drivers/media/i2c/ov13b10.c index c1430044fb1e..6110fb1e6bc6 100644 --- a/drivers/media/i2c/ov13b10.c +++ b/drivers/media/i2c/ov13b10.c @@ -1496,7 +1496,7 @@ static struct i2c_driver ov13b10_i2c_driver = { .pm = &ov13b10_pm_ops, .acpi_match_table = ACPI_PTR(ov13b10_acpi_ids), }, - .probe_new = ov13b10_probe, + .probe = ov13b10_probe, .remove = ov13b10_remove, .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; diff --git a/drivers/media/i2c/ov2640.c b/drivers/media/i2c/ov2640.c index 39d56838a4ef..ec801a81c2d0 100644 --- a/drivers/media/i2c/ov2640.c +++ b/drivers/media/i2c/ov2640.c @@ -1298,7 +1298,7 @@ static struct i2c_driver ov2640_i2c_driver = { .name = "ov2640", .of_match_table = of_match_ptr(ov2640_of_match), }, - .probe_new = ov2640_probe, + .probe = ov2640_probe, .remove = ov2640_remove, .id_table = ov2640_id, }; diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c index 42fc64ada08c..5429bd2eb053 100644 --- a/drivers/media/i2c/ov2659.c +++ b/drivers/media/i2c/ov2659.c @@ -1584,7 +1584,7 @@ static struct i2c_driver ov2659_i2c_driver = { .pm = &ov2659_pm_ops, .of_match_table = of_match_ptr(ov2659_of_match), }, - .probe_new = ov2659_probe, + .probe = ov2659_probe, .remove = ov2659_remove, .id_table = ov2659_id, }; diff --git a/drivers/media/i2c/ov2680.c b/drivers/media/i2c/ov2680.c index 54153bf66bdd..d06e9fc37f77 100644 --- a/drivers/media/i2c/ov2680.c +++ b/drivers/media/i2c/ov2680.c @@ -1158,7 +1158,7 @@ static struct i2c_driver ov2680_i2c_driver = { .pm = &ov2680_pm_ops, .of_match_table = of_match_ptr(ov2680_dt_ids), }, - .probe_new = ov2680_probe, + .probe = ov2680_probe, .remove = ov2680_remove, }; module_i2c_driver(ov2680_i2c_driver); diff --git a/drivers/media/i2c/ov2685.c b/drivers/media/i2c/ov2685.c index f119a93e7c64..303793e1f97d 100644 --- a/drivers/media/i2c/ov2685.c +++ b/drivers/media/i2c/ov2685.c @@ -903,8 +903,8 @@ static struct i2c_driver ov2685_i2c_driver = { .pm = &ov2685_pm_ops, .of_match_table = of_match_ptr(ov2685_of_match), }, - .probe_new = &ov2685_probe, - .remove = &ov2685_remove, + .probe = ov2685_probe, + .remove = ov2685_remove, }; module_i2c_driver(ov2685_i2c_driver); diff --git a/drivers/media/i2c/ov2740.c b/drivers/media/i2c/ov2740.c index 89d126240c34..158d934733c3 100644 --- a/drivers/media/i2c/ov2740.c +++ b/drivers/media/i2c/ov2740.c @@ -1215,7 +1215,7 @@ static struct i2c_driver ov2740_i2c_driver = { .pm = pm_sleep_ptr(&ov2740_pm_ops), .acpi_match_table = ov2740_acpi_ids, }, - .probe_new = ov2740_probe, + .probe = ov2740_probe, .remove = ov2740_remove, .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; diff --git a/drivers/media/i2c/ov4689.c b/drivers/media/i2c/ov4689.c index c602e507d42b..fda217d2cb10 100644 --- a/drivers/media/i2c/ov4689.c +++ b/drivers/media/i2c/ov4689.c @@ -1008,7 +1008,7 @@ static struct i2c_driver ov4689_i2c_driver = { .pm = &ov4689_pm_ops, .of_match_table = ov4689_of_match, }, - .probe_new = ov4689_probe, + .probe = ov4689_probe, .remove = ov4689_remove, }; diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c index 1536649b9e90..3a9dc7d11dec 100644 --- a/drivers/media/i2c/ov5640.c +++ b/drivers/media/i2c/ov5640.c @@ -4011,7 +4011,7 @@ static struct i2c_driver ov5640_i2c_driver = { .pm = &ov5640_pm_ops, }, .id_table = ov5640_id, - .probe_new = ov5640_probe, + .probe = ov5640_probe, .remove = ov5640_remove, }; diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c index c8999fc4f26f..a70db7e601a4 100644 --- a/drivers/media/i2c/ov5645.c +++ b/drivers/media/i2c/ov5645.c @@ -1286,7 +1286,7 @@ static struct i2c_driver ov5645_i2c_driver = { .name = "ov5645", .pm = &ov5645_pm_ops, }, - .probe_new = ov5645_probe, + .probe = ov5645_probe, .remove = ov5645_remove, .id_table = ov5645_id, }; diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c index 233576ee9503..8de398423b7c 100644 --- a/drivers/media/i2c/ov5647.c +++ b/drivers/media/i2c/ov5647.c @@ -1515,7 +1515,7 @@ static struct i2c_driver ov5647_driver = { .name = "ov5647", .pm = &ov5647_pm_ops, }, - .probe_new = ov5647_probe, + .probe = ov5647_probe, .remove = ov5647_remove, .id_table = ov5647_id, }; diff --git a/drivers/media/i2c/ov5648.c b/drivers/media/i2c/ov5648.c index 17465fcf28e3..aa10eb4e3991 100644 --- a/drivers/media/i2c/ov5648.c +++ b/drivers/media/i2c/ov5648.c @@ -2616,8 +2616,8 @@ static struct i2c_driver ov5648_driver = { .of_match_table = ov5648_of_match, .pm = &ov5648_pm_ops, }, - .probe_new = ov5648_probe, - .remove = ov5648_remove, + .probe = ov5648_probe, + .remove = ov5648_remove, }; module_i2c_driver(ov5648_driver); diff --git a/drivers/media/i2c/ov5670.c b/drivers/media/i2c/ov5670.c index c026610d0f31..d722348b938b 100644 --- a/drivers/media/i2c/ov5670.c +++ b/drivers/media/i2c/ov5670.c @@ -2853,7 +2853,7 @@ static struct i2c_driver ov5670_i2c_driver = { .acpi_match_table = ACPI_PTR(ov5670_acpi_ids), .of_match_table = ov5670_of_ids, }, - .probe_new = ov5670_probe, + .probe = ov5670_probe, .remove = ov5670_remove, .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; diff --git a/drivers/media/i2c/ov5675.c b/drivers/media/i2c/ov5675.c index d55180b3b7aa..700c4b69846f 100644 --- a/drivers/media/i2c/ov5675.c +++ b/drivers/media/i2c/ov5675.c @@ -1435,7 +1435,7 @@ static struct i2c_driver ov5675_i2c_driver = { .acpi_match_table = ACPI_PTR(ov5675_acpi_ids), .of_match_table = ov5675_of_match, }, - .probe_new = ov5675_probe, + .probe = ov5675_probe, .remove = ov5675_remove, .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c index e3c3bed69ad6..9a786ff4b5b7 100644 --- a/drivers/media/i2c/ov5693.c +++ b/drivers/media/i2c/ov5693.c @@ -1554,7 +1554,7 @@ static struct i2c_driver ov5693_driver = { .of_match_table = ov5693_of_match, .pm = &ov5693_pm_ops, }, - .probe_new = ov5693_probe, + .probe = ov5693_probe, .remove = ov5693_remove, }; module_i2c_driver(ov5693_driver); diff --git a/drivers/media/i2c/ov5695.c b/drivers/media/i2c/ov5695.c index b287c28920a6..3023b7254167 100644 --- a/drivers/media/i2c/ov5695.c +++ b/drivers/media/i2c/ov5695.c @@ -1392,8 +1392,8 @@ static struct i2c_driver ov5695_i2c_driver = { .pm = &ov5695_pm_ops, .of_match_table = of_match_ptr(ov5695_of_match), }, - .probe_new = &ov5695_probe, - .remove = &ov5695_remove, + .probe = ov5695_probe, + .remove = ov5695_remove, }; module_i2c_driver(ov5695_i2c_driver); diff --git a/drivers/media/i2c/ov6650.c b/drivers/media/i2c/ov6650.c index 4c0ea2ae671b..1ad07935f046 100644 --- a/drivers/media/i2c/ov6650.c +++ b/drivers/media/i2c/ov6650.c @@ -1113,7 +1113,7 @@ static struct i2c_driver ov6650_i2c_driver = { .driver = { .name = "ov6650", }, - .probe_new = ov6650_probe, + .probe = ov6650_probe, .remove = ov6650_remove, .id_table = ov6650_id, }; diff --git a/drivers/media/i2c/ov7251.c b/drivers/media/i2c/ov7251.c index 88e987435285..675fb37a6fea 100644 --- a/drivers/media/i2c/ov7251.c +++ b/drivers/media/i2c/ov7251.c @@ -1806,7 +1806,7 @@ static struct i2c_driver ov7251_i2c_driver = { .name = "ov7251", .pm = &ov7251_pm_ops, }, - .probe_new = ov7251_probe, + .probe = ov7251_probe, .remove = ov7251_remove, }; diff --git a/drivers/media/i2c/ov7640.c b/drivers/media/i2c/ov7640.c index e6751d5cc64b..293f5f404358 100644 --- a/drivers/media/i2c/ov7640.c +++ b/drivers/media/i2c/ov7640.c @@ -86,7 +86,7 @@ static struct i2c_driver ov7640_driver = { .driver = { .name = "ov7640", }, - .probe_new = ov7640_probe, + .probe = ov7640_probe, .remove = ov7640_remove, .id_table = ov7640_id, }; diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index ecbded4f0765..2f55491ef571 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -2033,7 +2033,7 @@ static struct i2c_driver ov7670_driver = { .name = "ov7670", .of_match_table = of_match_ptr(ov7670_of_match), }, - .probe_new = ov7670_probe, + .probe = ov7670_probe, .remove = ov7670_remove, .id_table = ov7670_id, }; diff --git a/drivers/media/i2c/ov772x.c b/drivers/media/i2c/ov772x.c index a238e63425f8..386d69c8e074 100644 --- a/drivers/media/i2c/ov772x.c +++ b/drivers/media/i2c/ov772x.c @@ -1551,7 +1551,7 @@ static struct i2c_driver ov772x_i2c_driver = { .name = "ov772x", .of_match_table = ov772x_of_match, }, - .probe_new = ov772x_probe, + .probe = ov772x_probe, .remove = ov772x_remove, .id_table = ov772x_id, }; diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c index c9fd9b0bc54a..10e47c7d4e0c 100644 --- a/drivers/media/i2c/ov7740.c +++ b/drivers/media/i2c/ov7740.c @@ -1212,7 +1212,7 @@ static struct i2c_driver ov7740_i2c_driver = { .pm = &ov7740_pm_ops, .of_match_table = of_match_ptr(ov7740_of_match), }, - .probe_new = ov7740_probe, + .probe = ov7740_probe, .remove = ov7740_remove, .id_table = ov7740_id, }; diff --git a/drivers/media/i2c/ov8856.c b/drivers/media/i2c/ov8856.c index b5c7881383ca..f053c3a7676a 100644 --- a/drivers/media/i2c/ov8856.c +++ b/drivers/media/i2c/ov8856.c @@ -2527,7 +2527,7 @@ static struct i2c_driver ov8856_i2c_driver = { .acpi_match_table = ACPI_PTR(ov8856_acpi_ids), .of_match_table = ov8856_of_match, }, - .probe_new = ov8856_probe, + .probe = ov8856_probe, .remove = ov8856_remove, .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, }; diff --git a/drivers/media/i2c/ov8858.c b/drivers/media/i2c/ov8858.c index 9ca8a17bfbb9..3af6125a2eee 100644 --- a/drivers/media/i2c/ov8858.c +++ b/drivers/media/i2c/ov8858.c @@ -1998,8 +1998,8 @@ static struct i2c_driver ov8858_i2c_driver = { .pm = &ov8858_pm_ops, .of_match_table = ov8858_of_match, }, - .probe_new = &ov8858_probe, - .remove = &ov8858_remove, + .probe = ov8858_probe, + .remove = ov8858_remove, }; module_i2c_driver(ov8858_i2c_driver); diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c index cae1866134a0..f2213c6158d3 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -3158,8 +3158,8 @@ static struct i2c_driver ov8865_driver = { .acpi_match_table = ov8865_acpi_match, .pm = &ov8865_pm_ops, }, - .probe_new = ov8865_probe, - .remove = ov8865_remove, + .probe = ov8865_probe, + .remove = ov8865_remove, }; module_i2c_driver(ov8865_driver); diff --git a/drivers/media/i2c/ov9282.c b/drivers/media/i2c/ov9282.c index 7f46cac38aab..068c7449f50e 100644 --- a/drivers/media/i2c/ov9282.c +++ b/drivers/media/i2c/ov9282.c @@ -1512,7 +1512,7 @@ static const struct of_device_id ov9282_of_match[] = { MODULE_DEVICE_TABLE(of, ov9282_of_match); static struct i2c_driver ov9282_driver = { - .probe_new = ov9282_probe, + .probe = ov9282_probe, .remove = ov9282_remove, .driver = { .name = "ov9282", diff --git a/drivers/media/i2c/ov9640.c b/drivers/media/i2c/ov9640.c index a80fa59bf2ae..cbaea049531d 100644 --- a/drivers/media/i2c/ov9640.c +++ b/drivers/media/i2c/ov9640.c @@ -762,7 +762,7 @@ static struct i2c_driver ov9640_i2c_driver = { .driver = { .name = "ov9640", }, - .probe_new = ov9640_probe, + .probe = ov9640_probe, .remove = ov9640_remove, .id_table = ov9640_id, }; diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c index 7e7cb1e4520e..da1ab5135eaa 100644 --- a/drivers/media/i2c/ov9650.c +++ b/drivers/media/i2c/ov9650.c @@ -1571,7 +1571,7 @@ static struct i2c_driver ov965x_i2c_driver = { .name = DRIVER_NAME, .of_match_table = of_match_ptr(ov965x_of_match), }, - .probe_new = ov965x_probe, + .probe = ov965x_probe, .remove = ov965x_remove, .id_table = ov965x_id, }; diff --git a/drivers/media/i2c/ov9734.c b/drivers/media/i2c/ov9734.c index 8b0a158cb297..b6244772bc59 100644 --- a/drivers/media/i2c/ov9734.c +++ b/drivers/media/i2c/ov9734.c @@ -1028,7 +1028,7 @@ static struct i2c_driver ov9734_i2c_driver = { .pm = &ov9734_pm_ops, .acpi_match_table = ov9734_acpi_ids, }, - .probe_new = ov9734_probe, + .probe = ov9734_probe, .remove = ov9734_remove, }; diff --git a/drivers/media/i2c/rdacm20.c b/drivers/media/i2c/rdacm20.c index a2263fa825b5..01a2596282f0 100644 --- a/drivers/media/i2c/rdacm20.c +++ b/drivers/media/i2c/rdacm20.c @@ -676,7 +676,7 @@ static struct i2c_driver rdacm20_i2c_driver = { .name = "rdacm20", .of_match_table = rdacm20_of_ids, }, - .probe_new = rdacm20_probe, + .probe = rdacm20_probe, .remove = rdacm20_remove, .shutdown = rdacm20_shutdown, }; diff --git a/drivers/media/i2c/rdacm21.c b/drivers/media/i2c/rdacm21.c index 9ccc56c30d3b..043fec778a5e 100644 --- a/drivers/media/i2c/rdacm21.c +++ b/drivers/media/i2c/rdacm21.c @@ -635,7 +635,7 @@ static struct i2c_driver rdacm21_i2c_driver = { .name = "rdacm21", .of_match_table = rdacm21_of_ids, }, - .probe_new = rdacm21_probe, + .probe = rdacm21_probe, .remove = rdacm21_remove, }; diff --git a/drivers/media/i2c/rj54n1cb0c.c b/drivers/media/i2c/rj54n1cb0c.c index 9db5473daba0..b430046f9e2a 100644 --- a/drivers/media/i2c/rj54n1cb0c.c +++ b/drivers/media/i2c/rj54n1cb0c.c @@ -1421,7 +1421,7 @@ static struct i2c_driver rj54n1_i2c_driver = { .driver = { .name = "rj54n1cb0c", }, - .probe_new = rj54n1_probe, + .probe = rj54n1_probe, .remove = rj54n1_remove, .id_table = rj54n1_id, }; diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index 7938a3327d3e..ed5b10731a14 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -1729,7 +1729,7 @@ static struct i2c_driver s5c73m3_i2c_driver = { .of_match_table = of_match_ptr(s5c73m3_of_match), .name = DRIVER_NAME, }, - .probe_new = s5c73m3_probe, + .probe = s5c73m3_probe, .remove = s5c73m3_remove, .id_table = s5c73m3_id, }; diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c index 960fbf6428ea..67da2045f543 100644 --- a/drivers/media/i2c/s5k5baf.c +++ b/drivers/media/i2c/s5k5baf.c @@ -2021,7 +2021,7 @@ static struct i2c_driver s5k5baf_i2c_driver = { .of_match_table = s5k5baf_of_match, .name = S5K5BAF_DRIVER_NAME }, - .probe_new = s5k5baf_probe, + .probe = s5k5baf_probe, .remove = s5k5baf_remove, .id_table = s5k5baf_id, }; diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c index ef6673b10580..b3560c8f8b41 100644 --- a/drivers/media/i2c/s5k6a3.c +++ b/drivers/media/i2c/s5k6a3.c @@ -373,7 +373,7 @@ static struct i2c_driver s5k6a3_driver = { .of_match_table = of_match_ptr(s5k6a3_of_match), .name = S5K6A3_DRV_NAME, }, - .probe_new = s5k6a3_probe, + .probe = s5k6a3_probe, .remove = s5k6a3_remove, .id_table = s5k6a3_ids, }; diff --git a/drivers/media/i2c/saa6588.c b/drivers/media/i2c/saa6588.c index 8752f7cff611..dea9fc09356f 100644 --- a/drivers/media/i2c/saa6588.c +++ b/drivers/media/i2c/saa6588.c @@ -505,7 +505,7 @@ static struct i2c_driver saa6588_driver = { .driver = { .name = "saa6588", }, - .probe_new = saa6588_probe, + .probe = saa6588_probe, .remove = saa6588_remove, .id_table = saa6588_id, }; diff --git a/drivers/media/i2c/saa6752hs.c b/drivers/media/i2c/saa6752hs.c index 892d64fe6e81..c106e7a7d1f4 100644 --- a/drivers/media/i2c/saa6752hs.c +++ b/drivers/media/i2c/saa6752hs.c @@ -781,7 +781,7 @@ static struct i2c_driver saa6752hs_driver = { .driver = { .name = "saa6752hs", }, - .probe_new = saa6752hs_probe, + .probe = saa6752hs_probe, .remove = saa6752hs_remove, .id_table = saa6752hs_id, }; diff --git a/drivers/media/i2c/saa7110.c b/drivers/media/i2c/saa7110.c index b58e71517376..1520790338ce 100644 --- a/drivers/media/i2c/saa7110.c +++ b/drivers/media/i2c/saa7110.c @@ -448,7 +448,7 @@ static struct i2c_driver saa7110_driver = { .driver = { .name = "saa7110", }, - .probe_new = saa7110_probe, + .probe = saa7110_probe, .remove = saa7110_remove, .id_table = saa7110_id, }; diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index efeda3956f81..a1c71187e773 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -1951,7 +1951,7 @@ static struct i2c_driver saa711x_driver = { .driver = { .name = "saa7115", }, - .probe_new = saa711x_probe, + .probe = saa711x_probe, .remove = saa711x_remove, .id_table = saa711x_id, }; diff --git a/drivers/media/i2c/saa7127.c b/drivers/media/i2c/saa7127.c index f98f3a1c38a9..818ed19cf37b 100644 --- a/drivers/media/i2c/saa7127.c +++ b/drivers/media/i2c/saa7127.c @@ -810,7 +810,7 @@ static struct i2c_driver saa7127_driver = { .driver = { .name = "saa7127", }, - .probe_new = saa7127_probe, + .probe = saa7127_probe, .remove = saa7127_remove, .id_table = saa7127_id, }; diff --git a/drivers/media/i2c/saa717x.c b/drivers/media/i2c/saa717x.c index df01059076fa..933ec0171430 100644 --- a/drivers/media/i2c/saa717x.c +++ b/drivers/media/i2c/saa717x.c @@ -1343,7 +1343,7 @@ static struct i2c_driver saa717x_driver = { .driver = { .name = "saa717x", }, - .probe_new = saa717x_probe, + .probe = saa717x_probe, .remove = saa717x_remove, .id_table = saa717x_id, }; diff --git a/drivers/media/i2c/saa7185.c b/drivers/media/i2c/saa7185.c index c78f2e95ba37..5535d71f4860 100644 --- a/drivers/media/i2c/saa7185.c +++ b/drivers/media/i2c/saa7185.c @@ -343,7 +343,7 @@ static struct i2c_driver saa7185_driver = { .driver = { .name = "saa7185", }, - .probe_new = saa7185_probe, + .probe = saa7185_probe, .remove = saa7185_remove, .id_table = saa7185_id, }; diff --git a/drivers/media/i2c/sony-btf-mpx.c b/drivers/media/i2c/sony-btf-mpx.c index eef6c8a7c9c9..0f53834f3ae4 100644 --- a/drivers/media/i2c/sony-btf-mpx.c +++ b/drivers/media/i2c/sony-btf-mpx.c @@ -375,7 +375,7 @@ static struct i2c_driver sony_btf_mpx_driver = { .driver = { .name = "sony-btf-mpx", }, - .probe_new = sony_btf_mpx_probe, + .probe = sony_btf_mpx_probe, .remove = sony_btf_mpx_remove, .id_table = sony_btf_mpx_id, }; diff --git a/drivers/media/i2c/st-mipid02.c b/drivers/media/i2c/st-mipid02.c index 31b89aff0e86..19efefe38727 100644 --- a/drivers/media/i2c/st-mipid02.c +++ b/drivers/media/i2c/st-mipid02.c @@ -1091,7 +1091,7 @@ static struct i2c_driver mipid02_i2c_driver = { .name = "st-mipid02", .of_match_table = mipid02_dt_ids, }, - .probe_new = mipid02_probe, + .probe = mipid02_probe, .remove = mipid02_remove, }; diff --git a/drivers/media/i2c/st-vgxy61.c b/drivers/media/i2c/st-vgxy61.c index adbd093ad190..30f82ca344c4 100644 --- a/drivers/media/i2c/st-vgxy61.c +++ b/drivers/media/i2c/st-vgxy61.c @@ -1951,7 +1951,7 @@ static struct i2c_driver vgxy61_i2c_driver = { .of_match_table = vgxy61_dt_ids, .pm = &vgxy61_pm_ops, }, - .probe_new = vgxy61_probe, + .probe = vgxy61_probe, .remove = vgxy61_remove, }; diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 9197fa0b1bc2..15f8163be9bf 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -2206,7 +2206,7 @@ static struct i2c_driver tc358743_driver = { .name = "tc358743", .of_match_table = of_match_ptr(tc358743_of_match), }, - .probe_new = tc358743_probe, + .probe = tc358743_probe, .remove = tc358743_remove, .id_table = tc358743_id, }; diff --git a/drivers/media/i2c/tc358746.c b/drivers/media/i2c/tc358746.c index ec1a193ba161..e9b2d906c177 100644 --- a/drivers/media/i2c/tc358746.c +++ b/drivers/media/i2c/tc358746.c @@ -1686,7 +1686,7 @@ static struct i2c_driver tc358746_driver = { .pm = pm_ptr(&tc358746_pm_ops), .of_match_table = tc358746_of_match, }, - .probe_new = tc358746_probe, + .probe = tc358746_probe, .remove = tc358746_remove, }; diff --git a/drivers/media/i2c/tda1997x.c b/drivers/media/i2c/tda1997x.c index 27f6393dc327..325e99125941 100644 --- a/drivers/media/i2c/tda1997x.c +++ b/drivers/media/i2c/tda1997x.c @@ -2834,7 +2834,7 @@ static struct i2c_driver tda1997x_i2c_driver = { .name = "tda1997x", .of_match_table = of_match_ptr(tda1997x_of_id), }, - .probe_new = tda1997x_probe, + .probe = tda1997x_probe, .remove = tda1997x_remove, .id_table = tda1997x_i2c_id, }; diff --git a/drivers/media/i2c/tda7432.c b/drivers/media/i2c/tda7432.c index bbceaac8e0b3..6ecdc8e2e0c6 100644 --- a/drivers/media/i2c/tda7432.c +++ b/drivers/media/i2c/tda7432.c @@ -409,7 +409,7 @@ static struct i2c_driver tda7432_driver = { .driver = { .name = "tda7432", }, - .probe_new = tda7432_probe, + .probe = tda7432_probe, .remove = tda7432_remove, .id_table = tda7432_id, }; diff --git a/drivers/media/i2c/tda9840.c b/drivers/media/i2c/tda9840.c index 25fbd7e3950e..1911ef2126be 100644 --- a/drivers/media/i2c/tda9840.c +++ b/drivers/media/i2c/tda9840.c @@ -191,7 +191,7 @@ static struct i2c_driver tda9840_driver = { .driver = { .name = "tda9840", }, - .probe_new = tda9840_probe, + .probe = tda9840_probe, .remove = tda9840_remove, .id_table = tda9840_id, }; diff --git a/drivers/media/i2c/tea6415c.c b/drivers/media/i2c/tea6415c.c index d375d2d24354..3ed6e441d515 100644 --- a/drivers/media/i2c/tea6415c.c +++ b/drivers/media/i2c/tea6415c.c @@ -150,7 +150,7 @@ static struct i2c_driver tea6415c_driver = { .driver = { .name = "tea6415c", }, - .probe_new = tea6415c_probe, + .probe = tea6415c_probe, .remove = tea6415c_remove, .id_table = tea6415c_id, }; diff --git a/drivers/media/i2c/tea6420.c b/drivers/media/i2c/tea6420.c index 9da1f3b02c57..63f23784bb41 100644 --- a/drivers/media/i2c/tea6420.c +++ b/drivers/media/i2c/tea6420.c @@ -132,7 +132,7 @@ static struct i2c_driver tea6420_driver = { .driver = { .name = "tea6420", }, - .probe_new = tea6420_probe, + .probe = tea6420_probe, .remove = tea6420_remove, .id_table = tea6420_id, }; diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c index 67de90cf696e..ea70c1c13872 100644 --- a/drivers/media/i2c/ths7303.c +++ b/drivers/media/i2c/ths7303.c @@ -376,7 +376,7 @@ static struct i2c_driver ths7303_driver = { .driver = { .name = "ths73x3", }, - .probe_new = ths7303_probe, + .probe = ths7303_probe, .remove = ths7303_remove, .id_table = ths7303_id, }; diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c index 081ef5a4b950..0e0f676cd221 100644 --- a/drivers/media/i2c/ths8200.c +++ b/drivers/media/i2c/ths8200.c @@ -499,7 +499,7 @@ static struct i2c_driver ths8200_driver = { .name = "ths8200", .of_match_table = of_match_ptr(ths8200_of_match), }, - .probe_new = ths8200_probe, + .probe = ths8200_probe, .remove = ths8200_remove, .id_table = ths8200_id, }; diff --git a/drivers/media/i2c/tlv320aic23b.c b/drivers/media/i2c/tlv320aic23b.c index 47198e803817..d800ff8af1ff 100644 --- a/drivers/media/i2c/tlv320aic23b.c +++ b/drivers/media/i2c/tlv320aic23b.c @@ -197,7 +197,7 @@ static struct i2c_driver tlv320aic23b_driver = { .driver = { .name = "tlv320aic23b", }, - .probe_new = tlv320aic23b_probe, + .probe = tlv320aic23b_probe, .remove = tlv320aic23b_remove, .id_table = tlv320aic23b_id, }; diff --git a/drivers/media/i2c/tvaudio.c b/drivers/media/i2c/tvaudio.c index a54c76d9e23b..ba20f35cafd5 100644 --- a/drivers/media/i2c/tvaudio.c +++ b/drivers/media/i2c/tvaudio.c @@ -2095,7 +2095,7 @@ static struct i2c_driver tvaudio_driver = { .driver = { .name = "tvaudio", }, - .probe_new = tvaudio_probe, + .probe = tvaudio_probe, .remove = tvaudio_remove, .id_table = tvaudio_id, }; diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index f294cae72b01..aa6d4b67b6d5 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -1208,7 +1208,7 @@ static struct i2c_driver tvp514x_driver = { .of_match_table = of_match_ptr(tvp514x_of_match), .name = TVP514X_MODULE_NAME, }, - .probe_new = tvp514x_probe, + .probe = tvp514x_probe, .remove = tvp514x_remove, .id_table = tvp514x_id, }; diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 859f1cb2fa74..c7fb35ee3f9d 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -2280,7 +2280,7 @@ static struct i2c_driver tvp5150_driver = { .name = "tvp5150", .pm = &tvp5150_pm_ops, }, - .probe_new = tvp5150_probe, + .probe = tvp5150_probe, .remove = tvp5150_remove, .id_table = tvp5150_id, }; diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index 4ccd218f5584..a2d7bc799849 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c @@ -1079,7 +1079,7 @@ static struct i2c_driver tvp7002_driver = { .of_match_table = of_match_ptr(tvp7002_of_match), .name = TVP7002_MODULE_NAME, }, - .probe_new = tvp7002_probe, + .probe = tvp7002_probe, .remove = tvp7002_remove, .id_table = tvp7002_id, }; diff --git a/drivers/media/i2c/tw2804.c b/drivers/media/i2c/tw2804.c index 710790ece11b..6a2521e3a25c 100644 --- a/drivers/media/i2c/tw2804.c +++ b/drivers/media/i2c/tw2804.c @@ -423,7 +423,7 @@ static struct i2c_driver tw2804_driver = { .driver = { .name = "tw2804", }, - .probe_new = tw2804_probe, + .probe = tw2804_probe, .remove = tw2804_remove, .id_table = tw2804_id, }; diff --git a/drivers/media/i2c/tw9903.c b/drivers/media/i2c/tw9903.c index 428ee55787e1..996be3960af3 100644 --- a/drivers/media/i2c/tw9903.c +++ b/drivers/media/i2c/tw9903.c @@ -254,7 +254,7 @@ static struct i2c_driver tw9903_driver = { .driver = { .name = "tw9903", }, - .probe_new = tw9903_probe, + .probe = tw9903_probe, .remove = tw9903_remove, .id_table = tw9903_id, }; diff --git a/drivers/media/i2c/tw9906.c b/drivers/media/i2c/tw9906.c index 7824ed9b04ed..25c625f6d6e4 100644 --- a/drivers/media/i2c/tw9906.c +++ b/drivers/media/i2c/tw9906.c @@ -222,7 +222,7 @@ static struct i2c_driver tw9906_driver = { .driver = { .name = "tw9906", }, - .probe_new = tw9906_probe, + .probe = tw9906_probe, .remove = tw9906_remove, .id_table = tw9906_id, }; diff --git a/drivers/media/i2c/tw9910.c b/drivers/media/i2c/tw9910.c index 459fa22f4341..477a64d8f8ab 100644 --- a/drivers/media/i2c/tw9910.c +++ b/drivers/media/i2c/tw9910.c @@ -1012,7 +1012,7 @@ static struct i2c_driver tw9910_i2c_driver = { .driver = { .name = "tw9910", }, - .probe_new = tw9910_probe, + .probe = tw9910_probe, .remove = tw9910_remove, .id_table = tw9910_id, }; diff --git a/drivers/media/i2c/uda1342.c b/drivers/media/i2c/uda1342.c index b6873d866272..da7bc4700bed 100644 --- a/drivers/media/i2c/uda1342.c +++ b/drivers/media/i2c/uda1342.c @@ -88,7 +88,7 @@ static struct i2c_driver uda1342_driver = { .driver = { .name = "uda1342", }, - .probe_new = uda1342_probe, + .probe = uda1342_probe, .remove = uda1342_remove, .id_table = uda1342_id, }; diff --git a/drivers/media/i2c/upd64031a.c b/drivers/media/i2c/upd64031a.c index 47eed3aab060..54c2ba0ba375 100644 --- a/drivers/media/i2c/upd64031a.c +++ b/drivers/media/i2c/upd64031a.c @@ -228,7 +228,7 @@ static struct i2c_driver upd64031a_driver = { .driver = { .name = "upd64031a", }, - .probe_new = upd64031a_probe, + .probe = upd64031a_probe, .remove = upd64031a_remove, .id_table = upd64031a_id, }; diff --git a/drivers/media/i2c/upd64083.c b/drivers/media/i2c/upd64083.c index 3f5a7d4853a1..2a820589a4cb 100644 --- a/drivers/media/i2c/upd64083.c +++ b/drivers/media/i2c/upd64083.c @@ -199,7 +199,7 @@ static struct i2c_driver upd64083_driver = { .driver = { .name = "upd64083", }, - .probe_new = upd64083_probe, + .probe = upd64083_probe, .remove = upd64083_remove, .id_table = upd64083_id, }; diff --git a/drivers/media/i2c/video-i2c.c b/drivers/media/i2c/video-i2c.c index dddf9827b314..4ba2c5518579 100644 --- a/drivers/media/i2c/video-i2c.c +++ b/drivers/media/i2c/video-i2c.c @@ -959,7 +959,7 @@ static struct i2c_driver video_i2c_driver = { .of_match_table = video_i2c_of_match, .pm = &video_i2c_pm_ops, }, - .probe_new = video_i2c_probe, + .probe = video_i2c_probe, .remove = video_i2c_remove, .id_table = video_i2c_id_table, }; diff --git a/drivers/media/i2c/vp27smpx.c b/drivers/media/i2c/vp27smpx.c index ed1c58ea8ed3..0ba3c2b68037 100644 --- a/drivers/media/i2c/vp27smpx.c +++ b/drivers/media/i2c/vp27smpx.c @@ -181,7 +181,7 @@ static struct i2c_driver vp27smpx_driver = { .driver = { .name = "vp27smpx", }, - .probe_new = vp27smpx_probe, + .probe = vp27smpx_probe, .remove = vp27smpx_remove, .id_table = vp27smpx_id, }; diff --git a/drivers/media/i2c/vpx3220.c b/drivers/media/i2c/vpx3220.c index aa73d5dcc3e7..1eaae886f217 100644 --- a/drivers/media/i2c/vpx3220.c +++ b/drivers/media/i2c/vpx3220.c @@ -546,7 +546,7 @@ static struct i2c_driver vpx3220_driver = { .driver = { .name = "vpx3220", }, - .probe_new = vpx3220_probe, + .probe = vpx3220_probe, .remove = vpx3220_remove, .id_table = vpx3220_id, }; diff --git a/drivers/media/i2c/wm8739.c b/drivers/media/i2c/wm8739.c index 8b34a673ffd3..19bf7a00dff9 100644 --- a/drivers/media/i2c/wm8739.c +++ b/drivers/media/i2c/wm8739.c @@ -252,7 +252,7 @@ static struct i2c_driver wm8739_driver = { .driver = { .name = "wm8739", }, - .probe_new = wm8739_probe, + .probe = wm8739_probe, .remove = wm8739_remove, .id_table = wm8739_id, }; diff --git a/drivers/media/i2c/wm8775.c b/drivers/media/i2c/wm8775.c index 56d98518f7eb..d1b716fd6f11 100644 --- a/drivers/media/i2c/wm8775.c +++ b/drivers/media/i2c/wm8775.c @@ -298,7 +298,7 @@ static struct i2c_driver wm8775_driver = { .driver = { .name = "wm8775", }, - .probe_new = wm8775_probe, + .probe = wm8775_probe, .remove = wm8775_remove, .id_table = wm8775_id, }; diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index 2cb74afba49c..14e7dd3889ff 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -511,7 +511,7 @@ static struct i2c_driver tea5764_i2c_driver = { .driver = { .name = "radio-tea5764", }, - .probe_new = tea5764_i2c_probe, + .probe = tea5764_i2c_probe, .remove = tea5764_i2c_remove, .id_table = tea5764_id, }; diff --git a/drivers/media/radio/saa7706h.c b/drivers/media/radio/saa7706h.c index 3c758a983344..91345198bbf1 100644 --- a/drivers/media/radio/saa7706h.c +++ b/drivers/media/radio/saa7706h.c @@ -405,7 +405,7 @@ static struct i2c_driver saa7706h_driver = { .driver = { .name = DRIVER_NAME, }, - .probe_new = saa7706h_probe, + .probe = saa7706h_probe, .remove = saa7706h_remove, .id_table = saa7706h_id, }; diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index a6ad926c2b4e..fd449e42c191 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -532,7 +532,7 @@ static struct i2c_driver si470x_i2c_driver = { .pm = &si470x_i2c_pm, #endif }, - .probe_new = si470x_i2c_probe, + .probe = si470x_i2c_probe, .remove = si470x_i2c_remove, .id_table = si470x_i2c_id, }; diff --git a/drivers/media/radio/si4713/si4713.c b/drivers/media/radio/si4713/si4713.c index 93d847c294e8..ddaf7a60b7d0 100644 --- a/drivers/media/radio/si4713/si4713.c +++ b/drivers/media/radio/si4713/si4713.c @@ -1657,7 +1657,7 @@ static struct i2c_driver si4713_i2c_driver = { .name = "si4713", .of_match_table = of_match_ptr(si4713_of_match), }, - .probe_new = si4713_probe, + .probe = si4713_probe, .remove = si4713_remove, .id_table = si4713_id, }; diff --git a/drivers/media/radio/tef6862.c b/drivers/media/radio/tef6862.c index d14c97d79e83..215168aa1588 100644 --- a/drivers/media/radio/tef6862.c +++ b/drivers/media/radio/tef6862.c @@ -183,7 +183,7 @@ static struct i2c_driver tef6862_driver = { .driver = { .name = DRIVER_NAME, }, - .probe_new = tef6862_probe, + .probe = tef6862_probe, .remove = tef6862_remove, .id_table = tef6862_id, }; diff --git a/drivers/media/test-drivers/vidtv/vidtv_demod.c b/drivers/media/test-drivers/vidtv/vidtv_demod.c index b878db798686..7a0cd9601917 100644 --- a/drivers/media/test-drivers/vidtv/vidtv_demod.c +++ b/drivers/media/test-drivers/vidtv/vidtv_demod.c @@ -449,7 +449,7 @@ static struct i2c_driver vidtv_demod_i2c_driver = { .name = "dvb_vidtv_demod", .suppress_bind_attrs = true, }, - .probe_new = vidtv_demod_i2c_probe, + .probe = vidtv_demod_i2c_probe, .remove = vidtv_demod_i2c_remove, .id_table = vidtv_demod_i2c_id_table, }; diff --git a/drivers/media/test-drivers/vidtv/vidtv_tuner.c b/drivers/media/test-drivers/vidtv/vidtv_tuner.c index 55a4387f3854..a748737d47f3 100644 --- a/drivers/media/test-drivers/vidtv/vidtv_tuner.c +++ b/drivers/media/test-drivers/vidtv/vidtv_tuner.c @@ -425,7 +425,7 @@ static struct i2c_driver vidtv_tuner_i2c_driver = { .name = "dvb_vidtv_tuner", .suppress_bind_attrs = true, }, - .probe_new = vidtv_tuner_i2c_probe, + .probe = vidtv_tuner_i2c_probe, .remove = vidtv_tuner_i2c_remove, .id_table = vidtv_tuner_i2c_id_table, }; diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c index 7c269f3159ef..3893a00c18ce 100644 --- a/drivers/media/tuners/e4000.c +++ b/drivers/media/tuners/e4000.c @@ -729,7 +729,7 @@ static struct i2c_driver e4000_driver = { .name = "e4000", .suppress_bind_attrs = true, }, - .probe_new = e4000_probe, + .probe = e4000_probe, .remove = e4000_remove, .id_table = e4000_id_table, }; diff --git a/drivers/media/tuners/fc2580.c b/drivers/media/tuners/fc2580.c index 3cd8279f4f2e..f6613dcf40a3 100644 --- a/drivers/media/tuners/fc2580.c +++ b/drivers/media/tuners/fc2580.c @@ -610,7 +610,7 @@ static struct i2c_driver fc2580_driver = { .name = "fc2580", .suppress_bind_attrs = true, }, - .probe_new = fc2580_probe, + .probe = fc2580_probe, .remove = fc2580_remove, .id_table = fc2580_id_table, }; diff --git a/drivers/media/tuners/m88rs6000t.c b/drivers/media/tuners/m88rs6000t.c index 7d172a5a66d9..2cd7f0e0c70d 100644 --- a/drivers/media/tuners/m88rs6000t.c +++ b/drivers/media/tuners/m88rs6000t.c @@ -718,7 +718,7 @@ static struct i2c_driver m88rs6000t_driver = { .driver = { .name = "m88rs6000t", }, - .probe_new = m88rs6000t_probe, + .probe = m88rs6000t_probe, .remove = m88rs6000t_remove, .id_table = m88rs6000t_id, }; diff --git a/drivers/media/tuners/mt2060.c b/drivers/media/tuners/mt2060.c index e5d86874adb3..0278a9f0aeef 100644 --- a/drivers/media/tuners/mt2060.c +++ b/drivers/media/tuners/mt2060.c @@ -524,7 +524,7 @@ static struct i2c_driver mt2060_driver = { .name = "mt2060", .suppress_bind_attrs = true, }, - .probe_new = mt2060_probe, + .probe = mt2060_probe, .remove = mt2060_remove, .id_table = mt2060_id_table, }; diff --git a/drivers/media/tuners/mxl301rf.c b/drivers/media/tuners/mxl301rf.c index c35442a77ae5..9b2b237745ae 100644 --- a/drivers/media/tuners/mxl301rf.c +++ b/drivers/media/tuners/mxl301rf.c @@ -326,7 +326,7 @@ static struct i2c_driver mxl301rf_driver = { .driver = { .name = "mxl301rf", }, - .probe_new = mxl301rf_probe, + .probe = mxl301rf_probe, .remove = mxl301rf_remove, .id_table = mxl301rf_id, }; diff --git a/drivers/media/tuners/qm1d1b0004.c b/drivers/media/tuners/qm1d1b0004.c index 0b6f750c54ad..af2d3618b9d5 100644 --- a/drivers/media/tuners/qm1d1b0004.c +++ b/drivers/media/tuners/qm1d1b0004.c @@ -253,7 +253,7 @@ static struct i2c_driver qm1d1b0004_driver = { .driver = { .name = "qm1d1b0004", }, - .probe_new = qm1d1b0004_probe, + .probe = qm1d1b0004_probe, .remove = qm1d1b0004_remove, .id_table = qm1d1b0004_id, }; diff --git a/drivers/media/tuners/qm1d1c0042.c b/drivers/media/tuners/qm1d1c0042.c index f9be7a721d2c..ce7223315b0c 100644 --- a/drivers/media/tuners/qm1d1c0042.c +++ b/drivers/media/tuners/qm1d1c0042.c @@ -443,7 +443,7 @@ static struct i2c_driver qm1d1c0042_driver = { .driver = { .name = "qm1d1c0042", }, - .probe_new = qm1d1c0042_probe, + .probe = qm1d1c0042_probe, .remove = qm1d1c0042_remove, .id_table = qm1d1c0042_id, }; diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 3fa3dcda917a..def06c262ea2 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -990,7 +990,7 @@ static struct i2c_driver si2157_driver = { .name = "si2157", .suppress_bind_attrs = true, }, - .probe_new = si2157_probe, + .probe = si2157_probe, .remove = si2157_remove, .id_table = si2157_id_table, }; diff --git a/drivers/media/tuners/tda18212.c b/drivers/media/tuners/tda18212.c index 5fdf05a97415..8d742bd61df0 100644 --- a/drivers/media/tuners/tda18212.c +++ b/drivers/media/tuners/tda18212.c @@ -263,7 +263,7 @@ static struct i2c_driver tda18212_driver = { .driver = { .name = "tda18212", }, - .probe_new = tda18212_probe, + .probe = tda18212_probe, .remove = tda18212_remove, .id_table = tda18212_id, }; diff --git a/drivers/media/tuners/tda18250.c b/drivers/media/tuners/tda18250.c index 66ff2d035de7..32ea473f3f49 100644 --- a/drivers/media/tuners/tda18250.c +++ b/drivers/media/tuners/tda18250.c @@ -877,7 +877,7 @@ static struct i2c_driver tda18250_driver = { .driver = { .name = "tda18250", }, - .probe_new = tda18250_probe, + .probe = tda18250_probe, .remove = tda18250_remove, .id_table = tda18250_id_table, }; diff --git a/drivers/media/tuners/tua9001.c b/drivers/media/tuners/tua9001.c index ac38afd3441a..03a3a022b0a8 100644 --- a/drivers/media/tuners/tua9001.c +++ b/drivers/media/tuners/tua9001.c @@ -255,7 +255,7 @@ static struct i2c_driver tua9001_driver = { .name = "tua9001", .suppress_bind_attrs = true, }, - .probe_new = tua9001_probe, + .probe = tua9001_probe, .remove = tua9001_remove, .id_table = tua9001_id_table, }; diff --git a/drivers/media/usb/go7007/s2250-board.c b/drivers/media/usb/go7007/s2250-board.c index 29dfcc6d0b0a..db1fab96d529 100644 --- a/drivers/media/usb/go7007/s2250-board.c +++ b/drivers/media/usb/go7007/s2250-board.c @@ -620,7 +620,7 @@ static struct i2c_driver s2250_driver = { .driver = { .name = "s2250", }, - .probe_new = s2250_probe, + .probe = s2250_probe, .remove = s2250_remove, .id_table = s2250_id, }; diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c index 1c0d23c52203..5687089bea6e 100644 --- a/drivers/media/v4l2-core/tuner-core.c +++ b/drivers/media/v4l2-core/tuner-core.c @@ -1411,7 +1411,7 @@ static struct i2c_driver tuner_driver = { .name = "tuner", .pm = &tuner_pm_ops, }, - .probe_new = tuner_probe, + .probe = tuner_probe, .remove = tuner_remove, .command = tuner_command, .id_table = tuner_id, From ae440c5da33cdb90a109f2df2a0360c67b3fab7e Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 24 May 2023 16:07:38 +0800 Subject: [PATCH 059/253] media: uapi: HEVC: Add num_delta_pocs_of_ref_rps_idx field Some drivers firmwares parse by themselves slice header and need num_delta_pocs_of_ref_rps_idx value to parse slice header short_term_ref_pic_set(). Use one of the 4 reserved bytes to store this value without changing the v4l2_ctrl_hevc_decode_params structure size and padding. This value also exist in DXVA API. Signed-off-by: Benjamin Gaignard Signed-off-by: Yunfei Dong Reviewed-by: Nicolas Dufresne Signed-off-by: Hans Verkuil [hverkuil: fix typo in num_delta_pocs_of_ref_rps_idx doc] --- .../userspace-api/media/v4l/ext-ctrls-codec-stateless.rst | 7 +++++++ include/uapi/linux/v4l2-controls.h | 6 +++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst index 3d8411acd5b8..677bf0fbcc5a 100644 --- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst +++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst @@ -2923,6 +2923,13 @@ This structure contains all loop filter related parameters. See sections - ``poc_lt_curr[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` - PocLtCurr as described in section 8.3.2 "Decoding process for reference picture set": provides the index of the long term references in DPB array. + * - __u8 + - ``num_delta_pocs_of_ref_rps_idx`` + - When the short_term_ref_pic_set_sps_flag in the slice header is equal to 0, + it is the same as the derived value NumDeltaPocs[RefRpsIdx]. It can be used to parse + the RPS data in slice headers instead of skipping it with @short_term_ref_pic_set_size. + When the value of short_term_ref_pic_set_sps_flag in the slice header is + equal to 1, num_delta_pocs_of_ref_rps_idx shall be set to 0. * - struct :c:type:`v4l2_hevc_dpb_entry` - ``dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` - The decoded picture buffer, for meta-data about reference frames. diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 5e80daa4ffe0..7bf59a87a1bf 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -2385,6 +2385,9 @@ struct v4l2_ctrl_hevc_slice_params { * @poc_st_curr_after: provides the index of the short term after references * in DPB array * @poc_lt_curr: provides the index of the long term references in DPB array + * @num_delta_pocs_of_ref_rps_idx: same as the derived value NumDeltaPocs[RefRpsIdx], + * can be used to parse the RPS data in slice headers + * instead of skipping it with @short_term_ref_pic_set_size. * @reserved: padding field. Should be zeroed by applications. * @dpb: the decoded picture buffer, for meta-data about reference frames * @flags: see V4L2_HEVC_DECODE_PARAM_FLAG_{} @@ -2400,7 +2403,8 @@ struct v4l2_ctrl_hevc_decode_params { __u8 poc_st_curr_before[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; __u8 poc_st_curr_after[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; __u8 poc_lt_curr[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; - __u8 reserved[4]; + __u8 num_delta_pocs_of_ref_rps_idx; + __u8 reserved[3]; struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; __u64 flags; }; From 2674486aac7d9c95ceb77daf7c30f862d4295c1c Mon Sep 17 00:00:00 2001 From: Yunfei Dong Date: Wed, 24 May 2023 16:07:39 +0800 Subject: [PATCH 060/253] media: mediatek: vcodec: support stateless hevc decoder Add mediatek hevc decoder linux driver which use the stateless API in MT8195. Signed-off-by: Yunfei Dong Reviewed-by: AngeloGioacchino Del Regno Tested-by: Nicolas Dufresne Tested-by: Nathan Hebert Signed-off-by: Hans Verkuil [hverkuil: add () around 'flag' in macro] --- .../media/platform/mediatek/vcodec/Makefile | 1 + .../vcodec/mtk_vcodec_dec_stateless.c | 59 +- .../platform/mediatek/vcodec/mtk_vcodec_drv.h | 1 + .../vcodec/vdec/vdec_hevc_req_multi_if.c | 1097 +++++++++++++++++ .../platform/mediatek/vcodec/vdec_drv_if.c | 4 + .../platform/mediatek/vcodec/vdec_drv_if.h | 1 + 6 files changed, 1162 insertions(+), 1 deletion(-) create mode 100644 drivers/media/platform/mediatek/vcodec/vdec/vdec_hevc_req_multi_if.c diff --git a/drivers/media/platform/mediatek/vcodec/Makefile b/drivers/media/platform/mediatek/vcodec/Makefile index 93e7a343b5b0..d24b452d0fb3 100644 --- a/drivers/media/platform/mediatek/vcodec/Makefile +++ b/drivers/media/platform/mediatek/vcodec/Makefile @@ -13,6 +13,7 @@ mtk-vcodec-dec-y := vdec/vdec_h264_if.o \ vdec/vdec_h264_req_if.o \ vdec/vdec_h264_req_common.o \ vdec/vdec_h264_req_multi_if.o \ + vdec/vdec_hevc_req_multi_if.o \ mtk_vcodec_dec_drv.o \ vdec_drv_if.o \ vdec_vpu_if.o \ diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c index 3000db975e5f..995997f702a0 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c @@ -107,11 +107,63 @@ static const struct mtk_stateless_control mtk_stateless_controls[] = { }, .codec_type = V4L2_PIX_FMT_VP9_FRAME, }, + { + .cfg = { + .id = V4L2_CID_STATELESS_HEVC_SPS, + }, + .codec_type = V4L2_PIX_FMT_HEVC_SLICE, + }, + { + .cfg = { + .id = V4L2_CID_STATELESS_HEVC_PPS, + }, + .codec_type = V4L2_PIX_FMT_HEVC_SLICE, + }, + { + .cfg = { + .id = V4L2_CID_STATELESS_HEVC_SCALING_MATRIX, + }, + .codec_type = V4L2_PIX_FMT_HEVC_SLICE, + }, + { + .cfg = { + .id = V4L2_CID_STATELESS_HEVC_DECODE_PARAMS, + }, + .codec_type = V4L2_PIX_FMT_HEVC_SLICE, + }, + { + .cfg = { + .id = V4L2_CID_MPEG_VIDEO_HEVC_PROFILE, + .def = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN, + .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10, + .menu_skip_mask = + BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE), + }, + .codec_type = V4L2_PIX_FMT_HEVC_SLICE, + }, + { + .cfg = { + .id = V4L2_CID_STATELESS_HEVC_DECODE_MODE, + .min = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED, + .def = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED, + .max = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED, + }, + .codec_type = V4L2_PIX_FMT_HEVC_SLICE, + }, + { + .cfg = { + .id = V4L2_CID_STATELESS_HEVC_START_CODE, + .min = V4L2_STATELESS_HEVC_START_CODE_ANNEX_B, + .def = V4L2_STATELESS_HEVC_START_CODE_ANNEX_B, + .max = V4L2_STATELESS_HEVC_START_CODE_ANNEX_B, + }, + .codec_type = V4L2_PIX_FMT_HEVC_SLICE, + }, }; #define NUM_CTRLS ARRAY_SIZE(mtk_stateless_controls) -static struct mtk_video_fmt mtk_video_formats[5]; +static struct mtk_video_fmt mtk_video_formats[6]; static struct mtk_video_fmt default_out_format; static struct mtk_video_fmt default_cap_format; @@ -356,6 +408,7 @@ static void mtk_vcodec_add_formats(unsigned int fourcc, case V4L2_PIX_FMT_H264_SLICE: case V4L2_PIX_FMT_VP8_FRAME: case V4L2_PIX_FMT_VP9_FRAME: + case V4L2_PIX_FMT_HEVC_SLICE: mtk_video_formats[count_formats].fourcc = fourcc; mtk_video_formats[count_formats].type = MTK_FMT_DEC; mtk_video_formats[count_formats].num_planes = 1; @@ -412,6 +465,10 @@ static void mtk_vcodec_get_supported_formats(struct mtk_vcodec_ctx *ctx) mtk_vcodec_add_formats(V4L2_PIX_FMT_VP9_FRAME, ctx); out_format_count++; } + if (ctx->dev->dec_capability & MTK_VDEC_FORMAT_HEVC_FRAME) { + mtk_vcodec_add_formats(V4L2_PIX_FMT_HEVC_SLICE, ctx); + out_format_count++; + } if (cap_format_count) default_cap_format = mtk_video_formats[cap_format_count - 1]; diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h index 9acab54fd650..144252fa8bea 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h @@ -347,6 +347,7 @@ enum mtk_vdec_format_types { MTK_VDEC_FORMAT_H264_SLICE = 0x100, MTK_VDEC_FORMAT_VP8_FRAME = 0x200, MTK_VDEC_FORMAT_VP9_FRAME = 0x400, + MTK_VDEC_FORMAT_HEVC_FRAME = 0x1000, MTK_VCODEC_INNER_RACING = 0x20000, }; diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_hevc_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_hevc_req_multi_if.c new file mode 100644 index 000000000000..e8758e5db961 --- /dev/null +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_hevc_req_multi_if.c @@ -0,0 +1,1097 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 MediaTek Inc. + * Author: Yunfei Dong + */ + +#include +#include +#include + +#include "../mtk_vcodec_util.h" +#include "../mtk_vcodec_dec.h" +#include "../mtk_vcodec_intr.h" +#include "../vdec_drv_base.h" +#include "../vdec_drv_if.h" +#include "../vdec_vpu_if.h" + +/* the size used to store hevc wrap information */ +#define VDEC_HEVC_WRAP_SZ (532 * SZ_1K) + +#define HEVC_MAX_MV_NUM 32 + +/* get used parameters for sps/pps */ +#define GET_HEVC_VDEC_FLAG(cond, flag) \ + { dst_param->cond = ((src_param->flags & (flag)) ? (1) : (0)); } +#define GET_HEVC_VDEC_PARAM(param) \ + { dst_param->param = src_param->param; } + +/** + * enum vdec_hevc_core_dec_err_type - core decode error type + * + * @TRANS_BUFFER_FULL: trans buffer is full + * @SLICE_HEADER_FULL: slice header buffer is full + */ +enum vdec_hevc_core_dec_err_type { + TRANS_BUFFER_FULL = 1, + SLICE_HEADER_FULL, +}; + +/** + * struct mtk_hevc_dpb_info - hevc dpb information + * + * @y_dma_addr: Y plane physical address + * @c_dma_addr: CbCr plane physical address + * @reference_flag: reference picture flag (short/long term reference picture) + * @field: field picture flag + */ +struct mtk_hevc_dpb_info { + dma_addr_t y_dma_addr; + dma_addr_t c_dma_addr; + int reference_flag; + int field; +}; + +/* + * struct mtk_hevc_sps_param - parameters for sps + */ +struct mtk_hevc_sps_param { + unsigned char video_parameter_set_id; + unsigned char seq_parameter_set_id; + unsigned short pic_width_in_luma_samples; + unsigned short pic_height_in_luma_samples; + unsigned char bit_depth_luma_minus8; + unsigned char bit_depth_chroma_minus8; + unsigned char log2_max_pic_order_cnt_lsb_minus4; + unsigned char sps_max_dec_pic_buffering_minus1; + unsigned char sps_max_num_reorder_pics; + unsigned char sps_max_latency_increase_plus1; + unsigned char log2_min_luma_coding_block_size_minus3; + unsigned char log2_diff_max_min_luma_coding_block_size; + unsigned char log2_min_luma_transform_block_size_minus2; + unsigned char log2_diff_max_min_luma_transform_block_size; + unsigned char max_transform_hierarchy_depth_inter; + unsigned char max_transform_hierarchy_depth_intra; + unsigned char pcm_sample_bit_depth_luma_minus1; + unsigned char pcm_sample_bit_depth_chroma_minus1; + unsigned char log2_min_pcm_luma_coding_block_size_minus3; + unsigned char log2_diff_max_min_pcm_luma_coding_block_size; + unsigned char num_short_term_ref_pic_sets; + unsigned char num_long_term_ref_pics_sps; + unsigned char chroma_format_idc; + unsigned char sps_max_sub_layers_minus1; + unsigned char separate_colour_plane; + unsigned char scaling_list_enabled; + unsigned char amp_enabled; + unsigned char sample_adaptive_offset; + unsigned char pcm_enabled; + unsigned char pcm_loop_filter_disabled; + unsigned char long_term_ref_pics_enabled; + unsigned char sps_temporal_mvp_enabled; + unsigned char strong_intra_smoothing_enabled; + unsigned char reserved[5]; +}; + +/* + * struct mtk_hevc_pps_param - parameters for pps + */ +struct mtk_hevc_pps_param { + unsigned char pic_parameter_set_id; + unsigned char num_extra_slice_header_bits; + unsigned char num_ref_idx_l0_default_active_minus1; + unsigned char num_ref_idx_l1_default_active_minus1; + char init_qp_minus26; + unsigned char diff_cu_qp_delta_depth; + char pps_cb_qp_offset; + char pps_cr_qp_offset; + unsigned char num_tile_columns_minus1; + unsigned char num_tile_rows_minus1; + unsigned char column_width_minus1[20]; + unsigned char row_height_minus1[22]; + char pps_beta_offset_div2; + char pps_tc_offset_div2; + unsigned char log2_parallel_merge_level_minus2; + char dependent_slice_segment_enabled; + char output_flag_present; + char sign_data_hiding_enabled; + char cabac_init_present; + char constrained_intra_pred; + char transform_skip_enabled; + char cu_qp_delta_enabled; + char pps_slice_chroma_qp_offsets_present; + char weighted_pred; + char weighted_bipred; + char transquant_bypass_enabled; + char pps_flag_tiles_enabled; + char entropy_coding_sync_enabled; + char loop_filter_across_tiles_enabled; + char pps_loop_filter_across_slices_enabled; + char deblocking_filter_override_enabled; + char pps_disable_deflocking_filter; + char lists_modification_present; + char slice_segment_header_extersion_present; + char deblocking_filter_control_present; + char uniform_spacing; + char reserved[6]; +}; + +/* + * struct mtk_hevc_slice_header_param - parameters for slice header + */ +struct mtk_hevc_slice_header_param { + unsigned int slice_type; + unsigned int num_active_ref_layer_pics; + int slice_qp; + int slice_qp_delta_cb; + int slice_qp_delta_cr; + int num_ref_idx[3]; + unsigned int col_ref_idx; + unsigned int five_minus_max_num_merge_cand; + int slice_deblocking_filter_beta_offset_div2; + int slice_deblocking_filter_tc_offset_div2; + unsigned char sao_enable_flag; + unsigned char sao_enable_flag_chroma; + unsigned char cabac_init_flag; + unsigned char slice_tmvp_flags_present; + unsigned char col_from_l0_flag; + unsigned char mvd_l1_zero_flag; + unsigned char slice_loop_filter_across_slices_enabled_flag; + unsigned char deblocking_filter_disable_flag; + unsigned int slice_reg0; + unsigned int slice_reg1; + unsigned int slice_reg2; + unsigned int num_rps_curr_temp_list; + unsigned int ref_list_mode; + int str_num_delta_pocs; + int str_num_negtive_pos_pics; + int num_long_term; + int num_long_term_sps; + unsigned int max_cu_width; + unsigned int max_cu_height; + unsigned int num_entry_point_offsets; + unsigned int last_lcu_x_in_tile[17]; + unsigned int last_lcu_y_in_tile[17]; + unsigned char nal_unit_type; +}; + +/* + * struct slice_api_hevc_scaling_matrix - parameters for scaling list + */ +struct slice_api_hevc_scaling_matrix { + unsigned char scaling_list_4x4[6][16]; + unsigned char scaling_list_8x8[6][64]; + unsigned char scaling_list_16x16[6][64]; + unsigned char scaling_list_32x32[2][64]; + unsigned char scaling_list_dc_coef_16x16[6]; + unsigned char scaling_list_dc_coef_32x32[2]; +}; + +/* + * struct slice_hevc_dpb_entry - each dpb information + */ +struct slice_hevc_dpb_entry { + u64 timestamp; + unsigned char flags; + unsigned char field_pic; + int pic_order_cnt_val; +}; + +/* + * struct slice_api_hevc_decode_param - parameters for decode. + */ +struct slice_api_hevc_decode_param { + struct slice_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + int pic_order_cnt_val; + unsigned short short_term_ref_pic_set_size; + unsigned short long_term_ref_pic_set_size; + unsigned char num_active_dpb_entries; + unsigned char num_poc_st_curr_before; + unsigned char num_poc_st_curr_after; + unsigned char num_poc_lt_curr; + unsigned char poc_st_curr_before[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + unsigned char poc_st_curr_after[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + unsigned char poc_lt_curr[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; + unsigned char num_delta_pocs_of_ref_rps_idx; + int flags; +}; + +/** + * struct hevc_fb - hevc decode frame buffer information + * + * @vdec_fb_va: virtual address of struct vdec_fb + * @y_fb_dma: dma address of Y frame buffer (luma) + * @c_fb_dma: dma address of C frame buffer (chroma) + * @poc: picture order count of frame buffer + * @reserved: for 8 bytes alignment + */ +struct hevc_fb { + u64 vdec_fb_va; + u64 y_fb_dma; + u64 c_fb_dma; + s32 poc; + u32 reserved; +}; + +/** + * struct vdec_hevc_slice_lat_dec_param - parameters for decode current frame + * + * @sps: hevc sps syntax parameters + * @pps: hevc pps syntax parameters + * @slice_header: hevc slice header syntax parameters + * @scaling_matrix: hevc scaling list parameters + * @decode_params: decoder parameters of each frame used for hardware decode + * @hevc_dpb_info: dpb reference list + */ +struct vdec_hevc_slice_lat_dec_param { + struct mtk_hevc_sps_param sps; + struct mtk_hevc_pps_param pps; + struct mtk_hevc_slice_header_param slice_header; + struct slice_api_hevc_scaling_matrix scaling_matrix; + struct slice_api_hevc_decode_param decode_params; + struct mtk_hevc_dpb_info hevc_dpb_info[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; +}; + +/** + * struct vdec_hevc_slice_info - decode information + * + * @wdma_end_addr_offset: wdma end address offset + * @timeout: Decode timeout: 1 timeout, 0 no timeount + * @vdec_fb_va: VDEC frame buffer struct virtual address + * @crc: Used to check whether hardware's status is right + */ +struct vdec_hevc_slice_info { + u64 wdma_end_addr_offset; + u64 timeout; + u64 vdec_fb_va; + u32 crc[8]; +}; + +/* + * struct vdec_hevc_slice_mem - memory address and size + */ +struct vdec_hevc_slice_mem { + union { + u64 buf; + dma_addr_t dma_addr; + }; + union { + size_t size; + dma_addr_t dma_addr_end; + u64 padding; + }; +}; + +/** + * struct vdec_hevc_slice_fb - frame buffer for decoding + * @y: current y buffer address info + * @c: current c buffer address info + */ +struct vdec_hevc_slice_fb { + struct vdec_hevc_slice_mem y; + struct vdec_hevc_slice_mem c; +}; + +/** + * struct vdec_hevc_slice_vsi - shared memory for decode information exchange + * between SCP and Host. + * + * @bs: input buffer info + * + * @ube: ube buffer + * @trans: transcoded buffer + * @err_map: err map buffer + * @slice_bc: slice bc buffer + * @wrap: temp buffer + * + * @fb: current y/c buffer + * @mv_buf_dma: HW working motion vector buffer + * @dec: decode information (AP-R, VPU-W) + * @hevc_slice_params: decode parameters for hw used + */ +struct vdec_hevc_slice_vsi { + /* used in LAT stage */ + struct vdec_hevc_slice_mem bs; + + struct vdec_hevc_slice_mem ube; + struct vdec_hevc_slice_mem trans; + struct vdec_hevc_slice_mem err_map; + struct vdec_hevc_slice_mem slice_bc; + struct vdec_hevc_slice_mem wrap; + + struct vdec_hevc_slice_fb fb; + struct vdec_hevc_slice_mem mv_buf_dma[HEVC_MAX_MV_NUM]; + struct vdec_hevc_slice_info dec; + struct vdec_hevc_slice_lat_dec_param hevc_slice_params; +}; + +/** + * struct vdec_hevc_slice_share_info - shared information used to exchange + * message between lat and core + * + * @sps: sequence header information from user space + * @dec_params: decoder params from user space + * @hevc_slice_params: decoder params used for hardware + * @trans: trans buffer dma address + */ +struct vdec_hevc_slice_share_info { + struct v4l2_ctrl_hevc_sps sps; + struct v4l2_ctrl_hevc_decode_params dec_params; + struct vdec_hevc_slice_lat_dec_param hevc_slice_params; + struct vdec_hevc_slice_mem trans; +}; + +/** + * struct vdec_hevc_slice_inst - hevc decoder instance + * + * @slice_dec_num: how many picture be decoded + * @ctx: point to mtk_vcodec_ctx + * @mv_buf: HW working motion vector buffer + * @vpu: VPU instance + * @vsi: vsi used for lat + * @vsi_core: vsi used for core + * @wrap_addr: wrap address used for hevc + * + * @hevc_slice_param: the parameters that hardware use to decode + * + * @resolution_changed: resolution changed + * @realloc_mv_buf: reallocate mv buffer + * @cap_num_planes: number of capture queue plane + */ +struct vdec_hevc_slice_inst { + unsigned int slice_dec_num; + struct mtk_vcodec_ctx *ctx; + struct mtk_vcodec_mem mv_buf[HEVC_MAX_MV_NUM]; + struct vdec_vpu_inst vpu; + struct vdec_hevc_slice_vsi *vsi; + struct vdec_hevc_slice_vsi *vsi_core; + struct mtk_vcodec_mem wrap_addr; + + struct vdec_hevc_slice_lat_dec_param hevc_slice_param; + + unsigned int resolution_changed; + unsigned int realloc_mv_buf; + unsigned int cap_num_planes; +}; + +static unsigned int vdec_hevc_get_mv_buf_size(unsigned int width, unsigned int height) +{ + const unsigned int unit_size = (width / 16) * (height / 16) + 8; + + return 64 * unit_size; +} + +static void *vdec_hevc_get_ctrl_ptr(struct mtk_vcodec_ctx *ctx, int id) +{ + struct v4l2_ctrl *ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, id); + + if (!ctrl) + return ERR_PTR(-EINVAL); + + return ctrl->p_cur.p; +} + +static void vdec_hevc_fill_dpb_info(struct mtk_vcodec_ctx *ctx, + struct slice_api_hevc_decode_param *decode_params, + struct mtk_hevc_dpb_info *hevc_dpb_info) +{ + const struct slice_hevc_dpb_entry *dpb; + struct vb2_queue *vq; + struct vb2_buffer *vb; + int index; + + vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + for (index = 0; index < V4L2_HEVC_DPB_ENTRIES_NUM_MAX; index++) { + dpb = &decode_params->dpb[index]; + if (index >= decode_params->num_active_dpb_entries) + continue; + + vb = vb2_find_buffer(vq, dpb->timestamp); + if (!vb) { + dev_err(&ctx->dev->plat_dev->dev, + "Reference invalid: dpb_index(%d) timestamp(%lld)", + index, dpb->timestamp); + continue; + } + + hevc_dpb_info[index].field = dpb->field_pic; + + hevc_dpb_info[index].y_dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0); + if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 2) + hevc_dpb_info[index].c_dma_addr = vb2_dma_contig_plane_dma_addr(vb, 1); + else + hevc_dpb_info[index].c_dma_addr = + hevc_dpb_info[index].y_dma_addr + ctx->picinfo.fb_sz[0]; + } +} + +static void vdec_hevc_copy_sps_params(struct mtk_hevc_sps_param *dst_param, + const struct v4l2_ctrl_hevc_sps *src_param) +{ + GET_HEVC_VDEC_PARAM(video_parameter_set_id); + GET_HEVC_VDEC_PARAM(seq_parameter_set_id); + GET_HEVC_VDEC_PARAM(pic_width_in_luma_samples); + GET_HEVC_VDEC_PARAM(pic_height_in_luma_samples); + GET_HEVC_VDEC_PARAM(bit_depth_luma_minus8); + GET_HEVC_VDEC_PARAM(bit_depth_chroma_minus8); + GET_HEVC_VDEC_PARAM(log2_max_pic_order_cnt_lsb_minus4); + GET_HEVC_VDEC_PARAM(sps_max_dec_pic_buffering_minus1); + GET_HEVC_VDEC_PARAM(sps_max_num_reorder_pics); + GET_HEVC_VDEC_PARAM(sps_max_latency_increase_plus1); + GET_HEVC_VDEC_PARAM(log2_min_luma_coding_block_size_minus3); + GET_HEVC_VDEC_PARAM(log2_diff_max_min_luma_coding_block_size); + GET_HEVC_VDEC_PARAM(log2_min_luma_transform_block_size_minus2); + GET_HEVC_VDEC_PARAM(log2_diff_max_min_luma_transform_block_size); + GET_HEVC_VDEC_PARAM(max_transform_hierarchy_depth_inter); + GET_HEVC_VDEC_PARAM(max_transform_hierarchy_depth_intra); + GET_HEVC_VDEC_PARAM(pcm_sample_bit_depth_luma_minus1); + GET_HEVC_VDEC_PARAM(pcm_sample_bit_depth_chroma_minus1); + GET_HEVC_VDEC_PARAM(log2_min_pcm_luma_coding_block_size_minus3); + GET_HEVC_VDEC_PARAM(log2_diff_max_min_pcm_luma_coding_block_size); + GET_HEVC_VDEC_PARAM(num_short_term_ref_pic_sets); + GET_HEVC_VDEC_PARAM(num_long_term_ref_pics_sps); + GET_HEVC_VDEC_PARAM(chroma_format_idc); + GET_HEVC_VDEC_PARAM(sps_max_sub_layers_minus1); + + GET_HEVC_VDEC_FLAG(separate_colour_plane, + V4L2_HEVC_SPS_FLAG_SEPARATE_COLOUR_PLANE); + GET_HEVC_VDEC_FLAG(scaling_list_enabled, + V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED); + GET_HEVC_VDEC_FLAG(amp_enabled, + V4L2_HEVC_SPS_FLAG_AMP_ENABLED); + GET_HEVC_VDEC_FLAG(sample_adaptive_offset, + V4L2_HEVC_SPS_FLAG_SAMPLE_ADAPTIVE_OFFSET); + GET_HEVC_VDEC_FLAG(pcm_enabled, + V4L2_HEVC_SPS_FLAG_PCM_ENABLED); + GET_HEVC_VDEC_FLAG(pcm_loop_filter_disabled, + V4L2_HEVC_SPS_FLAG_PCM_LOOP_FILTER_DISABLED); + GET_HEVC_VDEC_FLAG(long_term_ref_pics_enabled, + V4L2_HEVC_SPS_FLAG_LONG_TERM_REF_PICS_PRESENT); + GET_HEVC_VDEC_FLAG(sps_temporal_mvp_enabled, + V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED); + GET_HEVC_VDEC_FLAG(strong_intra_smoothing_enabled, + V4L2_HEVC_SPS_FLAG_STRONG_INTRA_SMOOTHING_ENABLED); +} + +static void vdec_hevc_copy_pps_params(struct mtk_hevc_pps_param *dst_param, + const struct v4l2_ctrl_hevc_pps *src_param) +{ + int i; + + GET_HEVC_VDEC_PARAM(pic_parameter_set_id); + GET_HEVC_VDEC_PARAM(num_extra_slice_header_bits); + GET_HEVC_VDEC_PARAM(num_ref_idx_l0_default_active_minus1); + GET_HEVC_VDEC_PARAM(num_ref_idx_l1_default_active_minus1); + GET_HEVC_VDEC_PARAM(init_qp_minus26); + GET_HEVC_VDEC_PARAM(diff_cu_qp_delta_depth); + GET_HEVC_VDEC_PARAM(pps_cb_qp_offset); + GET_HEVC_VDEC_PARAM(pps_cr_qp_offset); + GET_HEVC_VDEC_PARAM(num_tile_columns_minus1); + GET_HEVC_VDEC_PARAM(num_tile_rows_minus1); + GET_HEVC_VDEC_PARAM(init_qp_minus26); + GET_HEVC_VDEC_PARAM(diff_cu_qp_delta_depth); + GET_HEVC_VDEC_PARAM(pic_parameter_set_id); + GET_HEVC_VDEC_PARAM(num_extra_slice_header_bits); + GET_HEVC_VDEC_PARAM(num_ref_idx_l0_default_active_minus1); + GET_HEVC_VDEC_PARAM(num_ref_idx_l1_default_active_minus1); + GET_HEVC_VDEC_PARAM(pps_beta_offset_div2); + GET_HEVC_VDEC_PARAM(pps_tc_offset_div2); + GET_HEVC_VDEC_PARAM(log2_parallel_merge_level_minus2); + + for (i = 0; i < ARRAY_SIZE(src_param->column_width_minus1); i++) + GET_HEVC_VDEC_PARAM(column_width_minus1[i]); + for (i = 0; i < ARRAY_SIZE(src_param->row_height_minus1); i++) + GET_HEVC_VDEC_PARAM(row_height_minus1[i]); + + GET_HEVC_VDEC_FLAG(dependent_slice_segment_enabled, + V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED); + GET_HEVC_VDEC_FLAG(output_flag_present, + V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT); + GET_HEVC_VDEC_FLAG(sign_data_hiding_enabled, + V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED); + GET_HEVC_VDEC_FLAG(cabac_init_present, + V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT); + GET_HEVC_VDEC_FLAG(constrained_intra_pred, + V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED); + GET_HEVC_VDEC_FLAG(transform_skip_enabled, + V4L2_HEVC_PPS_FLAG_TRANSFORM_SKIP_ENABLED); + GET_HEVC_VDEC_FLAG(cu_qp_delta_enabled, + V4L2_HEVC_PPS_FLAG_CU_QP_DELTA_ENABLED); + GET_HEVC_VDEC_FLAG(pps_slice_chroma_qp_offsets_present, + V4L2_HEVC_PPS_FLAG_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT); + GET_HEVC_VDEC_FLAG(weighted_pred, + V4L2_HEVC_PPS_FLAG_WEIGHTED_PRED); + GET_HEVC_VDEC_FLAG(weighted_bipred, + V4L2_HEVC_PPS_FLAG_WEIGHTED_BIPRED); + GET_HEVC_VDEC_FLAG(transquant_bypass_enabled, + V4L2_HEVC_PPS_FLAG_TRANSQUANT_BYPASS_ENABLED); + GET_HEVC_VDEC_FLAG(pps_flag_tiles_enabled, + V4L2_HEVC_PPS_FLAG_TILES_ENABLED); + GET_HEVC_VDEC_FLAG(entropy_coding_sync_enabled, + V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED); + GET_HEVC_VDEC_FLAG(loop_filter_across_tiles_enabled, + V4L2_HEVC_PPS_FLAG_LOOP_FILTER_ACROSS_TILES_ENABLED); + GET_HEVC_VDEC_FLAG(pps_loop_filter_across_slices_enabled, + V4L2_HEVC_PPS_FLAG_PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED); + GET_HEVC_VDEC_FLAG(deblocking_filter_override_enabled, + V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_OVERRIDE_ENABLED); + GET_HEVC_VDEC_FLAG(pps_disable_deflocking_filter, + V4L2_HEVC_PPS_FLAG_PPS_DISABLE_DEBLOCKING_FILTER); + GET_HEVC_VDEC_FLAG(lists_modification_present, + V4L2_HEVC_PPS_FLAG_LISTS_MODIFICATION_PRESENT); + GET_HEVC_VDEC_FLAG(slice_segment_header_extersion_present, + V4L2_HEVC_PPS_FLAG_SLICE_SEGMENT_HEADER_EXTENSION_PRESENT); + GET_HEVC_VDEC_FLAG(deblocking_filter_control_present, + V4L2_HEVC_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT); + GET_HEVC_VDEC_FLAG(uniform_spacing, + V4L2_HEVC_PPS_FLAG_UNIFORM_SPACING); +} + +static void vdec_hevc_copy_scaling_matrix(struct slice_api_hevc_scaling_matrix *dst_matrix, + const struct v4l2_ctrl_hevc_scaling_matrix *src_matrix) +{ + memcpy(dst_matrix, src_matrix, sizeof(*src_matrix)); +} + +static void +vdec_hevc_copy_decode_params(struct slice_api_hevc_decode_param *dst_param, + const struct v4l2_ctrl_hevc_decode_params *src_param, + const struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]) +{ + struct slice_hevc_dpb_entry *dst_entry; + const struct v4l2_hevc_dpb_entry *src_entry; + int i; + + for (i = 0; i < ARRAY_SIZE(dst_param->dpb); i++) { + dst_entry = &dst_param->dpb[i]; + src_entry = &dpb[i]; + + dst_entry->timestamp = src_entry->timestamp; + dst_entry->flags = src_entry->flags; + dst_entry->field_pic = src_entry->field_pic; + dst_entry->pic_order_cnt_val = src_entry->pic_order_cnt_val; + + GET_HEVC_VDEC_PARAM(poc_st_curr_before[i]); + GET_HEVC_VDEC_PARAM(poc_st_curr_after[i]); + GET_HEVC_VDEC_PARAM(poc_lt_curr[i]); + } + + GET_HEVC_VDEC_PARAM(pic_order_cnt_val); + GET_HEVC_VDEC_PARAM(short_term_ref_pic_set_size); + GET_HEVC_VDEC_PARAM(long_term_ref_pic_set_size); + GET_HEVC_VDEC_PARAM(num_active_dpb_entries); + GET_HEVC_VDEC_PARAM(num_poc_st_curr_before); + GET_HEVC_VDEC_PARAM(num_poc_st_curr_after); + GET_HEVC_VDEC_PARAM(num_delta_pocs_of_ref_rps_idx); + GET_HEVC_VDEC_PARAM(num_poc_lt_curr); + GET_HEVC_VDEC_PARAM(flags); +} + +static int vdec_hevc_slice_fill_decode_parameters(struct vdec_hevc_slice_inst *inst, + struct vdec_hevc_slice_share_info *share_info) +{ + struct vdec_hevc_slice_lat_dec_param *slice_param = &inst->vsi->hevc_slice_params; + const struct v4l2_ctrl_hevc_decode_params *dec_params; + const struct v4l2_ctrl_hevc_scaling_matrix *src_matrix; + const struct v4l2_ctrl_hevc_sps *sps; + const struct v4l2_ctrl_hevc_pps *pps; + + dec_params = + vdec_hevc_get_ctrl_ptr(inst->ctx, V4L2_CID_STATELESS_HEVC_DECODE_PARAMS); + if (IS_ERR(dec_params)) + return PTR_ERR(dec_params); + + src_matrix = + vdec_hevc_get_ctrl_ptr(inst->ctx, V4L2_CID_STATELESS_HEVC_SCALING_MATRIX); + if (IS_ERR(src_matrix)) + return PTR_ERR(src_matrix); + + sps = vdec_hevc_get_ctrl_ptr(inst->ctx, V4L2_CID_STATELESS_HEVC_SPS); + if (IS_ERR(sps)) + return PTR_ERR(sps); + + pps = vdec_hevc_get_ctrl_ptr(inst->ctx, V4L2_CID_STATELESS_HEVC_PPS); + if (IS_ERR(pps)) + return PTR_ERR(pps); + + vdec_hevc_copy_sps_params(&slice_param->sps, sps); + vdec_hevc_copy_pps_params(&slice_param->pps, pps); + vdec_hevc_copy_scaling_matrix(&slice_param->scaling_matrix, src_matrix); + + memcpy(&share_info->sps, sps, sizeof(*sps)); + memcpy(&share_info->dec_params, dec_params, sizeof(*dec_params)); + + slice_param->decode_params.num_poc_st_curr_before = dec_params->num_poc_st_curr_before; + slice_param->decode_params.num_poc_st_curr_after = dec_params->num_poc_st_curr_after; + slice_param->decode_params.num_poc_lt_curr = dec_params->num_poc_lt_curr; + slice_param->decode_params.num_delta_pocs_of_ref_rps_idx = + dec_params->num_delta_pocs_of_ref_rps_idx; + + return 0; +} + +static void vdec_hevc_slice_fill_decode_reflist(struct vdec_hevc_slice_inst *inst, + struct vdec_hevc_slice_lat_dec_param *slice_param, + struct vdec_hevc_slice_share_info *share_info) +{ + struct v4l2_ctrl_hevc_decode_params *dec_params = &share_info->dec_params; + + vdec_hevc_copy_decode_params(&slice_param->decode_params, dec_params, + share_info->dec_params.dpb); + + vdec_hevc_fill_dpb_info(inst->ctx, &slice_param->decode_params, + slice_param->hevc_dpb_info); +} + +static int vdec_hevc_slice_alloc_mv_buf(struct vdec_hevc_slice_inst *inst, + struct vdec_pic_info *pic) +{ + unsigned int buf_sz = vdec_hevc_get_mv_buf_size(pic->buf_w, pic->buf_h); + struct mtk_vcodec_mem *mem; + int i, err; + + mtk_v4l2_debug(3, "allocate mv buffer size = 0x%x", buf_sz); + for (i = 0; i < HEVC_MAX_MV_NUM; i++) { + mem = &inst->mv_buf[i]; + if (mem->va) + mtk_vcodec_mem_free(inst->ctx, mem); + mem->size = buf_sz; + err = mtk_vcodec_mem_alloc(inst->ctx, mem); + if (err) { + mtk_vcodec_err(inst, "failed to allocate mv buf"); + return err; + } + } + + return 0; +} + +static void vdec_hevc_slice_free_mv_buf(struct vdec_hevc_slice_inst *inst) +{ + int i; + struct mtk_vcodec_mem *mem; + + for (i = 0; i < HEVC_MAX_MV_NUM; i++) { + mem = &inst->mv_buf[i]; + if (mem->va) + mtk_vcodec_mem_free(inst->ctx, mem); + } +} + +static void vdec_hevc_slice_get_pic_info(struct vdec_hevc_slice_inst *inst) +{ + struct mtk_vcodec_ctx *ctx = inst->ctx; + u32 data[3]; + + data[0] = ctx->picinfo.pic_w; + data[1] = ctx->picinfo.pic_h; + data[2] = ctx->capture_fourcc; + vpu_dec_get_param(&inst->vpu, data, 3, GET_PARAM_PIC_INFO); + + ctx->picinfo.buf_w = ALIGN(ctx->picinfo.pic_w, VCODEC_DEC_ALIGNED_64); + ctx->picinfo.buf_h = ALIGN(ctx->picinfo.pic_h, VCODEC_DEC_ALIGNED_64); + ctx->picinfo.fb_sz[0] = inst->vpu.fb_sz[0]; + ctx->picinfo.fb_sz[1] = inst->vpu.fb_sz[1]; + inst->cap_num_planes = + ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes; + + mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)", + ctx->picinfo.pic_w, ctx->picinfo.pic_h, + ctx->picinfo.buf_w, ctx->picinfo.buf_h); + mtk_vcodec_debug(inst, "Y/C(%d, %d)", ctx->picinfo.fb_sz[0], + ctx->picinfo.fb_sz[1]); + + if (ctx->last_decoded_picinfo.pic_w != ctx->picinfo.pic_w || + ctx->last_decoded_picinfo.pic_h != ctx->picinfo.pic_h) { + inst->resolution_changed = true; + if (ctx->last_decoded_picinfo.buf_w != ctx->picinfo.buf_w || + ctx->last_decoded_picinfo.buf_h != ctx->picinfo.buf_h) + inst->realloc_mv_buf = true; + + mtk_v4l2_debug(1, "resChg: (%d %d) : old(%d, %d) -> new(%d, %d)", + inst->resolution_changed, + inst->realloc_mv_buf, + ctx->last_decoded_picinfo.pic_w, + ctx->last_decoded_picinfo.pic_h, + ctx->picinfo.pic_w, ctx->picinfo.pic_h); + } +} + +static void vdec_hevc_slice_get_crop_info(struct vdec_hevc_slice_inst *inst, + struct v4l2_rect *cr) +{ + cr->left = 0; + cr->top = 0; + cr->width = inst->ctx->picinfo.pic_w; + cr->height = inst->ctx->picinfo.pic_h; + + mtk_vcodec_debug(inst, "l=%d, t=%d, w=%d, h=%d", + cr->left, cr->top, cr->width, cr->height); +} + +static int vdec_hevc_slice_setup_lat_buffer(struct vdec_hevc_slice_inst *inst, + struct mtk_vcodec_mem *bs, + struct vdec_lat_buf *lat_buf, + bool *res_chg) +{ + struct mtk_vcodec_mem *mem; + struct mtk_video_dec_buf *src_buf_info; + struct vdec_hevc_slice_share_info *share_info; + int i, err; + + inst->vsi->bs.dma_addr = (u64)bs->dma_addr; + inst->vsi->bs.size = bs->size; + + src_buf_info = container_of(bs, struct mtk_video_dec_buf, bs_buffer); + lat_buf->src_buf_req = src_buf_info->m2m_buf.vb.vb2_buf.req_obj.req; + v4l2_m2m_buf_copy_metadata(&src_buf_info->m2m_buf.vb, &lat_buf->ts_info, true); + + *res_chg = inst->resolution_changed; + if (inst->resolution_changed) { + mtk_vcodec_debug(inst, "- resolution changed -"); + if (inst->realloc_mv_buf) { + err = vdec_hevc_slice_alloc_mv_buf(inst, &inst->ctx->picinfo); + inst->realloc_mv_buf = false; + if (err) + return err; + } + inst->resolution_changed = false; + } + + for (i = 0; i < HEVC_MAX_MV_NUM; i++) { + mem = &inst->mv_buf[i]; + inst->vsi->mv_buf_dma[i].dma_addr = mem->dma_addr; + inst->vsi->mv_buf_dma[i].size = mem->size; + } + + inst->vsi->ube.dma_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr; + inst->vsi->ube.size = lat_buf->ctx->msg_queue.wdma_addr.size; + + inst->vsi->err_map.dma_addr = lat_buf->wdma_err_addr.dma_addr; + inst->vsi->err_map.size = lat_buf->wdma_err_addr.size; + + inst->vsi->slice_bc.dma_addr = lat_buf->slice_bc_addr.dma_addr; + inst->vsi->slice_bc.size = lat_buf->slice_bc_addr.size; + + inst->vsi->trans.dma_addr_end = inst->ctx->msg_queue.wdma_rptr_addr; + inst->vsi->trans.dma_addr = inst->ctx->msg_queue.wdma_wptr_addr; + + share_info = lat_buf->private_data; + share_info->trans.dma_addr = inst->vsi->trans.dma_addr; + share_info->trans.dma_addr_end = inst->vsi->trans.dma_addr_end; + + mtk_vcodec_debug(inst, "lat: ube addr/size(0x%llx 0x%llx) err:0x%llx", + inst->vsi->ube.buf, + inst->vsi->ube.padding, + inst->vsi->err_map.buf); + + mtk_vcodec_debug(inst, "slice addr/size(0x%llx 0x%llx) trans start/end((0x%llx 0x%llx))", + inst->vsi->slice_bc.buf, + inst->vsi->slice_bc.padding, + inst->vsi->trans.buf, + inst->vsi->trans.padding); + + return 0; +} + +static int vdec_hevc_slice_setup_core_buffer(struct vdec_hevc_slice_inst *inst, + struct vdec_hevc_slice_share_info *share_info, + struct vdec_lat_buf *lat_buf) +{ + struct mtk_vcodec_mem *mem; + struct mtk_vcodec_ctx *ctx = inst->ctx; + struct vb2_v4l2_buffer *vb2_v4l2; + struct vdec_fb *fb; + u64 y_fb_dma, c_fb_dma; + int i; + + fb = ctx->dev->vdec_pdata->get_cap_buffer(ctx); + if (!fb) { + mtk_vcodec_err(inst, "fb buffer is NULL"); + return -EBUSY; + } + + y_fb_dma = (u64)fb->base_y.dma_addr; + if (ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 1) + c_fb_dma = + y_fb_dma + inst->ctx->picinfo.buf_w * inst->ctx->picinfo.buf_h; + else + c_fb_dma = (u64)fb->base_c.dma_addr; + + mtk_vcodec_debug(inst, "[hevc-core] y/c addr = 0x%llx 0x%llx", y_fb_dma, + c_fb_dma); + + inst->vsi_core->fb.y.dma_addr = y_fb_dma; + inst->vsi_core->fb.y.size = ctx->picinfo.fb_sz[0]; + inst->vsi_core->fb.c.dma_addr = c_fb_dma; + inst->vsi_core->fb.y.size = ctx->picinfo.fb_sz[1]; + + inst->vsi_core->dec.vdec_fb_va = (unsigned long)fb; + + inst->vsi_core->ube.dma_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr; + inst->vsi_core->ube.size = lat_buf->ctx->msg_queue.wdma_addr.size; + + inst->vsi_core->err_map.dma_addr = lat_buf->wdma_err_addr.dma_addr; + inst->vsi_core->err_map.size = lat_buf->wdma_err_addr.size; + + inst->vsi_core->slice_bc.dma_addr = lat_buf->slice_bc_addr.dma_addr; + inst->vsi_core->slice_bc.size = lat_buf->slice_bc_addr.size; + + inst->vsi_core->trans.dma_addr = share_info->trans.dma_addr; + inst->vsi_core->trans.dma_addr_end = share_info->trans.dma_addr_end; + + inst->vsi_core->wrap.dma_addr = inst->wrap_addr.dma_addr; + inst->vsi_core->wrap.size = inst->wrap_addr.size; + + for (i = 0; i < HEVC_MAX_MV_NUM; i++) { + mem = &inst->mv_buf[i]; + inst->vsi_core->mv_buf_dma[i].dma_addr = mem->dma_addr; + inst->vsi_core->mv_buf_dma[i].size = mem->size; + } + + vb2_v4l2 = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + v4l2_m2m_buf_copy_metadata(&lat_buf->ts_info, vb2_v4l2, true); + + return 0; +} + +static int vdec_hevc_slice_init(struct mtk_vcodec_ctx *ctx) +{ + struct vdec_hevc_slice_inst *inst; + int err, vsi_size; + + inst = kzalloc(sizeof(*inst), GFP_KERNEL); + if (!inst) + return -ENOMEM; + + inst->ctx = ctx; + + inst->vpu.id = SCP_IPI_VDEC_LAT; + inst->vpu.core_id = SCP_IPI_VDEC_CORE; + inst->vpu.ctx = ctx; + inst->vpu.codec_type = ctx->current_codec; + inst->vpu.capture_type = ctx->capture_fourcc; + + ctx->drv_handle = inst; + err = vpu_dec_init(&inst->vpu); + if (err) { + mtk_vcodec_err(inst, "vdec_hevc init err=%d", err); + goto error_free_inst; + } + + vsi_size = round_up(sizeof(struct vdec_hevc_slice_vsi), VCODEC_DEC_ALIGNED_64); + inst->vsi = inst->vpu.vsi; + inst->vsi_core = + (struct vdec_hevc_slice_vsi *)(((char *)inst->vpu.vsi) + vsi_size); + + inst->resolution_changed = true; + inst->realloc_mv_buf = true; + + inst->wrap_addr.size = VDEC_HEVC_WRAP_SZ; + err = mtk_vcodec_mem_alloc(ctx, &inst->wrap_addr); + if (err) + goto error_free_inst; + + mtk_vcodec_debug(inst, "lat struct size = %d,%d,%d,%d vsi: %d\n", + (int)sizeof(struct mtk_hevc_sps_param), + (int)sizeof(struct mtk_hevc_pps_param), + (int)sizeof(struct vdec_hevc_slice_lat_dec_param), + (int)sizeof(struct mtk_hevc_dpb_info), + vsi_size); + mtk_vcodec_debug(inst, "lat hevc instance >> %p, codec_type = 0x%x", + inst, inst->vpu.codec_type); + + return 0; +error_free_inst: + kfree(inst); + return err; +} + +static void vdec_hevc_slice_deinit(void *h_vdec) +{ + struct vdec_hevc_slice_inst *inst = h_vdec; + struct mtk_vcodec_mem *mem; + + mtk_vcodec_debug_enter(inst); + + vpu_dec_deinit(&inst->vpu); + vdec_hevc_slice_free_mv_buf(inst); + + mem = &inst->wrap_addr; + if (mem->va) + mtk_vcodec_mem_free(inst->ctx, mem); + + vdec_msg_queue_deinit(&inst->ctx->msg_queue, inst->ctx); + kfree(inst); +} + +static int vdec_hevc_slice_core_decode(struct vdec_lat_buf *lat_buf) +{ + int err, timeout; + struct mtk_vcodec_ctx *ctx = lat_buf->ctx; + struct vdec_hevc_slice_inst *inst = ctx->drv_handle; + struct vdec_hevc_slice_share_info *share_info = lat_buf->private_data; + struct vdec_vpu_inst *vpu = &inst->vpu; + + mtk_vcodec_debug(inst, "[hevc-core] vdec_hevc core decode"); + memcpy(&inst->vsi_core->hevc_slice_params, &share_info->hevc_slice_params, + sizeof(share_info->hevc_slice_params)); + + err = vdec_hevc_slice_setup_core_buffer(inst, share_info, lat_buf); + if (err) + goto vdec_dec_end; + + vdec_hevc_slice_fill_decode_reflist(inst, &inst->vsi_core->hevc_slice_params, + share_info); + err = vpu_dec_core(vpu); + if (err) { + mtk_vcodec_err(inst, "core decode err=%d", err); + goto vdec_dec_end; + } + + /* wait decoder done interrupt */ + timeout = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED, + WAIT_INTR_TIMEOUT_MS, MTK_VDEC_CORE); + if (timeout) + mtk_vcodec_err(inst, "core decode timeout: pic_%d", + ctx->decoded_frame_cnt); + inst->vsi_core->dec.timeout = !!timeout; + + vpu_dec_core_end(vpu); + mtk_vcodec_debug(inst, "pic[%d] crc: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", + ctx->decoded_frame_cnt, + inst->vsi_core->dec.crc[0], inst->vsi_core->dec.crc[1], + inst->vsi_core->dec.crc[2], inst->vsi_core->dec.crc[3], + inst->vsi_core->dec.crc[4], inst->vsi_core->dec.crc[5], + inst->vsi_core->dec.crc[6], inst->vsi_core->dec.crc[7]); + +vdec_dec_end: + vdec_msg_queue_update_ube_rptr(&lat_buf->ctx->msg_queue, share_info->trans.dma_addr_end); + ctx->dev->vdec_pdata->cap_to_disp(ctx, !!err, lat_buf->src_buf_req); + mtk_vcodec_debug(inst, "core decode done err=%d", err); + ctx->decoded_frame_cnt++; + return 0; +} + +static int vdec_hevc_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, + struct vdec_fb *fb, bool *res_chg) +{ + struct vdec_hevc_slice_inst *inst = h_vdec; + struct vdec_vpu_inst *vpu = &inst->vpu; + int err, timeout = 0; + unsigned int data[2]; + struct vdec_lat_buf *lat_buf; + struct vdec_hevc_slice_share_info *share_info; + + if (vdec_msg_queue_init(&inst->ctx->msg_queue, inst->ctx, + vdec_hevc_slice_core_decode, + sizeof(*share_info))) + return -ENOMEM; + + /* bs NULL means flush decoder */ + if (!bs) { + vdec_msg_queue_wait_lat_buf_full(&inst->ctx->msg_queue); + return vpu_dec_reset(vpu); + } + + lat_buf = vdec_msg_queue_dqbuf(&inst->ctx->msg_queue.lat_ctx); + if (!lat_buf) { + mtk_vcodec_debug(inst, "failed to get lat buffer"); + return -EAGAIN; + } + + share_info = lat_buf->private_data; + err = vdec_hevc_slice_fill_decode_parameters(inst, share_info); + if (err) + goto err_free_fb_out; + + err = vdec_hevc_slice_setup_lat_buffer(inst, bs, lat_buf, res_chg); + if (err) + goto err_free_fb_out; + + err = vpu_dec_start(vpu, data, 2); + if (err) { + mtk_vcodec_debug(inst, "lat decode err: %d", err); + goto err_free_fb_out; + } + + if (IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) { + memcpy(&share_info->hevc_slice_params, &inst->vsi->hevc_slice_params, + sizeof(share_info->hevc_slice_params)); + vdec_msg_queue_qbuf(&inst->ctx->dev->msg_queue_core_ctx, lat_buf); + } + + /* wait decoder done interrupt */ + timeout = mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED, + WAIT_INTR_TIMEOUT_MS, MTK_VDEC_LAT0); + if (timeout) + mtk_vcodec_err(inst, "lat decode timeout: pic_%d", inst->slice_dec_num); + inst->vsi->dec.timeout = !!timeout; + + err = vpu_dec_end(vpu); + if (err == SLICE_HEADER_FULL || err == TRANS_BUFFER_FULL) { + if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) + vdec_msg_queue_qbuf(&inst->ctx->msg_queue.lat_ctx, lat_buf); + inst->slice_dec_num++; + mtk_vcodec_err(inst, "lat dec fail: pic_%d err:%d", inst->slice_dec_num, err); + return -EINVAL; + } + + share_info->trans.dma_addr_end = inst->ctx->msg_queue.wdma_addr.dma_addr + + inst->vsi->dec.wdma_end_addr_offset; + vdec_msg_queue_update_ube_wptr(&lat_buf->ctx->msg_queue, share_info->trans.dma_addr_end); + + if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) { + memcpy(&share_info->hevc_slice_params, &inst->vsi->hevc_slice_params, + sizeof(share_info->hevc_slice_params)); + vdec_msg_queue_qbuf(&inst->ctx->dev->msg_queue_core_ctx, lat_buf); + } + mtk_vcodec_debug(inst, "dec num: %d lat crc: 0x%x 0x%x 0x%x", inst->slice_dec_num, + inst->vsi->dec.crc[0], inst->vsi->dec.crc[1], inst->vsi->dec.crc[2]); + + inst->slice_dec_num++; + return 0; +err_free_fb_out: + vdec_msg_queue_qbuf(&inst->ctx->msg_queue.lat_ctx, lat_buf); + mtk_vcodec_err(inst, "slice dec number: %d err: %d", inst->slice_dec_num, err); + return err; +} + +static int vdec_hevc_slice_decode(void *h_vdec, struct mtk_vcodec_mem *bs, + struct vdec_fb *unused, bool *res_chg) +{ + struct vdec_hevc_slice_inst *inst = h_vdec; + + if (!h_vdec || inst->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_PURE_SINGLE_CORE) + return -EINVAL; + + return vdec_hevc_slice_lat_decode(h_vdec, bs, unused, res_chg); +} + +static int vdec_hevc_slice_get_param(void *h_vdec, enum vdec_get_param_type type, + void *out) +{ + struct vdec_hevc_slice_inst *inst = h_vdec; + + switch (type) { + case GET_PARAM_PIC_INFO: + vdec_hevc_slice_get_pic_info(inst); + break; + case GET_PARAM_DPB_SIZE: + *(unsigned int *)out = 6; + break; + case GET_PARAM_CROP_INFO: + vdec_hevc_slice_get_crop_info(inst, out); + break; + default: + mtk_vcodec_err(inst, "invalid get parameter type=%d", type); + return -EINVAL; + } + return 0; +} + +const struct vdec_common_if vdec_hevc_slice_multi_if = { + .init = vdec_hevc_slice_init, + .decode = vdec_hevc_slice_decode, + .get_param = vdec_hevc_slice_get_param, + .deinit = vdec_hevc_slice_deinit, +}; diff --git a/drivers/media/platform/mediatek/vcodec/vdec_drv_if.c b/drivers/media/platform/mediatek/vcodec/vdec_drv_if.c index f3807f03d880..0bde1eb04015 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec_drv_if.c +++ b/drivers/media/platform/mediatek/vcodec/vdec_drv_if.c @@ -49,6 +49,10 @@ int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc) ctx->dec_if = &vdec_vp9_slice_lat_if; ctx->hw_id = IS_VDEC_LAT_ARCH(hw_arch) ? MTK_VDEC_LAT0 : MTK_VDEC_CORE; break; + case V4L2_PIX_FMT_HEVC_SLICE: + ctx->dec_if = &vdec_hevc_slice_multi_if; + ctx->hw_id = MTK_VDEC_LAT0; + break; default: return -EINVAL; } diff --git a/drivers/media/platform/mediatek/vcodec/vdec_drv_if.h b/drivers/media/platform/mediatek/vcodec/vdec_drv_if.h index 076306ff2dd4..ef3a0762fdc8 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec_drv_if.h +++ b/drivers/media/platform/mediatek/vcodec/vdec_drv_if.h @@ -61,6 +61,7 @@ extern const struct vdec_common_if vdec_vp8_if; extern const struct vdec_common_if vdec_vp8_slice_if; extern const struct vdec_common_if vdec_vp9_if; extern const struct vdec_common_if vdec_vp9_slice_lat_if; +extern const struct vdec_common_if vdec_hevc_slice_multi_if; /** * vdec_if_init() - initialize decode driver From 1b3565dbc6aa124f34674e3dcf6966f663817e05 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 22 Feb 2023 16:59:51 +0300 Subject: [PATCH 061/253] media: i2c: imx296: fix error checking in imx296_read_temperature() The "& IMX296_TMDOUT_MASK" means that "tmdout" can't be negative so the error checking will not work. Fixes: cb33db2b6ccf ("media: i2c: IMX296 camera sensor driver") Signed-off-by: Dan Carpenter Reviewed-by: Laurent Pinchart Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/i2c/imx296.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/imx296.c b/drivers/media/i2c/imx296.c index 70c129833601..c0b9a5349668 100644 --- a/drivers/media/i2c/imx296.c +++ b/drivers/media/i2c/imx296.c @@ -922,10 +922,12 @@ static int imx296_read_temperature(struct imx296 *sensor, int *temp) if (ret < 0) return ret; - tmdout = imx296_read(sensor, IMX296_TMDOUT) & IMX296_TMDOUT_MASK; + tmdout = imx296_read(sensor, IMX296_TMDOUT); if (tmdout < 0) return tmdout; + tmdout &= IMX296_TMDOUT_MASK; + /* T(°C) = 246.312 - 0.304 * TMDOUT */; *temp = 246312 - 304 * tmdout; From a73206f33bd1e7f9c7579a0555e2ad634455fddf Mon Sep 17 00:00:00 2001 From: Jack Zhu Date: Wed, 15 Mar 2023 11:00:40 +0800 Subject: [PATCH 062/253] media: admin-guide: Update rkisp1.rst Update Rockchip ISP1 driver file path Signed-off-by: Jack Zhu Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- Documentation/admin-guide/media/rkisp1.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/admin-guide/media/rkisp1.rst b/Documentation/admin-guide/media/rkisp1.rst index ccf418713623..6f14d9561fa5 100644 --- a/Documentation/admin-guide/media/rkisp1.rst +++ b/Documentation/admin-guide/media/rkisp1.rst @@ -10,8 +10,8 @@ Introduction ============ This file documents the driver for the Rockchip ISP1 that is part of RK3288 -and RK3399 SoCs. The driver is located under drivers/staging/media/rkisp1 -and uses the Media-Controller API. +and RK3399 SoCs. The driver is located under drivers/media/platform/rockchip/ +rkisp1 and uses the Media-Controller API. Revisions ========= From 71511a24eeec900b1a7e81b5f141c95313624ade Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 28 Mar 2023 15:54:59 +0300 Subject: [PATCH 063/253] Documentation: v4l: Document rotation and orientation for sensor drivers Document how rotation and orientation should be taken into account in writing camera sensor drivers. Signed-off-by: Sakari Ailus Reviewed-by: Jacopo Mondi Signed-off-by: Hans Verkuil --- .../driver-api/media/camera-sensor.rst | 22 +++++++++++++++++++ .../media/v4l/ext-ctrls-camera.rst | 3 +++ 2 files changed, 25 insertions(+) diff --git a/Documentation/driver-api/media/camera-sensor.rst b/Documentation/driver-api/media/camera-sensor.rst index c7d4891bd24e..93f4f2536c25 100644 --- a/Documentation/driver-api/media/camera-sensor.rst +++ b/Documentation/driver-api/media/camera-sensor.rst @@ -151,3 +151,25 @@ used to obtain device's power state after the power state transition: The function returns a non-zero value if it succeeded getting the power count or runtime PM was disabled, in either of which cases the driver may proceed to access the device. + +Rotation, orientation and flipping +---------------------------------- + +Some systems have the camera sensor mounted upside down compared to its natural +mounting rotation. In such cases, drivers shall expose the information to +userspace with the :ref:`V4L2_CID_CAMERA_SENSOR_ROTATION +` control. + +Sensor drivers shall also report the sensor's mounting orientation with the +:ref:`V4L2_CID_CAMERA_SENSOR_ORIENTATION `. + +Use ``v4l2_fwnode_device_parse()`` to obtain rotation and orientation +information from system firmware and ``v4l2_ctrl_new_fwnode_properties()`` to +register the appropriate controls. + +Sensor drivers that have any vertical or horizontal flips embedded in the +register programming sequences shall initialize the V4L2_CID_HFLIP and +V4L2_CID_VFLIP controls with the values programmed by the register sequences. +The default values of these controls shall be 0 (disabled). Especially these +controls shall not be inverted, independently of the sensor's mounting +rotation. diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-camera.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-camera.rst index daa4f40869f8..cdc515c60468 100644 --- a/Documentation/userspace-api/media/v4l/ext-ctrls-camera.rst +++ b/Documentation/userspace-api/media/v4l/ext-ctrls-camera.rst @@ -506,6 +506,8 @@ enum v4l2_scene_mode - value down. A value of zero stops the motion if one is in progress and has no effect otherwise. +.. _v4l2-camera-sensor-orientation: + ``V4L2_CID_CAMERA_ORIENTATION (menu)`` This read-only control describes the camera orientation by reporting its mounting position on the device where the camera is installed. The control @@ -536,6 +538,7 @@ enum v4l2_scene_mode - - The camera is not directly attached to the device and is freely movable. +.. _v4l2-camera-sensor-rotation: ``V4L2_CID_CAMERA_SENSOR_ROTATION (integer)`` This read-only control describes the rotation correction in degrees in the From ec178312b81448b30947b2cb66b849e4bf43d941 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 5 May 2023 16:27:49 +0300 Subject: [PATCH 064/253] media: mc: Make media_entity_get_fwnode_pad() fwnode argument const fwnode_graph_parse_endpoint() fwnode argument is now const, therefore make media_entity_get_fwnode_pad() fwnode argument const as well. Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/mc/mc-entity.c | 2 +- include/media/media-entity.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c index e7216a985ba6..8d6e7a68975a 100644 --- a/drivers/media/mc/mc-entity.c +++ b/drivers/media/mc/mc-entity.c @@ -1416,7 +1416,7 @@ struct media_pad *media_pad_remote_pad_unique(const struct media_pad *pad) EXPORT_SYMBOL_GPL(media_pad_remote_pad_unique); int media_entity_get_fwnode_pad(struct media_entity *entity, - struct fwnode_handle *fwnode, + const struct fwnode_handle *fwnode, unsigned long direction_flags) { struct fwnode_endpoint endpoint; diff --git a/include/media/media-entity.h b/include/media/media-entity.h index 741f9c629c6f..452d9c9bea54 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -1079,7 +1079,7 @@ struct media_pipeline *media_pad_pipeline(struct media_pad *pad); * Return: returns the pad number on success or a negative error code. */ int media_entity_get_fwnode_pad(struct media_entity *entity, - struct fwnode_handle *fwnode, + const struct fwnode_handle *fwnode, unsigned long direction_flags); /** From 7ab9484332d9688df1ce4b87d3adfcb4ded9b903 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 2 May 2023 12:14:08 +0300 Subject: [PATCH 065/253] media: pci: ipu3-cio2: Obtain remote pad from endpoint Use the endpoint fwnode to find out the remote pad, instead of using the first source pad found. Also improve error messages. Signed-off-by: Sakari Ailus Reviewed-by: Bingbu Cao Signed-off-by: Hans Verkuil --- drivers/media/pci/intel/ipu3/ipu3-cio2-main.c | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c index 3c84cb121632..2c9d035255d6 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c @@ -1417,31 +1417,27 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier) struct sensor_async_subdev *s_asd; struct v4l2_async_subdev *asd; struct cio2_queue *q; - unsigned int pad; int ret; list_for_each_entry(asd, &cio2->notifier.asd_list, asd_list) { s_asd = to_sensor_asd(asd); q = &cio2->queue[s_asd->csi2.port]; - for (pad = 0; pad < q->sensor->entity.num_pads; pad++) - if (q->sensor->entity.pads[pad].flags & - MEDIA_PAD_FL_SOURCE) - break; - - if (pad == q->sensor->entity.num_pads) { - dev_err(dev, "failed to find src pad for %s\n", - q->sensor->name); - return -ENXIO; + ret = media_entity_get_fwnode_pad(&q->sensor->entity, + s_asd->asd.match.fwnode, + MEDIA_PAD_FL_SOURCE); + if (ret < 0) { + dev_err(dev, "no pad for endpoint %pfw (%d)\n", + s_asd->asd.match.fwnode, ret); + return ret; } - ret = media_create_pad_link( - &q->sensor->entity, pad, - &q->subdev.entity, CIO2_PAD_SINK, - 0); + ret = media_create_pad_link(&q->sensor->entity, ret, + &q->subdev.entity, CIO2_PAD_SINK, + 0); if (ret) { - dev_err(dev, "failed to create link for %s\n", - q->sensor->name); + dev_err(dev, "failed to create link for %s (endpoint %pfw, error %d)\n", + q->sensor->name, s_asd->asd.match.fwnode, ret); return ret; } } From 4fd463e9389f9c5ea00a327b4ff01daf5869e774 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 25 Apr 2023 13:23:00 +0300 Subject: [PATCH 066/253] media: mc: Make media_get_pad_index() use pad type flag Use the pad flag specifying the pad type instead of a boolean in preparation for internal source pads. Also make the loop variable unsigned. Signed-off-by: Sakari Ailus Reviewed-by: Laurent Pinchart Signed-off-by: Hans Verkuil --- drivers/media/dvb-core/dvbdev.c | 4 +-- drivers/media/mc/mc-entity.c | 16 ++++------- drivers/media/usb/au0828/au0828-core.c | 2 +- drivers/media/v4l2-core/v4l2-mc.c | 38 +++++++++++++++++--------- include/media/media-entity.h | 4 +-- 5 files changed, 35 insertions(+), 29 deletions(-) diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index fb81fa46d92e..305bb21d843c 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -730,7 +730,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap, MEDIA_LNK_FL_ENABLED, false); } else { - pad_sink = media_get_pad_index(tuner, true, + pad_sink = media_get_pad_index(tuner, MEDIA_PAD_FL_SINK, PAD_SIGNAL_ANALOG); if (pad_sink < 0) return -EINVAL; @@ -748,7 +748,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap, if (ntuner && ndemod) { /* NOTE: first found tuner source pad presumed correct */ - pad_source = media_get_pad_index(tuner, false, + pad_source = media_get_pad_index(tuner, MEDIA_PAD_FL_SOURCE, PAD_SIGNAL_ANALOG); if (pad_source < 0) return -EINVAL; diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c index 8d6e7a68975a..83468d4a440b 100644 --- a/drivers/media/mc/mc-entity.c +++ b/drivers/media/mc/mc-entity.c @@ -1052,25 +1052,19 @@ static void __media_entity_remove_link(struct media_entity *entity, kfree(link); } -int media_get_pad_index(struct media_entity *entity, bool is_sink, +int media_get_pad_index(struct media_entity *entity, u32 pad_type, enum media_pad_signal_type sig_type) { - int i; - bool pad_is_sink; + unsigned int i; if (!entity) return -EINVAL; for (i = 0; i < entity->num_pads; i++) { - if (entity->pads[i].flags & MEDIA_PAD_FL_SINK) - pad_is_sink = true; - else if (entity->pads[i].flags & MEDIA_PAD_FL_SOURCE) - pad_is_sink = false; - else - continue; /* This is an error! */ - - if (pad_is_sink != is_sink) + if ((entity->pads[i].flags & + (MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_SOURCE)) != pad_type) continue; + if (entity->pads[i].sig_type == sig_type) return i; } diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index b3a09d3ac7d2..1e246b47766d 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -250,7 +250,7 @@ static void au0828_media_graph_notify(struct media_entity *new, create_link: if (decoder && mixer) { - ret = media_get_pad_index(decoder, false, + ret = media_get_pad_index(decoder, MEDIA_PAD_FL_SOURCE, PAD_SIGNAL_AUDIO); if (ret >= 0) ret = media_create_pad_link(decoder, ret, diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c index bf0c18100664..209a7efd08fe 100644 --- a/drivers/media/v4l2-core/v4l2-mc.c +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -105,9 +105,11 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) /* Link the tuner and IF video output pads */ if (tuner) { if (if_vid) { - pad_source = media_get_pad_index(tuner, false, + pad_source = media_get_pad_index(tuner, + MEDIA_PAD_FL_SOURCE, PAD_SIGNAL_ANALOG); - pad_sink = media_get_pad_index(if_vid, true, + pad_sink = media_get_pad_index(if_vid, + MEDIA_PAD_FL_SINK, PAD_SIGNAL_ANALOG); if (pad_source < 0 || pad_sink < 0) { dev_warn(mdev->dev, "Couldn't get tuner and/or PLL pad(s): (%d, %d)\n", @@ -122,9 +124,11 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) return ret; } - pad_source = media_get_pad_index(if_vid, false, + pad_source = media_get_pad_index(if_vid, + MEDIA_PAD_FL_SOURCE, PAD_SIGNAL_ANALOG); - pad_sink = media_get_pad_index(decoder, true, + pad_sink = media_get_pad_index(decoder, + MEDIA_PAD_FL_SINK, PAD_SIGNAL_ANALOG); if (pad_source < 0 || pad_sink < 0) { dev_warn(mdev->dev, "get decoder and/or PLL pad(s): (%d, %d)\n", @@ -139,9 +143,11 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) return ret; } } else { - pad_source = media_get_pad_index(tuner, false, + pad_source = media_get_pad_index(tuner, + MEDIA_PAD_FL_SOURCE, PAD_SIGNAL_ANALOG); - pad_sink = media_get_pad_index(decoder, true, + pad_sink = media_get_pad_index(decoder, + MEDIA_PAD_FL_SINK, PAD_SIGNAL_ANALOG); if (pad_source < 0 || pad_sink < 0) { dev_warn(mdev->dev, "couldn't get tuner and/or decoder pad(s): (%d, %d)\n", @@ -156,9 +162,11 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) } if (if_aud) { - pad_source = media_get_pad_index(tuner, false, + pad_source = media_get_pad_index(tuner, + MEDIA_PAD_FL_SOURCE, PAD_SIGNAL_AUDIO); - pad_sink = media_get_pad_index(if_aud, true, + pad_sink = media_get_pad_index(if_aud, + MEDIA_PAD_FL_SINK, PAD_SIGNAL_AUDIO); if (pad_source < 0 || pad_sink < 0) { dev_warn(mdev->dev, "couldn't get tuner and/or decoder pad(s) for audio: (%d, %d)\n", @@ -180,7 +188,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) /* Create demod to V4L, VBI and SDR radio links */ if (io_v4l) { - pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV); + pad_source = media_get_pad_index(decoder, MEDIA_PAD_FL_SOURCE, + PAD_SIGNAL_DV); if (pad_source < 0) { dev_warn(mdev->dev, "couldn't get decoder output pad for V4L I/O\n"); return -EINVAL; @@ -195,7 +204,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) } if (io_swradio) { - pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV); + pad_source = media_get_pad_index(decoder, MEDIA_PAD_FL_SOURCE, + PAD_SIGNAL_DV); if (pad_source < 0) { dev_warn(mdev->dev, "couldn't get decoder output pad for SDR\n"); return -EINVAL; @@ -210,7 +220,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) } if (io_vbi) { - pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV); + pad_source = media_get_pad_index(decoder, MEDIA_PAD_FL_SOURCE, + PAD_SIGNAL_DV); if (pad_source < 0) { dev_warn(mdev->dev, "couldn't get decoder output pad for VBI\n"); return -EINVAL; @@ -231,7 +242,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) case MEDIA_ENT_F_CONN_RF: if (!tuner) continue; - pad_sink = media_get_pad_index(tuner, true, + pad_sink = media_get_pad_index(tuner, MEDIA_PAD_FL_SINK, PAD_SIGNAL_ANALOG); if (pad_sink < 0) { dev_warn(mdev->dev, "couldn't get tuner analog pad sink\n"); @@ -243,7 +254,8 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) break; case MEDIA_ENT_F_CONN_SVIDEO: case MEDIA_ENT_F_CONN_COMPOSITE: - pad_sink = media_get_pad_index(decoder, true, + pad_sink = media_get_pad_index(decoder, + MEDIA_PAD_FL_SINK, PAD_SIGNAL_ANALOG); if (pad_sink < 0) { dev_warn(mdev->dev, "couldn't get decoder analog pad sink\n"); diff --git a/include/media/media-entity.h b/include/media/media-entity.h index 452d9c9bea54..2b6cd343ee9e 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -741,7 +741,7 @@ static inline void media_entity_cleanup(struct media_entity *entity) {} * media_get_pad_index() - retrieves a pad index from an entity * * @entity: entity where the pads belong - * @is_sink: true if the pad is a sink, false if it is a source + * @pad_type: the type of the pad, one of MEDIA_PAD_FL_* pad types * @sig_type: type of signal of the pad to be search * * This helper function finds the first pad index inside an entity that @@ -752,7 +752,7 @@ static inline void media_entity_cleanup(struct media_entity *entity) {} * On success, return the pad number. If the pad was not found or the media * entity is a NULL pointer, return -EINVAL. */ -int media_get_pad_index(struct media_entity *entity, bool is_sink, +int media_get_pad_index(struct media_entity *entity, u32 pad_type, enum media_pad_signal_type sig_type); /** From e6a4702394383888961fc6cae7b99f387db03de4 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 26 Apr 2023 12:50:39 +0300 Subject: [PATCH 067/253] media: Documentation: Rename meta format files Rename meta format files, using "metafmt" prefix instead of "pixfmt-meta". These are metadata formats, not pixel formats. Signed-off-by: Sakari Ailus Cc: Bingbu Cao Cc: Dafna Hirschfeld Reviewed-by: Laurent Pinchart Signed-off-by: Hans Verkuil --- .../userspace-api/media/v4l/meta-formats.rst | 14 +++++++------- .../v4l/{pixfmt-meta-d4xx.rst => metafmt-d4xx.rst} | 0 ...-meta-intel-ipu3.rst => metafmt-intel-ipu3.rst} | 0 .../{pixfmt-meta-rkisp1.rst => metafmt-rkisp1.rst} | 0 .../v4l/{pixfmt-meta-uvc.rst => metafmt-uvc.rst} | 0 .../{pixfmt-meta-vivid.rst => metafmt-vivid.rst} | 0 ...xfmt-meta-vsp1-hgo.rst => metafmt-vsp1-hgo.rst} | 0 ...xfmt-meta-vsp1-hgt.rst => metafmt-vsp1-hgt.rst} | 0 MAINTAINERS | 4 ++-- 9 files changed, 9 insertions(+), 9 deletions(-) rename Documentation/userspace-api/media/v4l/{pixfmt-meta-d4xx.rst => metafmt-d4xx.rst} (100%) rename Documentation/userspace-api/media/v4l/{pixfmt-meta-intel-ipu3.rst => metafmt-intel-ipu3.rst} (100%) rename Documentation/userspace-api/media/v4l/{pixfmt-meta-rkisp1.rst => metafmt-rkisp1.rst} (100%) rename Documentation/userspace-api/media/v4l/{pixfmt-meta-uvc.rst => metafmt-uvc.rst} (100%) rename Documentation/userspace-api/media/v4l/{pixfmt-meta-vivid.rst => metafmt-vivid.rst} (100%) rename Documentation/userspace-api/media/v4l/{pixfmt-meta-vsp1-hgo.rst => metafmt-vsp1-hgo.rst} (100%) rename Documentation/userspace-api/media/v4l/{pixfmt-meta-vsp1-hgt.rst => metafmt-vsp1-hgt.rst} (100%) diff --git a/Documentation/userspace-api/media/v4l/meta-formats.rst b/Documentation/userspace-api/media/v4l/meta-formats.rst index fff25357fe86..0bb61fc5bc00 100644 --- a/Documentation/userspace-api/media/v4l/meta-formats.rst +++ b/Documentation/userspace-api/media/v4l/meta-formats.rst @@ -12,10 +12,10 @@ These formats are used for the :ref:`metadata` interface only. .. toctree:: :maxdepth: 1 - pixfmt-meta-d4xx - pixfmt-meta-intel-ipu3 - pixfmt-meta-rkisp1 - pixfmt-meta-uvc - pixfmt-meta-vsp1-hgo - pixfmt-meta-vsp1-hgt - pixfmt-meta-vivid + metafmt-d4xx + metafmt-intel-ipu3 + metafmt-rkisp1 + metafmt-uvc + metafmt-vsp1-hgo + metafmt-vsp1-hgt + metafmt-vivid diff --git a/Documentation/userspace-api/media/v4l/pixfmt-meta-d4xx.rst b/Documentation/userspace-api/media/v4l/metafmt-d4xx.rst similarity index 100% rename from Documentation/userspace-api/media/v4l/pixfmt-meta-d4xx.rst rename to Documentation/userspace-api/media/v4l/metafmt-d4xx.rst diff --git a/Documentation/userspace-api/media/v4l/pixfmt-meta-intel-ipu3.rst b/Documentation/userspace-api/media/v4l/metafmt-intel-ipu3.rst similarity index 100% rename from Documentation/userspace-api/media/v4l/pixfmt-meta-intel-ipu3.rst rename to Documentation/userspace-api/media/v4l/metafmt-intel-ipu3.rst diff --git a/Documentation/userspace-api/media/v4l/pixfmt-meta-rkisp1.rst b/Documentation/userspace-api/media/v4l/metafmt-rkisp1.rst similarity index 100% rename from Documentation/userspace-api/media/v4l/pixfmt-meta-rkisp1.rst rename to Documentation/userspace-api/media/v4l/metafmt-rkisp1.rst diff --git a/Documentation/userspace-api/media/v4l/pixfmt-meta-uvc.rst b/Documentation/userspace-api/media/v4l/metafmt-uvc.rst similarity index 100% rename from Documentation/userspace-api/media/v4l/pixfmt-meta-uvc.rst rename to Documentation/userspace-api/media/v4l/metafmt-uvc.rst diff --git a/Documentation/userspace-api/media/v4l/pixfmt-meta-vivid.rst b/Documentation/userspace-api/media/v4l/metafmt-vivid.rst similarity index 100% rename from Documentation/userspace-api/media/v4l/pixfmt-meta-vivid.rst rename to Documentation/userspace-api/media/v4l/metafmt-vivid.rst diff --git a/Documentation/userspace-api/media/v4l/pixfmt-meta-vsp1-hgo.rst b/Documentation/userspace-api/media/v4l/metafmt-vsp1-hgo.rst similarity index 100% rename from Documentation/userspace-api/media/v4l/pixfmt-meta-vsp1-hgo.rst rename to Documentation/userspace-api/media/v4l/metafmt-vsp1-hgo.rst diff --git a/Documentation/userspace-api/media/v4l/pixfmt-meta-vsp1-hgt.rst b/Documentation/userspace-api/media/v4l/metafmt-vsp1-hgt.rst similarity index 100% rename from Documentation/userspace-api/media/v4l/pixfmt-meta-vsp1-hgt.rst rename to Documentation/userspace-api/media/v4l/metafmt-vsp1-hgt.rst diff --git a/MAINTAINERS b/MAINTAINERS index a2878f5f59f3..517ce68c6102 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10454,7 +10454,7 @@ L: linux-media@vger.kernel.org S: Maintained F: Documentation/admin-guide/media/ipu3.rst F: Documentation/admin-guide/media/ipu3_rcb.svg -F: Documentation/userspace-api/media/v4l/pixfmt-meta-intel-ipu3.rst +F: Documentation/userspace-api/media/v4l/metafmt-intel-ipu3.rst F: drivers/staging/media/ipu3/ INTEL ISHTP ECLITE DRIVER @@ -18199,7 +18199,7 @@ L: linux-rockchip@lists.infradead.org S: Maintained F: Documentation/admin-guide/media/rkisp1.rst F: Documentation/devicetree/bindings/media/rockchip-isp1.yaml -F: Documentation/userspace-api/media/v4l/pixfmt-meta-rkisp1.rst +F: Documentation/userspace-api/media/v4l/metafmt-rkisp1.rst F: drivers/media/platform/rockchip/rkisp1 F: include/uapi/linux/rkisp1-config.h From 98b9564243805810b7d412368e512bd7b1c3837e Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 24 Apr 2023 12:52:12 +0300 Subject: [PATCH 068/253] media: uapi: Use unsigned int values for assigning bits in u32 fields Use unsigned int values annoted by "U" for u32 fields. While this is a good practice, there doesn't appear to be a bug that this patch would fix. The patch has been generated using the following command: perl -i -pe 's/\([0-9]+\K < Reviewed-by: Laurent Pinchart Signed-off-by: Hans Verkuil --- include/uapi/linux/media.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index 3ddadaea849f..1c80b1d6bbaf 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -140,8 +140,8 @@ struct media_device_info { #define MEDIA_ENT_F_DV_ENCODER (MEDIA_ENT_F_BASE + 0x6002) /* Entity flags */ -#define MEDIA_ENT_FL_DEFAULT (1 << 0) -#define MEDIA_ENT_FL_CONNECTOR (1 << 1) +#define MEDIA_ENT_FL_DEFAULT (1U << 0) +#define MEDIA_ENT_FL_CONNECTOR (1U << 1) /* OR with the entity id value to find the next entity */ #define MEDIA_ENT_ID_FLAG_NEXT (1U << 31) @@ -205,9 +205,9 @@ struct media_entity_desc { }; }; -#define MEDIA_PAD_FL_SINK (1 << 0) -#define MEDIA_PAD_FL_SOURCE (1 << 1) -#define MEDIA_PAD_FL_MUST_CONNECT (1 << 2) +#define MEDIA_PAD_FL_SINK (1U << 0) +#define MEDIA_PAD_FL_SOURCE (1U << 1) +#define MEDIA_PAD_FL_MUST_CONNECT (1U << 2) struct media_pad_desc { __u32 entity; /* entity ID */ @@ -216,14 +216,14 @@ struct media_pad_desc { __u32 reserved[2]; }; -#define MEDIA_LNK_FL_ENABLED (1 << 0) -#define MEDIA_LNK_FL_IMMUTABLE (1 << 1) -#define MEDIA_LNK_FL_DYNAMIC (1 << 2) +#define MEDIA_LNK_FL_ENABLED (1U << 0) +#define MEDIA_LNK_FL_IMMUTABLE (1U << 1) +#define MEDIA_LNK_FL_DYNAMIC (1U << 2) #define MEDIA_LNK_FL_LINK_TYPE (0xf << 28) -# define MEDIA_LNK_FL_DATA_LINK (0 << 28) -# define MEDIA_LNK_FL_INTERFACE_LINK (1 << 28) -# define MEDIA_LNK_FL_ANCILLARY_LINK (2 << 28) +# define MEDIA_LNK_FL_DATA_LINK (0U << 28) +# define MEDIA_LNK_FL_INTERFACE_LINK (1U << 28) +# define MEDIA_LNK_FL_ANCILLARY_LINK (2U << 28) struct media_link_desc { struct media_pad_desc source; @@ -293,7 +293,7 @@ struct media_links_enum { * struct media_device_info. */ #define MEDIA_V2_ENTITY_HAS_FLAGS(media_version) \ - ((media_version) >= ((4 << 16) | (19 << 8) | 0)) + ((media_version) >= ((4U << 16) | (19U << 8) | 0U)) struct media_v2_entity { __u32 id; @@ -328,7 +328,7 @@ struct media_v2_interface { * struct media_device_info. */ #define MEDIA_V2_PAD_HAS_INDEX(media_version) \ - ((media_version) >= ((4 << 16) | (19 << 8) | 0)) + ((media_version) >= ((4U << 16) | (19U << 8) | 0U)) struct media_v2_pad { __u32 id; @@ -432,7 +432,7 @@ struct media_v2_topology { #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) +#define MEDIA_API_VERSION ((0U << 16) | (1U << 8) | 0U) #endif From 1e82d01b88eda8c4907e5901b9f5a7ff39970320 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 15 Apr 2023 18:28:58 +0200 Subject: [PATCH 069/253] media: ov5693: Simplify an error message dev_err_probe() already display the error code. There is no need to duplicate it explicitly in the error message. Signed-off-by: Christophe JAILLET Reviewed-by: Daniel Scally Signed-off-by: Hans Verkuil --- drivers/media/i2c/ov5693.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c index 9a786ff4b5b7..7f9212cce239 100644 --- a/drivers/media/i2c/ov5693.c +++ b/drivers/media/i2c/ov5693.c @@ -404,8 +404,8 @@ static int ov5693_read_reg(struct ov5693_device *ov5693, u32 addr, u32 *value) ret = i2c_transfer(client->adapter, msg, 2); if (ret < 0) return dev_err_probe(&client->dev, ret, - "Failed to read register 0x%04x: %d\n", - addr & OV5693_REG_ADDR_MASK, ret); + "Failed to read register 0x%04x\n", + addr & OV5693_REG_ADDR_MASK); *value = 0; for (i = 0; i < len; ++i) { From 8e4a559769795ae6fc6395231766bc223b36913b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 20 Apr 2023 09:24:42 +0200 Subject: [PATCH 070/253] media: dt-bindings: qcom: camss: correct unit address Match unit-address to first reg entry. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Konrad Dybcio Acked-by: Rob Herring Reviewed-by: Bryan O'Donoghue Signed-off-by: Hans Verkuil --- Documentation/devicetree/bindings/media/qcom,msm8916-camss.yaml | 2 +- Documentation/devicetree/bindings/media/qcom,msm8996-camss.yaml | 2 +- Documentation/devicetree/bindings/media/qcom,sdm660-camss.yaml | 2 +- Documentation/devicetree/bindings/media/qcom,sdm845-camss.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/media/qcom,msm8916-camss.yaml b/Documentation/devicetree/bindings/media/qcom,msm8916-camss.yaml index eb1499912c58..9cc0a968a401 100644 --- a/Documentation/devicetree/bindings/media/qcom,msm8916-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,msm8916-camss.yaml @@ -155,7 +155,7 @@ examples: #include #include - camss: camss@1b00000 { + camss: camss@1b0ac00 { compatible = "qcom,msm8916-camss"; clocks = <&gcc GCC_CAMSS_TOP_AHB_CLK>, diff --git a/Documentation/devicetree/bindings/media/qcom,msm8996-camss.yaml b/Documentation/devicetree/bindings/media/qcom,msm8996-camss.yaml index 8a10aa1cafc5..5cb0e337ea6e 100644 --- a/Documentation/devicetree/bindings/media/qcom,msm8996-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,msm8996-camss.yaml @@ -221,7 +221,7 @@ examples: #include #include - camss: camss@a00000 { + camss: camss@a34000 { compatible = "qcom,msm8996-camss"; clocks = <&mmcc CAMSS_TOP_AHB_CLK>, diff --git a/Documentation/devicetree/bindings/media/qcom,sdm660-camss.yaml b/Documentation/devicetree/bindings/media/qcom,sdm660-camss.yaml index 0a109e126064..584106e275f6 100644 --- a/Documentation/devicetree/bindings/media/qcom,sdm660-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,sdm660-camss.yaml @@ -227,7 +227,7 @@ examples: #include #include - camss: camss@ca00000 { + camss: camss@ca00020 { compatible = "qcom,sdm660-camss"; clocks = <&mmcc CAMSS_AHB_CLK>, diff --git a/Documentation/devicetree/bindings/media/qcom,sdm845-camss.yaml b/Documentation/devicetree/bindings/media/qcom,sdm845-camss.yaml index 1530ad0d80bd..ec4380a0a03f 100644 --- a/Documentation/devicetree/bindings/media/qcom,sdm845-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,sdm845-camss.yaml @@ -219,7 +219,7 @@ examples: #address-cells = <2>; #size-cells = <2>; - camss: camss@a00000 { + camss: camss@acb3000 { compatible = "qcom,sdm845-camss"; clocks = <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>, From 950e9a295b984b011bcbfb90af167e4e20a077f3 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 24 Apr 2023 15:22:37 +0300 Subject: [PATCH 071/253] media: uapi: Fix [GS]_ROUTING ACTIVE flag value The value of the V4L2_SUBDEV_ROUTE_FL_ACTIVE is 1, not 0. Use hexadecimal numbers as is done elsewhere in the documentation. Cc: stable@vger.kernel.org # for >= v6.3 Fixes: ea73eda50813 ("media: Documentation: Add GS_ROUTING documentation") Signed-off-by: Sakari Ailus Reviewed-by: Jacopo Mondi Signed-off-by: Hans Verkuil --- .../userspace-api/media/v4l/vidioc-subdev-g-routing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst index 68ca343c3b44..2d6e3bbdd040 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst @@ -122,7 +122,7 @@ for all the route entries and call ``VIDIOC_SUBDEV_G_ROUTING`` again. :widths: 3 1 4 * - V4L2_SUBDEV_ROUTE_FL_ACTIVE - - 0 + - 0x0001 - The route is enabled. Set by applications. Return Value From 25857a007d521acee63012876ba00d94112c2ba3 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 17 Apr 2023 12:29:59 +0300 Subject: [PATCH 072/253] media: ipu3-cio2: Fix container_of() macro wrapper arguments The argument of the to_sensor_asd() is called the same as the field name for the container_of() macro, so it only works if the argument name is "asd". Fix it. Also switch to container_of_const(). Reviewed-by: Bingbu Cao Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/pci/intel/ipu3/ipu3-cio2-main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c index 2c9d035255d6..34984a7474ed 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c @@ -1375,7 +1375,8 @@ struct sensor_async_subdev { struct csi2_bus_info csi2; }; -#define to_sensor_asd(asd) container_of(asd, struct sensor_async_subdev, asd) +#define to_sensor_asd(__asd) \ + container_of_const(__asd, struct sensor_async_subdev, asd) /* The .bound() notifier callback when a match is found */ static int cio2_notifier_bound(struct v4l2_async_notifier *notifier, From e3269ea5148d39119c4a603b4391e0adbe32af37 Mon Sep 17 00:00:00 2001 From: Shravan Chippa Date: Fri, 14 Apr 2023 18:03:11 +0530 Subject: [PATCH 073/253] media: i2c: imx334: update pixel, hblank and link frequency Update pixel_rate and link frequency for 1920x1080@30 while changing mode. Update vblank value while changing mode Add support to handle multiple link frequencies. Add dummy ctrl cases for pixel_rate and link frequency to avoid error while changing the modes dynamically. Update default link frequency from device tree max link frequency value. Update init_cfg() function to update the link frequency menu_skip_mask value. Suggested-by: Sakari Ailus Signed-off-by: Shravan Chippa [Sakari Ailus: Document menu_skip_mask, remove extra blank line.] Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/i2c/imx334.c | 62 +++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/drivers/media/i2c/imx334.c b/drivers/media/i2c/imx334.c index bd79ebfe41ec..d722c9b7cd31 100644 --- a/drivers/media/i2c/imx334.c +++ b/drivers/media/i2c/imx334.c @@ -49,7 +49,8 @@ #define IMX334_INCLK_RATE 24000000 /* CSI2 HW configuration */ -#define IMX334_LINK_FREQ 891000000 +#define IMX334_LINK_FREQ_891M 891000000 +#define IMX334_LINK_FREQ_445M 445500000 #define IMX334_NUM_DATA_LANES 4 #define IMX334_REG_MIN 0x00 @@ -117,6 +118,7 @@ struct imx334_mode { * @vblank: Vertical blanking in lines * @cur_mode: Pointer to current selected sensor mode * @mutex: Mutex for serializing sensor controls + * @menu_skip_mask: Menu skip mask for link_freq_ctrl * @cur_code: current selected format code * @streaming: Flag indicating streaming state */ @@ -139,12 +141,14 @@ struct imx334 { u32 vblank; const struct imx334_mode *cur_mode; struct mutex mutex; + unsigned long menu_skip_mask; u32 cur_code; bool streaming; }; static const s64 link_freq[] = { - IMX334_LINK_FREQ, + IMX334_LINK_FREQ_891M, + IMX334_LINK_FREQ_445M, }; /* Sensor mode registers for 1920x1080@30fps */ @@ -468,7 +472,7 @@ static const struct imx334_mode supported_modes[] = { .vblank_min = 45, .vblank_max = 132840, .pclk = 297000000, - .link_freq_idx = 0, + .link_freq_idx = 1, .reg_list = { .num_of_regs = ARRAY_SIZE(mode_1920x1080_regs), .regs = mode_1920x1080_regs, @@ -598,13 +602,22 @@ static int imx334_update_controls(struct imx334 *imx334, if (ret) return ret; + ret = __v4l2_ctrl_modify_range(imx334->pclk_ctrl, mode->pclk, + mode->pclk, 1, mode->pclk); + if (ret) + return ret; + ret = __v4l2_ctrl_modify_range(imx334->hblank_ctrl, mode->hblank, mode->hblank, 1, mode->hblank); if (ret) return ret; - return __v4l2_ctrl_modify_range(imx334->vblank_ctrl, mode->vblank_min, + ret = __v4l2_ctrl_modify_range(imx334->vblank_ctrl, mode->vblank_min, mode->vblank_max, 1, mode->vblank); + if (ret) + return ret; + + return __v4l2_ctrl_s_ctrl(imx334->vblank_ctrl, mode->vblank); } /** @@ -698,6 +711,8 @@ static int imx334_set_ctrl(struct v4l2_ctrl *ctrl) pm_runtime_put(imx334->dev); break; + case V4L2_CID_PIXEL_RATE: + case V4L2_CID_LINK_FREQ: case V4L2_CID_HBLANK: ret = 0; break; @@ -885,7 +900,17 @@ static int imx334_init_pad_cfg(struct v4l2_subdev *sd, struct v4l2_subdev_format fmt = { 0 }; fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; - imx334_fill_pad_format(imx334, &supported_modes[0], &fmt); + + mutex_lock(&imx334->mutex); + + imx334_fill_pad_format(imx334, imx334->cur_mode, &fmt); + + __v4l2_ctrl_modify_range(imx334->link_freq_ctrl, 0, + __fls(imx334->menu_skip_mask), + ~(imx334->menu_skip_mask), + __ffs(imx334->menu_skip_mask)); + + mutex_unlock(&imx334->mutex); return imx334_set_pad_format(sd, sd_state, &fmt); } @@ -1046,8 +1071,8 @@ static int imx334_parse_hw_config(struct imx334 *imx334) }; struct fwnode_handle *ep; unsigned long rate; + unsigned int i, j; int ret; - int i; if (!fwnode) return -ENXIO; @@ -1097,11 +1122,20 @@ static int imx334_parse_hw_config(struct imx334 *imx334) goto done_endpoint_free; } - for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) - if (bus_cfg.link_frequencies[i] == IMX334_LINK_FREQ) - goto done_endpoint_free; + for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) { + for (j = 0; j < ARRAY_SIZE(link_freq); j++) { + if (bus_cfg.link_frequencies[i] == link_freq[j]) { + set_bit(j, &imx334->menu_skip_mask); + break; + } + } - ret = -EINVAL; + if (j == ARRAY_SIZE(link_freq)) { + ret = dev_err_probe(imx334->dev, -EINVAL, + "no supported link freq found\n"); + goto done_endpoint_free; + } + } done_endpoint_free: v4l2_fwnode_endpoint_free(&bus_cfg); @@ -1232,10 +1266,10 @@ static int imx334_init_controls(struct imx334 *imx334) imx334->link_freq_ctrl = v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx334_ctrl_ops, V4L2_CID_LINK_FREQ, - ARRAY_SIZE(link_freq) - - 1, - mode->link_freq_idx, + __fls(imx334->menu_skip_mask), + __ffs(imx334->menu_skip_mask), link_freq); + if (imx334->link_freq_ctrl) imx334->link_freq_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; @@ -1302,7 +1336,7 @@ static int imx334_probe(struct i2c_client *client) } /* Set default mode to max resolution */ - imx334->cur_mode = &supported_modes[0]; + imx334->cur_mode = &supported_modes[__ffs(imx334->menu_skip_mask)]; imx334->cur_code = imx334_mbus_codes[0]; imx334->vblank = imx334->cur_mode->vblank; From 290cebd13a6e111c4e998c9b712ec20e9a3e9e17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Tue, 9 May 2023 21:00:31 +0200 Subject: [PATCH 074/253] dt-bindings: i2c: maxim,max96712: Require setting bus-type property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MAX96712 can support both a CSI-2 C-PHY and D-PHY bus. The initial staging driver however only supported D-PHY and the bus-type property was left optional. In preparation for adding C-PHY support to the staging driver make the bus-type property mandatory as it is needed to select the correct PHY mode. Without the bus-type property present, the driver falls-back to D-PHY mode, so the change is functionally backward compatible with old DTS files lacking the property. The only in-tree DTS file (renesas/r8a779a0-falcon-csi-dsi.dtsi) that lacked the property uses D-PHY and have been updated. Signed-off-by: Niklas Söderlund Reviewed-by: Conor Dooley Reviewed-by: Geert Uytterhoeven Acked-by: Krzysztof Kozlowski Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- .../devicetree/bindings/media/i2c/maxim,max96712.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml index 444f24838d3d..6c72e77b927c 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml @@ -65,9 +65,14 @@ properties: properties: data-lanes: true + bus-type: + enum: + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY required: - data-lanes + - bus-type required: - port@4 @@ -82,6 +87,7 @@ additionalProperties: false examples: - | #include + #include i2c@e6508000 { #address-cells = <1>; @@ -101,6 +107,7 @@ examples: port@4 { reg = <4>; max96712_out0: endpoint { + bus-type = ; clock-lanes = <0>; data-lanes = <1 2 3 4>; remote-endpoint = <&csi40_in>; From afe25fbc5d078556986fcd1df9dc9140adffff26 Mon Sep 17 00:00:00 2001 From: "Guoniu.zhou" Date: Tue, 9 May 2023 14:56:45 +0800 Subject: [PATCH 075/253] media: ov5640: correct comments for default VGA to avoid confusion When OV5640 work at DVP mode, the default initialization settings make it output 30 frames per second. But when it work at CSI-2 mode the default link frequency will make it output 60 frames per second, so correct the comments to make it more clear. Signed-off-by: Guoniu.zhou Reviewed-by: Jacopo Mondi Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/i2c/ov5640.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c index 3a9dc7d11dec..5b43bbfe4774 100644 --- a/drivers/media/i2c/ov5640.c +++ b/drivers/media/i2c/ov5640.c @@ -3851,7 +3851,7 @@ static int ov5640_probe(struct i2c_client *client) /* * default init sequence initialize sensor to - * YUV422 UYVY VGA@30fps + * YUV422 UYVY VGA(30FPS in parallel mode, 60 in MIPI CSI-2 mode) */ sensor->frame_interval.numerator = 1; sensor->frame_interval.denominator = ov5640_framerates[OV5640_30_FPS]; From 25affde33b234b214b3e8f49a703b78a4b3bf8ca Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Fri, 5 May 2023 09:16:18 +0200 Subject: [PATCH 076/253] media: ov5640: Remove unused 'framerate' parameter The 'current framerate' parameter passed to ov5640_try_fmt_internal() is unsued. Drop it. Signed-off-by: Jacopo Mondi Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/i2c/ov5640.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c index 5b43bbfe4774..0f1d87a7a219 100644 --- a/drivers/media/i2c/ov5640.c +++ b/drivers/media/i2c/ov5640.c @@ -2815,7 +2815,6 @@ static int ov5640_get_fmt(struct v4l2_subdev *sd, static int ov5640_try_fmt_internal(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt, - enum ov5640_frame_rate fr, const struct ov5640_mode_info **new_mode) { struct ov5640_dev *sensor = to_ov5640_dev(sd); @@ -2975,8 +2974,7 @@ static int ov5640_set_fmt(struct v4l2_subdev *sd, goto out; } - ret = ov5640_try_fmt_internal(sd, mbus_fmt, - sensor->current_fr, &new_mode); + ret = ov5640_try_fmt_internal(sd, mbus_fmt, &new_mode); if (ret) goto out; From eeaa47d182fedfe68b8fd40ef3798761c8904791 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Fri, 5 May 2023 09:16:19 +0200 Subject: [PATCH 077/253] media: ov5640: Drop dead code using frame_interval The ov5640_update_pixel_rate() function handles the parallel and MIPI CSI-2 cases separately. When running on a parallel setup the V4L2_CID_PIXEL_RATE value is calculated at the beginning of the function using the values configured with the frame_interval operations, and then the function immediately returns. The remaining of the function handles the MIPI CSI-2 configuration and should not use the 'current_fr' and 'def_fps' fields as those are only relevant for parallel mode. Drop a small section of dead code that updates vblank using frame_interval on a MIPI CSI-2 setup. Signed-off-by: Jacopo Mondi Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/i2c/ov5640.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c index 0f1d87a7a219..36b509714c8c 100644 --- a/drivers/media/i2c/ov5640.c +++ b/drivers/media/i2c/ov5640.c @@ -2926,19 +2926,6 @@ static int ov5640_update_pixel_rate(struct ov5640_dev *sensor) hblank, hblank, 1, hblank); vblank = timings->vblank_def; - - if (sensor->current_fr != mode->def_fps) { - /* - * Compute the vertical blanking according to the framerate - * configured with s_frame_interval. - */ - int fie_num = sensor->frame_interval.numerator; - int fie_denom = sensor->frame_interval.denominator; - - vblank = ((fie_num * pixel_rate / fie_denom) / timings->htot) - - mode->height; - } - __v4l2_ctrl_modify_range(sensor->ctrls.vblank, OV5640_MIN_VBLANK, OV5640_MAX_VTS - mode->height, 1, vblank); __v4l2_ctrl_s_ctrl(sensor->ctrls.vblank, vblank); From cd78824dd989ad733b650f42e078095ff231a215 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 11 May 2023 19:54:41 +0200 Subject: [PATCH 078/253] media: i2c: video: constify pointers to hwmon_channel_info Statically allocated array of pointers to hwmon_channel_info can be made const for safety. Reviewed-by: Matt Ranostay Acked-by: Sakari Ailus Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/i2c/video-i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/video-i2c.c b/drivers/media/i2c/video-i2c.c index 4ba2c5518579..6f98abc7ccc1 100644 --- a/drivers/media/i2c/video-i2c.c +++ b/drivers/media/i2c/video-i2c.c @@ -274,7 +274,7 @@ static const struct hwmon_channel_info amg88xx_temp = { .config = amg88xx_temp_config, }; -static const struct hwmon_channel_info *amg88xx_info[] = { +static const struct hwmon_channel_info * const amg88xx_info[] = { &amg88xx_temp, NULL }; From ad5929547b545f6335f7a65cd5dd978967a02be3 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Tue, 2 May 2023 16:15:43 +0200 Subject: [PATCH 079/253] media: video-mux: Add missing media_entity_cleanup upon async register fail Although media_entity_pads_init has been called, a call to media_entity_cleanup in the cleanup code was missing. Signed-off-by: Alexander Stein Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/platform/video-mux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c index 1d9f32e5a917..b244873d593a 100644 --- a/drivers/media/platform/video-mux.c +++ b/drivers/media/platform/video-mux.c @@ -474,6 +474,7 @@ static int video_mux_probe(struct platform_device *pdev) ret = video_mux_async_register(vmux, num_pads - 1); if (ret) { + media_entity_cleanup(&vmux->subdev.entity); v4l2_async_nf_unregister(&vmux->notifier); v4l2_async_nf_cleanup(&vmux->notifier); } From 306c3190b30d4d6a098888b9d7d4cefaa0ddcb91 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 2 May 2023 11:35:46 +0100 Subject: [PATCH 080/253] media: i2c: Correct format propagation for st-mipid02 Format propagation in the st-mipid02 driver is incorrect in that when setting format for V4L2_SUBDEV_FORMAT_TRY on the source pad, the _active_ rather than _try_ format from the sink pad is propagated. This causes problems with format negotiation - update the function to propagate the correct format. Fixes: 642bb5e88fed ("media: st-mipid02: MIPID02 CSI-2 to PARALLEL bridge driver") Signed-off-by: Daniel Scally Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/i2c/st-mipid02.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/st-mipid02.c b/drivers/media/i2c/st-mipid02.c index 19efefe38727..dcd3ff2bbde9 100644 --- a/drivers/media/i2c/st-mipid02.c +++ b/drivers/media/i2c/st-mipid02.c @@ -736,8 +736,13 @@ static void mipid02_set_fmt_source(struct v4l2_subdev *sd, { struct mipid02_dev *bridge = to_mipid02_dev(sd); - /* source pad mirror active sink pad */ - format->format = bridge->fmt; + /* source pad mirror sink pad */ + if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) + format->format = bridge->fmt; + else + format->format = *v4l2_subdev_get_try_format(sd, sd_state, + MIPID02_SINK_0); + /* but code may need to be converted */ format->format.code = serial_to_parallel_code(format->format.code); From 6c01e6f3f27b7baee6264e490eb608939fec9bbf Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 2 May 2023 11:35:47 +0100 Subject: [PATCH 081/253] media: st-mipid02: Propagate format from sink to source pad When setting formats on the sink pad, propagate the adjusted format over to the subdev's source pad. Use the MIPID02_SOURCE macro to fetch the pad's try format rather than relying on the pad field of the format to facilitate this - the function is specific to the source pad anyway. Signed-off-by: Daniel Scally [Sakari Ailus: Line wrap, fix subject] Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/i2c/st-mipid02.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/st-mipid02.c b/drivers/media/i2c/st-mipid02.c index dcd3ff2bbde9..906553a28676 100644 --- a/drivers/media/i2c/st-mipid02.c +++ b/drivers/media/i2c/st-mipid02.c @@ -750,7 +750,8 @@ static void mipid02_set_fmt_source(struct v4l2_subdev *sd, if (format->which != V4L2_SUBDEV_FORMAT_TRY) return; - *v4l2_subdev_get_try_format(sd, sd_state, format->pad) = format->format; + *v4l2_subdev_get_try_format(sd, sd_state, MIPID02_SOURCE) = + format->format; } static void mipid02_set_fmt_sink(struct v4l2_subdev *sd, @@ -768,6 +769,9 @@ static void mipid02_set_fmt_sink(struct v4l2_subdev *sd, fmt = &bridge->fmt; *fmt = format->format; + + /* Propagate the format change to the source pad */ + mipid02_set_fmt_source(sd, sd_state, format); } static int mipid02_set_fmt(struct v4l2_subdev *sd, From 59a95979638664a905cd46845e7cac1b3ff942f7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 26 Apr 2023 12:18:24 +0200 Subject: [PATCH 082/253] media: renesas: fdp1: Identify R-Car Gen2 versions On R-Car M2-W: rcar_fdp1 fe940000.fdp1: FDP1 Unidentifiable (0x02010101) rcar_fdp1 fe944000.fdp1: FDP1 Unidentifiable (0x02010101) Although the IP Internal Data Register on R-Car Gen2 is documented to contain all zeros, the actual register contents seem to match the FDP1 version ID of R-Car H3 ES1.*, which has just been removed. Fortunately this version is not used for any other purposes yet. Fix this by re-adding the ID, now using an R-Car Gen2-specific name. Fixes: af4273b43f2b ("media: renesas: fdp1: remove R-Car H3 ES1.* handling") Signed-off-by: Geert Uytterhoeven Reviewed-by: Wolfram Sang Reviewed-by: Laurent Pinchart Reviewed-by: Kieran Bingham Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/platform/renesas/rcar_fdp1.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/media/platform/renesas/rcar_fdp1.c b/drivers/media/platform/renesas/rcar_fdp1.c index f43e458590b8..ab39cd2201c8 100644 --- a/drivers/media/platform/renesas/rcar_fdp1.c +++ b/drivers/media/platform/renesas/rcar_fdp1.c @@ -254,6 +254,8 @@ MODULE_PARM_DESC(debug, "activate debug info"); /* Internal Data (HW Version) */ #define FD1_IP_INTDATA 0x0800 +/* R-Car Gen2 HW manual says zero, but actual value matches R-Car H3 ES1.x */ +#define FD1_IP_GEN2 0x02010101 #define FD1_IP_M3W 0x02010202 #define FD1_IP_H3 0x02010203 #define FD1_IP_M3N 0x02010204 @@ -2360,6 +2362,9 @@ static int fdp1_probe(struct platform_device *pdev) hw_version = fdp1_read(fdp1, FD1_IP_INTDATA); switch (hw_version) { + case FD1_IP_GEN2: + dprintk(fdp1, "FDP1 Version R-Car Gen2\n"); + break; case FD1_IP_M3W: dprintk(fdp1, "FDP1 Version R-Car M3-W\n"); break; From 0827b58dabff5b2ba624e8c776573ddb18172c01 Mon Sep 17 00:00:00 2001 From: Bingbu Cao Date: Sun, 23 Apr 2023 16:06:55 +0800 Subject: [PATCH 083/253] media: i2c: add ov01a10 image sensor driver Add v4l2 device driver for OmniVision ov01a10 image sensor, ov01a10 image sensor can deliver 1280x800 resolution BGGR10 images at 60 fps. Signed-off-by: Yating Wang Signed-off-by: Bingbu Cao Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- MAINTAINERS | 7 + drivers/media/i2c/Kconfig | 13 + drivers/media/i2c/Makefile | 1 + drivers/media/i2c/ov01a10.c | 1004 +++++++++++++++++++++++++++++++++++ 4 files changed, 1025 insertions(+) create mode 100644 drivers/media/i2c/ov01a10.c diff --git a/MAINTAINERS b/MAINTAINERS index 517ce68c6102..c329679adee4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15444,6 +15444,13 @@ L: linux-media@vger.kernel.org S: Maintained F: drivers/media/i2c/og01a1b.c +OMNIVISION OV01A10 SENSOR DRIVER +M: Bingbu Cao +L: linux-media@vger.kernel.org +S: Maintained +T: git git://linuxtv.org/media_tree.git +F: drivers/media/i2c/ov01a10.c + OMNIVISION OV02A10 SENSOR DRIVER M: Dongchun Zhu L: linux-media@vger.kernel.org diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 256d55bb2b1d..cf675ac4b132 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -338,6 +338,19 @@ config VIDEO_OG01A1B To compile this driver as a module, choose M here: the module will be called og01a1b. +config VIDEO_OV01A10 + tristate "OmniVision OV01A10 sensor support" + depends on VIDEO_DEV && I2C + select MEDIA_CONTROLLER + select VIDEO_V4L2_SUBDEV_API + select V4L2_FWNODE + help + This is a Video4Linux2 sensor driver for the OmniVision + OV01A10 camera. + + To compile this driver as a module, choose M here: the + module will be called ov01a10. + config VIDEO_OV02A10 tristate "OmniVision OV02A10 sensor support" depends on VIDEO_DEV && I2C diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index b44dacf935f4..c743aeb5d1ad 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o obj-$(CONFIG_VIDEO_MT9V111) += mt9v111.o obj-$(CONFIG_VIDEO_OG01A1B) += og01a1b.o +obj-$(CONFIG_VIDEO_OV01A10) += ov01a10.o obj-$(CONFIG_VIDEO_OV02A10) += ov02a10.o obj-$(CONFIG_VIDEO_OV08D10) += ov08d10.o obj-$(CONFIG_VIDEO_OV08X40) += ov08x40.o diff --git a/drivers/media/i2c/ov01a10.c b/drivers/media/i2c/ov01a10.c new file mode 100644 index 000000000000..de5bc19e715b --- /dev/null +++ b/drivers/media/i2c/ov01a10.c @@ -0,0 +1,1004 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023 Intel Corporation. + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define OV01A10_LINK_FREQ_400MHZ 400000000ULL +#define OV01A10_SCLK 40000000LL +#define OV01A10_DATA_LANES 1 + +#define OV01A10_REG_CHIP_ID 0x300a +#define OV01A10_CHIP_ID 0x560141 + +#define OV01A10_REG_MODE_SELECT 0x0100 +#define OV01A10_MODE_STANDBY 0x00 +#define OV01A10_MODE_STREAMING 0x01 + +/* pixel array */ +#define OV01A10_PIXEL_ARRAY_WIDTH 1296 +#define OV01A10_PIXEL_ARRAY_HEIGHT 816 +#define OV01A10_ACITVE_WIDTH 1280 +#define OV01A10_ACITVE_HEIGHT 800 + +/* vertical and horizontal timings */ +#define OV01A10_REG_VTS 0x380e +#define OV01A10_VTS_DEF 0x0380 +#define OV01A10_VTS_MIN 0x0380 +#define OV01A10_VTS_MAX 0xffff +#define OV01A10_HTS_DEF 1488 + +/* exposure controls */ +#define OV01A10_REG_EXPOSURE 0x3501 +#define OV01A10_EXPOSURE_MIN 4 +#define OV01A10_EXPOSURE_MAX_MARGIN 8 +#define OV01A10_EXPOSURE_STEP 1 + +/* analog gain controls */ +#define OV01A10_REG_ANALOG_GAIN 0x3508 +#define OV01A10_ANAL_GAIN_MIN 0x100 +#define OV01A10_ANAL_GAIN_MAX 0xffff +#define OV01A10_ANAL_GAIN_STEP 1 + +/* digital gain controls */ +#define OV01A10_REG_DIGITAL_GAIN_B 0x350a +#define OV01A10_REG_DIGITAL_GAIN_GB 0x3510 +#define OV01A10_REG_DIGITAL_GAIN_GR 0x3513 +#define OV01A10_REG_DIGITAL_GAIN_R 0x3516 +#define OV01A10_DGTL_GAIN_MIN 0 +#define OV01A10_DGTL_GAIN_MAX 0x3ffff +#define OV01A10_DGTL_GAIN_STEP 1 +#define OV01A10_DGTL_GAIN_DEFAULT 1024 + +/* test pattern control */ +#define OV01A10_REG_TEST_PATTERN 0x4503 +#define OV01A10_TEST_PATTERN_ENABLE BIT(7) +#define OV01A10_LINK_FREQ_400MHZ_INDEX 0 + +/* flip and mirror control */ +#define OV01A10_REG_FORMAT1 0x3820 +#define OV01A10_VFLIP_MASK BIT(4) +#define OV01A10_HFLIP_MASK BIT(3) + +/* window offset */ +#define OV01A10_REG_X_WIN 0x3811 +#define OV01A10_REG_Y_WIN 0x3813 + +struct ov01a10_reg { + u16 address; + u8 val; +}; + +struct ov01a10_reg_list { + u32 num_of_regs; + const struct ov01a10_reg *regs; +}; + +struct ov01a10_link_freq_config { + const struct ov01a10_reg_list reg_list; +}; + +struct ov01a10_mode { + u32 width; + u32 height; + u32 hts; + u32 vts_def; + u32 vts_min; + u32 link_freq_index; + + const struct ov01a10_reg_list reg_list; +}; + +static const struct ov01a10_reg mipi_data_rate_720mbps[] = { + {0x0103, 0x01}, + {0x0302, 0x00}, + {0x0303, 0x06}, + {0x0304, 0x01}, + {0x0305, 0xe0}, + {0x0306, 0x00}, + {0x0308, 0x01}, + {0x0309, 0x00}, + {0x030c, 0x01}, + {0x0322, 0x01}, + {0x0323, 0x06}, + {0x0324, 0x01}, + {0x0325, 0x68}, +}; + +static const struct ov01a10_reg sensor_1280x800_setting[] = { + {0x3002, 0xa1}, + {0x301e, 0xf0}, + {0x3022, 0x01}, + {0x3501, 0x03}, + {0x3502, 0x78}, + {0x3504, 0x0c}, + {0x3508, 0x01}, + {0x3509, 0x00}, + {0x3601, 0xc0}, + {0x3603, 0x71}, + {0x3610, 0x68}, + {0x3611, 0x86}, + {0x3640, 0x10}, + {0x3641, 0x80}, + {0x3642, 0xdc}, + {0x3646, 0x55}, + {0x3647, 0x57}, + {0x364b, 0x00}, + {0x3653, 0x10}, + {0x3655, 0x00}, + {0x3656, 0x00}, + {0x365f, 0x0f}, + {0x3661, 0x45}, + {0x3662, 0x24}, + {0x3663, 0x11}, + {0x3664, 0x07}, + {0x3709, 0x34}, + {0x370b, 0x6f}, + {0x3714, 0x22}, + {0x371b, 0x27}, + {0x371c, 0x67}, + {0x371d, 0xa7}, + {0x371e, 0xe7}, + {0x3730, 0x81}, + {0x3733, 0x10}, + {0x3734, 0x40}, + {0x3737, 0x04}, + {0x3739, 0x1c}, + {0x3767, 0x00}, + {0x376c, 0x81}, + {0x3772, 0x14}, + {0x37c2, 0x04}, + {0x37d8, 0x03}, + {0x37d9, 0x0c}, + {0x37e0, 0x00}, + {0x37e1, 0x08}, + {0x37e2, 0x10}, + {0x37e3, 0x04}, + {0x37e4, 0x04}, + {0x37e5, 0x03}, + {0x37e6, 0x04}, + {0x3800, 0x00}, + {0x3801, 0x00}, + {0x3802, 0x00}, + {0x3803, 0x00}, + {0x3804, 0x05}, + {0x3805, 0x0f}, + {0x3806, 0x03}, + {0x3807, 0x2f}, + {0x3808, 0x05}, + {0x3809, 0x00}, + {0x380a, 0x03}, + {0x380b, 0x20}, + {0x380c, 0x02}, + {0x380d, 0xe8}, + {0x380e, 0x03}, + {0x380f, 0x80}, + {0x3810, 0x00}, + {0x3811, 0x08}, + {0x3812, 0x00}, + {0x3813, 0x08}, + {0x3814, 0x01}, + {0x3815, 0x01}, + {0x3816, 0x01}, + {0x3817, 0x01}, + {0x3820, 0xa0}, + {0x3822, 0x13}, + {0x3832, 0x28}, + {0x3833, 0x10}, + {0x3b00, 0x00}, + {0x3c80, 0x00}, + {0x3c88, 0x02}, + {0x3c8c, 0x07}, + {0x3c8d, 0x40}, + {0x3cc7, 0x80}, + {0x4000, 0xc3}, + {0x4001, 0xe0}, + {0x4003, 0x40}, + {0x4008, 0x02}, + {0x4009, 0x19}, + {0x400a, 0x01}, + {0x400b, 0x6c}, + {0x4011, 0x00}, + {0x4041, 0x00}, + {0x4300, 0xff}, + {0x4301, 0x00}, + {0x4302, 0x0f}, + {0x4503, 0x00}, + {0x4601, 0x50}, + {0x4800, 0x64}, + {0x481f, 0x34}, + {0x4825, 0x33}, + {0x4837, 0x11}, + {0x4881, 0x40}, + {0x4883, 0x01}, + {0x4890, 0x00}, + {0x4901, 0x00}, + {0x4902, 0x00}, + {0x4b00, 0x2a}, + {0x4b0d, 0x00}, + {0x450a, 0x04}, + {0x450b, 0x00}, + {0x5000, 0x65}, + {0x5200, 0x18}, + {0x5004, 0x00}, + {0x5080, 0x40}, + {0x0305, 0xf4}, + {0x0325, 0xc2}, +}; + +static const char * const ov01a10_test_pattern_menu[] = { + "Disabled", + "Color Bar", + "Top-Bottom Darker Color Bar", + "Right-Left Darker Color Bar", + "Color Bar type 4", +}; + +static const s64 link_freq_menu_items[] = { + OV01A10_LINK_FREQ_400MHZ, +}; + +static const struct ov01a10_link_freq_config link_freq_configs[] = { + [OV01A10_LINK_FREQ_400MHZ_INDEX] = { + .reg_list = { + .num_of_regs = ARRAY_SIZE(mipi_data_rate_720mbps), + .regs = mipi_data_rate_720mbps, + } + }, +}; + +static const struct ov01a10_mode supported_modes[] = { + { + .width = OV01A10_ACITVE_WIDTH, + .height = OV01A10_ACITVE_HEIGHT, + .hts = OV01A10_HTS_DEF, + .vts_def = OV01A10_VTS_DEF, + .vts_min = OV01A10_VTS_MIN, + .reg_list = { + .num_of_regs = ARRAY_SIZE(sensor_1280x800_setting), + .regs = sensor_1280x800_setting, + }, + .link_freq_index = OV01A10_LINK_FREQ_400MHZ_INDEX, + }, +}; + +struct ov01a10 { + struct v4l2_subdev sd; + struct media_pad pad; + struct v4l2_ctrl_handler ctrl_handler; + + /* v4l2 controls */ + struct v4l2_ctrl *link_freq; + struct v4l2_ctrl *pixel_rate; + struct v4l2_ctrl *vblank; + struct v4l2_ctrl *hblank; + struct v4l2_ctrl *exposure; + + const struct ov01a10_mode *cur_mode; + + /* streaming state */ + bool streaming; +}; + +static inline struct ov01a10 *to_ov01a10(struct v4l2_subdev *subdev) +{ + return container_of(subdev, struct ov01a10, sd); +} + +static int ov01a10_read_reg(struct ov01a10 *ov01a10, u16 reg, u16 len, u32 *val) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); + struct i2c_msg msgs[2]; + u8 addr_buf[2]; + u8 data_buf[4] = {0}; + int ret = 0; + + if (len > sizeof(data_buf)) + return -EINVAL; + + put_unaligned_be16(reg, addr_buf); + msgs[0].addr = client->addr; + msgs[0].flags = 0; + msgs[0].len = sizeof(addr_buf); + msgs[0].buf = addr_buf; + msgs[1].addr = client->addr; + msgs[1].flags = I2C_M_RD; + msgs[1].len = len; + msgs[1].buf = &data_buf[sizeof(data_buf) - len]; + + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + + if (ret != ARRAY_SIZE(msgs)) + return ret < 0 ? ret : -EIO; + + *val = get_unaligned_be32(data_buf); + + return 0; +} + +static int ov01a10_write_reg(struct ov01a10 *ov01a10, u16 reg, u16 len, u32 val) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); + u8 buf[6]; + int ret = 0; + + if (len > 4) + return -EINVAL; + + put_unaligned_be16(reg, buf); + put_unaligned_be32(val << 8 * (4 - len), buf + 2); + + ret = i2c_master_send(client, buf, len + 2); + if (ret != len + 2) + return ret < 0 ? ret : -EIO; + + return 0; +} + +static int ov01a10_write_reg_list(struct ov01a10 *ov01a10, + const struct ov01a10_reg_list *r_list) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); + unsigned int i; + int ret = 0; + + for (i = 0; i < r_list->num_of_regs; i++) { + ret = ov01a10_write_reg(ov01a10, r_list->regs[i].address, 1, + r_list->regs[i].val); + if (ret) { + dev_err_ratelimited(&client->dev, + "write reg 0x%4.4x err = %d\n", + r_list->regs[i].address, ret); + return ret; + } + } + + return 0; +} + +static int ov01a10_update_digital_gain(struct ov01a10 *ov01a10, u32 d_gain) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); + u32 real = d_gain << 6; + int ret = 0; + + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_DIGITAL_GAIN_B, 3, real); + if (ret) { + dev_err(&client->dev, "failed to set DIGITAL_GAIN_B\n"); + return ret; + } + + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_DIGITAL_GAIN_GB, 3, real); + if (ret) { + dev_err(&client->dev, "failed to set DIGITAL_GAIN_GB\n"); + return ret; + } + + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_DIGITAL_GAIN_GR, 3, real); + if (ret) { + dev_err(&client->dev, "failed to set DIGITAL_GAIN_GR\n"); + return ret; + } + + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_DIGITAL_GAIN_R, 3, real); + if (ret) + dev_err(&client->dev, "failed to set DIGITAL_GAIN_R\n"); + + return ret; +} + +static int ov01a10_test_pattern(struct ov01a10 *ov01a10, u32 pattern) +{ + if (!pattern) + return 0; + + pattern = (pattern - 1) | OV01A10_TEST_PATTERN_ENABLE; + + return ov01a10_write_reg(ov01a10, OV01A10_REG_TEST_PATTERN, 1, pattern); +} + +/* for vflip and hflip, use 0x9 as window offset to keep the bayer */ +static int ov01a10_set_hflip(struct ov01a10 *ov01a10, u32 hflip) +{ + int ret; + u32 val, offset; + + offset = hflip ? 0x9 : 0x8; + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_X_WIN, 1, offset); + if (ret) + return ret; + + ret = ov01a10_read_reg(ov01a10, OV01A10_REG_FORMAT1, 1, &val); + if (ret) + return ret; + + val = hflip ? val | FIELD_PREP(OV01A10_HFLIP_MASK, 0x1) : + val & ~OV01A10_HFLIP_MASK; + + return ov01a10_write_reg(ov01a10, OV01A10_REG_FORMAT1, 1, val); +} + +static int ov01a10_set_vflip(struct ov01a10 *ov01a10, u32 vflip) +{ + int ret; + u32 val, offset; + + offset = vflip ? 0x9 : 0x8; + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_Y_WIN, 1, offset); + if (ret) + return ret; + + ret = ov01a10_read_reg(ov01a10, OV01A10_REG_FORMAT1, 1, &val); + if (ret) + return ret; + + val = vflip ? val | FIELD_PREP(OV01A10_VFLIP_MASK, 0x1) : + val & ~OV01A10_VFLIP_MASK; + + return ov01a10_write_reg(ov01a10, OV01A10_REG_FORMAT1, 1, val); +} + +static int ov01a10_set_ctrl(struct v4l2_ctrl *ctrl) +{ + struct ov01a10 *ov01a10 = container_of(ctrl->handler, + struct ov01a10, ctrl_handler); + struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); + s64 exposure_max; + int ret = 0; + + if (ctrl->id == V4L2_CID_VBLANK) { + exposure_max = ov01a10->cur_mode->height + ctrl->val - + OV01A10_EXPOSURE_MAX_MARGIN; + __v4l2_ctrl_modify_range(ov01a10->exposure, + ov01a10->exposure->minimum, + exposure_max, ov01a10->exposure->step, + exposure_max); + } + + if (!pm_runtime_get_if_in_use(&client->dev)) + return 0; + + switch (ctrl->id) { + case V4L2_CID_ANALOGUE_GAIN: + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_ANALOG_GAIN, 2, + ctrl->val); + break; + + case V4L2_CID_DIGITAL_GAIN: + ret = ov01a10_update_digital_gain(ov01a10, ctrl->val); + break; + + case V4L2_CID_EXPOSURE: + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_EXPOSURE, 2, + ctrl->val); + break; + + case V4L2_CID_VBLANK: + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_VTS, 2, + ov01a10->cur_mode->height + ctrl->val); + break; + + case V4L2_CID_TEST_PATTERN: + ret = ov01a10_test_pattern(ov01a10, ctrl->val); + break; + + case V4L2_CID_HFLIP: + ov01a10_set_hflip(ov01a10, ctrl->val); + break; + + case V4L2_CID_VFLIP: + ov01a10_set_vflip(ov01a10, ctrl->val); + break; + + default: + ret = -EINVAL; + break; + } + + pm_runtime_put(&client->dev); + + return ret; +} + +static const struct v4l2_ctrl_ops ov01a10_ctrl_ops = { + .s_ctrl = ov01a10_set_ctrl, +}; + +static int ov01a10_init_controls(struct ov01a10 *ov01a10) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); + struct v4l2_fwnode_device_properties props; + u32 vblank_min, vblank_max, vblank_default; + struct v4l2_ctrl_handler *ctrl_hdlr; + const struct ov01a10_mode *cur_mode; + s64 exposure_max, h_blank; + int ret = 0; + int size; + + ret = v4l2_fwnode_device_parse(&client->dev, &props); + if (ret) + return ret; + + ctrl_hdlr = &ov01a10->ctrl_handler; + ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12); + if (ret) + return ret; + + cur_mode = ov01a10->cur_mode; + size = ARRAY_SIZE(link_freq_menu_items); + + ov01a10->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, + &ov01a10_ctrl_ops, + V4L2_CID_LINK_FREQ, + size - 1, 0, + link_freq_menu_items); + if (ov01a10->link_freq) + ov01a10->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + ov01a10->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, + V4L2_CID_PIXEL_RATE, 0, + OV01A10_SCLK, 1, OV01A10_SCLK); + + vblank_min = cur_mode->vts_min - cur_mode->height; + vblank_max = OV01A10_VTS_MAX - cur_mode->height; + vblank_default = cur_mode->vts_def - cur_mode->height; + ov01a10->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, + V4L2_CID_VBLANK, vblank_min, + vblank_max, 1, vblank_default); + + h_blank = cur_mode->hts - cur_mode->width; + ov01a10->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, + V4L2_CID_HBLANK, h_blank, h_blank, + 1, h_blank); + if (ov01a10->hblank) + ov01a10->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, + OV01A10_ANAL_GAIN_MIN, OV01A10_ANAL_GAIN_MAX, + OV01A10_ANAL_GAIN_STEP, OV01A10_ANAL_GAIN_MIN); + v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, V4L2_CID_DIGITAL_GAIN, + OV01A10_DGTL_GAIN_MIN, OV01A10_DGTL_GAIN_MAX, + OV01A10_DGTL_GAIN_STEP, OV01A10_DGTL_GAIN_DEFAULT); + + exposure_max = cur_mode->vts_def - OV01A10_EXPOSURE_MAX_MARGIN; + ov01a10->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, + V4L2_CID_EXPOSURE, + OV01A10_EXPOSURE_MIN, + exposure_max, + OV01A10_EXPOSURE_STEP, + exposure_max); + + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &ov01a10_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(ov01a10_test_pattern_menu) - 1, + 0, 0, ov01a10_test_pattern_menu); + + v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, V4L2_CID_HFLIP, + 0, 1, 1, 0); + v4l2_ctrl_new_std(ctrl_hdlr, &ov01a10_ctrl_ops, V4L2_CID_VFLIP, + 0, 1, 1, 0); + + ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &ov01a10_ctrl_ops, + &props); + if (ret) + goto fail; + + if (ctrl_hdlr->error) { + ret = ctrl_hdlr->error; + goto fail; + } + + ov01a10->sd.ctrl_handler = ctrl_hdlr; + + return 0; +fail: + v4l2_ctrl_handler_free(ctrl_hdlr); + + return ret; +} + +static void ov01a10_update_pad_format(const struct ov01a10_mode *mode, + struct v4l2_mbus_framefmt *fmt) +{ + fmt->width = mode->width; + fmt->height = mode->height; + fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10; + fmt->field = V4L2_FIELD_NONE; + fmt->colorspace = V4L2_COLORSPACE_RAW; +} + +static int ov01a10_start_streaming(struct ov01a10 *ov01a10) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); + const struct ov01a10_reg_list *reg_list; + int link_freq_index; + int ret = 0; + + link_freq_index = ov01a10->cur_mode->link_freq_index; + reg_list = &link_freq_configs[link_freq_index].reg_list; + ret = ov01a10_write_reg_list(ov01a10, reg_list); + if (ret) { + dev_err(&client->dev, "failed to set plls\n"); + return ret; + } + + reg_list = &ov01a10->cur_mode->reg_list; + ret = ov01a10_write_reg_list(ov01a10, reg_list); + if (ret) { + dev_err(&client->dev, "failed to set mode\n"); + return ret; + } + + ret = __v4l2_ctrl_handler_setup(ov01a10->sd.ctrl_handler); + if (ret) + return ret; + + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_MODE_SELECT, 1, + OV01A10_MODE_STREAMING); + if (ret) + dev_err(&client->dev, "failed to start streaming\n"); + + return ret; +} + +static void ov01a10_stop_streaming(struct ov01a10 *ov01a10) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); + int ret = 0; + + ret = ov01a10_write_reg(ov01a10, OV01A10_REG_MODE_SELECT, 1, + OV01A10_MODE_STANDBY); + if (ret) + dev_err(&client->dev, "failed to stop streaming\n"); +} + +static int ov01a10_set_stream(struct v4l2_subdev *sd, int enable) +{ + struct ov01a10 *ov01a10 = to_ov01a10(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct v4l2_subdev_state *state; + int ret = 0; + + state = v4l2_subdev_lock_and_get_active_state(sd); + if (ov01a10->streaming == enable) + goto unlock; + + if (enable) { + ret = pm_runtime_resume_and_get(&client->dev); + if (ret < 0) + goto unlock; + + ret = ov01a10_start_streaming(ov01a10); + if (ret) { + pm_runtime_put(&client->dev); + goto unlock; + } + + goto done; + } + + ov01a10_stop_streaming(ov01a10); + pm_runtime_put(&client->dev); +done: + ov01a10->streaming = enable; +unlock: + v4l2_subdev_unlock_state(state); + + return ret; +} + +static int __maybe_unused ov01a10_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ov01a10 *ov01a10 = to_ov01a10(sd); + struct v4l2_subdev_state *state; + + state = v4l2_subdev_lock_and_get_active_state(sd); + if (ov01a10->streaming) + ov01a10_stop_streaming(ov01a10); + + v4l2_subdev_unlock_state(state); + + return 0; +} + +static int __maybe_unused ov01a10_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ov01a10 *ov01a10 = to_ov01a10(sd); + struct v4l2_subdev_state *state; + int ret = 0; + + state = v4l2_subdev_lock_and_get_active_state(sd); + if (!ov01a10->streaming) + goto exit; + + ret = ov01a10_start_streaming(ov01a10); + if (ret) { + ov01a10->streaming = false; + ov01a10_stop_streaming(ov01a10); + } + +exit: + v4l2_subdev_unlock_state(state); + + return ret; +} + +static int ov01a10_set_format(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +{ + struct ov01a10 *ov01a10 = to_ov01a10(sd); + const struct ov01a10_mode *mode; + struct v4l2_mbus_framefmt *format; + s32 vblank_def, h_blank; + + mode = v4l2_find_nearest_size(supported_modes, + ARRAY_SIZE(supported_modes), width, + height, fmt->format.width, + fmt->format.height); + + ov01a10_update_pad_format(mode, &fmt->format); + + if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { + ov01a10->cur_mode = mode; + __v4l2_ctrl_s_ctrl(ov01a10->link_freq, mode->link_freq_index); + __v4l2_ctrl_s_ctrl_int64(ov01a10->pixel_rate, OV01A10_SCLK); + + vblank_def = mode->vts_def - mode->height; + __v4l2_ctrl_modify_range(ov01a10->vblank, + mode->vts_min - mode->height, + OV01A10_VTS_MAX - mode->height, 1, + vblank_def); + __v4l2_ctrl_s_ctrl(ov01a10->vblank, vblank_def); + h_blank = mode->hts - mode->width; + __v4l2_ctrl_modify_range(ov01a10->hblank, h_blank, h_blank, 1, + h_blank); + } + + format = v4l2_subdev_get_pad_format(sd, sd_state, fmt->stream); + *format = fmt->format; + + return 0; +} + +static int ov01a10_init_cfg(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state) +{ + struct v4l2_subdev_format fmt = { + .which = V4L2_SUBDEV_FORMAT_TRY, + .format = { + .width = OV01A10_ACITVE_WIDTH, + .height = OV01A10_ACITVE_HEIGHT, + }, + }; + + ov01a10_set_format(sd, state, &fmt); + + return 0; +} + +static int ov01a10_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->index > 0) + return -EINVAL; + + code->code = MEDIA_BUS_FMT_SBGGR10_1X10; + + return 0; +} + +static int ov01a10_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_size_enum *fse) +{ + if (fse->index >= ARRAY_SIZE(supported_modes) || + fse->code != MEDIA_BUS_FMT_SBGGR10_1X10) + return -EINVAL; + + fse->min_width = supported_modes[fse->index].width; + fse->max_width = fse->min_width; + fse->min_height = supported_modes[fse->index].height; + fse->max_height = fse->min_height; + + return 0; +} + +static int ov01a10_get_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_selection *sel) +{ + if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + + switch (sel->target) { + case V4L2_SEL_TGT_NATIVE_SIZE: + case V4L2_SEL_TGT_CROP_BOUNDS: + sel->r.top = 0; + sel->r.left = 0; + sel->r.width = OV01A10_PIXEL_ARRAY_WIDTH; + sel->r.height = OV01A10_PIXEL_ARRAY_HEIGHT; + return 0; + case V4L2_SEL_TGT_CROP: + case V4L2_SEL_TGT_CROP_DEFAULT: + sel->r.top = (OV01A10_PIXEL_ARRAY_HEIGHT - + OV01A10_ACITVE_HEIGHT) / 2; + sel->r.left = (OV01A10_PIXEL_ARRAY_WIDTH - + OV01A10_ACITVE_WIDTH) / 2; + sel->r.width = OV01A10_ACITVE_WIDTH; + sel->r.height = OV01A10_ACITVE_HEIGHT; + return 0; + } + + return -EINVAL; +} + +static const struct v4l2_subdev_core_ops ov01a10_core_ops = { + .log_status = v4l2_ctrl_subdev_log_status, + .subscribe_event = v4l2_ctrl_subdev_subscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, +}; + +static const struct v4l2_subdev_video_ops ov01a10_video_ops = { + .s_stream = ov01a10_set_stream, +}; + +static const struct v4l2_subdev_pad_ops ov01a10_pad_ops = { + .init_cfg = ov01a10_init_cfg, + .set_fmt = ov01a10_set_format, + .get_fmt = v4l2_subdev_get_fmt, + .get_selection = ov01a10_get_selection, + .enum_mbus_code = ov01a10_enum_mbus_code, + .enum_frame_size = ov01a10_enum_frame_size, +}; + +static const struct v4l2_subdev_ops ov01a10_subdev_ops = { + .core = &ov01a10_core_ops, + .video = &ov01a10_video_ops, + .pad = &ov01a10_pad_ops, +}; + +static const struct media_entity_operations ov01a10_subdev_entity_ops = { + .link_validate = v4l2_subdev_link_validate, +}; + +static int ov01a10_identify_module(struct ov01a10 *ov01a10) +{ + struct i2c_client *client = v4l2_get_subdevdata(&ov01a10->sd); + int ret; + u32 val; + + ret = ov01a10_read_reg(ov01a10, OV01A10_REG_CHIP_ID, 3, &val); + if (ret) + return ret; + + if (val != OV01A10_CHIP_ID) { + dev_err(&client->dev, "chip id mismatch: %x!=%x\n", + OV01A10_CHIP_ID, val); + return -EIO; + } + + return 0; +} + +static void ov01a10_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_async_unregister_subdev(sd); + media_entity_cleanup(&sd->entity); + v4l2_ctrl_handler_free(sd->ctrl_handler); + + pm_runtime_disable(&client->dev); +} + +static int ov01a10_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct ov01a10 *ov01a10; + int ret = 0; + + ov01a10 = devm_kzalloc(dev, sizeof(*ov01a10), GFP_KERNEL); + if (!ov01a10) + return -ENOMEM; + + v4l2_i2c_subdev_init(&ov01a10->sd, client, &ov01a10_subdev_ops); + + ret = ov01a10_identify_module(ov01a10); + if (ret) + return dev_err_probe(dev, ret, + "failed to find sensor\n"); + + ov01a10->cur_mode = &supported_modes[0]; + + ret = ov01a10_init_controls(ov01a10); + if (ret) { + dev_err(dev, "failed to init controls: %d\n", ret); + return ret; + } + + ov01a10->sd.state_lock = ov01a10->ctrl_handler.lock; + ov01a10->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | + V4L2_SUBDEV_FL_HAS_EVENTS; + ov01a10->sd.entity.ops = &ov01a10_subdev_entity_ops; + ov01a10->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + ov01a10->pad.flags = MEDIA_PAD_FL_SOURCE; + + ret = media_entity_pads_init(&ov01a10->sd.entity, 1, &ov01a10->pad); + if (ret) { + dev_err(dev, "Failed to init entity pads: %d\n", ret); + goto err_handler_free; + } + + ret = v4l2_subdev_init_finalize(&ov01a10->sd); + if (ret) { + dev_err(dev, "Failed to allocate subdev state: %d\n", ret); + goto err_media_entity_cleanup; + } + + ret = v4l2_async_register_subdev_sensor(&ov01a10->sd); + if (ret < 0) { + dev_err(dev, "Failed to register subdev: %d\n", ret); + goto err_media_entity_cleanup; + } + + pm_runtime_enable(dev); + pm_runtime_idle(dev); + + return 0; + +err_media_entity_cleanup: + media_entity_cleanup(&ov01a10->sd.entity); + +err_handler_free: + v4l2_ctrl_handler_free(ov01a10->sd.ctrl_handler); + + return ret; +} + +static const struct dev_pm_ops ov01a10_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(ov01a10_suspend, ov01a10_resume) +}; + +#ifdef CONFIG_ACPI +static const struct acpi_device_id ov01a10_acpi_ids[] = { + { "OVTI01A0" }, + { } +}; + +MODULE_DEVICE_TABLE(acpi, ov01a10_acpi_ids); +#endif + +static struct i2c_driver ov01a10_i2c_driver = { + .driver = { + .name = "ov01a10", + .pm = &ov01a10_pm_ops, + .acpi_match_table = ACPI_PTR(ov01a10_acpi_ids), + }, + .probe_new = ov01a10_probe, + .remove = ov01a10_remove, +}; + +module_i2c_driver(ov01a10_i2c_driver); + +MODULE_AUTHOR("Bingbu Cao "); +MODULE_AUTHOR("Wang Yating "); +MODULE_DESCRIPTION("OmniVision OV01A10 sensor driver"); +MODULE_LICENSE("GPL"); From a73116db88299af2c2b2aa69d7df5ccf5a1c6f75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Mon, 24 Apr 2023 20:59:32 +0200 Subject: [PATCH 084/253] media: rcar-csi2: Prepare for Gen4 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prepare the driver for supporting R-Car Gen4. The starting of the receiver and how to enter standby differs between Gen3 and Gen4, create function pointers in the device info structure to control the different behavior. Signed-off-by: Niklas Söderlund Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- .../platform/renesas/rcar-vin/rcar-csi2.c | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c b/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c index e34060c2b039..1fe85db87d61 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c @@ -483,6 +483,8 @@ enum rcar_csi2_pads { struct rcar_csi2_info { int (*init_phtw)(struct rcar_csi2 *priv, unsigned int mbps); int (*phy_post_init)(struct rcar_csi2 *priv); + int (*start_receiver)(struct rcar_csi2 *priv); + void (*enter_standby)(struct rcar_csi2 *priv); const struct rcsi2_mbps_reg *hsfreqrange; unsigned int csi0clkfreqrange; unsigned int num_channels; @@ -533,10 +535,17 @@ static void rcsi2_write(struct rcar_csi2 *priv, unsigned int reg, u32 data) iowrite32(data, priv->base + reg); } -static void rcsi2_enter_standby(struct rcar_csi2 *priv) +static void rcsi2_enter_standby_gen3(struct rcar_csi2 *priv) { rcsi2_write(priv, PHYCNT_REG, 0); rcsi2_write(priv, PHTC_REG, PHTC_TESTCLR); +} + +static void rcsi2_enter_standby(struct rcar_csi2 *priv) +{ + if (priv->info->enter_standby) + priv->info->enter_standby(priv); + reset_control_assert(priv->rstc); usleep_range(100, 150); pm_runtime_put(priv->dev); @@ -674,7 +683,7 @@ static int rcsi2_get_active_lanes(struct rcar_csi2 *priv, return 0; } -static int rcsi2_start_receiver(struct rcar_csi2 *priv) +static int rcsi2_start_receiver_gen3(struct rcar_csi2 *priv) { const struct rcar_csi2_format *format; u32 phycnt, vcdt = 0, vcdt2 = 0, fld = 0; @@ -821,7 +830,7 @@ static int rcsi2_start(struct rcar_csi2 *priv) if (ret < 0) return ret; - ret = rcsi2_start_receiver(priv); + ret = priv->info->start_receiver(priv); if (ret) { rcsi2_enter_standby(priv); return ret; @@ -1363,6 +1372,8 @@ static int rcsi2_probe_resources(struct rcar_csi2 *priv, static const struct rcar_csi2_info rcar_csi2_info_r8a7795 = { .init_phtw = rcsi2_init_phtw_h3_v3h_m3n, + .start_receiver = rcsi2_start_receiver_gen3, + .enter_standby = rcsi2_enter_standby_gen3, .hsfreqrange = hsfreqrange_h3_v3h_m3n, .csi0clkfreqrange = 0x20, .num_channels = 4, @@ -1371,6 +1382,8 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a7795 = { static const struct rcar_csi2_info rcar_csi2_info_r8a7795es2 = { .init_phtw = rcsi2_init_phtw_h3es2, + .start_receiver = rcsi2_start_receiver_gen3, + .enter_standby = rcsi2_enter_standby_gen3, .hsfreqrange = hsfreqrange_h3_v3h_m3n, .csi0clkfreqrange = 0x20, .num_channels = 4, @@ -1378,17 +1391,23 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a7795es2 = { }; static const struct rcar_csi2_info rcar_csi2_info_r8a7796 = { + .start_receiver = rcsi2_start_receiver_gen3, + .enter_standby = rcsi2_enter_standby_gen3, .hsfreqrange = hsfreqrange_m3w, .num_channels = 4, }; static const struct rcar_csi2_info rcar_csi2_info_r8a77961 = { + .start_receiver = rcsi2_start_receiver_gen3, + .enter_standby = rcsi2_enter_standby_gen3, .hsfreqrange = hsfreqrange_m3w, .num_channels = 4, }; static const struct rcar_csi2_info rcar_csi2_info_r8a77965 = { .init_phtw = rcsi2_init_phtw_h3_v3h_m3n, + .start_receiver = rcsi2_start_receiver_gen3, + .enter_standby = rcsi2_enter_standby_gen3, .hsfreqrange = hsfreqrange_h3_v3h_m3n, .csi0clkfreqrange = 0x20, .num_channels = 4, @@ -1398,11 +1417,15 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a77965 = { static const struct rcar_csi2_info rcar_csi2_info_r8a77970 = { .init_phtw = rcsi2_init_phtw_v3m_e3, .phy_post_init = rcsi2_phy_post_init_v3m_e3, + .start_receiver = rcsi2_start_receiver_gen3, + .enter_standby = rcsi2_enter_standby_gen3, .num_channels = 4, }; static const struct rcar_csi2_info rcar_csi2_info_r8a77980 = { .init_phtw = rcsi2_init_phtw_h3_v3h_m3n, + .start_receiver = rcsi2_start_receiver_gen3, + .enter_standby = rcsi2_enter_standby_gen3, .hsfreqrange = hsfreqrange_h3_v3h_m3n, .csi0clkfreqrange = 0x20, .clear_ulps = true, @@ -1411,11 +1434,15 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a77980 = { static const struct rcar_csi2_info rcar_csi2_info_r8a77990 = { .init_phtw = rcsi2_init_phtw_v3m_e3, .phy_post_init = rcsi2_phy_post_init_v3m_e3, + .start_receiver = rcsi2_start_receiver_gen3, + .enter_standby = rcsi2_enter_standby_gen3, .num_channels = 2, }; static const struct rcar_csi2_info rcar_csi2_info_r8a779a0 = { .init_phtw = rcsi2_init_phtw_v3u, + .start_receiver = rcsi2_start_receiver_gen3, + .enter_standby = rcsi2_enter_standby_gen3, .hsfreqrange = hsfreqrange_v3u, .csi0clkfreqrange = 0x20, .clear_ulps = true, From e103484c76ab0898e6cf5067b1e3d45019a4fe0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Mon, 24 Apr 2023 20:59:33 +0200 Subject: [PATCH 085/253] media: rcar-csi2: Prepare for C-PHY support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gen4 will support both D-PHY and C-PHY, while Gen3 only supports D-PHY. Add two flags to the device information structure to be able to record what each SoC supports. Extend the device node parsing to accept both CSI_2 D-PHY and C-PHY buses, while at the same time taking the SoC support into account. Signed-off-by: Niklas Söderlund [Sakari Ailus: Line wrap.] Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- .../platform/renesas/rcar-vin/rcar-csi2.c | 67 ++++++++++++++++--- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c b/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c index 1fe85db87d61..7a134c0eff57 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-csi2.c @@ -490,6 +490,8 @@ struct rcar_csi2_info { unsigned int num_channels; bool clear_ulps; bool use_isp; + bool support_dphy; + bool support_cphy; }; struct rcar_csi2 { @@ -511,6 +513,7 @@ struct rcar_csi2 { struct v4l2_mbus_framefmt mf; int stream_count; + bool cphy; unsigned short lanes; unsigned char lane_swap[4]; }; @@ -665,7 +668,16 @@ static int rcsi2_get_active_lanes(struct rcar_csi2 *priv, return ret; } - if (mbus_config.type != V4L2_MBUS_CSI2_DPHY) { + switch (mbus_config.type) { + case V4L2_MBUS_CSI2_CPHY: + if (!priv->cphy) + return -EINVAL; + break; + case V4L2_MBUS_CSI2_DPHY: + if (priv->cphy) + return -EINVAL; + break; + default: dev_err(priv->dev, "Unsupported media bus type %u\n", mbus_config.type); return -EINVAL; @@ -1025,15 +1037,41 @@ static int rcsi2_parse_v4l2(struct rcar_csi2 *priv, if (vep->base.port || vep->base.id) return -ENOTCONN; - if (vep->bus_type != V4L2_MBUS_CSI2_DPHY) { - dev_err(priv->dev, "Unsupported bus: %u\n", vep->bus_type); - return -EINVAL; - } - priv->lanes = vep->bus.mipi_csi2.num_data_lanes; - if (priv->lanes != 1 && priv->lanes != 2 && priv->lanes != 4) { - dev_err(priv->dev, "Unsupported number of data-lanes: %u\n", - priv->lanes); + + switch (vep->bus_type) { + case V4L2_MBUS_CSI2_DPHY: + if (!priv->info->support_dphy) { + dev_err(priv->dev, "D-PHY not supported\n"); + return -EINVAL; + } + + if (priv->lanes != 1 && priv->lanes != 2 && priv->lanes != 4) { + dev_err(priv->dev, + "Unsupported number of data-lanes for D-PHY: %u\n", + priv->lanes); + return -EINVAL; + } + + priv->cphy = false; + break; + case V4L2_MBUS_CSI2_CPHY: + if (!priv->info->support_cphy) { + dev_err(priv->dev, "C-PHY not supported\n"); + return -EINVAL; + } + + if (priv->lanes != 3) { + dev_err(priv->dev, + "Unsupported number of data-lanes for C-PHY: %u\n", + priv->lanes); + return -EINVAL; + } + + priv->cphy = true; + break; + default: + dev_err(priv->dev, "Unsupported bus: %u\n", vep->bus_type); return -EINVAL; } @@ -1057,7 +1095,7 @@ static int rcsi2_parse_dt(struct rcar_csi2 *priv) struct fwnode_handle *fwnode; struct fwnode_handle *ep; struct v4l2_fwnode_endpoint v4l2_ep = { - .bus_type = V4L2_MBUS_CSI2_DPHY + .bus_type = V4L2_MBUS_UNKNOWN, }; int ret; @@ -1378,6 +1416,7 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a7795 = { .csi0clkfreqrange = 0x20, .num_channels = 4, .clear_ulps = true, + .support_dphy = true, }; static const struct rcar_csi2_info rcar_csi2_info_r8a7795es2 = { @@ -1388,6 +1427,7 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a7795es2 = { .csi0clkfreqrange = 0x20, .num_channels = 4, .clear_ulps = true, + .support_dphy = true, }; static const struct rcar_csi2_info rcar_csi2_info_r8a7796 = { @@ -1395,6 +1435,7 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a7796 = { .enter_standby = rcsi2_enter_standby_gen3, .hsfreqrange = hsfreqrange_m3w, .num_channels = 4, + .support_dphy = true, }; static const struct rcar_csi2_info rcar_csi2_info_r8a77961 = { @@ -1402,6 +1443,7 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a77961 = { .enter_standby = rcsi2_enter_standby_gen3, .hsfreqrange = hsfreqrange_m3w, .num_channels = 4, + .support_dphy = true, }; static const struct rcar_csi2_info rcar_csi2_info_r8a77965 = { @@ -1412,6 +1454,7 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a77965 = { .csi0clkfreqrange = 0x20, .num_channels = 4, .clear_ulps = true, + .support_dphy = true, }; static const struct rcar_csi2_info rcar_csi2_info_r8a77970 = { @@ -1420,6 +1463,7 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a77970 = { .start_receiver = rcsi2_start_receiver_gen3, .enter_standby = rcsi2_enter_standby_gen3, .num_channels = 4, + .support_dphy = true, }; static const struct rcar_csi2_info rcar_csi2_info_r8a77980 = { @@ -1429,6 +1473,7 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a77980 = { .hsfreqrange = hsfreqrange_h3_v3h_m3n, .csi0clkfreqrange = 0x20, .clear_ulps = true, + .support_dphy = true, }; static const struct rcar_csi2_info rcar_csi2_info_r8a77990 = { @@ -1437,6 +1482,7 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a77990 = { .start_receiver = rcsi2_start_receiver_gen3, .enter_standby = rcsi2_enter_standby_gen3, .num_channels = 2, + .support_dphy = true, }; static const struct rcar_csi2_info rcar_csi2_info_r8a779a0 = { @@ -1447,6 +1493,7 @@ static const struct rcar_csi2_info rcar_csi2_info_r8a779a0 = { .csi0clkfreqrange = 0x20, .clear_ulps = true, .use_isp = true, + .support_dphy = true, }; static const struct of_device_id rcar_csi2_of_table[] = { From 04fc06f6dc1592ed5d675311ac50d8fba5db62ab Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Tue, 25 Apr 2023 11:47:47 +0200 Subject: [PATCH 086/253] media: hi846: fix usage of pm_runtime_get_if_in_use() pm_runtime_get_if_in_use() does not only return nonzero values when the device is in use, it can return a negative errno too. And especially during resuming from system suspend, when runtime pm is not yet up again, -EAGAIN is being returned, so the subsequent pm_runtime_put() call results in a refcount underflow. Fix system-resume by handling -EAGAIN of pm_runtime_get_if_in_use(). Signed-off-by: Martin Kepplinger Fixes: e8c0882685f9 ("media: i2c: add driver for the SK Hynix Hi-846 8M pixel camera") Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/i2c/hi846.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/hi846.c b/drivers/media/i2c/hi846.c index 5283a09fd359..fa0038749a3b 100644 --- a/drivers/media/i2c/hi846.c +++ b/drivers/media/i2c/hi846.c @@ -1353,7 +1353,8 @@ static int hi846_set_ctrl(struct v4l2_ctrl *ctrl) exposure_max); } - if (!pm_runtime_get_if_in_use(&client->dev)) + ret = pm_runtime_get_if_in_use(&client->dev); + if (!ret || ret == -EAGAIN) return 0; switch (ctrl->id) { From 6f482c4729d9040945f6d1e7ca1171eba9b5a5d6 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Wed, 19 Apr 2023 09:07:09 +0200 Subject: [PATCH 087/253] media: imx: imx7-media-csi: Get rid of superfluous call to imx7_csi_mbus_fmt_to_pix_fmt There is no need to convert input pixformat to mbus_framefmt and back again. Instead apply pixformat width constrains directly. Assign compose values before adjusting pixformat height/width. Signed-off-by: Alexander Stein Reviewed-by: Laurent Pinchart Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/platform/nxp/imx7-media-csi.c | 22 ++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/media/platform/nxp/imx7-media-csi.c b/drivers/media/platform/nxp/imx7-media-csi.c index b701e823436a..b149374b07ee 100644 --- a/drivers/media/platform/nxp/imx7-media-csi.c +++ b/drivers/media/platform/nxp/imx7-media-csi.c @@ -1145,9 +1145,13 @@ static const struct imx7_csi_pixfmt * __imx7_csi_video_try_fmt(struct v4l2_pix_format *pixfmt, struct v4l2_rect *compose) { - struct v4l2_mbus_framefmt fmt_src; const struct imx7_csi_pixfmt *cc; + if (compose) { + compose->width = pixfmt->width; + compose->height = pixfmt->height; + } + /* * Find the pixel format, default to the first supported format if not * found. @@ -1172,13 +1176,17 @@ __imx7_csi_video_try_fmt(struct v4l2_pix_format *pixfmt, } } - v4l2_fill_mbus_format(&fmt_src, pixfmt, 0); - imx7_csi_mbus_fmt_to_pix_fmt(pixfmt, &fmt_src, cc); + /* + * Round up width for minimum burst size. + * + * TODO: Implement configurable stride support, and check what the real + * hardware alignment constraint on the width is. + */ + v4l_bound_align_image(&pixfmt->width, 1, 0xffff, 8, + &pixfmt->height, 1, 0xffff, 1, 0); - if (compose) { - compose->width = fmt_src.width; - compose->height = fmt_src.height; - } + pixfmt->bytesperline = pixfmt->width * cc->bpp / 8; + pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; return cc; } From 79bb4c7df8af769615a1f049aa85cbe6ecc84ec6 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Wed, 19 Apr 2023 09:07:10 +0200 Subject: [PATCH 088/253] media: imx: imx7-media-csi: Remove incorrect interlacing support The driver doesn't currently support interlacing, but due to legacy leftovers, it accepts values for the pixel format "field" field other than V4L2_FIELD_NONE. Fix it by hardcoding V4L2_FIELD_NONE. Proper interlacing support can be implemented later if desired. Signed-off-by: Alexander Stein Reviewed-by: Laurent Pinchart Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/platform/nxp/imx7-media-csi.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/media/platform/nxp/imx7-media-csi.c b/drivers/media/platform/nxp/imx7-media-csi.c index b149374b07ee..1315f5743b76 100644 --- a/drivers/media/platform/nxp/imx7-media-csi.c +++ b/drivers/media/platform/nxp/imx7-media-csi.c @@ -1162,20 +1162,6 @@ __imx7_csi_video_try_fmt(struct v4l2_pix_format *pixfmt, cc = imx7_csi_find_pixel_format(pixfmt->pixelformat); } - /* Allow IDMAC interweave but enforce field order from source. */ - if (V4L2_FIELD_IS_INTERLACED(pixfmt->field)) { - switch (pixfmt->field) { - case V4L2_FIELD_SEQ_TB: - pixfmt->field = V4L2_FIELD_INTERLACED_TB; - break; - case V4L2_FIELD_SEQ_BT: - pixfmt->field = V4L2_FIELD_INTERLACED_BT; - break; - default: - break; - } - } - /* * Round up width for minimum burst size. * @@ -1187,6 +1173,7 @@ __imx7_csi_video_try_fmt(struct v4l2_pix_format *pixfmt, pixfmt->bytesperline = pixfmt->width * cc->bpp / 8; pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; + pixfmt->field = V4L2_FIELD_NONE; return cc; } From bef1bb620ca6932950dc7897412acb09de525c33 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Wed, 19 Apr 2023 09:07:11 +0200 Subject: [PATCH 089/253] media: imx: imx7-media-csi: Relax width constraints for non-8bpp formats The driver unconditionally aligns the image width to multiples of 8 pixels. The real alignment constraint is 8 bytes, as indicated by the CSI_IMAG_PARA.IMAGE_WIDTH documentation that calls for 8 pixel alignment for 8bpp formats and 4 pixel alignment for other formats. Signed-off-by: Alexander Stein Reviewed-by: Laurent Pinchart Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/platform/nxp/imx7-media-csi.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/nxp/imx7-media-csi.c b/drivers/media/platform/nxp/imx7-media-csi.c index 1315f5743b76..e6abbfbc5c12 100644 --- a/drivers/media/platform/nxp/imx7-media-csi.c +++ b/drivers/media/platform/nxp/imx7-media-csi.c @@ -1146,6 +1146,7 @@ __imx7_csi_video_try_fmt(struct v4l2_pix_format *pixfmt, struct v4l2_rect *compose) { const struct imx7_csi_pixfmt *cc; + u32 walign; if (compose) { compose->width = pixfmt->width; @@ -1163,12 +1164,13 @@ __imx7_csi_video_try_fmt(struct v4l2_pix_format *pixfmt, } /* - * Round up width for minimum burst size. + * The width alignment is 8 bytes as indicated by the + * CSI_IMAG_PARA.IMAGE_WIDTH documentation. Convert it to pixels. * - * TODO: Implement configurable stride support, and check what the real - * hardware alignment constraint on the width is. + * TODO: Implement configurable stride support. */ - v4l_bound_align_image(&pixfmt->width, 1, 0xffff, 8, + walign = 8 * 8 / cc->bpp; + v4l_bound_align_image(&pixfmt->width, 1, 0xffff, walign, &pixfmt->height, 1, 0xffff, 1, 0); pixfmt->bytesperline = pixfmt->width * cc->bpp / 8; From 9f43234ef07c5d1978b02e5996927c110666d96e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 19 Apr 2023 09:07:12 +0200 Subject: [PATCH 090/253] media: imx: imx7-media-csi: Init default format with __imx7_csi_video_try_fmt() Use the __imx7_csi_video_try_fmt() helper function to initialize the default format at probe time. This improves consistency by using the same code path for both default initialization and validation at runtime, and allows dropping the now unused imx7_csi_find_pixel_format() function. Signed-off-by: Laurent Pinchart Signed-off-by: Alexander Stein Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/platform/nxp/imx7-media-csi.c | 55 +++------------------ 1 file changed, 6 insertions(+), 49 deletions(-) diff --git a/drivers/media/platform/nxp/imx7-media-csi.c b/drivers/media/platform/nxp/imx7-media-csi.c index e6abbfbc5c12..0bd2613b9320 100644 --- a/drivers/media/platform/nxp/imx7-media-csi.c +++ b/drivers/media/platform/nxp/imx7-media-csi.c @@ -1014,39 +1014,6 @@ static int imx7_csi_enum_mbus_formats(u32 *code, u32 index) return -EINVAL; } -static int imx7_csi_mbus_fmt_to_pix_fmt(struct v4l2_pix_format *pix, - const struct v4l2_mbus_framefmt *mbus, - const struct imx7_csi_pixfmt *cc) -{ - u32 width; - u32 stride; - - if (!cc) { - cc = imx7_csi_find_mbus_format(mbus->code); - if (!cc) - return -EINVAL; - } - - /* Round up width for minimum burst size */ - width = round_up(mbus->width, 8); - - /* Round up stride for IDMAC line start address alignment */ - stride = round_up((width * cc->bpp) >> 3, 8); - - pix->width = width; - pix->height = mbus->height; - pix->pixelformat = cc->fourcc; - pix->colorspace = mbus->colorspace; - pix->xfer_func = mbus->xfer_func; - pix->ycbcr_enc = mbus->ycbcr_enc; - pix->quantization = mbus->quantization; - pix->field = mbus->field; - pix->bytesperline = stride; - pix->sizeimage = stride * pix->height; - - return 0; -} - /* ----------------------------------------------------------------------------- * Video Capture Device - IOCTLs */ @@ -1603,22 +1570,14 @@ static struct imx7_csi_vb2_buffer *imx7_csi_video_next_buf(struct imx7_csi *csi) return buf; } -static int imx7_csi_video_init_format(struct imx7_csi *csi) +static void imx7_csi_video_init_format(struct imx7_csi *csi) { - struct v4l2_mbus_framefmt format = { }; + struct v4l2_pix_format *pixfmt = &csi->vdev_fmt; - format.code = IMX7_CSI_DEF_MBUS_CODE; - format.width = IMX7_CSI_DEF_PIX_WIDTH; - format.height = IMX7_CSI_DEF_PIX_HEIGHT; - format.field = V4L2_FIELD_NONE; + pixfmt->width = IMX7_CSI_DEF_PIX_WIDTH; + pixfmt->height = IMX7_CSI_DEF_PIX_HEIGHT; - imx7_csi_mbus_fmt_to_pix_fmt(&csi->vdev_fmt, &format, NULL); - csi->vdev_compose.width = format.width; - csi->vdev_compose.height = format.height; - - csi->vdev_cc = imx7_csi_find_pixel_format(csi->vdev_fmt.pixelformat); - - return 0; + csi->vdev_cc = __imx7_csi_video_try_fmt(pixfmt, &csi->vdev_compose); } static int imx7_csi_video_register(struct imx7_csi *csi) @@ -1631,9 +1590,7 @@ static int imx7_csi_video_register(struct imx7_csi *csi) vdev->v4l2_dev = v4l2_dev; /* Initialize the default format and compose rectangle. */ - ret = imx7_csi_video_init_format(csi); - if (ret < 0) - return ret; + imx7_csi_video_init_format(csi); /* Register the video device. */ ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); From 6311a0d0220f18c436391b75a5c217f9d27b9b49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Sat, 11 Feb 2023 15:46:14 +0100 Subject: [PATCH 091/253] media: staging: max96712: Add support for 3-lane C-PHY MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add basic support for outputting the test patterns on a 3-lane CSI-2 C-PHY bus. As the driver only can output frames form its internal test pattern generator, enabling C-PHY output is as simple as setting the output mode to C-PHY instead of D-PHY. Signed-off-by: Niklas Söderlund [Sakari Ailus: Wrap long lines.] Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/staging/media/max96712/max96712.c | 38 +++++++++++++++++++---- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/drivers/staging/media/max96712/max96712.c b/drivers/staging/media/max96712/max96712.c index 99b333b68198..ce4ebb63d54d 100644 --- a/drivers/staging/media/max96712/max96712.c +++ b/drivers/staging/media/max96712/max96712.c @@ -30,6 +30,7 @@ struct max96712_priv { struct regmap *regmap; struct gpio_desc *gpiod_pwdn; + bool cphy; struct v4l2_mbus_config_mipi_csi2 mipi; struct v4l2_subdev sd; @@ -127,10 +128,18 @@ static void max96712_mipi_configure(struct max96712_priv *priv) /* Select 2x4 mode. */ max96712_write(priv, 0x8a0, 0x04); - /* Configure a 4-lane DPHY using PHY0 and PHY1. */ /* TODO: Add support for 2-lane and 1-lane configurations. */ - /* TODO: Add support CPHY mode. */ - max96712_write(priv, 0x94a, 0xc0); + if (priv->cphy) { + /* Configure a 3-lane C-PHY using PHY0 and PHY1. */ + max96712_write(priv, 0x94a, 0xa0); + + /* Configure C-PHY timings. */ + max96712_write(priv, 0x8ad, 0x3f); + max96712_write(priv, 0x8ae, 0x7d); + } else { + /* Configure a 4-lane D-PHY using PHY0 and PHY1. */ + max96712_write(priv, 0x94a, 0xc0); + } /* Configure lane mapping for PHY0 and PHY1. */ /* TODO: Add support for lane swapping. */ @@ -332,8 +341,9 @@ static int max96712_parse_dt(struct max96712_priv *priv) { struct fwnode_handle *ep; struct v4l2_fwnode_endpoint v4l2_ep = { - .bus_type = V4L2_MBUS_CSI2_DPHY + .bus_type = V4L2_MBUS_UNKNOWN, }; + unsigned int supported_lanes; int ret; ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(&priv->client->dev), 4, @@ -350,8 +360,24 @@ static int max96712_parse_dt(struct max96712_priv *priv) return -EINVAL; } - if (v4l2_ep.bus.mipi_csi2.num_data_lanes != 4) { - dev_err(&priv->client->dev, "Only 4 data lanes supported\n"); + switch (v4l2_ep.bus_type) { + case V4L2_MBUS_CSI2_DPHY: + supported_lanes = 4; + priv->cphy = false; + break; + case V4L2_MBUS_CSI2_CPHY: + supported_lanes = 3; + priv->cphy = true; + break; + default: + dev_err(&priv->client->dev, "Unsupported bus-type %u\n", + v4l2_ep.bus_type); + return -EINVAL; + } + + if (v4l2_ep.bus.mipi_csi2.num_data_lanes != supported_lanes) { + dev_err(&priv->client->dev, "Only %u data lanes supported\n", + supported_lanes); return -EINVAL; } From 8e85c1ad3d49f5a51947d74b66b7b6a255fd370c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Sat, 11 Feb 2023 15:54:36 +0100 Subject: [PATCH 092/253] media: rcar-isp: Add support for R-Car V4H MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for R-Car V4H. The ISP Channel Selector is used to route channels to the different VIN modules. The ISP CS found in the V4H is very similar to the one found on the V3U. Signed-off-by: Niklas Söderlund Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/platform/renesas/rcar-isp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/renesas/rcar-isp.c b/drivers/media/platform/renesas/rcar-isp.c index f666b621338d..fee1a066f56b 100644 --- a/drivers/media/platform/renesas/rcar-isp.c +++ b/drivers/media/platform/renesas/rcar-isp.c @@ -430,6 +430,7 @@ static int risp_probe_resources(struct rcar_isp *isp, static const struct of_device_id risp_of_id_table[] = { { .compatible = "renesas,r8a779a0-isp" }, + { .compatible = "renesas,r8a779g0-isp" }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, risp_of_id_table); From a650b821fa57989deab9f7274a33af6ffab28e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Sat, 11 Feb 2023 15:55:19 +0100 Subject: [PATCH 093/253] media: rcar-vin: Add support for R-Car V4H MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for R-Car V4H. The V4H uses the ISP Channel Selector as its only possible video input source. Even tho V4H is a Gen3 board the VIN interface is very close to the one found on the V3U, for this reason mark it as a Gen3 model internally. Signed-off-by: Niklas Söderlund Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/platform/renesas/rcar-vin/rcar-core.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-core.c b/drivers/media/platform/renesas/rcar-vin/rcar-core.c index ff4bde9cc0e3..3c4f5eb93be1 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-core.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-core.c @@ -1284,6 +1284,15 @@ static const struct rvin_info rcar_info_r8a779a0 = { .max_height = 4096, }; +static const struct rvin_info rcar_info_r8a779g0 = { + .model = RCAR_GEN3, + .use_mc = true, + .use_isp = true, + .nv12 = true, + .max_width = 4096, + .max_height = 4096, +}; + static const struct of_device_id rvin_of_id_table[] = { { .compatible = "renesas,vin-r8a774a1", @@ -1349,6 +1358,10 @@ static const struct of_device_id rvin_of_id_table[] = { .compatible = "renesas,vin-r8a779a0", .data = &rcar_info_r8a779a0, }, + { + .compatible = "renesas,vin-r8a779g0", + .data = &rcar_info_r8a779g0, + }, { /* Sentinel */ }, }; MODULE_DEVICE_TABLE(of, rvin_of_id_table); From 7d4be90b3deb6b32fb99644a158e6cff0a0520f4 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 3 Feb 2023 15:13:48 -0800 Subject: [PATCH 094/253] media: c8sectpfe: switch to using gpiod API This switches the driver from using legacy gpio API and to the newer gpiod API. Since ordinary gpiod APIs operate on logical and not electrical levels, handling of the reset GPIO is adjusted accordingly. Signed-off-by: Dmitry Torokhov Reviewed-by: Andy Shevchenko Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- .../st/sti/c8sectpfe/c8sectpfe-core.c | 31 ++++++++----------- .../st/sti/c8sectpfe/c8sectpfe-core.h | 4 ++- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c index 120830973d22..03d5d6eac473 100644 --- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c +++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c @@ -16,8 +16,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -812,30 +814,23 @@ static int c8sectpfe_probe(struct platform_device *pdev) } of_node_put(i2c_bus); - tsin->rst_gpio = of_get_named_gpio(child, "reset-gpios", 0); - - ret = gpio_is_valid(tsin->rst_gpio); - if (!ret) { - dev_err(dev, - "reset gpio for tsin%d not valid (gpio=%d)\n", - tsin->tsin_id, tsin->rst_gpio); - ret = -EINVAL; - goto err_node_put; - } - - ret = devm_gpio_request_one(dev, tsin->rst_gpio, - GPIOF_OUT_INIT_LOW, "NIM reset"); + /* Acquire reset GPIO and activate it */ + tsin->rst_gpio = devm_fwnode_gpiod_get(dev, + of_fwnode_handle(child), + "reset", GPIOD_OUT_HIGH, + "NIM reset"); + ret = PTR_ERR_OR_ZERO(tsin->rst_gpio); if (ret && ret != -EBUSY) { - dev_err(dev, "Can't request tsin%d reset gpio\n" - , fei->channel_data[index]->tsin_id); + dev_err(dev, "Can't request tsin%d reset gpio\n", + fei->channel_data[index]->tsin_id); goto err_node_put; } if (!ret) { - /* toggle reset lines */ - gpio_direction_output(tsin->rst_gpio, 0); + /* wait for the chip to reset */ usleep_range(3500, 5000); - gpio_direction_output(tsin->rst_gpio, 1); + /* release the reset line */ + gpiod_set_value_cansleep(tsin->rst_gpio, 0); usleep_range(3000, 5000); } diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h index c9d6021904cd..bf377cc82225 100644 --- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h +++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.h @@ -16,6 +16,8 @@ #define C8SECTPFE_MAX_TSIN_CHAN 8 +struct gpio_desc; + struct channel_info { int tsin_id; @@ -25,7 +27,7 @@ struct channel_info { int i2c; int dvb_card; - int rst_gpio; + struct gpio_desc *rst_gpio; struct i2c_adapter *i2c_adapter; struct i2c_adapter *tuner_i2c; From 11aaa0ec9c1848bb68df9c7e6eedab6d5b0a3cca Mon Sep 17 00:00:00 2001 From: Alain Volmat Date: Sat, 4 Feb 2023 21:29:40 +0100 Subject: [PATCH 095/253] media: sti: c8sectpfe: drop of_match_ptr() to avoid unused variables When CONFIG_OF is not set, "of_match_ptr()" compiles to NULL, which leaves unused, leading to warning such as: drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c:1175:34: warning: unused variable 'c8sectpfe_match' [-Wunused-const-variable] Drop the of_match_ptr usage to avoid such warning. Reported-by: kernel test robot Signed-off-by: Alain Volmat Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c index 03d5d6eac473..5dc1f908b49b 100644 --- a/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c +++ b/drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c @@ -1168,7 +1168,7 @@ MODULE_DEVICE_TABLE(of, c8sectpfe_match); static struct platform_driver c8sectpfe_driver = { .driver = { .name = "c8sectpfe", - .of_match_table = of_match_ptr(c8sectpfe_match), + .of_match_table = c8sectpfe_match, }, .probe = c8sectpfe_probe, .remove_new = c8sectpfe_remove, From 2a7d6b9c55baabfbad03946f2b0c695df72cfb06 Mon Sep 17 00:00:00 2001 From: Vaishnav Achath Date: Fri, 21 Apr 2023 11:04:30 +0100 Subject: [PATCH 096/253] media: v4l2-mc: Drop subdev check in v4l2_create_fwnode_links_to_pad() While updating v4l2_create_fwnode_links_to_pad() to accept non-subdev sinks, the check is_media_entity_v4l2_subdev() was not removed which prevented the function from being used with non-subdev sinks, Drop the unnecessary check. Fixes: bd5a03bc5be8 ("media: Accept non-subdev sinks in v4l2_create_fwnode_links_to_pad()") Signed-off-by: Vaishnav Achath Reviewed-by: Laurent Pinchart Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-mc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c index 209a7efd08fe..52d349e72b8c 100644 --- a/drivers/media/v4l2-core/v4l2-mc.c +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -326,8 +326,7 @@ int v4l2_create_fwnode_links_to_pad(struct v4l2_subdev *src_sd, { struct fwnode_handle *endpoint; - if (!(sink->flags & MEDIA_PAD_FL_SINK) || - !is_media_entity_v4l2_subdev(sink->entity)) + if (!(sink->flags & MEDIA_PAD_FL_SINK)) return -EINVAL; fwnode_graph_for_each_endpoint(dev_fwnode(src_sd->dev), endpoint) { From 2f16c95e7aa9716f7332b30d578dc496399d7d8f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 18 Apr 2023 08:46:52 +0100 Subject: [PATCH 097/253] media: staging: media: imx: initialize hs_settle to avoid warning Initialize hs_settle to 0 to avoid this compiler warning: imx8mq-mipi-csi2.c: In function 'imx8mq_mipi_csi_start_stream.part.0': imx8mq-mipi-csi2.c:91:55: warning: 'hs_settle' may be used uninitialized [-Wmaybe-uninitialized] 91 | #define GPR_CSI2_1_S_PRG_RXHS_SETTLE(x) (((x) & 0x3f) << 2) | ^~ imx8mq-mipi-csi2.c:357:13: note: 'hs_settle' was declared here 357 | u32 hs_settle; | ^~~~~~~~~ It's a false positive, but it is too complicated for the compiler to detect that. Signed-off-by: Hans Verkuil Reviewed-by: Martin Kepplinger Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx8mq-mipi-csi2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/imx/imx8mq-mipi-csi2.c b/drivers/staging/media/imx/imx8mq-mipi-csi2.c index 32700cb8bc4d..ca2efcc21efe 100644 --- a/drivers/staging/media/imx/imx8mq-mipi-csi2.c +++ b/drivers/staging/media/imx/imx8mq-mipi-csi2.c @@ -354,7 +354,7 @@ static int imx8mq_mipi_csi_start_stream(struct csi_state *state, struct v4l2_subdev_state *sd_state) { int ret; - u32 hs_settle; + u32 hs_settle = 0; ret = imx8mq_mipi_csi_sw_reset(state); if (ret) From 15ff9e7f49bc107fce067d8b0ea5ebf4bd9fc9cf Mon Sep 17 00:00:00 2001 From: Yunfei Dong Date: Thu, 25 May 2023 02:40:06 +0100 Subject: [PATCH 098/253] media: mediatek: vcodec: Avoid unneeded error logging Since the LAT decoder works faster than its CORE, getting the trans buffer may be done only after CORE finishes processing: avoid printing an error if the decode function returns -EAGAIN, as this means that the buffer from CORE is not yet available, but will be at a later time. Also change the log level for calls to vdec_msg_queue_dqbuf() in H264 and VP9 LAT decoder drivers to avoid excessive logging. Signed-off-by: Yunfei Dong Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c | 2 +- .../platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c | 2 +- .../media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c index 995997f702a0..7b3eb0ccb522 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c @@ -292,7 +292,7 @@ static void mtk_vdec_worker(struct work_struct *work) mtk_v4l2_err("vb2 buffer media request is NULL"); ret = vdec_if_decode(ctx, bs_src, NULL, &res_chg); - if (ret) { + if (ret && ret != -EAGAIN) { mtk_v4l2_err(" <===[%d], src_buf[%d] sz=0x%zx pts=%llu vdec_if_decode() ret=%d res_chg=%d===>", ctx->id, vb2_src->index, bs_src->size, vb2_src->timestamp, ret, res_chg); diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c index 999ce7ee5fdc..181cc52e0847 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c @@ -596,7 +596,7 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, lat_buf = vdec_msg_queue_dqbuf(&inst->ctx->msg_queue.lat_ctx); if (!lat_buf) { - mtk_vcodec_err(inst, "failed to get lat buffer"); + mtk_vcodec_debug(inst, "failed to get lat buffer"); return -EAGAIN; } share_info = lat_buf->private_data; diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c index cf16cf2807f0..6d981d7341d2 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c @@ -2069,7 +2069,7 @@ static int vdec_vp9_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, lat_buf = vdec_msg_queue_dqbuf(&instance->ctx->msg_queue.lat_ctx); if (!lat_buf) { - mtk_vcodec_err(instance, "Failed to get VP9 lat buf\n"); + mtk_vcodec_debug(instance, "Failed to get VP9 lat buf\n"); return -EAGAIN; } pfc = (struct vdec_vp9_slice_pfc *)lat_buf->private_data; From 2864e304faec04c2674328aad0e820a9cd84cdec Mon Sep 17 00:00:00 2001 From: Yunfei Dong Date: Thu, 25 May 2023 02:40:07 +0100 Subject: [PATCH 099/253] media: mediatek: vcodec: using decoder status instead of core work count Adding the definition of decoder status to separate different decoder period for core hardware. core_work_cnt is the number of core work queued to work queue, the control is very complex, leading to some unreasonable test result. Using parameter status to indicate whether queue core work to work queue. Fixes: 2e0ef56d81cb ("media: mediatek: vcodec: making sure queue_work successfully") Signed-off-by: Yunfei Dong Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../platform/mediatek/vcodec/vdec_msg_queue.c | 33 ++++++++----------- .../platform/mediatek/vcodec/vdec_msg_queue.h | 16 +++++++-- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c index f3073d1e7f42..03f8d7cd8edd 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c +++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c @@ -71,7 +71,6 @@ static void vdec_msg_queue_dec(struct vdec_msg_queue *msg_queue, int hardware_in int vdec_msg_queue_qbuf(struct vdec_msg_queue_ctx *msg_ctx, struct vdec_lat_buf *buf) { struct list_head *head; - int status; head = vdec_get_buf_list(msg_ctx->hardware_index, buf); if (!head) { @@ -87,12 +86,9 @@ int vdec_msg_queue_qbuf(struct vdec_msg_queue_ctx *msg_ctx, struct vdec_lat_buf if (msg_ctx->hardware_index != MTK_VDEC_CORE) { wake_up_all(&msg_ctx->ready_to_use); } else { - if (buf->ctx->msg_queue.core_work_cnt < - atomic_read(&buf->ctx->msg_queue.core_list_cnt)) { - status = queue_work(buf->ctx->dev->core_workqueue, - &buf->ctx->msg_queue.core_work); - if (status) - buf->ctx->msg_queue.core_work_cnt++; + if (!(buf->ctx->msg_queue.status & CONTEXT_LIST_QUEUED)) { + queue_work(buf->ctx->dev->core_workqueue, &buf->ctx->msg_queue.core_work); + buf->ctx->msg_queue.status |= CONTEXT_LIST_QUEUED; } } @@ -261,7 +257,10 @@ static void vdec_msg_queue_core_work(struct work_struct *work) container_of(msg_queue, struct mtk_vcodec_ctx, msg_queue); struct mtk_vcodec_dev *dev = ctx->dev; struct vdec_lat_buf *lat_buf; - int status; + + spin_lock(&ctx->dev->msg_queue_core_ctx.ready_lock); + ctx->msg_queue.status &= ~CONTEXT_LIST_QUEUED; + spin_unlock(&ctx->dev->msg_queue_core_ctx.ready_lock); lat_buf = vdec_msg_queue_dqbuf(&dev->msg_queue_core_ctx); if (!lat_buf) @@ -278,17 +277,13 @@ static void vdec_msg_queue_core_work(struct work_struct *work) vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf); wake_up_all(&ctx->msg_queue.core_dec_done); - spin_lock(&dev->msg_queue_core_ctx.ready_lock); - lat_buf->ctx->msg_queue.core_work_cnt--; - - if (lat_buf->ctx->msg_queue.core_work_cnt < - atomic_read(&lat_buf->ctx->msg_queue.core_list_cnt)) { - status = queue_work(lat_buf->ctx->dev->core_workqueue, - &lat_buf->ctx->msg_queue.core_work); - if (status) - lat_buf->ctx->msg_queue.core_work_cnt++; + if (!(ctx->msg_queue.status & CONTEXT_LIST_QUEUED) && + atomic_read(&msg_queue->core_list_cnt)) { + spin_lock(&ctx->dev->msg_queue_core_ctx.ready_lock); + ctx->msg_queue.status |= CONTEXT_LIST_QUEUED; + spin_unlock(&ctx->dev->msg_queue_core_ctx.ready_lock); + queue_work(ctx->dev->core_workqueue, &msg_queue->core_work); } - spin_unlock(&dev->msg_queue_core_ctx.ready_lock); } int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue, @@ -303,13 +298,13 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue, return 0; msg_queue->ctx = ctx; - msg_queue->core_work_cnt = 0; vdec_msg_queue_init_ctx(&msg_queue->lat_ctx, MTK_VDEC_LAT0); INIT_WORK(&msg_queue->core_work, vdec_msg_queue_core_work); atomic_set(&msg_queue->lat_list_cnt, 0); atomic_set(&msg_queue->core_list_cnt, 0); init_waitqueue_head(&msg_queue->core_dec_done); + msg_queue->status = CONTEXT_LIST_EMPTY; msg_queue->wdma_addr.size = vde_msg_queue_get_trans_size(ctx->picinfo.buf_w, diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h index a5d44bc97c16..8f82d1484772 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h +++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h @@ -21,6 +21,18 @@ struct mtk_vcodec_ctx; struct mtk_vcodec_dev; typedef int (*core_decode_cb_t)(struct vdec_lat_buf *lat_buf); +/** + * enum core_ctx_status - Context decode status for core hardwre. + * @CONTEXT_LIST_EMPTY: No buffer queued on core hardware(must always be 0) + * @CONTEXT_LIST_QUEUED: Buffer queued to core work list + * @CONTEXT_LIST_DEC_DONE: context decode done + */ +enum core_ctx_status { + CONTEXT_LIST_EMPTY = 0, + CONTEXT_LIST_QUEUED, + CONTEXT_LIST_DEC_DONE, +}; + /** * struct vdec_msg_queue_ctx - represents a queue for buffers ready to be processed * @ready_to_use: ready used queue used to signalize when get a job queue @@ -77,7 +89,7 @@ struct vdec_lat_buf { * @lat_list_cnt: used to record each instance lat list count * @core_list_cnt: used to record each instance core list count * @core_dec_done: core work queue decode done event - * @core_work_cnt: the number of core work in work queue + * @status: current context decode status for core hardware */ struct vdec_msg_queue { struct vdec_lat_buf lat_buf[NUM_BUFFER_COUNT]; @@ -93,7 +105,7 @@ struct vdec_msg_queue { atomic_t lat_list_cnt; atomic_t core_list_cnt; wait_queue_head_t core_dec_done; - int core_work_cnt; + int status; }; /** From 297160d411e3271c5a6c7df2edda30a1508afb34 Mon Sep 17 00:00:00 2001 From: Yunfei Dong Date: Thu, 25 May 2023 02:40:08 +0100 Subject: [PATCH 100/253] media: mediatek: vcodec: move core context from device to each instance There are so many lat buffer in core context list, some instances maybe be scheduled for a very long time. Moving the core context to each instance, it only be used to control lat buffer of each instance. And the core work queue of each instance is scheduled by system. Fixes: 2cfca6c1bf80 ("media: mediatek: vcodec: move lat_buf to the top of core list") Signed-off-by: Yunfei Dong Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../mediatek/vcodec/mtk_vcodec_dec_drv.c | 1 - .../platform/mediatek/vcodec/mtk_vcodec_drv.h | 2 - .../vcodec/vdec/vdec_h264_req_multi_if.c | 4 +- .../vcodec/vdec/vdec_hevc_req_multi_if.c | 4 +- .../vcodec/vdec/vdec_vp9_req_lat_if.c | 2 +- .../platform/mediatek/vcodec/vdec_msg_queue.c | 55 +++++++------------ .../platform/mediatek/vcodec/vdec_msg_queue.h | 4 +- 7 files changed, 26 insertions(+), 46 deletions(-) diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c index 9c652beb3f19..7bd300341cf0 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c @@ -310,7 +310,6 @@ static int mtk_vcodec_probe(struct platform_device *pdev) } if (IS_VDEC_LAT_ARCH(dev->vdec_pdata->hw_arch)) { - vdec_msg_queue_init_ctx(&dev->msg_queue_core_ctx, MTK_VDEC_CORE); dev->core_workqueue = alloc_ordered_workqueue("core-decoder", WQ_MEM_RECLAIM | WQ_FREEZABLE); diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h index 144252fa8bea..1f4c5774ec47 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h @@ -462,7 +462,6 @@ struct mtk_vcodec_enc_pdata { * @enc_capability: used to identify encode capability * * @core_workqueue: queue used for core hardware decode - * @msg_queue_core_ctx: msg queue context used for core workqueue * * @subdev_dev: subdev hardware device * @subdev_prob_done: check whether all used hw device is prob done @@ -511,7 +510,6 @@ struct mtk_vcodec_dev { unsigned int enc_capability; struct workqueue_struct *core_workqueue; - struct vdec_msg_queue_ctx msg_queue_core_ctx; void *subdev_dev[MTK_VDEC_HW_MAX]; int (*subdev_prob_done)(struct mtk_vcodec_dev *vdec_dev); diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c index 181cc52e0847..a7e8e3257b7f 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c @@ -672,7 +672,7 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, if (IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) { memcpy(&share_info->h264_slice_params, &inst->vsi->h264_slice_params, sizeof(share_info->h264_slice_params)); - vdec_msg_queue_qbuf(&inst->ctx->dev->msg_queue_core_ctx, lat_buf); + vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf); } /* wait decoder done interrupt */ @@ -698,7 +698,7 @@ static int vdec_h264_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) { memcpy(&share_info->h264_slice_params, &inst->vsi->h264_slice_params, sizeof(share_info->h264_slice_params)); - vdec_msg_queue_qbuf(&inst->ctx->dev->msg_queue_core_ctx, lat_buf); + vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf); } mtk_vcodec_debug(inst, "dec num: %d lat crc: 0x%x 0x%x 0x%x", inst->slice_dec_num, inst->vsi->dec.crc[0], inst->vsi->dec.crc[1], inst->vsi->dec.crc[2]); diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_hevc_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_hevc_req_multi_if.c index e8758e5db961..1e6ab138b0bb 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_hevc_req_multi_if.c +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_hevc_req_multi_if.c @@ -1017,7 +1017,7 @@ static int vdec_hevc_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, if (IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) { memcpy(&share_info->hevc_slice_params, &inst->vsi->hevc_slice_params, sizeof(share_info->hevc_slice_params)); - vdec_msg_queue_qbuf(&inst->ctx->dev->msg_queue_core_ctx, lat_buf); + vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf); } /* wait decoder done interrupt */ @@ -1043,7 +1043,7 @@ static int vdec_hevc_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, if (!IS_VDEC_INNER_RACING(inst->ctx->dev->dec_capability)) { memcpy(&share_info->hevc_slice_params, &inst->vsi->hevc_slice_params, sizeof(share_info->hevc_slice_params)); - vdec_msg_queue_qbuf(&inst->ctx->dev->msg_queue_core_ctx, lat_buf); + vdec_msg_queue_qbuf(&inst->ctx->msg_queue.core_ctx, lat_buf); } mtk_vcodec_debug(inst, "dec num: %d lat crc: 0x%x 0x%x 0x%x", inst->slice_dec_num, inst->vsi->dec.crc[0], inst->vsi->dec.crc[1], inst->vsi->dec.crc[2]); diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c index 6d981d7341d2..c2f90848f498 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c @@ -2119,7 +2119,7 @@ static int vdec_vp9_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, vdec_msg_queue_update_ube_wptr(&ctx->msg_queue, vsi->trans.dma_addr_end + ctx->msg_queue.wdma_addr.dma_addr); - vdec_msg_queue_qbuf(&ctx->dev->msg_queue_core_ctx, lat_buf); + vdec_msg_queue_qbuf(&ctx->msg_queue.core_ctx, lat_buf); return 0; err_free_fb_out: diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c index 03f8d7cd8edd..3f571cbc8331 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c +++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c @@ -177,29 +177,20 @@ void vdec_msg_queue_update_ube_wptr(struct vdec_msg_queue *msg_queue, uint64_t u bool vdec_msg_queue_wait_lat_buf_full(struct vdec_msg_queue *msg_queue) { - struct vdec_lat_buf *buf, *tmp; - struct list_head *list_core[3]; - struct vdec_msg_queue_ctx *core_ctx; - int ret, i, in_core_count = 0, count = 0; + int ret; long timeout_jiff; - core_ctx = &msg_queue->ctx->dev->msg_queue_core_ctx; - spin_lock(&core_ctx->ready_lock); - list_for_each_entry_safe(buf, tmp, &core_ctx->ready_queue, core_list) { - if (buf && buf->ctx == msg_queue->ctx) { - list_core[in_core_count++] = &buf->core_list; - list_del(&buf->core_list); - } + if (atomic_read(&msg_queue->lat_list_cnt) == NUM_BUFFER_COUNT) { + mtk_v4l2_debug(3, "wait buf full: list(%d %d) ready_num:%d status:%d", + atomic_read(&msg_queue->lat_list_cnt), + atomic_read(&msg_queue->core_list_cnt), + msg_queue->lat_ctx.ready_num, + msg_queue->status); + return true; } - for (i = 0; i < in_core_count; i++) { - list_add(list_core[in_core_count - (1 + i)], &core_ctx->ready_queue); - queue_work(msg_queue->ctx->dev->core_workqueue, &msg_queue->core_work); - } - spin_unlock(&core_ctx->ready_lock); - timeout_jiff = msecs_to_jiffies(1000 * (NUM_BUFFER_COUNT + 2)); - ret = wait_event_timeout(msg_queue->ctx->msg_queue.core_dec_done, + ret = wait_event_timeout(msg_queue->core_dec_done, msg_queue->lat_ctx.ready_num == NUM_BUFFER_COUNT, timeout_jiff); if (ret) { @@ -208,18 +199,9 @@ bool vdec_msg_queue_wait_lat_buf_full(struct vdec_msg_queue *msg_queue) return true; } - spin_lock(&core_ctx->ready_lock); - list_for_each_entry_safe(buf, tmp, &core_ctx->ready_queue, core_list) { - if (buf && buf->ctx == msg_queue->ctx) { - count++; - list_del(&buf->core_list); - } - } - spin_unlock(&core_ctx->ready_lock); - - mtk_v4l2_err("failed with lat buf isn't full: list(%d %d) count:%d", + mtk_v4l2_err("failed with lat buf isn't full: list(%d %d)", atomic_read(&msg_queue->lat_list_cnt), - atomic_read(&msg_queue->core_list_cnt), count); + atomic_read(&msg_queue->core_list_cnt)); return false; } @@ -247,6 +229,8 @@ void vdec_msg_queue_deinit(struct vdec_msg_queue *msg_queue, kfree(lat_buf->private_data); } + + cancel_work_sync(&msg_queue->core_work); } static void vdec_msg_queue_core_work(struct work_struct *work) @@ -258,11 +242,11 @@ static void vdec_msg_queue_core_work(struct work_struct *work) struct mtk_vcodec_dev *dev = ctx->dev; struct vdec_lat_buf *lat_buf; - spin_lock(&ctx->dev->msg_queue_core_ctx.ready_lock); + spin_lock(&msg_queue->core_ctx.ready_lock); ctx->msg_queue.status &= ~CONTEXT_LIST_QUEUED; - spin_unlock(&ctx->dev->msg_queue_core_ctx.ready_lock); + spin_unlock(&msg_queue->core_ctx.ready_lock); - lat_buf = vdec_msg_queue_dqbuf(&dev->msg_queue_core_ctx); + lat_buf = vdec_msg_queue_dqbuf(&msg_queue->core_ctx); if (!lat_buf) return; @@ -276,12 +260,11 @@ static void vdec_msg_queue_core_work(struct work_struct *work) mtk_vcodec_dec_disable_hardware(ctx, MTK_VDEC_CORE); vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf); - wake_up_all(&ctx->msg_queue.core_dec_done); if (!(ctx->msg_queue.status & CONTEXT_LIST_QUEUED) && atomic_read(&msg_queue->core_list_cnt)) { - spin_lock(&ctx->dev->msg_queue_core_ctx.ready_lock); + spin_lock(&msg_queue->core_ctx.ready_lock); ctx->msg_queue.status |= CONTEXT_LIST_QUEUED; - spin_unlock(&ctx->dev->msg_queue_core_ctx.ready_lock); + spin_unlock(&msg_queue->core_ctx.ready_lock); queue_work(ctx->dev->core_workqueue, &msg_queue->core_work); } } @@ -297,8 +280,8 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue, if (msg_queue->wdma_addr.size) return 0; - msg_queue->ctx = ctx; vdec_msg_queue_init_ctx(&msg_queue->lat_ctx, MTK_VDEC_LAT0); + vdec_msg_queue_init_ctx(&msg_queue->core_ctx, MTK_VDEC_CORE); INIT_WORK(&msg_queue->core_work, vdec_msg_queue_core_work); atomic_set(&msg_queue->lat_list_cnt, 0); diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h index 8f82d1484772..efc94165e016 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h +++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h @@ -84,7 +84,7 @@ struct vdec_lat_buf { * @wdma_wptr_addr: ube write point * @core_work: core hardware work * @lat_ctx: used to store lat buffer list - * @ctx: point to mtk_vcodec_ctx + * @core_ctx: used to store core buffer list * * @lat_list_cnt: used to record each instance lat list count * @core_list_cnt: used to record each instance core list count @@ -100,7 +100,7 @@ struct vdec_msg_queue { struct work_struct core_work; struct vdec_msg_queue_ctx lat_ctx; - struct mtk_vcodec_ctx *ctx; + struct vdec_msg_queue_ctx core_ctx; atomic_t lat_list_cnt; atomic_t core_list_cnt; From 962508e31c77de6daee780233084e521b9724cd0 Mon Sep 17 00:00:00 2001 From: Yunfei Dong Date: Thu, 25 May 2023 02:40:09 +0100 Subject: [PATCH 101/253] media: mediatek: vcodec: using empty lat buffer as the last one Adding one empty lat buffer with parameter 'is_empty_flag = true' used to flush core work queue decode. Queue the empty lat buffer to core list when driver need to flush decode. It's mean core already decode all existed lat buffer when get empty lat buffer, then wake up core decode done event, the driver will exit when getting core dec done event. Fixes: d227af847ac2 ("media: mediatek: vcodec: add core decode done event") Signed-off-by: Yunfei Dong Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../platform/mediatek/vcodec/vdec_msg_queue.c | 35 +++++++++++-------- .../platform/mediatek/vcodec/vdec_msg_queue.h | 8 +++++ 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c index 3f571cbc8331..66b4175601e3 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c +++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c @@ -177,9 +177,6 @@ void vdec_msg_queue_update_ube_wptr(struct vdec_msg_queue *msg_queue, uint64_t u bool vdec_msg_queue_wait_lat_buf_full(struct vdec_msg_queue *msg_queue) { - int ret; - long timeout_jiff; - if (atomic_read(&msg_queue->lat_list_cnt) == NUM_BUFFER_COUNT) { mtk_v4l2_debug(3, "wait buf full: list(%d %d) ready_num:%d status:%d", atomic_read(&msg_queue->lat_list_cnt), @@ -189,19 +186,14 @@ bool vdec_msg_queue_wait_lat_buf_full(struct vdec_msg_queue *msg_queue) return true; } - timeout_jiff = msecs_to_jiffies(1000 * (NUM_BUFFER_COUNT + 2)); - ret = wait_event_timeout(msg_queue->core_dec_done, - msg_queue->lat_ctx.ready_num == NUM_BUFFER_COUNT, - timeout_jiff); - if (ret) { - mtk_v4l2_debug(3, "success to get lat buf: %d", - msg_queue->lat_ctx.ready_num); - return true; - } + msg_queue->flush_done = false; + vdec_msg_queue_qbuf(&msg_queue->core_ctx, &msg_queue->empty_lat_buf); + wait_event(msg_queue->core_dec_done, msg_queue->flush_done); - mtk_v4l2_err("failed with lat buf isn't full: list(%d %d)", - atomic_read(&msg_queue->lat_list_cnt), - atomic_read(&msg_queue->core_list_cnt)); + mtk_v4l2_debug(3, "flush done => ready_num:%d status:%d list(%d %d)", + msg_queue->lat_ctx.ready_num, msg_queue->status, + atomic_read(&msg_queue->lat_list_cnt), + atomic_read(&msg_queue->core_list_cnt)); return false; } @@ -250,6 +242,14 @@ static void vdec_msg_queue_core_work(struct work_struct *work) if (!lat_buf) return; + if (lat_buf->is_last_frame) { + ctx->msg_queue.status = CONTEXT_LIST_DEC_DONE; + msg_queue->flush_done = true; + wake_up(&ctx->msg_queue.core_dec_done); + + return; + } + ctx = lat_buf->ctx; mtk_vcodec_dec_enable_hardware(ctx, MTK_VDEC_CORE); mtk_vcodec_set_curr_ctx(dev, ctx, MTK_VDEC_CORE); @@ -300,6 +300,10 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue, msg_queue->wdma_rptr_addr = msg_queue->wdma_addr.dma_addr; msg_queue->wdma_wptr_addr = msg_queue->wdma_addr.dma_addr; + msg_queue->empty_lat_buf.ctx = ctx; + msg_queue->empty_lat_buf.core_decode = NULL; + msg_queue->empty_lat_buf.is_last_frame = true; + for (i = 0; i < NUM_BUFFER_COUNT; i++) { lat_buf = &msg_queue->lat_buf[i]; @@ -325,6 +329,7 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue, lat_buf->ctx = ctx; lat_buf->core_decode = core_decode; + lat_buf->is_last_frame = false; err = vdec_msg_queue_qbuf(&msg_queue->lat_ctx, lat_buf); if (err) { mtk_v4l2_err("failed to qbuf buf[%d]", i); diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h index efc94165e016..8f771874f8e6 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h +++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h @@ -62,6 +62,8 @@ struct vdec_msg_queue_ctx { * @core_decode: different codec use different decode callback function * @lat_list: add lat buffer to lat head list * @core_list: add lat buffer to core head list + * + * @is_last_frame: meaning this buffer is the last frame */ struct vdec_lat_buf { struct mtk_vcodec_mem wdma_err_addr; @@ -74,6 +76,8 @@ struct vdec_lat_buf { core_decode_cb_t core_decode; struct list_head lat_list; struct list_head core_list; + + bool is_last_frame; }; /** @@ -88,6 +92,8 @@ struct vdec_lat_buf { * * @lat_list_cnt: used to record each instance lat list count * @core_list_cnt: used to record each instance core list count + * @flush_done: core flush done status + * @empty_lat_buf: the last lat buf used to flush decode * @core_dec_done: core work queue decode done event * @status: current context decode status for core hardware */ @@ -104,6 +110,8 @@ struct vdec_msg_queue { atomic_t lat_list_cnt; atomic_t core_list_cnt; + bool flush_done; + struct vdec_lat_buf empty_lat_buf; wait_queue_head_t core_dec_done; int status; }; From 645dec333f5f9451ea0f888a8dd9ececa7300424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 24 May 2023 16:16:44 +0100 Subject: [PATCH 102/253] media: staging: max96712: Switch i2c driver back to use .probe() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After commit b8a1a4cd5a98 ("i2c: Provide a temporary .probe_new() call-back type"), all drivers being converted to .probe_new() and then commit 03c835f498b5 ("i2c: Switch .probe() to not take an id parameter") convert back to (the new) .probe() to be able to eventually drop .probe_new() from struct i2c_driver. Signed-off-by: Uwe Kleine-König Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/max96712/max96712.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/max96712/max96712.c b/drivers/staging/media/max96712/max96712.c index ce4ebb63d54d..c44145284aa1 100644 --- a/drivers/staging/media/max96712/max96712.c +++ b/drivers/staging/media/max96712/max96712.c @@ -453,7 +453,7 @@ static struct i2c_driver max96712_i2c_driver = { .name = "max96712", .of_match_table = of_match_ptr(max96712_of_table), }, - .probe_new = max96712_probe, + .probe = max96712_probe, .remove = max96712_remove, }; From bd947783a2177f9083c4bde5b9db45df2d5adc8b Mon Sep 17 00:00:00 2001 From: Artur Weber Date: Fri, 19 May 2023 19:28:53 +0100 Subject: [PATCH 103/253] media: Revert "media: exynos4-is: Remove dependency on obsolete SoC support" Support for the Exynos4212 SoC was originally dropped as there were no boards using it. We will be adding a device that uses it, so add it back. This reverts commit 2d41a0c9ae51ac363d107f2510022106e7234b33. Signed-off-by: Artur Weber Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/samsung/exynos4-is/Kconfig | 2 +- drivers/media/platform/samsung/exynos4-is/fimc-core.c | 2 +- drivers/media/platform/samsung/exynos4-is/fimc-lite.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/samsung/exynos4-is/Kconfig b/drivers/media/platform/samsung/exynos4-is/Kconfig index da33faa7132e..7f9ba053dd8e 100644 --- a/drivers/media/platform/samsung/exynos4-is/Kconfig +++ b/drivers/media/platform/samsung/exynos4-is/Kconfig @@ -47,7 +47,7 @@ config VIDEO_S5P_MIPI_CSIS config VIDEO_EXYNOS_FIMC_LITE tristate "EXYNOS FIMC-LITE camera interface driver" depends on I2C - depends on SOC_EXYNOS4412 || SOC_EXYNOS5250 || COMPILE_TEST + depends on SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250 || COMPILE_TEST depends on HAS_DMA select VIDEOBUF2_DMA_CONTIG select VIDEO_EXYNOS4_IS_COMMON diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-core.c b/drivers/media/platform/samsung/exynos4-is/fimc-core.c index a2034ade8b9e..976b4f747ad4 100644 --- a/drivers/media/platform/samsung/exynos4-is/fimc-core.c +++ b/drivers/media/platform/samsung/exynos4-is/fimc-core.c @@ -1128,7 +1128,7 @@ static const struct fimc_drvdata fimc_drvdata_exynos4210 = { .out_buf_count = 32, }; -/* EXYNOS4412 */ +/* EXYNOS4212, EXYNOS4412 */ static const struct fimc_drvdata fimc_drvdata_exynos4x12 = { .num_entities = 4, .lclk_frequency = 166000000UL, diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-lite.c b/drivers/media/platform/samsung/exynos4-is/fimc-lite.c index 24b3dda26714..c3146ae08447 100644 --- a/drivers/media/platform/samsung/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/samsung/exynos4-is/fimc-lite.c @@ -1621,7 +1621,7 @@ static const struct dev_pm_ops fimc_lite_pm_ops = { NULL) }; -/* EXYNOS4412 */ +/* EXYNOS4212, EXYNOS4412 */ static struct flite_drvdata fimc_lite_drvdata_exynos4 = { .max_width = 8192, .max_height = 8192, From fe1b585ce91da47af7e7f8985428099d52eeca3c Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 24 May 2023 01:20:38 +0100 Subject: [PATCH 104/253] media: pci: cx18-av-vbi: Replace one-element array with flexible-array member One-element arrays are deprecated, and we are replacing them with flexible array members instead. So, replace one-element arrays with flexible-array members in struct vbi_anc_data. This results in no differences in binary output. Link: https://github.com/KSPP/linux/issues/79 Signed-off-by: Gustavo A. R. Silva Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/cx18/cx18-av-vbi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/cx18/cx18-av-vbi.c b/drivers/media/pci/cx18/cx18-av-vbi.c index a0d465924e75..65281d40c681 100644 --- a/drivers/media/pci/cx18/cx18-av-vbi.c +++ b/drivers/media/pci/cx18/cx18-av-vbi.c @@ -51,7 +51,7 @@ struct vbi_anc_data { u8 sdid; u8 data_count; u8 idid[2]; - u8 payload[1]; /* data_count of payload */ + u8 payload[]; /* data_count of payload */ /* u8 checksum; */ /* u8 fill[]; Variable number of fill bytes */ }; From 5aa8de7ad14f3bb7c39a67a63767de50b5fe122d Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 24 May 2023 14:29:24 +0100 Subject: [PATCH 105/253] media: video-mux: fix error paths Move notifier cleanup into video_mux_async_register() to avoid calling v4l2_async_nf_unregister() when v4l2_async_subdev_nf_register() failed. In case video_mux_async_register() fails, call media_entity_cleanup(). Signed-off-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/video-mux.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c index b244873d593a..4fe31386afc7 100644 --- a/drivers/media/platform/video-mux.c +++ b/drivers/media/platform/video-mux.c @@ -389,7 +389,7 @@ static int video_mux_async_register(struct video_mux *vmux, ret = PTR_ERR(asd); /* OK if asd already exists */ if (ret != -EEXIST) - return ret; + goto err_nf_cleanup; } } @@ -397,9 +397,19 @@ static int video_mux_async_register(struct video_mux *vmux, ret = v4l2_async_subdev_nf_register(&vmux->subdev, &vmux->notifier); if (ret) - return ret; + goto err_nf_cleanup; - return v4l2_async_register_subdev(&vmux->subdev); + ret = v4l2_async_register_subdev(&vmux->subdev); + if (ret) + goto err_nf_unregister; + + return 0; + +err_nf_unregister: + v4l2_async_nf_unregister(&vmux->notifier); +err_nf_cleanup: + v4l2_async_nf_cleanup(&vmux->notifier); + return ret; } static int video_mux_probe(struct platform_device *pdev) @@ -473,12 +483,13 @@ static int video_mux_probe(struct platform_device *pdev) vmux->subdev.entity.ops = &video_mux_ops; ret = video_mux_async_register(vmux, num_pads - 1); - if (ret) { - media_entity_cleanup(&vmux->subdev.entity); - v4l2_async_nf_unregister(&vmux->notifier); - v4l2_async_nf_cleanup(&vmux->notifier); - } + if (ret) + goto err_entity_cleanup; + return 0; + +err_entity_cleanup: + media_entity_cleanup(&vmux->subdev.entity); return ret; } From aafeeaf3d2a8a91a5407c774c578abec79dcff00 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 24 May 2023 14:29:25 +0100 Subject: [PATCH 106/253] media: video-mux: update driver to active state Drop the open coded pad format array, use subdev active state instead. Signed-off-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/video-mux.c | 78 +++++++++--------------------- 1 file changed, 24 insertions(+), 54 deletions(-) diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c index 4fe31386afc7..6d273abfe16c 100644 --- a/drivers/media/platform/video-mux.c +++ b/drivers/media/platform/video-mux.c @@ -24,7 +24,6 @@ struct video_mux { struct v4l2_subdev subdev; struct v4l2_async_notifier notifier; struct media_pad *pads; - struct v4l2_mbus_framefmt *format_mbus; struct mux_control *mux; struct mutex lock; int active; @@ -71,6 +70,9 @@ static int video_mux_link_setup(struct media_entity *entity, mutex_lock(&vmux->lock); if (flags & MEDIA_LNK_FL_ENABLED) { + struct v4l2_subdev_state *sd_state; + struct v4l2_mbus_framefmt *source_mbusformat; + if (vmux->active == local->index) goto out; @@ -86,7 +88,12 @@ static int video_mux_link_setup(struct media_entity *entity, vmux->active = local->index; /* Propagate the active format to the source */ - vmux->format_mbus[source_pad] = vmux->format_mbus[vmux->active]; + sd_state = v4l2_subdev_lock_and_get_active_state(sd); + source_mbusformat = v4l2_subdev_get_pad_format(sd, sd_state, + source_pad); + *source_mbusformat = *v4l2_subdev_get_pad_format(sd, sd_state, + vmux->active); + v4l2_subdev_unlock_state(sd_state); } else { if (vmux->active != local->index) goto out; @@ -138,40 +145,6 @@ static const struct v4l2_subdev_video_ops video_mux_subdev_video_ops = { .s_stream = video_mux_s_stream, }; -static struct v4l2_mbus_framefmt * -__video_mux_get_pad_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - unsigned int pad, u32 which) -{ - struct video_mux *vmux = v4l2_subdev_to_video_mux(sd); - - switch (which) { - case V4L2_SUBDEV_FORMAT_TRY: - return v4l2_subdev_get_try_format(sd, sd_state, pad); - case V4L2_SUBDEV_FORMAT_ACTIVE: - return &vmux->format_mbus[pad]; - default: - return NULL; - } -} - -static int video_mux_get_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *sdformat) -{ - struct video_mux *vmux = v4l2_subdev_to_video_mux(sd); - - mutex_lock(&vmux->lock); - - sdformat->format = *__video_mux_get_pad_format(sd, sd_state, - sdformat->pad, - sdformat->which); - - mutex_unlock(&vmux->lock); - - return 0; -} - static int video_mux_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *sdformat) @@ -181,14 +154,11 @@ static int video_mux_set_format(struct v4l2_subdev *sd, struct media_pad *pad = &vmux->pads[sdformat->pad]; u16 source_pad = sd->entity.num_pads - 1; - mbusformat = __video_mux_get_pad_format(sd, sd_state, sdformat->pad, - sdformat->which); + mbusformat = v4l2_subdev_get_pad_format(sd, sd_state, sdformat->pad); if (!mbusformat) return -EINVAL; - source_mbusformat = __video_mux_get_pad_format(sd, sd_state, - source_pad, - sdformat->which); + source_mbusformat = v4l2_subdev_get_pad_format(sd, sd_state, source_pad); if (!source_mbusformat) return -EINVAL; @@ -298,7 +268,8 @@ static int video_mux_set_format(struct v4l2_subdev *sd, /* Source pad mirrors active sink pad, no limitations on sink pads */ if ((pad->flags & MEDIA_PAD_FL_SOURCE) && vmux->active >= 0) - sdformat->format = vmux->format_mbus[vmux->active]; + sdformat->format = *v4l2_subdev_get_pad_format(sd, sd_state, + vmux->active); *mbusformat = sdformat->format; @@ -321,7 +292,7 @@ static int video_mux_init_cfg(struct v4l2_subdev *sd, mutex_lock(&vmux->lock); for (i = 0; i < sd->entity.num_pads; i++) { - mbusformat = v4l2_subdev_get_try_format(sd, sd_state, i); + mbusformat = v4l2_subdev_get_pad_format(sd, sd_state, i); *mbusformat = video_mux_format_mbus_default; } @@ -332,7 +303,7 @@ static int video_mux_init_cfg(struct v4l2_subdev *sd, static const struct v4l2_subdev_pad_ops video_mux_pad_ops = { .init_cfg = video_mux_init_cfg, - .get_fmt = video_mux_get_format, + .get_fmt = v4l2_subdev_get_fmt, .set_fmt = video_mux_set_format, }; @@ -462,17 +433,9 @@ static int video_mux_probe(struct platform_device *pdev) 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++) { + for (i = 0; i < num_pads; i++) vmux->pads[i].flags = (i < num_pads - 1) ? MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE; - vmux->format_mbus[i] = video_mux_format_mbus_default; - } vmux->subdev.entity.function = MEDIA_ENT_F_VID_MUX; ret = media_entity_pads_init(&vmux->subdev.entity, num_pads, @@ -482,12 +445,18 @@ static int video_mux_probe(struct platform_device *pdev) vmux->subdev.entity.ops = &video_mux_ops; + ret = v4l2_subdev_init_finalize(&vmux->subdev); + if (ret < 0) + goto err_entity_cleanup; + ret = video_mux_async_register(vmux, num_pads - 1); if (ret) - goto err_entity_cleanup; + goto err_subdev_cleanup; return 0; +err_subdev_cleanup: + v4l2_subdev_cleanup(&vmux->subdev); err_entity_cleanup: media_entity_cleanup(&vmux->subdev.entity); return ret; @@ -501,6 +470,7 @@ static void video_mux_remove(struct platform_device *pdev) v4l2_async_nf_unregister(&vmux->notifier); v4l2_async_nf_cleanup(&vmux->notifier); v4l2_async_unregister_subdev(sd); + v4l2_subdev_cleanup(sd); media_entity_cleanup(&sd->entity); } From 98d4351847bb45d956722f81f4948aebf3b8df2d Mon Sep 17 00:00:00 2001 From: Qinglang Miao Date: Mon, 21 Sep 2020 14:10:38 +0100 Subject: [PATCH 107/253] media: venus: simplify the return expression of session_process_buf() Simplify the return expression. Signed-off-by: Qinglang Miao Reviewed-by: Bjorn Andersson Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/helpers.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index a2ceab7f9ddb..3267a4ebe4af 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -502,7 +502,6 @@ session_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf) struct vb2_buffer *vb = &vbuf->vb2_buf; unsigned int type = vb->type; struct hfi_frame_data fdata; - int ret; memset(&fdata, 0, sizeof(fdata)); fdata.alloc_len = buf->size; @@ -533,11 +532,7 @@ session_process_buf(struct venus_inst *inst, struct vb2_v4l2_buffer *vbuf) fdata.offset = 0; } - ret = hfi_session_process_buf(inst, &fdata); - if (ret) - return ret; - - return 0; + return hfi_session_process_buf(inst, &fdata); } static bool is_dynamic_bufmode(struct venus_inst *inst) From 751be5c63f542b794328c9b1c8fd4a934c24fdeb Mon Sep 17 00:00:00 2001 From: Liu Shixin Date: Mon, 21 Sep 2020 09:24:40 +0100 Subject: [PATCH 108/253] media: venus: simplify the return expression of venus_sys_set_* function Simplify the return expression. Signed-off-by: Liu Shixin Reviewed-by: Bjorn Andersson Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/hfi_venus.c | 28 +++---------------- 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index 2ad40b3945b0..f0b46389e8d5 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -835,34 +835,24 @@ static int venus_sys_set_debug(struct venus_hfi_device *hdev, u32 debug) { struct hfi_sys_set_property_pkt *pkt; u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE]; - int ret; pkt = (struct hfi_sys_set_property_pkt *)packet; pkt_sys_debug_config(pkt, HFI_DEBUG_MODE_QUEUE, debug); - ret = venus_iface_cmdq_write(hdev, pkt, false); - if (ret) - return ret; - - return 0; + return venus_iface_cmdq_write(hdev, pkt, false); } static int venus_sys_set_coverage(struct venus_hfi_device *hdev, u32 mode) { struct hfi_sys_set_property_pkt *pkt; u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE]; - int ret; pkt = (struct hfi_sys_set_property_pkt *)packet; pkt_sys_coverage_config(pkt, mode); - ret = venus_iface_cmdq_write(hdev, pkt, false); - if (ret) - return ret; - - return 0; + return venus_iface_cmdq_write(hdev, pkt, false); } static int venus_sys_set_idle_message(struct venus_hfi_device *hdev, @@ -870,7 +860,6 @@ static int venus_sys_set_idle_message(struct venus_hfi_device *hdev, { struct hfi_sys_set_property_pkt *pkt; u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE]; - int ret; if (!enable) return 0; @@ -879,11 +868,7 @@ static int venus_sys_set_idle_message(struct venus_hfi_device *hdev, pkt_sys_idle_indicator(pkt, enable); - ret = venus_iface_cmdq_write(hdev, pkt, false); - if (ret) - return ret; - - return 0; + return venus_iface_cmdq_write(hdev, pkt, false); } static int venus_sys_set_power_control(struct venus_hfi_device *hdev, @@ -891,17 +876,12 @@ static int venus_sys_set_power_control(struct venus_hfi_device *hdev, { struct hfi_sys_set_property_pkt *pkt; u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE]; - int ret; pkt = (struct hfi_sys_set_property_pkt *)packet; pkt_sys_power_control(pkt, enable); - ret = venus_iface_cmdq_write(hdev, pkt, false); - if (ret) - return ret; - - return 0; + return venus_iface_cmdq_write(hdev, pkt, false); } static int venus_sys_set_ubwc_config(struct venus_hfi_device *hdev) From 927e78ac8bc58155316cf6f46026e1912bbbbcfc Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Sat, 12 Sep 2020 20:03:01 +0100 Subject: [PATCH 109/253] media: venus: helpers: Fix ALIGN() of non power of two ALIGN() expects its second argument to be a power of 2, otherwise incorrect results are produced for some inputs. The output can be both larger or smaller than what is expected. For example, ALIGN(304, 192) equals 320 instead of 384, and ALIGN(65, 192) equals 256 instead of 192. However, nestling two ALIGN() as is done in this case seem to only produce results equal to or bigger than the expected result if ALIGN() had handled non powers of two, and that in turn results in framesizes that are either the correct size or too large. Fortunately, since 192 * 4 / 3 equals 256, it turns out that one ALIGN() is sufficient. Fixes: ab1eda449c6e ("media: venus: vdec: handle 10bit bitstreams") Signed-off-by: Rikard Falkeborn Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/helpers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 3267a4ebe4af..7281bc6cdb39 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -1031,8 +1031,8 @@ static u32 get_framesize_raw_yuv420_tp10_ubwc(u32 width, u32 height) u32 extradata = SZ_16K; u32 size; - y_stride = ALIGN(ALIGN(width, 192) * 4 / 3, 256); - uv_stride = ALIGN(ALIGN(width, 192) * 4 / 3, 256); + y_stride = ALIGN(width * 4 / 3, 256); + uv_stride = ALIGN(width * 4 / 3, 256); y_sclines = ALIGN(height, 16); uv_sclines = ALIGN((height + 1) >> 1, 16); From a0eadbe92610cfaa0f5d519778c0297564e6a3a2 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 17 May 2023 02:03:39 +0100 Subject: [PATCH 110/253] media: venus: hfi_cmds: Replace fake flex-array with flexible-array member One-element arrays are deprecated, and we are replacing them with flexible array members instead. So, replace one-element arrays with flexible-array members in struct hfi_sys_set_resource_pkt, and refactor the rest of the code, accordingly. This helps with the ongoing efforts to tighten the FORTIFY_SOURCE routines on memcpy() and help us make progress towards globally enabling -fstrict-flex-arrays=3 [1]. The only binary differences seen before/after changes are the following: 17ba: mov %rbx,%rdi 17bd: call 17c2 17be: R_X86_64_PLT32 __tsan_write4-0x4 - 17c2: movl $0x14,(%rbx) + 17c2: movl $0x10,(%rbx) 17c8: lea 0x4(%rbx),%rdi 17cc: call 17d1 17cd: R_X86_64_PLT32 __tsan_write4-0x4 which is expected once this accounts for the following line of code at drivers/media/platform/qcom/venus/hfi_cmds.c:73 73 pkt->hdr.size = sizeof(*pkt); and as *pkt is of type struct hfi_sys_set_resource_pkt, sizeof(*pkt) is reduced by 4 bytes, due to the flex-array transformation. Link: https://github.com/KSPP/linux/issues/79 Link: https://github.com/KSPP/linux/issues/293 Link: https://gcc.gnu.org/pipermail/gcc-patches/2022-October/602902.html [1] Signed-off-by: Gustavo A. R. Silva Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/hfi_cmds.c | 2 +- drivers/media/platform/qcom/venus/hfi_cmds.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.c b/drivers/media/platform/qcom/venus/hfi_cmds.c index bc3f8ff05840..33474f718398 100644 --- a/drivers/media/platform/qcom/venus/hfi_cmds.c +++ b/drivers/media/platform/qcom/venus/hfi_cmds.c @@ -83,7 +83,7 @@ int pkt_sys_set_resource(struct hfi_sys_set_resource_pkt *pkt, u32 id, u32 size, res->size = size; res->mem = addr; pkt->resource_type = HFI_RESOURCE_OCMEM; - pkt->hdr.size += sizeof(*res) - sizeof(u32); + pkt->hdr.size += sizeof(*res); break; } case VIDC_RESOURCE_NONE: diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.h b/drivers/media/platform/qcom/venus/hfi_cmds.h index 99bc0b6db67c..fa2cb1ac4670 100644 --- a/drivers/media/platform/qcom/venus/hfi_cmds.h +++ b/drivers/media/platform/qcom/venus/hfi_cmds.h @@ -56,7 +56,7 @@ struct hfi_sys_set_resource_pkt { struct hfi_pkt_hdr hdr; u32 resource_handle; u32 resource_type; - u32 resource_data[1]; + u32 resource_data[]; }; struct hfi_sys_release_resource_pkt { From a80d6771ae067c3ec2313897fd999d3649a81c9c Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 16 May 2023 21:17:32 +0100 Subject: [PATCH 111/253] media: venus: Replace one-element arrays with flexible-array members One-element arrays are deprecated, and we are replacing them with flexible array members instead. So, replace one-element arrays with flexible-array members in multiple structures, and refactor the rest of the code, accordingly. This helps with the ongoing efforts to tighten the FORTIFY_SOURCE routines on memcpy() and help us make progress towards globally enabling -fstrict-flex-arrays=3 [1]. This results in no differences in binary output. Link: https://github.com/KSPP/linux/issues/79 Link: https://github.com/KSPP/linux/issues/291 Link: https://gcc.gnu.org/pipermail/gcc-patches/2022-October/602902.html [1] Signed-off-by: Gustavo A. R. Silva Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/hfi_msgs.c | 4 ++-- drivers/media/platform/qcom/venus/hfi_msgs.h | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c index df96db3761a7..6efd78606d9b 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.c +++ b/drivers/media/platform/qcom/venus/hfi_msgs.c @@ -233,7 +233,7 @@ static void hfi_sys_init_done(struct venus_core *core, struct venus_inst *inst, goto done; } - rem_bytes = pkt->hdr.size - sizeof(*pkt) + sizeof(u32); + rem_bytes = pkt->hdr.size - sizeof(*pkt); if (rem_bytes <= 0) { /* missing property data */ error = HFI_ERR_SYS_INSUFFICIENT_RESOURCES; @@ -434,7 +434,7 @@ static void hfi_session_init_done(struct venus_core *core, if (!IS_V1(core)) goto done; - rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt) + sizeof(u32); + rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt); if (rem_bytes <= 0) { error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES; goto done; diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.h b/drivers/media/platform/qcom/venus/hfi_msgs.h index 510513697335..8c2e17b0d36f 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.h +++ b/drivers/media/platform/qcom/venus/hfi_msgs.h @@ -50,7 +50,7 @@ struct hfi_msg_event_notify_pkt { u32 event_id; u32 event_data1; u32 event_data2; - u32 ext_event_data[1]; + u32 ext_event_data[]; }; struct hfi_msg_event_release_buffer_ref_pkt { @@ -63,7 +63,7 @@ struct hfi_msg_sys_init_done_pkt { struct hfi_pkt_hdr hdr; u32 error_type; u32 num_properties; - u32 data[1]; + u32 data[]; }; struct hfi_msg_sys_pc_prep_done_pkt { @@ -81,7 +81,7 @@ struct hfi_msg_session_init_done_pkt { struct hfi_session_hdr_pkt shdr; u32 error_type; u32 num_properties; - u32 data[1]; + u32 data[]; }; struct hfi_msg_session_end_done_pkt { @@ -228,7 +228,7 @@ struct hfi_msg_session_parse_sequence_header_done_pkt { struct hfi_session_hdr_pkt shdr; u32 error_type; u32 num_properties; - u32 data[1]; + u32 data[]; }; struct hfi_msg_session_property_info_pkt { @@ -247,7 +247,7 @@ struct hfi_msg_session_release_buffers_done_pkt { struct hfi_session_hdr_pkt shdr; u32 error_type; u32 num_buffers; - u32 buffer_info[1]; + u32 buffer_info[]; }; struct hfi_msg_sys_debug_pkt { @@ -256,7 +256,7 @@ struct hfi_msg_sys_debug_pkt { u32 msg_size; u32 time_stamp_hi; u32 time_stamp_lo; - u8 msg_data[1]; + u8 msg_data[]; }; struct hfi_msg_sys_coverage_pkt { @@ -264,7 +264,7 @@ struct hfi_msg_sys_coverage_pkt { u32 msg_size; u32 time_stamp_hi; u32 time_stamp_lo; - u8 msg_data[1]; + u8 msg_data[]; }; struct venus_core; From 40c02059645890d0525b693fc5b80d4c4db8d205 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 17 May 2023 00:14:27 +0100 Subject: [PATCH 112/253] media: venus: hfi_cmds: Replace one-element array with flexible-array member One-element arrays are deprecated, and we are replacing them with flexible array members instead. So, replace one-element arrays with flexible-array members in struct hfi_session_set_buffers_pkt, and refactor the rest of the code, accordingly. This helps with the ongoing efforts to tighten the FORTIFY_SOURCE routines on memcpy() and help us make progress towards globally enabling -fstrict-flex-arrays=3 [1]. This results in no differences in binary output. Link: https://github.com/KSPP/linux/issues/79 Link: https://github.com/KSPP/linux/issues/292 Link: https://gcc.gnu.org/pipermail/gcc-patches/2022-October/602902.html [1] Signed-off-by: Gustavo A. R. Silva Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/hfi_cmds.c | 12 ++++++------ drivers/media/platform/qcom/venus/hfi_cmds.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.c b/drivers/media/platform/qcom/venus/hfi_cmds.c index 33474f718398..2ceab5fe160f 100644 --- a/drivers/media/platform/qcom/venus/hfi_cmds.c +++ b/drivers/media/platform/qcom/venus/hfi_cmds.c @@ -200,8 +200,8 @@ int pkt_session_set_buffers(struct hfi_session_set_buffers_pkt *pkt, struct hfi_buffer_info *bi; pkt->extradata_size = bd->extradata_size; - pkt->shdr.hdr.size = sizeof(*pkt) - sizeof(u32) + - (bd->num_buffers * sizeof(*bi)); + pkt->shdr.hdr.size = sizeof(*pkt) + + bd->num_buffers * sizeof(*bi); bi = (struct hfi_buffer_info *)pkt->buffer_info; for (i = 0; i < pkt->num_buffers; i++) { bi->buffer_addr = bd->device_addr; @@ -210,7 +210,7 @@ int pkt_session_set_buffers(struct hfi_session_set_buffers_pkt *pkt, } else { pkt->extradata_size = 0; pkt->shdr.hdr.size = sizeof(*pkt) + - ((bd->num_buffers - 1) * sizeof(u32)); + bd->num_buffers * sizeof(u32); for (i = 0; i < pkt->num_buffers; i++) pkt->buffer_info[i] = bd->device_addr; } @@ -243,8 +243,8 @@ int pkt_session_unset_buffers(struct hfi_session_release_buffer_pkt *pkt, bi->extradata_addr = bd->extradata_addr; } pkt->shdr.hdr.size = - sizeof(struct hfi_session_set_buffers_pkt) - - sizeof(u32) + (bd->num_buffers * sizeof(*bi)); + sizeof(struct hfi_session_set_buffers_pkt) + + bd->num_buffers * sizeof(*bi); } else { for (i = 0; i < pkt->num_buffers; i++) pkt->buffer_info[i] = bd->device_addr; @@ -252,7 +252,7 @@ int pkt_session_unset_buffers(struct hfi_session_release_buffer_pkt *pkt, pkt->extradata_size = 0; pkt->shdr.hdr.size = sizeof(struct hfi_session_set_buffers_pkt) + - ((bd->num_buffers - 1) * sizeof(u32)); + bd->num_buffers * sizeof(u32); } pkt->response_req = bd->response_required; diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.h b/drivers/media/platform/qcom/venus/hfi_cmds.h index fa2cb1ac4670..dd9c5066442d 100644 --- a/drivers/media/platform/qcom/venus/hfi_cmds.h +++ b/drivers/media/platform/qcom/venus/hfi_cmds.h @@ -117,7 +117,7 @@ struct hfi_session_set_buffers_pkt { u32 extradata_size; u32 min_buffer_size; u32 num_buffers; - u32 buffer_info[1]; + u32 buffer_info[]; }; struct hfi_session_get_sequence_header_pkt { From e03ac40885db88cece5a5c866b6825d1eeacb24e Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 17 May 2023 00:14:49 +0100 Subject: [PATCH 113/253] media: venus: hfi_cmds: Use struct_size() helper Prefer struct_size() over open-coded versions of idiom: sizeof(struct-with-flex-array) + sizeof(typeof-flex-array-elements) * count where count is the max number of items the flexible array is supposed to contain. Link: https://github.com/KSPP/linux/issues/160 Signed-off-by: Gustavo A. R. Silva Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/hfi_cmds.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.c b/drivers/media/platform/qcom/venus/hfi_cmds.c index 2ceab5fe160f..7c82e212434e 100644 --- a/drivers/media/platform/qcom/venus/hfi_cmds.c +++ b/drivers/media/platform/qcom/venus/hfi_cmds.c @@ -209,8 +209,8 @@ int pkt_session_set_buffers(struct hfi_session_set_buffers_pkt *pkt, } } else { pkt->extradata_size = 0; - pkt->shdr.hdr.size = sizeof(*pkt) + - bd->num_buffers * sizeof(u32); + pkt->shdr.hdr.size = struct_size(pkt, buffer_info, + bd->num_buffers); for (i = 0; i < pkt->num_buffers; i++) pkt->buffer_info[i] = bd->device_addr; } @@ -251,8 +251,8 @@ int pkt_session_unset_buffers(struct hfi_session_release_buffer_pkt *pkt, pkt->extradata_size = 0; pkt->shdr.hdr.size = - sizeof(struct hfi_session_set_buffers_pkt) + - bd->num_buffers * sizeof(u32); + struct_size((struct hfi_session_set_buffers_pkt *)0, + buffer_info, bd->num_buffers); } pkt->response_req = bd->response_required; From ae8cdfc3f281ac28d5e64bc21dc1947224d98f37 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Mon, 22 May 2023 07:02:50 +0100 Subject: [PATCH 114/253] media: venus: add firmware version based check Add firmware version based checks to enable/disable features for different SOCs. Tested-by: Nathan Hebert Signed-off-by: Vikash Garodia Signed-off-by: Viswanath Boma Signed-off-by: Dikshita Agarwal Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/core.h | 20 +++++++++++++ drivers/media/platform/qcom/venus/hfi_msgs.c | 30 ++++++++++++++++++-- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 4f81669986ba..12a42fbeda47 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -201,6 +201,11 @@ struct venus_core { unsigned int core0_usage_count; unsigned int core1_usage_count; struct dentry *root; + struct venus_img_version { + u32 major; + u32 minor; + u32 rev; + } venus_ver; }; struct vdec_controls { @@ -508,4 +513,19 @@ venus_caps_by_codec(struct venus_core *core, u32 codec, u32 domain) return NULL; } +static inline bool +is_fw_rev_or_newer(struct venus_core *core, u32 vmajor, u32 vminor, u32 vrev) +{ + return ((core)->venus_ver.major == vmajor && + (core)->venus_ver.minor == vminor && + (core)->venus_ver.rev >= vrev); +} + +static inline bool +is_fw_rev_or_older(struct venus_core *core, u32 vmajor, u32 vminor, u32 vrev) +{ + return ((core)->venus_ver.major == vmajor && + (core)->venus_ver.minor == vminor && + (core)->venus_ver.rev <= vrev); +} #endif diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c index 6efd78606d9b..3d5dadfa1900 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.c +++ b/drivers/media/platform/qcom/venus/hfi_msgs.c @@ -248,13 +248,15 @@ done: } static void -sys_get_prop_image_version(struct device *dev, +sys_get_prop_image_version(struct venus_core *core, struct hfi_msg_sys_property_info_pkt *pkt) { + struct device *dev = core->dev; u8 *smem_tbl_ptr; u8 *img_ver; int req_bytes; size_t smem_blk_sz; + int ret; req_bytes = pkt->hdr.size - sizeof(*pkt); @@ -263,8 +265,30 @@ sys_get_prop_image_version(struct device *dev, return; img_ver = pkt->data; + if (!img_ver) + return; - dev_dbg(dev, VDBGL "F/W version: %s\n", img_ver); + ret = sscanf(img_ver, "14:video-firmware.%u.%u-%u", + &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev); + if (ret) + goto done; + + ret = sscanf(img_ver, "14:VIDEO.VPU.%u.%u-%u", + &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev); + if (ret) + goto done; + + ret = sscanf(img_ver, "14:VIDEO.VE.%u.%u-%u", + &core->venus_ver.major, &core->venus_ver.minor, &core->venus_ver.rev); + if (ret) + goto done; + + dev_err(dev, VDBGL "error reading F/W version\n"); + return; + +done: + dev_dbg(dev, VDBGL "F/W version: %s, major %u, minor %u, revision %u\n", + img_ver, core->venus_ver.major, core->venus_ver.minor, core->venus_ver.rev); smem_tbl_ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_IMG_VER_TBL, &smem_blk_sz); @@ -286,7 +310,7 @@ static void hfi_sys_property_info(struct venus_core *core, switch (pkt->property) { case HFI_PROPERTY_SYS_IMAGE_VERSION: - sys_get_prop_image_version(dev, pkt); + sys_get_prop_image_version(core, pkt); break; default: dev_dbg(dev, VDBGL "unknown property data\n"); From 938beb48f7653d27a270c68659d00a0f58643ac7 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Mon, 22 May 2023 07:02:51 +0100 Subject: [PATCH 115/253] media: venus: enable sufficient sequence change support for vp9 VP9 supports resolution change at interframe. Currenlty, if sequence change is detected at interframe and resources are sufficient, sequence change event is not raised by firmware to driver until the next keyframe. This change add the HFI to notify the sequence change in this case to driver. Reviewed-by: Konrad Dybcio Tested-by: Nathan Hebert Signed-off-by: Vikash Garodia Signed-off-by: Viswanath Boma Signed-off-by: Dikshita Agarwal Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/hfi_cmds.c | 1 + drivers/media/platform/qcom/venus/hfi_helper.h | 2 ++ drivers/media/platform/qcom/venus/vdec.c | 8 ++++++++ 3 files changed, 11 insertions(+) diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.c b/drivers/media/platform/qcom/venus/hfi_cmds.c index 7c82e212434e..7f0802a5518c 100644 --- a/drivers/media/platform/qcom/venus/hfi_cmds.c +++ b/drivers/media/platform/qcom/venus/hfi_cmds.c @@ -521,6 +521,7 @@ static int pkt_session_set_property_1x(struct hfi_session_set_property_pkt *pkt, pkt->shdr.hdr.size += sizeof(u32) + sizeof(*en); break; } + case HFI_PROPERTY_PARAM_VDEC_ENABLE_SUFFICIENT_SEQCHANGE_EVENT: case HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER: { struct hfi_enable *in = pdata; struct hfi_enable *en = prop_data; diff --git a/drivers/media/platform/qcom/venus/hfi_helper.h b/drivers/media/platform/qcom/venus/hfi_helper.h index 105792a68060..0abbc50c5864 100644 --- a/drivers/media/platform/qcom/venus/hfi_helper.h +++ b/drivers/media/platform/qcom/venus/hfi_helper.h @@ -469,6 +469,8 @@ #define HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH 0x1003007 #define HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT 0x1003009 #define HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE 0x100300a +#define HFI_PROPERTY_PARAM_VDEC_ENABLE_SUFFICIENT_SEQCHANGE_EVENT \ + 0x100300b /* * HFI_PROPERTY_CONFIG_VDEC_COMMON_START diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 51a53bf82bd3..f42570a816fe 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -684,6 +684,14 @@ static int vdec_set_properties(struct venus_inst *inst) return ret; } + /* Enabling sufficient sequence change support for VP9 */ + if (is_fw_rev_or_newer(inst->core, 5, 4, 51)) { + ptype = HFI_PROPERTY_PARAM_VDEC_ENABLE_SUFFICIENT_SEQCHANGE_EVENT; + ret = hfi_session_set_property(inst, ptype, &en); + if (ret) + return ret; + } + ptype = HFI_PROPERTY_PARAM_VDEC_CONCEAL_COLOR; conceal = ctr->conceal_color & 0xffff; conceal |= ((ctr->conceal_color >> 16) & 0xffff) << 10; From 47f867cb1b6364be6b3d50a333370d6f66a7e085 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Mon, 22 May 2023 07:02:52 +0100 Subject: [PATCH 116/253] media: venus: fix EOS handling in decoder stop command Use firmware version based check to assign correct device address for EOS buffer to fix the EOS handling with different firmware version. Reviewed-by: Konrad Dybcio Tested-by: Nathan Hebert Signed-off-by: Vikash Garodia Signed-off-by: Viswanath Boma Signed-off-by: Dikshita Agarwal Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/vdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index f42570a816fe..c6f0fd084758 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -551,7 +551,7 @@ vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd) fdata.buffer_type = HFI_BUFFER_INPUT; fdata.flags |= HFI_BUFFERFLAG_EOS; - if (IS_V6(inst->core)) + if (IS_V6(inst->core) && is_fw_rev_or_older(inst->core, 1, 0, 87)) fdata.device_addr = 0; else fdata.device_addr = 0xdeadb000; From 2b832a06a8c85bca42b3cd6aacd703eea1feb784 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Mon, 22 May 2023 07:17:09 +0100 Subject: [PATCH 117/253] media: venus: replace arrary index with enum for supported formats Use enums to list supported formats for encoder and decoder instead of array index which was a error prone design. Signed-off-by: Dikshita Agarwal Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/core.h | 16 +++++ drivers/media/platform/qcom/venus/vdec.c | 91 ++++++++++++++---------- drivers/media/platform/qcom/venus/venc.c | 33 +++++---- 3 files changed, 87 insertions(+), 53 deletions(-) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 12a42fbeda47..e988ed443d25 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -83,6 +83,22 @@ struct venus_resources { const char *fwname; }; +enum venus_fmt { + VENUS_FMT_NV12 = 0, + VENUS_FMT_QC08C = 1, + VENUS_FMT_QC10C = 2, + VENUS_FMT_H264 = 3, + VENUS_FMT_VP8 = 4, + VENUS_FMT_VP9 = 5, + VENUS_FMT_HEVC = 6, + VENUS_FMT_VC1_ANNEX_G = 7, + VENUS_FMT_VC1_ANNEX_L = 8, + VENUS_FMT_MPEG4 = 9, + VENUS_FMT_MPEG2 = 10, + VENUS_FMT_H263 = 11, + VENUS_FMT_XVID = 12, +}; + struct venus_format { u32 pixfmt; unsigned int num_planes; diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index c6f0fd084758..bab985b12c81 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -30,69 +30,82 @@ * - future firmware versions could add support for >1 planes */ static const struct venus_format vdec_formats[] = { - { + [VENUS_FMT_NV12] = { .pixfmt = V4L2_PIX_FMT_NV12, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - }, { + }, + [VENUS_FMT_QC08C] = { .pixfmt = V4L2_PIX_FMT_QC08C, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - }, { + }, + [VENUS_FMT_QC10C] = { .pixfmt = V4L2_PIX_FMT_QC10C, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - }, { - .pixfmt = V4L2_PIX_FMT_MPEG4, - .num_planes = 1, - .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, - .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, - }, { - .pixfmt = V4L2_PIX_FMT_MPEG2, - .num_planes = 1, - .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, - .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, - }, { - .pixfmt = V4L2_PIX_FMT_H263, - .num_planes = 1, - .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, - .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, - }, { - .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_G, - .num_planes = 1, - .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, - .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, - }, { - .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_L, - .num_planes = 1, - .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, - .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, - }, { + }, + [VENUS_FMT_H264] = { .pixfmt = V4L2_PIX_FMT_H264, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, - }, { + }, + [VENUS_FMT_VP8] = { .pixfmt = V4L2_PIX_FMT_VP8, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, - }, { + }, + [VENUS_FMT_VP9] = { .pixfmt = V4L2_PIX_FMT_VP9, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, - }, { - .pixfmt = V4L2_PIX_FMT_XVID, - .num_planes = 1, - .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, - .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, - }, { + }, + [VENUS_FMT_HEVC] = { .pixfmt = V4L2_PIX_FMT_HEVC, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, }, + [VENUS_FMT_VC1_ANNEX_G] = { + .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_G, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, + }, + [VENUS_FMT_VC1_ANNEX_L] = { + .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_L, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, + }, + [VENUS_FMT_MPEG4] = { + .pixfmt = V4L2_PIX_FMT_MPEG4, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, + }, + [VENUS_FMT_MPEG2] = { + .pixfmt = V4L2_PIX_FMT_MPEG2, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, + }, + [VENUS_FMT_H263] = { + .pixfmt = V4L2_PIX_FMT_H263, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, + }, + [VENUS_FMT_XVID] = { + .pixfmt = V4L2_PIX_FMT_XVID, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + .flags = V4L2_FMT_FLAG_DYN_RESOLUTION, + }, + }; static const struct venus_format * @@ -1575,8 +1588,8 @@ static const struct hfi_inst_ops vdec_hfi_ops = { static void vdec_inst_init(struct venus_inst *inst) { inst->hfi_codec = HFI_VIDEO_CODEC_H264; - inst->fmt_out = &vdec_formats[8]; - inst->fmt_cap = &vdec_formats[0]; + inst->fmt_out = &vdec_formats[VENUS_FMT_H264]; + inst->fmt_cap = &vdec_formats[VENUS_FMT_NV12]; inst->width = frame_width_min(inst); inst->height = ALIGN(frame_height_min(inst), 32); inst->crop.left = 0; diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index 4666f42feea3..b60772cc2cdc 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -32,31 +32,36 @@ * - future firmware versions could add support for >1 planes */ static const struct venus_format venc_formats[] = { - { + [VENUS_FMT_NV12] = { .pixfmt = V4L2_PIX_FMT_NV12, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, - }, { - .pixfmt = V4L2_PIX_FMT_MPEG4, - .num_planes = 1, - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - }, { - .pixfmt = V4L2_PIX_FMT_H263, - .num_planes = 1, - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - }, { + }, + [VENUS_FMT_H264] = { .pixfmt = V4L2_PIX_FMT_H264, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - }, { + }, + [VENUS_FMT_VP8] = { .pixfmt = V4L2_PIX_FMT_VP8, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - }, { + }, + [VENUS_FMT_HEVC] = { .pixfmt = V4L2_PIX_FMT_HEVC, .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, }, + [VENUS_FMT_MPEG4] = { + .pixfmt = V4L2_PIX_FMT_MPEG4, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + }, + [VENUS_FMT_H263] = { + .pixfmt = V4L2_PIX_FMT_H263, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + }, }; static const struct venus_format * @@ -1416,8 +1421,8 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq, static void venc_inst_init(struct venus_inst *inst) { - inst->fmt_cap = &venc_formats[3]; - inst->fmt_out = &venc_formats[0]; + inst->fmt_cap = &venc_formats[VENUS_FMT_H264]; + inst->fmt_out = &venc_formats[VENUS_FMT_NV12]; inst->width = 1280; inst->height = ALIGN(720, 32); inst->out_width = 1280; From 3095607739d820fc691ab0cc6b85e801f74d2dc5 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Mon, 22 May 2023 07:48:15 +0100 Subject: [PATCH 118/253] media: venus: add support for V4L2_PIX_FMT_P010 color format add V4L2_PIX_FMT_P010 as supported color format for decoder. Reviewed-by: Konrad Dybcio Signed-off-by: Dikshita Agarwal Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/core.h | 21 +++++++++++---------- drivers/media/platform/qcom/venus/helpers.c | 2 ++ drivers/media/platform/qcom/venus/vdec.c | 5 +++++ 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index e988ed443d25..250342d27a6f 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -87,16 +87,17 @@ enum venus_fmt { VENUS_FMT_NV12 = 0, VENUS_FMT_QC08C = 1, VENUS_FMT_QC10C = 2, - VENUS_FMT_H264 = 3, - VENUS_FMT_VP8 = 4, - VENUS_FMT_VP9 = 5, - VENUS_FMT_HEVC = 6, - VENUS_FMT_VC1_ANNEX_G = 7, - VENUS_FMT_VC1_ANNEX_L = 8, - VENUS_FMT_MPEG4 = 9, - VENUS_FMT_MPEG2 = 10, - VENUS_FMT_H263 = 11, - VENUS_FMT_XVID = 12, + VENUS_FMT_P010 = 3, + VENUS_FMT_H264 = 4, + VENUS_FMT_VP8 = 5, + VENUS_FMT_VP9 = 6, + VENUS_FMT_HEVC = 7, + VENUS_FMT_VC1_ANNEX_G = 8, + VENUS_FMT_VC1_ANNEX_L = 9, + VENUS_FMT_MPEG4 = 10, + VENUS_FMT_MPEG2 = 11, + VENUS_FMT_H263 = 12, + VENUS_FMT_XVID = 13, }; struct venus_format { diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 7281bc6cdb39..5e8cf67b69d5 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -607,6 +607,8 @@ static u32 to_hfi_raw_fmt(u32 v4l2_fmt) return HFI_COLOR_FORMAT_NV12_UBWC; case V4L2_PIX_FMT_QC10C: return HFI_COLOR_FORMAT_YUV420_TP10_UBWC; + case V4L2_PIX_FMT_P010: + return HFI_COLOR_FORMAT_P010; default: break; } diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index bab985b12c81..7aeaf77ef84e 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -45,6 +45,11 @@ static const struct venus_format vdec_formats[] = { .num_planes = 1, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, }, + [VENUS_FMT_P010] = { + .pixfmt = V4L2_PIX_FMT_P010, + .num_planes = 1, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + }, [VENUS_FMT_H264] = { .pixfmt = V4L2_PIX_FMT_H264, .num_planes = 1, From 58b64dd09fd83542effd621daf65b53114904619 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Mon, 22 May 2023 07:48:16 +0100 Subject: [PATCH 119/253] media: venus: update calculation for dpb buffers Use dpb color format, width and height of output port for calculating buffer size of dpb buffers. Acked-by: Konrad Dybcio Signed-off-by: Dikshita Agarwal Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/helpers.c | 4 ++++ drivers/media/platform/qcom/venus/hfi_plat_bufs.h | 3 +++ drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c | 11 ++++++++--- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 5e8cf67b69d5..d02060ffe558 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -636,12 +636,16 @@ static int platform_get_bufreq(struct venus_inst *inst, u32 buftype, if (is_dec) { params.width = inst->width; params.height = inst->height; + params.out_width = inst->out_width; + params.out_height = inst->out_height; params.codec = inst->fmt_out->pixfmt; params.hfi_color_fmt = to_hfi_raw_fmt(inst->fmt_cap->pixfmt); params.dec.max_mbs_per_frame = mbs_per_frame_max(inst); params.dec.buffer_size_limit = 0; params.dec.is_secondary_output = inst->opb_buftype == HFI_BUFFER_OUTPUT2; + if (params.dec.is_secondary_output) + params.hfi_dpb_color_fmt = inst->dpb_fmt; params.dec.is_interlaced = inst->pic_struct != HFI_INTERLACE_FRAME_PROGRESSIVE; } else { diff --git a/drivers/media/platform/qcom/venus/hfi_plat_bufs.h b/drivers/media/platform/qcom/venus/hfi_plat_bufs.h index 52a51a3b964a..25e607452096 100644 --- a/drivers/media/platform/qcom/venus/hfi_plat_bufs.h +++ b/drivers/media/platform/qcom/venus/hfi_plat_bufs.h @@ -12,8 +12,11 @@ struct hfi_plat_buffers_params { u32 width; u32 height; + u32 out_width; + u32 out_height; u32 codec; u32 hfi_color_fmt; + u32 hfi_dpb_color_fmt; enum hfi_version version; u32 num_vpp_pipes; union { diff --git a/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c b/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c index a9be31ec6927..e97ff8cf6d64 100644 --- a/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c +++ b/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c @@ -1185,6 +1185,7 @@ static int bufreq_dec(struct hfi_plat_buffers_params *params, u32 buftype, enum hfi_version version = params->version; u32 codec = params->codec; u32 width = params->width, height = params->height, out_min_count; + u32 out_width = params->out_width, out_height = params->out_height; struct dec_bufsize_ops *dec_ops; bool is_secondary_output = params->dec.is_secondary_output; bool is_interlaced = params->dec.is_interlaced; @@ -1230,12 +1231,16 @@ static int bufreq_dec(struct hfi_plat_buffers_params *params, u32 buftype, calculate_dec_input_frame_size(width, height, codec, max_mbs_per_frame, buffer_size_limit); - } else if (buftype == HFI_BUFFER_OUTPUT || - buftype == HFI_BUFFER_OUTPUT2) { + } else if (buftype == HFI_BUFFER_OUTPUT || buftype == HFI_BUFFER_OUTPUT2) { bufreq->count_min = out_min_count; bufreq->size = venus_helper_get_framesz_raw(params->hfi_color_fmt, - width, height); + out_width, out_height); + if (buftype == HFI_BUFFER_OUTPUT && + params->dec.is_secondary_output) + bufreq->size = + venus_helper_get_framesz_raw(params->hfi_dpb_color_fmt, + out_width, out_height); } else if (buftype == HFI_BUFFER_INTERNAL_SCRATCH(version)) { bufreq->size = dec_ops->scratch(width, height, is_interlaced); } else if (buftype == HFI_BUFFER_INTERNAL_SCRATCH_1(version)) { From 996d215547a877406e601439bd6533d8524d27db Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Mon, 22 May 2023 07:48:17 +0100 Subject: [PATCH 120/253] media: venus: add handling of bit depth change from firmware Set opb format to TP10_UWC and dpb to client set format when bit depth change to 10 bit is detecting by firmware. Acked-by: Konrad Dybcio Signed-off-by: Dikshita Agarwal Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/helpers.c | 16 ++++++++++++++++ drivers/media/platform/qcom/venus/vdec.c | 5 ++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index d02060ffe558..1822e85ab6bf 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -1765,6 +1765,22 @@ int venus_helper_get_out_fmts(struct venus_inst *inst, u32 v4l2_fmt, if (!caps) return -EINVAL; + if (inst->bit_depth == VIDC_BITDEPTH_10 && inst->session_type == VIDC_SESSION_TYPE_DEC) { + found_ubwc = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT, + HFI_COLOR_FORMAT_YUV420_TP10_UBWC); + found = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT2, fmt); + if (found_ubwc && found) { + /* + * Hard-code DPB buffers to be 10bit UBWC + * until V4L2 is able to expose compressed/tiled + * formats to applications. + */ + *out_fmt = HFI_COLOR_FORMAT_YUV420_TP10_UBWC; + *out2_fmt = fmt; + return 0; + } + } + if (ubwc) { ubwc_fmt = fmt | HFI_COLOR_FORMAT_UBWC_BASE; found_ubwc = find_fmt_from_caps(caps, HFI_BUFFER_OUTPUT, diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 7aeaf77ef84e..96ecedafe546 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -736,6 +736,9 @@ static int vdec_set_work_route(struct venus_inst *inst) } #define is_ubwc_fmt(fmt) (!!((fmt) & HFI_COLOR_FORMAT_UBWC_BASE)) +#define is_10bit_ubwc_fmt(fmt) (!!((fmt) & HFI_COLOR_FORMAT_10_BIT_BASE & \ + HFI_COLOR_FORMAT_UBWC_BASE)) + static int vdec_output_conf(struct venus_inst *inst) { @@ -783,7 +786,7 @@ static int vdec_output_conf(struct venus_inst *inst) inst->opb_fmt = out2_fmt; inst->dpb_buftype = HFI_BUFFER_OUTPUT; inst->dpb_fmt = out_fmt; - } else if (is_ubwc_fmt(out2_fmt)) { + } else if (is_ubwc_fmt(out2_fmt) || is_10bit_ubwc_fmt(out_fmt)) { inst->opb_buftype = HFI_BUFFER_OUTPUT; inst->opb_fmt = out_fmt; inst->dpb_buftype = HFI_BUFFER_OUTPUT2; From 08998cf30f66862916b7b21784f0640677415492 Mon Sep 17 00:00:00 2001 From: Dikshita Agarwal Date: Mon, 22 May 2023 07:48:18 +0100 Subject: [PATCH 121/253] media: venus: return P010 as preferred format for 10 bit decode If bit depth is detected as 10 bit by firmware, return P010 as preferred decoder format to the client. Signed-off-by: Dikshita Agarwal Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/vdec.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 96ecedafe546..12a2e99508f5 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -1503,8 +1503,13 @@ static void vdec_event_change(struct venus_inst *inst, inst->out_width = ev_data->width; inst->out_height = ev_data->height; - if (inst->bit_depth != ev_data->bit_depth) + if (inst->bit_depth != ev_data->bit_depth) { inst->bit_depth = ev_data->bit_depth; + if (inst->bit_depth == VIDC_BITDEPTH_10) + inst->fmt_cap = &vdec_formats[VENUS_FMT_P010]; + else + inst->fmt_cap = &vdec_formats[VENUS_FMT_NV12]; + } if (inst->pic_struct != ev_data->pic_struct) inst->pic_struct = ev_data->pic_struct; From 34318b808ef20cdddd4e187ea2df0455936cf61b Mon Sep 17 00:00:00 2001 From: Sergey Senozhatsky Date: Fri, 26 May 2023 07:29:34 +0100 Subject: [PATCH 122/253] media: venus: provide ctx queue lock for ioctl synchronization Video device has to provide a lock so that __video_do_ioctl() can serialize IOCTL calls. Introduce a dedicated venus_inst mutex for the purpose of vb2 operations synchronization. Signed-off-by: Sergey Senozhatsky Reviewed-by: Vikash Garodia Reviewed-by: Bryan O'Donoghue Signed-off-by: Stanimir Varbanov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/qcom/venus/core.h | 2 ++ drivers/media/platform/qcom/venus/vdec.c | 4 ++++ drivers/media/platform/qcom/venus/venc.c | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 250342d27a6f..320bde0f83cb 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -411,6 +411,7 @@ enum venus_inst_modes { * @sequence_out: a sequence counter for output queue * @m2m_dev: a reference to m2m device structure * @m2m_ctx: a reference to m2m context structure + * @ctx_q_lock: a lock to serialize video device ioctl calls * @state: current state of the instance * @done: a completion for sync HFI operation * @error: an error returned during last HFI sync operation @@ -482,6 +483,7 @@ struct venus_inst { u32 sequence_out; struct v4l2_m2m_dev *m2m_dev; struct v4l2_m2m_ctx *m2m_ctx; + struct mutex ctx_q_lock; unsigned int state; struct completion done; unsigned int error; diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 12a2e99508f5..f5676440dd36 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -1643,6 +1643,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq, src_vq->allow_zero_bytesused = 1; src_vq->min_buffers_needed = 0; src_vq->dev = inst->core->dev; + src_vq->lock = &inst->ctx_q_lock; ret = vb2_queue_init(src_vq); if (ret) return ret; @@ -1657,6 +1658,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq, dst_vq->allow_zero_bytesused = 1; dst_vq->min_buffers_needed = 0; dst_vq->dev = inst->core->dev; + dst_vq->lock = &inst->ctx_q_lock; return vb2_queue_init(dst_vq); } @@ -1675,6 +1677,7 @@ static int vdec_open(struct file *file) INIT_LIST_HEAD(&inst->internalbufs); INIT_LIST_HEAD(&inst->list); mutex_init(&inst->lock); + mutex_init(&inst->ctx_q_lock); inst->core = core; inst->session_type = VIDC_SESSION_TYPE_DEC; @@ -1750,6 +1753,7 @@ static int vdec_close(struct file *file) ida_destroy(&inst->dpb_ids); hfi_session_destroy(inst); mutex_destroy(&inst->lock); + mutex_destroy(&inst->ctx_q_lock); v4l2_fh_del(&inst->fh); v4l2_fh_exit(&inst->fh); diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index b60772cc2cdc..6d773b000e8a 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -1400,6 +1400,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq, src_vq->allow_zero_bytesused = 1; src_vq->min_buffers_needed = 1; src_vq->dev = inst->core->dev; + src_vq->lock = &inst->ctx_q_lock; if (inst->core->res->hfi_version == HFI_VERSION_1XX) src_vq->bidirectional = 1; ret = vb2_queue_init(src_vq); @@ -1416,6 +1417,7 @@ static int m2m_queue_init(void *priv, struct vb2_queue *src_vq, dst_vq->allow_zero_bytesused = 1; dst_vq->min_buffers_needed = 1; dst_vq->dev = inst->core->dev; + dst_vq->lock = &inst->ctx_q_lock; return vb2_queue_init(dst_vq); } @@ -1448,6 +1450,7 @@ static int venc_open(struct file *file) INIT_LIST_HEAD(&inst->internalbufs); INIT_LIST_HEAD(&inst->list); mutex_init(&inst->lock); + mutex_init(&inst->ctx_q_lock); inst->core = core; inst->session_type = VIDC_SESSION_TYPE_ENC; @@ -1517,6 +1520,7 @@ static int venc_close(struct file *file) venc_ctrl_deinit(inst); hfi_session_destroy(inst); mutex_destroy(&inst->lock); + mutex_destroy(&inst->ctx_q_lock); v4l2_fh_del(&inst->fh); v4l2_fh_exit(&inst->fh); From 0ece58b280a4fa5e34cac64524a991f3cadccc45 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 2 Jun 2023 16:19:19 +0300 Subject: [PATCH 123/253] Revert "media: uvcvideo: Limit power line control for Acer EasyCamera" This reverts commit 5dd0eab84ae9a4b292baf1ad02e1a273c475cd04. Revert this patch as it has been merged twice. The earlier merged commit is 81e78a6fc320 ("media: uvcvideo: Limit power line control for Acer EasyCamera"). Reported-by: Dmitry Perchanov Signed-off-by: Sakari Ailus Reviewed-by: Ricardo Ribalda Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_driver.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index d631ce4f9f7b..235fc4f52a98 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -3003,15 +3003,6 @@ static const struct usb_device_id uvc_ids[] = { .bInterfaceProtocol = 0, .driver_info = (kernel_ulong_t)&uvc_ctrl_power_line_limited }, /* Acer EasyCamera */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = 0x5986, - .idProduct = 0x1180, - .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = (kernel_ulong_t)&uvc_ctrl_power_line_limited }, - /* Acer EasyCamera */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x5986, From e7f61113edcac20f53068de46e7163004f46f99f Mon Sep 17 00:00:00 2001 From: Dmitry Perchanov Date: Thu, 1 Jun 2023 19:08:46 +0300 Subject: [PATCH 124/253] media: uapi: v4l: Intel metadata format update Update metadata structure for Intel RealSense UVC/MIPI cameras. Compliant to Intel Configuration version 3. Signed-off-by: Dmitry Perchanov Reviewed-by: Sakari Ailus Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- .../userspace-api/media/v4l/metafmt-d4xx.rst | 55 ++++++++++++++++--- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/Documentation/userspace-api/media/v4l/metafmt-d4xx.rst b/Documentation/userspace-api/media/v4l/metafmt-d4xx.rst index 4e437ba97a0e..541836074f94 100644 --- a/Documentation/userspace-api/media/v4l/metafmt-d4xx.rst +++ b/Documentation/userspace-api/media/v4l/metafmt-d4xx.rst @@ -12,7 +12,7 @@ Intel D4xx UVC Cameras Metadata Description =========== -Intel D4xx (D435 and other) cameras include per-frame metadata in their UVC +Intel D4xx (D435, D455 and others) cameras include per-frame metadata in their UVC payload headers, following the Microsoft(R) UVC extension proposal [1_]. That means, that the private D4XX metadata, following the standard UVC header, is organised in blocks. D4XX cameras implement several standard block types, @@ -26,6 +26,8 @@ V4L2_META_FMT_UVC with the only difference, that it also includes proprietary payload header data. D4xx cameras use bulk transfers and only send one payload per frame, therefore their headers cannot be larger than 255 bytes. +This document implements Intel Configuration version 3 [9_]. + Below are proprietary Microsoft style metadata types, used by D4xx cameras, where all fields are in little endian order: @@ -43,10 +45,10 @@ where all fields are in little endian order: * - __u32 ID - 0x80000000 * - __u32 Size - - Size in bytes (currently 56) + - Size in bytes, include ID (all protocol versions: 60) * - __u32 Version - - Version of this structure. The documentation herein corresponds to - version xxx. The version number will be incremented when new fields are + - Version of this structure. The documentation herein covers versions 1, + 2 and 3. The version number will be incremented when new fields are added. * - __u32 Flags - A bitmask of flags: see [2_] below @@ -72,13 +74,17 @@ where all fields are in little endian order: - Bottom border of the AE Region of Interest * - __u32 Preset - Preset selector value, default: 0, unless changed by the user - * - __u32 Laser mode - - 0: off, 1: on + * - __u8 Emitter mode (v3 only) (__u32 Laser mode for v1) [8_] + - 0: off, 1: on, same as __u32 Laser mode for v1 + * - __u8 RFU byte (v3 only) + - Spare byte for future use + * - __u16 LED Power (v3 only) + - Led power value 0-360 (F416 SKU) * - :cspan:`1` *Capture Timing* * - __u32 ID - 0x80000001 * - __u32 Size - - Size in bytes (currently 40) + - Size in bytes, include ID (all protocol versions: 40) * - __u32 Version - Version of this structure. The documentation herein corresponds to version xxx. The version number will be incremented when new fields are @@ -101,7 +107,7 @@ where all fields are in little endian order: * - __u32 ID - 0x80000002 * - __u32 Size - - Size in bytes (currently 40) + - Size in bytes, include ID (v1:36, v3:40) * - __u32 Version - Version of this structure. The documentation herein corresponds to version xxx. The version number will be incremented when new fields are @@ -124,6 +130,14 @@ where all fields are in little endian order: - Requested frame rate per second * - __u16 Trigger - Byte 0: bit 0: depth and RGB are synchronised, bit 1: external trigger + * - __u16 Calibration count (v3 only) + - Calibration counter, see [4_] below + * - __u8 GPIO input data (v3 only) + - GPIO readout, see [4_] below (Supported from FW 5.12.7.0) + * - __u32 Sub-preset info (v3 only) + - Sub-preset choice information, see [4_] below + * - __u8 reserved (v3 only) + - RFU byte. .. _1: @@ -140,6 +154,8 @@ where all fields are in little endian order: 0x00000010 Exposure priority 0x00000020 AE ROI 0x00000040 Preset + 0x00000080 Emitter mode + 0x00000100 LED Power .. _3: @@ -165,6 +181,8 @@ where all fields are in little endian order: 0x00000040 Framerate 0x00000080 Trigger 0x00000100 Cal count + 0x00000200 GPIO Input Data + 0x00000400 Sub-preset Info .. _5: @@ -211,3 +229,24 @@ Left sensor: :: Fish Eye sensor: :: 1 RAW8 + +.. _8: + +[8] The "Laser mode" has been replaced in version 3 by three different fields. +"Laser" has been renamed to "Emitter" as there are multiple technologies for +camera projectors. As we have another field for "Laser Power" we introduced +"LED Power" for extra emitter. + +The "Laser mode" __u32 fiels has been split into: :: + 1 __u8 Emitter mode + 2 __u8 RFU byte + 3 __u16 LED Power + +This is a change between versions 1 and 3. All versions 1, 2 and 3 are backward +compatible with the same data format and they are supported. See [2_] for which +attributes are valid. + +.. _9: + +[9] LibRealSense SDK metadata source: +https://github.com/IntelRealSense/librealsense/blob/master/src/metadata.h From e33ae66a2e22f65c8e43ef95b614d42a685789d6 Mon Sep 17 00:00:00 2001 From: Dmitry Perchanov Date: Thu, 20 Apr 2023 12:06:55 +0300 Subject: [PATCH 125/253] media: uvcvideo: Enable Intel RealSense metadata for devices Intel RealSense UVC Depth cameras produce metadata in a vendor-specific format that is already supported by the uvcvideo driver. Enable handling of this metadata for 7 additional RealSense devices. Co-developed-by: Yu MENG Co-developed-by: Evgeni Raikhel Signed-off-by: Dmitry Perchanov Reviewed-by: Laurent Pinchart Reviewed-by: Sakari Ailus Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_driver.c | 63 ++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 235fc4f52a98..a0e592d46fa2 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -3011,6 +3011,33 @@ static const struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = (kernel_ulong_t)&uvc_ctrl_power_line_limited }, + /* Intel D410/ASR depth camera */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x8086, + .idProduct = 0x0ad2, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, + /* Intel D415/ASRC depth camera */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x8086, + .idProduct = 0x0ad3, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, + /* Intel D430/AWG depth camera */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x8086, + .idProduct = 0x0ad4, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, /* Intel RealSense D4M */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, @@ -3020,6 +3047,42 @@ static const struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, + /* Intel D435/AWGC depth camera */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x8086, + .idProduct = 0x0b07, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, + /* Intel D435i depth camera */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x8086, + .idProduct = 0x0b3a, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, + /* Intel D405 Depth Camera */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x8086, + .idProduct = 0x0b5b, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, + /* Intel D455 Depth Camera */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x8086, + .idProduct = 0x0b5c, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, /* Generic USB Video Class */ { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_UNDEFINED) }, { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) }, From ccfad4e85e3da034b0cd1c24ded77647a60ce3ac Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 20 Apr 2023 06:33:03 +0300 Subject: [PATCH 126/253] media: uvcvideo: Rename uvc_streaming 'format' field to 'formats' The uvc_streaming 'format' field points to an array of formats. Rename it to 'formats' to make this clearer. Signed-off-by: Laurent Pinchart Reviewed-by: Ricardo Ribalda Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_driver.c | 4 ++-- drivers/media/usb/uvc/uvc_v4l2.c | 16 ++++++++-------- drivers/media/usb/uvc/uvc_video.c | 6 +++--- drivers/media/usb/uvc/uvcvideo.h | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index a0e592d46fa2..8a1698e12977 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -184,7 +184,7 @@ static void uvc_stream_delete(struct uvc_streaming *stream) usb_put_intf(stream->intf); - kfree(stream->format); + kfree(stream->formats); kfree(stream->header.bmaControls); kfree(stream); } @@ -677,7 +677,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, frame = (struct uvc_frame *)&format[nformats]; interval = (u32 *)&frame[nframes]; - streaming->format = format; + streaming->formats = format; streaming->nformats = 0; /* Parse the format descriptors. */ diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 35453f81c1d9..6960d7ebd904 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -235,7 +235,7 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, * format otherwise. */ for (i = 0; i < stream->nformats; ++i) { - format = &stream->format[i]; + format = &stream->formats[i]; if (format->fcc == fmt->fmt.pix.pixelformat) break; } @@ -319,8 +319,8 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, * accepted the requested format as-is. */ for (i = 0; i < stream->nformats; ++i) { - if (probe->bFormatIndex == stream->format[i].index) { - format = &stream->format[i]; + if (probe->bFormatIndex == stream->formats[i].index) { + format = &stream->formats[i]; break; } } @@ -708,7 +708,7 @@ static int uvc_ioctl_enum_fmt(struct uvc_streaming *stream, fmt->index = index; fmt->type = type; - format = &stream->format[fmt->index]; + format = &stream->formats[fmt->index]; fmt->flags = 0; if (format->flags & UVC_FMT_FLAG_COMPRESSED) fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; @@ -1256,8 +1256,8 @@ static int uvc_ioctl_enum_framesizes(struct file *file, void *fh, /* Look for the given pixel format */ for (i = 0; i < stream->nformats; i++) { - if (stream->format[i].fcc == fsize->pixel_format) { - format = &stream->format[i]; + if (stream->formats[i].fcc == fsize->pixel_format) { + format = &stream->formats[i]; break; } } @@ -1297,8 +1297,8 @@ static int uvc_ioctl_enum_frameintervals(struct file *file, void *fh, /* Look for the given pixel format and frame size */ for (i = 0; i < stream->nformats; i++) { - if (stream->format[i].fcc == fival->pixel_format) { - format = &stream->format[i]; + if (stream->formats[i].fcc == fival->pixel_format) { + format = &stream->formats[i]; break; } } diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index d4b023d4de7c..af540f435099 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -166,8 +166,8 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream, } for (i = 0; i < stream->nformats; ++i) { - if (stream->format[i].index == ctrl->bFormatIndex) { - format = &stream->format[i]; + if (stream->formats[i].index == ctrl->bFormatIndex) { + format = &stream->formats[i]; break; } } @@ -2161,7 +2161,7 @@ int uvc_video_init(struct uvc_streaming *stream) * available format otherwise. */ for (i = stream->nformats; i > 0; --i) { - format = &stream->format[i-1]; + format = &stream->formats[i-1]; if (format->index == probe->bFormatIndex) break; } diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 9a596c8d894a..05fec637417d 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -438,7 +438,7 @@ struct uvc_streaming { enum v4l2_buf_type type; unsigned int nformats; - struct uvc_format *format; + struct uvc_format *formats; struct uvc_streaming_control ctrl; struct uvc_format *def_format; From aa8db3adc7b2e4be80294bfcbbb20097dee76af6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 20 Apr 2023 06:33:03 +0300 Subject: [PATCH 127/253] media: uvcvideo: Rename uvc_format 'frame' field to 'frames' The uvc_format 'frame' field points to an array of frames. Rename it to 'frames' to make this clearer. Signed-off-by: Laurent Pinchart Reviewed-by: Ricardo Ribalda Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_driver.c | 8 ++++---- drivers/media/usb/uvc/uvc_v4l2.c | 32 +++++++++++++++--------------- drivers/media/usb/uvc/uvc_video.c | 6 +++--- drivers/media/usb/uvc/uvcvideo.h | 2 +- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 8a1698e12977..445a7ae69b9b 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -339,8 +339,8 @@ static int uvc_parse_format(struct uvc_device *dev, ftype = 0; /* Create a dummy frame descriptor. */ - frame = &format->frame[0]; - memset(&format->frame[0], 0, sizeof(format->frame[0])); + frame = &format->frames[0]; + memset(&format->frames[0], 0, sizeof(format->frames[0])); frame->bFrameIntervalType = 1; frame->dwDefaultFrameInterval = 1; frame->dwFrameInterval = *intervals; @@ -370,7 +370,7 @@ static int uvc_parse_format(struct uvc_device *dev, */ while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && buffer[2] == ftype) { - frame = &format->frame[format->nframes]; + frame = &format->frames[format->nframes]; if (ftype != UVC_VS_FRAME_FRAME_BASED) n = buflen > 25 ? buffer[25] : 0; else @@ -687,7 +687,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, case UVC_VS_FORMAT_MJPEG: case UVC_VS_FORMAT_DV: case UVC_VS_FORMAT_FRAME_BASED: - format->frame = frame; + format->frames = frame; ret = uvc_parse_format(dev, streaming, format, &interval, buffer, buflen); if (ret < 0) diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 6960d7ebd904..e7261b2543cb 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -255,14 +255,14 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, maxd = (unsigned int)-1; for (i = 0; i < format->nframes; ++i) { - u16 w = format->frame[i].wWidth; - u16 h = format->frame[i].wHeight; + u16 w = format->frames[i].wWidth; + u16 h = format->frames[i].wHeight; d = min(w, rw) * min(h, rh); d = w*h + rw*rh - 2*d; if (d < maxd) { maxd = d; - frame = &format->frame[i]; + frame = &format->frames[i]; } if (maxd == 0) @@ -331,8 +331,8 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, probe->bFormatIndex); for (i = 0; i < format->nframes; ++i) { - if (probe->bFrameIndex == format->frame[i].bFrameIndex) { - frame = &format->frame[i]; + if (probe->bFrameIndex == format->frames[i].bFrameIndex) { + frame = &format->frames[i]; break; } } @@ -501,19 +501,19 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, for (i = 0; i < format->nframes && maxd != 0; i++) { u32 d, ival; - if (&format->frame[i] == stream->cur_frame) + if (&format->frames[i] == stream->cur_frame) continue; - if (format->frame[i].wWidth != stream->cur_frame->wWidth || - format->frame[i].wHeight != stream->cur_frame->wHeight) + if (format->frames[i].wWidth != stream->cur_frame->wWidth || + format->frames[i].wHeight != stream->cur_frame->wHeight) continue; - ival = uvc_try_frame_interval(&format->frame[i], interval); + ival = uvc_try_frame_interval(&format->frames[i], interval); d = abs((s32)ival - interval); if (d >= maxd) continue; - frame = &format->frame[i]; + frame = &format->frames[i]; probe.bFrameIndex = frame->bFrameIndex; probe.dwFrameInterval = ival; maxd = d; @@ -1266,10 +1266,10 @@ static int uvc_ioctl_enum_framesizes(struct file *file, void *fh, /* Skip duplicate frame sizes */ for (i = 0, index = 0; i < format->nframes; i++) { - if (frame && frame->wWidth == format->frame[i].wWidth && - frame->wHeight == format->frame[i].wHeight) + if (frame && frame->wWidth == format->frames[i].wWidth && + frame->wHeight == format->frames[i].wHeight) continue; - frame = &format->frame[i]; + frame = &format->frames[i]; if (index == fsize->index) break; index++; @@ -1307,9 +1307,9 @@ static int uvc_ioctl_enum_frameintervals(struct file *file, void *fh, index = fival->index; for (i = 0; i < format->nframes; i++) { - if (format->frame[i].wWidth == fival->width && - format->frame[i].wHeight == fival->height) { - frame = &format->frame[i]; + if (format->frames[i].wWidth == fival->width && + format->frames[i].wHeight == fival->height) { + frame = &format->frames[i]; nintervals = frame->bFrameIntervalType ?: 1; if (index < nintervals) break; diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index af540f435099..34c781b7dee2 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -176,8 +176,8 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream, return; for (i = 0; i < format->nframes; ++i) { - if (format->frame[i].bFrameIndex == ctrl->bFrameIndex) { - frame = &format->frame[i]; + if (format->frames[i].bFrameIndex == ctrl->bFrameIndex) { + frame = &format->frames[i]; break; } } @@ -2179,7 +2179,7 @@ int uvc_video_init(struct uvc_streaming *stream) * descriptor is not found, use the first available frame. */ for (i = format->nframes; i > 0; --i) { - frame = &format->frame[i-1]; + frame = &format->frames[i-1]; if (frame->bFrameIndex == probe->bFrameIndex) break; } diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 05fec637417d..bb0773637171 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -265,7 +265,7 @@ struct uvc_format { u32 flags; unsigned int nframes; - struct uvc_frame *frame; + struct uvc_frame *frames; }; struct uvc_streaming_header { From 7c5dfb2d912c005285682508447585c15aa7b765 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 5 May 2023 14:45:24 +0300 Subject: [PATCH 128/253] media: uvcvideo: Use clamp() to replace manual implementation The kernel has a nice clamp() macro, use it to replace a manual implementation based on min() and max(). No functional change is intended. Signed-off-by: Laurent Pinchart Reviewed-by: Ricardo Ribalda Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_driver.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 445a7ae69b9b..9f89c781e885 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -437,9 +437,9 @@ static int uvc_parse_format(struct uvc_device *dev, */ n -= frame->bFrameIntervalType ? 1 : 2; frame->dwDefaultFrameInterval = - min(frame->dwFrameInterval[n], - max(frame->dwFrameInterval[0], - frame->dwDefaultFrameInterval)); + clamp(frame->dwDefaultFrameInterval, + frame->dwFrameInterval[0], + frame->dwFrameInterval[n]); if (dev->quirks & UVC_QUIRK_RESTRICT_FRAME_RATE) { frame->bFrameIntervalType = 1; From c9d597b9b7ef9ffcb54051f04798b608edc6850c Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 5 May 2023 14:45:24 +0300 Subject: [PATCH 129/253] media: uvcvideo: Reorganize format descriptor parsing Format descriptor parsing has grown over time and now mixes parsing of frame intervals with various quirk handling. Reorganize it to make the code easier to follow, by parsing frame intervals first, and then applying fixes and quirks. No functional change is intended. Signed-off-by: Laurent Pinchart Reviewed-by: Ricardo Ribalda Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_driver.c | 40 +++++++++++++++++++----------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 9f89c781e885..ef9066dcf535 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -405,8 +405,27 @@ static int uvc_parse_format(struct uvc_device *dev, get_unaligned_le32(&buffer[17]); frame->bFrameIntervalType = buffer[21]; } + + /* + * Copy the frame intervals. + * + * Some bogus devices report dwMinFrameInterval equal to + * dwMaxFrameInterval and have dwFrameIntervalStep set to + * zero. Setting all null intervals to 1 fixes the problem and + * some other divisions by zero that could happen. + */ frame->dwFrameInterval = *intervals; + for (i = 0; i < n; ++i) { + interval = get_unaligned_le32(&buffer[26+4*i]); + *(*intervals)++ = interval ? interval : 1; + } + + /* + * Apply more fixes, quirks and workarounds to handle incorrect + * or broken descriptors. + */ + /* * Several UVC chipsets screw up dwMaxVideoFrameBufferSize * completely. Observed behaviours range from setting the @@ -420,27 +439,18 @@ static int uvc_parse_format(struct uvc_device *dev, frame->dwMaxVideoFrameBufferSize = format->bpp * frame->wWidth * frame->wHeight / 8; - /* - * Some bogus devices report dwMinFrameInterval equal to - * dwMaxFrameInterval and have dwFrameIntervalStep set to - * zero. Setting all null intervals to 1 fixes the problem and - * some other divisions by zero that could happen. - */ - for (i = 0; i < n; ++i) { - interval = get_unaligned_le32(&buffer[26+4*i]); - *(*intervals)++ = interval ? interval : 1; - } - - /* - * Make sure that the default frame interval stays between - * the boundaries. - */ + /* Clamp the default frame interval to the boundaries. */ n -= frame->bFrameIntervalType ? 1 : 2; frame->dwDefaultFrameInterval = clamp(frame->dwDefaultFrameInterval, frame->dwFrameInterval[0], frame->dwFrameInterval[n]); + /* + * Some devices report frame intervals that are not functional. + * If the corresponding quirk is set, restrict operation to the + * first interval only. + */ if (dev->quirks & UVC_QUIRK_RESTRICT_FRAME_RATE) { frame->bFrameIntervalType = 1; frame->dwFrameInterval[0] = From 7691d900b9291417dc6a88262f43176a63536c31 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 5 May 2023 14:45:24 +0300 Subject: [PATCH 130/253] media: uvcvideo: Increment intervals pointer at end of parsing The intervals pointer is incremented for each interval when parsing the format descriptor. This doesn't cause any issue as such, but gets in the way of constifying some pointers. Modify the parsing code to index the intervals pointer as an array and increment it in one go at end of parsing. Careful readers will notice that the maxIntervalIndex variable is set to 1 instead of n - 2 when bFrameIntervalType has a zero value. This is functionally equivalent, as n is equal to 3 in that case. Signed-off-by: Laurent Pinchart Reviewed-by: Ricardo Ribalda Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_driver.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index ef9066dcf535..adfb0b08d129 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -370,6 +370,8 @@ static int uvc_parse_format(struct uvc_device *dev, */ while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && buffer[2] == ftype) { + unsigned int maxIntervalIndex; + frame = &format->frames[format->nframes]; if (ftype != UVC_VS_FRAME_FRAME_BASED) n = buflen > 25 ? buffer[25] : 0; @@ -418,7 +420,7 @@ static int uvc_parse_format(struct uvc_device *dev, for (i = 0; i < n; ++i) { interval = get_unaligned_le32(&buffer[26+4*i]); - *(*intervals)++ = interval ? interval : 1; + (*intervals)[i] = interval ? interval : 1; } /* @@ -439,12 +441,17 @@ static int uvc_parse_format(struct uvc_device *dev, frame->dwMaxVideoFrameBufferSize = format->bpp * frame->wWidth * frame->wHeight / 8; - /* Clamp the default frame interval to the boundaries. */ - n -= frame->bFrameIntervalType ? 1 : 2; + /* + * Clamp the default frame interval to the boundaries. A zero + * bFrameIntervalType value indicates a continuous frame + * interval range, with dwFrameInterval[0] storing the minimum + * value and dwFrameInterval[1] storing the maximum value. + */ + maxIntervalIndex = frame->bFrameIntervalType ? n - 1 : 1; frame->dwDefaultFrameInterval = clamp(frame->dwDefaultFrameInterval, frame->dwFrameInterval[0], - frame->dwFrameInterval[n]); + frame->dwFrameInterval[maxIntervalIndex]); /* * Some devices report frame intervals that are not functional. @@ -463,6 +470,8 @@ static int uvc_parse_format(struct uvc_device *dev, (100000000 / frame->dwDefaultFrameInterval) % 10); format->nframes++; + *intervals += n; + buflen -= buffer[0]; buffer += buffer[0]; } From af621ba2ede802bcd01b9d9af539f95030e21795 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 20 Apr 2023 06:47:57 +0300 Subject: [PATCH 131/253] media: uvcvideo: Constify formats, frames and intervals The formats, frames and intervals stored in the uvc_streaming structure are not meant to change after being parsed at probe time. Make them const to prevent unintended modifications, and adapt the probe code accordingly to use non-const pointers during parsing. Signed-off-by: Laurent Pinchart Reviewed-by: Ricardo Ribalda Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_driver.c | 16 +++++++-------- drivers/media/usb/uvc/uvc_v4l2.c | 31 +++++++++++++++--------------- drivers/media/usb/uvc/uvc_video.c | 8 ++++---- drivers/media/usb/uvc/uvcvideo.h | 12 ++++++------ 4 files changed, 34 insertions(+), 33 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index adfb0b08d129..1f40f92b79b7 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -221,7 +221,8 @@ static struct uvc_streaming *uvc_stream_new(struct uvc_device *dev, static int uvc_parse_format(struct uvc_device *dev, struct uvc_streaming *streaming, struct uvc_format *format, - u32 **intervals, unsigned char *buffer, int buflen) + struct uvc_frame *frames, u32 **intervals, unsigned char *buffer, + int buflen) { struct usb_interface *intf = streaming->intf; struct usb_host_interface *alts = intf->cur_altsetting; @@ -235,6 +236,7 @@ static int uvc_parse_format(struct uvc_device *dev, format->type = buffer[2]; format->index = buffer[3]; + format->frames = frames; switch (buffer[2]) { case UVC_VS_FORMAT_UNCOMPRESSED: @@ -339,8 +341,8 @@ static int uvc_parse_format(struct uvc_device *dev, ftype = 0; /* Create a dummy frame descriptor. */ - frame = &format->frames[0]; - memset(&format->frames[0], 0, sizeof(format->frames[0])); + frame = &frames[0]; + memset(frame, 0, sizeof(*frame)); frame->bFrameIntervalType = 1; frame->dwDefaultFrameInterval = 1; frame->dwFrameInterval = *intervals; @@ -372,7 +374,7 @@ static int uvc_parse_format(struct uvc_device *dev, buffer[2] == ftype) { unsigned int maxIntervalIndex; - frame = &format->frames[format->nframes]; + frame = &frames[format->nframes]; if (ftype != UVC_VS_FRAME_FRAME_BASED) n = buflen > 25 ? buffer[25] : 0; else @@ -460,8 +462,7 @@ static int uvc_parse_format(struct uvc_device *dev, */ if (dev->quirks & UVC_QUIRK_RESTRICT_FRAME_RATE) { frame->bFrameIntervalType = 1; - frame->dwFrameInterval[0] = - frame->dwDefaultFrameInterval; + (*intervals)[0] = frame->dwDefaultFrameInterval; } uvc_dbg(dev, DESCR, "- %ux%u (%u.%u fps)\n", @@ -706,8 +707,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, case UVC_VS_FORMAT_MJPEG: case UVC_VS_FORMAT_DV: case UVC_VS_FORMAT_FRAME_BASED: - format->frames = frame; - ret = uvc_parse_format(dev, streaming, format, + ret = uvc_parse_format(dev, streaming, format, frame, &interval, buffer, buflen); if (ret < 0) goto error; diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index e7261b2543cb..5ac2a424b13d 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -161,7 +161,7 @@ free_map: * the Video Probe and Commit negotiation, but some hardware don't implement * that feature. */ -static u32 uvc_try_frame_interval(struct uvc_frame *frame, u32 interval) +static u32 uvc_try_frame_interval(const struct uvc_frame *frame, u32 interval) { unsigned int i; @@ -210,10 +210,11 @@ static u32 uvc_v4l2_get_bytesperline(const struct uvc_format *format, static int uvc_v4l2_try_format(struct uvc_streaming *stream, struct v4l2_format *fmt, struct uvc_streaming_control *probe, - struct uvc_format **uvc_format, struct uvc_frame **uvc_frame) + const struct uvc_format **uvc_format, + const struct uvc_frame **uvc_frame) { - struct uvc_format *format = NULL; - struct uvc_frame *frame = NULL; + const struct uvc_format *format = NULL; + const struct uvc_frame *frame = NULL; u16 rw, rh; unsigned int d, maxd; unsigned int i; @@ -363,8 +364,8 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, static int uvc_v4l2_get_format(struct uvc_streaming *stream, struct v4l2_format *fmt) { - struct uvc_format *format; - struct uvc_frame *frame; + const struct uvc_format *format; + const struct uvc_frame *frame; int ret = 0; if (fmt->type != stream->type) @@ -398,8 +399,8 @@ static int uvc_v4l2_set_format(struct uvc_streaming *stream, struct v4l2_format *fmt) { struct uvc_streaming_control probe; - struct uvc_format *format; - struct uvc_frame *frame; + const struct uvc_format *format; + const struct uvc_frame *frame; int ret; if (fmt->type != stream->type) @@ -465,8 +466,8 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, { struct uvc_streaming_control probe; struct v4l2_fract timeperframe; - struct uvc_format *format; - struct uvc_frame *frame; + const struct uvc_format *format; + const struct uvc_frame *frame; u32 interval, maxd; unsigned int i; int ret; @@ -697,7 +698,7 @@ static int uvc_ioctl_querycap(struct file *file, void *fh, static int uvc_ioctl_enum_fmt(struct uvc_streaming *stream, struct v4l2_fmtdesc *fmt) { - struct uvc_format *format; + const struct uvc_format *format; enum v4l2_buf_type type = fmt->type; u32 index = fmt->index; @@ -1249,8 +1250,8 @@ static int uvc_ioctl_enum_framesizes(struct file *file, void *fh, { struct uvc_fh *handle = fh; struct uvc_streaming *stream = handle->stream; - struct uvc_format *format = NULL; - struct uvc_frame *frame = NULL; + const struct uvc_format *format = NULL; + const struct uvc_frame *frame = NULL; unsigned int index; unsigned int i; @@ -1289,8 +1290,8 @@ static int uvc_ioctl_enum_frameintervals(struct file *file, void *fh, { struct uvc_fh *handle = fh; struct uvc_streaming *stream = handle->stream; - struct uvc_format *format = NULL; - struct uvc_frame *frame = NULL; + const struct uvc_format *format = NULL; + const struct uvc_frame *frame = NULL; unsigned int nintervals; unsigned int index; unsigned int i; diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index 34c781b7dee2..28dde08ec6c5 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -137,8 +137,8 @@ static const struct usb_device_id elgato_cam_link_4k = { static void uvc_fixup_video_ctrl(struct uvc_streaming *stream, struct uvc_streaming_control *ctrl) { - struct uvc_format *format = NULL; - struct uvc_frame *frame = NULL; + const struct uvc_format *format = NULL; + const struct uvc_frame *frame = NULL; unsigned int i; /* @@ -2100,8 +2100,8 @@ int uvc_video_resume(struct uvc_streaming *stream, int reset) int uvc_video_init(struct uvc_streaming *stream) { struct uvc_streaming_control *probe = &stream->ctrl; - struct uvc_format *format = NULL; - struct uvc_frame *frame = NULL; + const struct uvc_format *format = NULL; + const struct uvc_frame *frame = NULL; struct uvc_urb *uvc_urb; unsigned int i; int ret; diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index bb0773637171..6fb0a78b1b00 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -251,7 +251,7 @@ struct uvc_frame { u32 dwMaxVideoFrameBufferSize; u8 bFrameIntervalType; u32 dwDefaultFrameInterval; - u32 *dwFrameInterval; + const u32 *dwFrameInterval; }; struct uvc_format { @@ -265,7 +265,7 @@ struct uvc_format { u32 flags; unsigned int nframes; - struct uvc_frame *frames; + const struct uvc_frame *frames; }; struct uvc_streaming_header { @@ -438,12 +438,12 @@ struct uvc_streaming { enum v4l2_buf_type type; unsigned int nformats; - struct uvc_format *formats; + const struct uvc_format *formats; struct uvc_streaming_control ctrl; - struct uvc_format *def_format; - struct uvc_format *cur_format; - struct uvc_frame *cur_frame; + const struct uvc_format *def_format; + const struct uvc_format *cur_format; + const struct uvc_frame *cur_frame; /* * Protect access to ctrl, cur_format, cur_frame and hardware video From 102df33eba00a0af226279b8da244af85cf47a39 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 20 Apr 2023 06:47:57 +0300 Subject: [PATCH 132/253] media: uvcvideo: Constify descriptor buffers There is no need to modify the content of UVC descriptor buffers during parsing. Make all the corresponding pointers const to avoid unintended modifications. Signed-off-by: Laurent Pinchart Reviewed-by: Ricardo Ribalda Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_driver.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 1f40f92b79b7..08fcd2ffa727 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -221,7 +221,7 @@ static struct uvc_streaming *uvc_stream_new(struct uvc_device *dev, static int uvc_parse_format(struct uvc_device *dev, struct uvc_streaming *streaming, struct uvc_format *format, - struct uvc_frame *frames, u32 **intervals, unsigned char *buffer, + struct uvc_frame *frames, u32 **intervals, const unsigned char *buffer, int buflen) { struct usb_interface *intf = streaming->intf; @@ -513,7 +513,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, struct uvc_format *format; struct uvc_frame *frame; struct usb_host_interface *alts = &intf->altsetting[0]; - unsigned char *_buffer, *buffer = alts->extra; + const unsigned char *_buffer, *buffer = alts->extra; int _buflen, buflen = alts->extralen; unsigned int nformats = 0, nframes = 0, nintervals = 0; unsigned int size, i, n, p; @@ -1166,7 +1166,7 @@ static int uvc_parse_standard_control(struct uvc_device *dev, static int uvc_parse_control(struct uvc_device *dev) { struct usb_host_interface *alts = dev->intf->cur_altsetting; - unsigned char *buffer = alts->extra; + const unsigned char *buffer = alts->extra; int buflen = alts->extralen; int ret; From bc13f2ffd5c0160128d7520f32767423fc044a45 Mon Sep 17 00:00:00 2001 From: Kate Hsuan Date: Mon, 8 May 2023 07:26:28 +0100 Subject: [PATCH 133/253] media: atomisp: sh_css: Remove #ifdef ISP2401 The actions of ISP2401 and 2400 are determined at the runtime. Link: https://lore.kernel.org/r/20230508062632.34537-1-hpa@redhat.com Signed-off-by: Kate Hsuan Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css.c | 524 ++++++++++----------- 1 file changed, 239 insertions(+), 285 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index 93789500416f..4b3fa6d93fe0 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -1529,15 +1529,14 @@ ia_css_init(struct device *dev, const struct ia_css_env *env, mipi_init(); -#ifndef ISP2401 /* * In case this has been programmed already, update internal * data structure ... * DEPRECATED */ - my_css.page_table_base_index = mmu_get_page_table_base_index(MMU0_ID); + if (!IS_ISP2401) + my_css.page_table_base_index = mmu_get_page_table_base_index(MMU0_ID); -#endif my_css.irq_type = irq_type; my_css_save.irq_type = irq_type; @@ -1596,10 +1595,8 @@ ia_css_init(struct device *dev, const struct ia_css_env *env, * sh_css_init_buffer_queues(); */ -#if defined(ISP2401) - gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 1); -#endif - + if (IS_ISP2401) + gp_device_reg_store(GP_DEVICE0_ID, _REG_GP_SWITCH_ISYS2401_ADDR, 1); if (!IS_ISP2401) dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN, @@ -2128,13 +2125,8 @@ ia_css_pipe_destroy(struct ia_css_pipe *pipe) err); } } -#ifndef ISP2401 ia_css_frame_free_multiple(NUM_VIDEO_TNR_FRAMES, pipe->pipe_settings.video.tnr_frames); -#else - ia_css_frame_free_multiple(NUM_VIDEO_TNR_FRAMES, - pipe->pipe_settings.video.tnr_frames); -#endif ia_css_frame_free_multiple(MAX_NUM_VIDEO_DELAY_FRAMES, pipe->pipe_settings.video.delay_frames); break; @@ -2238,11 +2230,10 @@ int ia_css_irq_translate( case virq_isys_csi: infos |= IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR; break; -#if !defined(ISP2401) case virq_ifmt0_id: - infos |= IA_CSS_IRQ_INFO_IF_ERROR; + if (!IS_ISP2401) + infos |= IA_CSS_IRQ_INFO_IF_ERROR; break; -#endif case virq_dma: infos |= IA_CSS_IRQ_INFO_DMA_ERROR; break; @@ -2277,27 +2268,34 @@ int ia_css_irq_enable( IA_CSS_ENTER("info=%d, enable=%d", info, enable); switch (info) { -#if !defined(ISP2401) case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF: + if (IS_ISP2401) + /* Just ignore those unused IRQs without printing errors */ + return 0; + irq = virq_isys_sof; break; case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF: + if (IS_ISP2401) + /* Just ignore those unused IRQs without printing errors */ + return 0; + irq = virq_isys_eof; break; case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR: + if (IS_ISP2401) + /* Just ignore those unused IRQs without printing errors */ + return 0; + irq = virq_isys_csi; break; case IA_CSS_IRQ_INFO_IF_ERROR: + if (IS_ISP2401) + /* Just ignore those unused IRQs without printing errors */ + return 0; + irq = virq_ifmt0_id; break; -#else - case IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF: - case IA_CSS_IRQ_INFO_CSS_RECEIVER_EOF: - case IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR: - case IA_CSS_IRQ_INFO_IF_ERROR: - /* Just ignore those unused IRQs without printing errors */ - return 0; -#endif case IA_CSS_IRQ_INFO_DMA_ERROR: irq = virq_dma; break; @@ -2413,14 +2411,14 @@ alloc_continuous_frames(struct ia_css_pipe *pipe, bool init_time) return -EINVAL; } -#if defined(ISP2401) - /* For CSI2+, the continuous frame will hold the full input frame */ - ref_info.res.width = pipe->stream->config.input_config.input_res.width; - ref_info.res.height = pipe->stream->config.input_config.input_res.height; + if (IS_ISP2401) { + /* For CSI2+, the continuous frame will hold the full input frame */ + ref_info.res.width = pipe->stream->config.input_config.input_res.width; + ref_info.res.height = pipe->stream->config.input_config.input_res.height; - /* Ensure padded width is aligned for 2401 */ - ref_info.padded_width = CEIL_MUL(ref_info.res.width, 2 * ISP_VEC_NELEMS); -#endif + /* Ensure padded width is aligned for 2401 */ + ref_info.padded_width = CEIL_MUL(ref_info.res.width, 2 * ISP_VEC_NELEMS); + } if (pipe->stream->config.pack_raw_pixels) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, @@ -2499,11 +2497,9 @@ load_preview_binaries(struct ia_css_pipe *pipe) int err = 0; bool need_vf_pp = false; bool need_isp_copy_binary = false; -#ifdef ISP2401 bool sensor = false; -#else bool continuous; -#endif + /* preview only have 1 output pin now */ struct ia_css_frame_info *pipe_out_info = &pipe->output_info[0]; struct ia_css_preview_settings *mycs = &pipe->pipe_settings.preview; @@ -2514,11 +2510,9 @@ load_preview_binaries(struct ia_css_pipe *pipe) assert(pipe->mode == IA_CSS_PIPE_ID_PREVIEW); online = pipe->stream->config.online; -#ifdef ISP2401 + sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; -#else continuous = pipe->stream->config.continuous; -#endif if (mycs->preview_binary.info) return 0; @@ -2627,24 +2621,22 @@ load_preview_binaries(struct ia_css_pipe *pipe) return err; } -#ifdef ISP2401 - /* - * When the input system is 2401, only the Direct Sensor Mode - * Offline Preview uses the ISP copy binary. - */ - need_isp_copy_binary = !online && sensor; -#else - /* - * About pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY: - * This is typical the case with SkyCam (which has no input system) but it also applies to all cases - * where the driver chooses for memory based input frames. In these cases, a copy binary (which typical - * copies sensor data to DDR) does not have much use. - */ - if (!IS_ISP2401) + if (IS_ISP2401) { + /* + * When the input system is 2401, only the Direct Sensor Mode + * Offline Preview uses the ISP copy binary. + */ + need_isp_copy_binary = !online && sensor; + } else { + /* + * About pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY: + * This is typical the case with SkyCam (which has no input system) but it also + * applies to all cases where the driver chooses for memory based input frames. + * In these cases, a copy binary (which typical copies sensor data to DDR) does + * not have much use. + */ need_isp_copy_binary = !online && !continuous; - else - need_isp_copy_binary = !online && !continuous && !(pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY); -#endif + } /* Copy */ if (need_isp_copy_binary) { @@ -3125,11 +3117,10 @@ init_in_frameinfo_memory_defaults(struct ia_css_pipe *pipe, in_frame->frame_info.format = format; -#ifdef ISP2401 - if (format == IA_CSS_FRAME_FORMAT_RAW) + if (IS_ISP2401 && format == IA_CSS_FRAME_FORMAT_RAW) { in_frame->frame_info.format = (pipe->stream->config.pack_raw_pixels) ? IA_CSS_FRAME_FORMAT_RAW_PACKED : IA_CSS_FRAME_FORMAT_RAW; -#endif + } in_frame->frame_info.res.width = pipe->stream->config.input_config.input_res.width; in_frame->frame_info.res.height = pipe->stream->config.input_config.input_res.height; @@ -3211,18 +3202,18 @@ static int create_host_video_pipeline(struct ia_css_pipe *pipe) me->dvs_frame_delay = pipe->dvs_frame_delay; -#ifdef ISP2401 - /* - * When the input system is 2401, always enable 'in_frameinfo_memory' - * except for the following: online or continuous - */ - need_in_frameinfo_memory = !(pipe->stream->config.online || - pipe->stream->config.continuous); -#else - /* Construct in_frame info (only in case we have dynamic input */ - need_in_frameinfo_memory = pipe->stream->config.mode == - IA_CSS_INPUT_MODE_MEMORY; -#endif + if (IS_ISP2401) { + /* + * When the input system is 2401, always enable 'in_frameinfo_memory' + * except for the following: online or continuous + */ + need_in_frameinfo_memory = !(pipe->stream->config.online || + pipe->stream->config.continuous); + } else { + /* Construct in_frame info (only in case we have dynamic input */ + need_in_frameinfo_memory = pipe->stream->config.mode == + IA_CSS_INPUT_MODE_MEMORY; + } /* Construct in_frame info (only in case we have dynamic input */ if (need_in_frameinfo_memory) { @@ -3268,15 +3259,14 @@ static int create_host_video_pipeline(struct ia_css_pipe *pipe) goto ERR; in_frame = me->stages->args.out_frame[0]; } else if (pipe->stream->config.continuous) { -#ifdef ISP2401 - /* - * When continuous is enabled, configure in_frame with the - * last pipe, which is the copy pipe. - */ - in_frame = pipe->stream->last_pipe->continuous_frames[0]; -#else - in_frame = pipe->continuous_frames[0]; -#endif + if (IS_ISP2401) + /* + * When continuous is enabled, configure in_frame with the + * last pipe, which is the copy pipe. + */ + in_frame = pipe->stream->last_pipe->continuous_frames[0]; + else + in_frame = pipe->continuous_frames[0]; } ia_css_pipe_util_set_output_frames(out_frames, 0, @@ -3373,12 +3363,10 @@ create_host_preview_pipeline(struct ia_css_pipe *pipe) struct ia_css_frame *out_frame; struct ia_css_frame *out_frames[IA_CSS_BINARY_MAX_OUTPUT_PORTS]; bool need_in_frameinfo_memory = false; -#ifdef ISP2401 bool sensor = false; bool buffered_sensor = false; bool online = false; bool continuous = false; -#endif IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_PREVIEW)) { @@ -3391,25 +3379,26 @@ create_host_preview_pipeline(struct ia_css_pipe *pipe) me = &pipe->pipeline; ia_css_pipeline_clean(me); -#ifdef ISP2401 - /* - * When the input system is 2401, always enable 'in_frameinfo_memory' - * except for the following: - * - Direct Sensor Mode Online Preview - * - Buffered Sensor Mode Online Preview - * - Direct Sensor Mode Continuous Preview - * - Buffered Sensor Mode Continuous Preview - */ - sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); - buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR); - online = pipe->stream->config.online; - continuous = pipe->stream->config.continuous; - need_in_frameinfo_memory = - !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous))); -#else - /* Construct in_frame info (only in case we have dynamic input */ - need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; -#endif + if (IS_ISP2401) { + /* + * When the input system is 2401, always enable 'in_frameinfo_memory' + * except for the following: + * - Direct Sensor Mode Online Preview + * - Buffered Sensor Mode Online Preview + * - Direct Sensor Mode Continuous Preview + * - Buffered Sensor Mode Continuous Preview + */ + sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); + buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR); + online = pipe->stream->config.online; + continuous = pipe->stream->config.continuous; + need_in_frameinfo_memory = + !((sensor && (online || continuous)) || (buffered_sensor && + (online || continuous))); + } else { + /* Construct in_frame info (only in case we have dynamic input */ + need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; + } if (need_in_frameinfo_memory) { err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame, IA_CSS_FRAME_FORMAT_RAW); @@ -3420,7 +3409,6 @@ create_host_preview_pipeline(struct ia_css_pipe *pipe) } else { in_frame = NULL; } - err = init_out_frameinfo_defaults(pipe, &me->out_frame[0], 0); if (err) goto ERR; @@ -3441,17 +3429,16 @@ create_host_preview_pipeline(struct ia_css_pipe *pipe) goto ERR; in_frame = me->stages->args.out_frame[0]; } else if (pipe->stream->config.continuous) { -#ifdef ISP2401 - /* - * When continuous is enabled, configure in_frame with the - * last pipe, which is the copy pipe. - */ - if (continuous || !online) - in_frame = pipe->stream->last_pipe->continuous_frames[0]; - -#else - in_frame = pipe->continuous_frames[0]; -#endif + if (IS_ISP2401) { + /* + * When continuous is enabled, configure in_frame with the + * last pipe, which is the copy pipe. + */ + if (continuous || !online) + in_frame = pipe->stream->last_pipe->continuous_frames[0]; + } else { + in_frame = pipe->continuous_frames[0]; + } } if (vf_pp_binary) { @@ -3925,19 +3912,19 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe, case IA_CSS_BUFFER_TYPE_OUTPUT_FRAME: case IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME: if (pipe && pipe->stop_requested) { -#if !defined(ISP2401) - /* - * free mipi frames only for old input - * system for 2401 it is done in - * ia_css_stream_destroy call - */ - return_err = free_mipi_frames(pipe); - if (return_err) { - IA_CSS_LOG("free_mipi_frames() failed"); - IA_CSS_LEAVE_ERR(return_err); - return return_err; + if (!IS_ISP2401) { + /* + * free mipi frames only for old input + * system for 2401 it is done in + * ia_css_stream_destroy call + */ + return_err = free_mipi_frames(pipe); + if (return_err) { + IA_CSS_LOG("free_mipi_frames() failed"); + IA_CSS_LEAVE_ERR(return_err); + return return_err; + } } -#endif pipe->stop_requested = false; } fallthrough; @@ -3959,12 +3946,11 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe, pipe->num_invalid_frames--; if (frame->frame_info.format == IA_CSS_FRAME_FORMAT_BINARY_8) { -#ifdef ISP2401 - frame->planes.binary.size = frame->data_bytes; -#else - frame->planes.binary.size = - sh_css_sp_get_binary_copy_size(); -#endif + if (IS_ISP2401) + frame->planes.binary.size = frame->data_bytes; + else + frame->planes.binary.size = + sh_css_sp_get_binary_copy_size(); } if (buf_type == IA_CSS_BUFFER_TYPE_OUTPUT_FRAME) { IA_CSS_LOG("pfp: dequeued OF %d with config id %d thread %d", @@ -4880,22 +4866,20 @@ static int load_video_binaries(struct ia_css_pipe *pipe) pipe->num_invalid_frames, pipe->dvs_frame_delay); /* pqiao TODO: temp hack for PO, should be removed after offline YUVPP is enabled */ -#if !defined(ISP2401) - /* Copy */ - if (!online && !continuous) { - /* - * TODO: what exactly needs doing, prepend the copy binary to - * video base this only on !online? - */ - err = load_copy_binary(pipe, - &mycs->copy_binary, - &mycs->video_binary); - if (err) - return err; + if (!IS_ISP2401) { + /* Copy */ + if (!online && !continuous) { + /* + * TODO: what exactly needs doing, prepend the copy binary to + * video base this only on !online? + */ + err = load_copy_binary(pipe, + &mycs->copy_binary, + &mycs->video_binary); + if (err) + return err; + } } -#else - (void)continuous; -#endif if (pipe->enable_viewfinder[IA_CSS_PIPE_OUTPUT_STAGE_0] && need_vf_pp) { struct ia_css_binary_descr vf_pp_descr; @@ -5227,11 +5211,8 @@ static int load_primary_binaries( bool need_pp = false; bool need_isp_copy_binary = false; bool need_ldc = false; -#ifdef ISP2401 bool sensor = false; -#else bool memory, continuous; -#endif struct ia_css_frame_info prim_in_info, prim_out_info, capt_pp_out_info, vf_info, @@ -5251,12 +5232,9 @@ static int load_primary_binaries( pipe->mode == IA_CSS_PIPE_ID_COPY); online = pipe->stream->config.online; -#ifdef ISP2401 sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); -#else memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; continuous = pipe->stream->config.continuous; -#endif mycs = &pipe->pipe_settings.capture; pipe_out_info = &pipe->output_info[0]; @@ -5462,15 +5440,14 @@ static int load_primary_binaries( if (err) return err; -#ifdef ISP2401 - /* - * When the input system is 2401, only the Direct Sensor Mode - * Offline Capture uses the ISP copy binary. - */ - need_isp_copy_binary = !online && sensor; -#else - need_isp_copy_binary = !online && !continuous && !memory; -#endif + if (IS_ISP2401) + /* + * When the input system is 2401, only the Direct Sensor Mode + * Offline Capture uses the ISP copy binary. + */ + need_isp_copy_binary = !online && sensor; + else + need_isp_copy_binary = !online && !continuous && !memory; /* ISP Copy */ if (need_isp_copy_binary) { @@ -5681,10 +5658,10 @@ static int load_advanced_binaries(struct ia_css_pipe *pipe) } /* Copy */ -#ifdef ISP2401 - /* For CSI2+, only the direct sensor mode/online requires ISP copy */ - need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; -#endif + if (IS_ISP2401) + /* For CSI2+, only the direct sensor mode/online requires ISP copy */ + need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; + if (need_isp_copy) load_copy_binary(pipe, &pipe->pipe_settings.capture.copy_binary, @@ -5829,10 +5806,10 @@ static int load_low_light_binaries(struct ia_css_pipe *pipe) } /* Copy */ -#ifdef ISP2401 - /* For CSI2+, only the direct sensor mode/online requires ISP copy */ - need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; -#endif + if (IS_ISP2401) + /* For CSI2+, only the direct sensor mode/online requires ISP copy */ + need_isp_copy = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; + if (need_isp_copy) err = load_copy_binary(pipe, &pipe->pipe_settings.capture.copy_binary, @@ -5902,10 +5879,9 @@ static int load_capture_binaries(struct ia_css_pipe *pipe) switch (pipe->config.default_capture_config.mode) { case IA_CSS_CAPTURE_MODE_RAW: err = load_copy_binaries(pipe); -#if defined(ISP2401) - if (!err) + if (!err && IS_ISP2401) pipe->pipe_settings.capture.copy_binary.online = pipe->stream->config.online; -#endif + break; case IA_CSS_CAPTURE_MODE_BAYER: err = load_bayer_isp_binaries(pipe); @@ -6409,7 +6385,6 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe) else next_binary = NULL; -#if defined(ISP2401) /* * NOTES * - Why does the "yuvpp" pipe needs "isp_copy_binary" (i.e. ISP Copy) when @@ -6427,11 +6402,11 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe) * pp_defs.h" for the list of input-frame formats that are supported by the * "yuv_scale_binary". */ - need_isp_copy_binary = - (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8); -#else /* !ISP2401 */ - need_isp_copy_binary = true; -#endif /* ISP2401 */ + if (IS_ISP2401) + need_isp_copy_binary = + (pipe->stream->config.input_config.format == ATOMISP_INPUT_FORMAT_YUV422_8); + else + need_isp_copy_binary = true; if (need_isp_copy_binary) { err = load_copy_binary(pipe, @@ -6678,12 +6653,10 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) struct ia_css_frame *vf_frame[IA_CSS_PIPE_MAX_OUTPUT_STAGE]; struct ia_css_pipeline_stage_desc stage_desc; bool need_in_frameinfo_memory = false; -#ifdef ISP2401 bool sensor = false; bool buffered_sensor = false; bool online = false; bool continuous = false; -#endif IA_CSS_ENTER_PRIVATE("pipe = %p", pipe); if ((!pipe) || (!pipe->stream) || (pipe->mode != IA_CSS_PIPE_ID_YUVPP)) { @@ -6700,24 +6673,24 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) num_stage = pipe->pipe_settings.yuvpp.num_yuv_scaler; num_output_stage = pipe->pipe_settings.yuvpp.num_output; -#ifdef ISP2401 - /* - * When the input system is 2401, always enable 'in_frameinfo_memory' - * except for the following: - * - Direct Sensor Mode Online Capture - * - Direct Sensor Mode Continuous Capture - * - Buffered Sensor Mode Continuous Capture - */ - sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; - buffered_sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR; - online = pipe->stream->config.online; - continuous = pipe->stream->config.continuous; - need_in_frameinfo_memory = - !((sensor && (online || continuous)) || (buffered_sensor && continuous)); -#else - /* Construct in_frame info (only in case we have dynamic input */ - need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; -#endif + if (IS_ISP2401) { + /* + * When the input system is 2401, always enable 'in_frameinfo_memory' + * except for the following: + * - Direct Sensor Mode Online Capture + * - Direct Sensor Mode Continuous Capture + * - Buffered Sensor Mode Continuous Capture + */ + sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR; + buffered_sensor = pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR; + online = pipe->stream->config.online; + continuous = pipe->stream->config.continuous; + need_in_frameinfo_memory = + !((sensor && (online || continuous)) || (buffered_sensor && continuous)); + } else { + /* Construct in_frame info (only in case we have dynamic input */ + need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; + } /* * the input frame can come from: * @@ -6808,11 +6781,10 @@ create_host_yuvpp_pipeline(struct ia_css_pipe *pipe) if (pipe->pipe_settings.yuvpp.copy_binary.info) { struct ia_css_frame *in_frame_local = NULL; -#ifdef ISP2401 - /* After isp copy is enabled in_frame needs to be passed. */ - if (!online) + if (IS_ISP2401 && !online) { + /* After isp copy is enabled in_frame needs to be passed. */ in_frame_local = in_frame; -#endif + } if (need_scaler) { ia_css_pipe_util_set_output_frames(bin_out_frame, @@ -7031,12 +7003,10 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) struct ia_css_frame *vf_frame; struct ia_css_pipeline_stage_desc stage_desc; bool need_in_frameinfo_memory = false; -#ifdef ISP2401 bool sensor = false; bool buffered_sensor = false; bool online = false; bool continuous = false; -#endif unsigned int i, num_yuv_scaler, num_primary_stage; bool need_yuv_pp = false; bool *is_output_stage = NULL; @@ -7054,25 +7024,27 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) ia_css_pipeline_clean(me); ia_css_pipe_util_create_output_frames(out_frames); -#ifdef ISP2401 - /* - * When the input system is 2401, always enable 'in_frameinfo_memory' - * except for the following: - * - Direct Sensor Mode Online Capture - * - Direct Sensor Mode Online Capture - * - Direct Sensor Mode Continuous Capture - * - Buffered Sensor Mode Continuous Capture - */ - sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); - buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR); - online = pipe->stream->config.online; - continuous = pipe->stream->config.continuous; - need_in_frameinfo_memory = - !((sensor && (online || continuous)) || (buffered_sensor && (online || continuous))); -#else - /* Construct in_frame info (only in case we have dynamic input */ - need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; -#endif + if (IS_ISP2401) { + /* + * When the input system is 2401, always enable 'in_frameinfo_memory' + * except for the following: + * - Direct Sensor Mode Online Capture + * - Direct Sensor Mode Online Capture + * - Direct Sensor Mode Continuous Capture + * - Buffered Sensor Mode Continuous Capture + */ + sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_SENSOR); + buffered_sensor = (pipe->stream->config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR); + online = pipe->stream->config.online; + continuous = pipe->stream->config.continuous; + need_in_frameinfo_memory = + !((sensor && (online || continuous)) || (buffered_sensor && + (online || continuous))); + } else { + /* Construct in_frame info (only in case we have dynamic input */ + need_in_frameinfo_memory = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; + } + if (need_in_frameinfo_memory) { err = init_in_frameinfo_memory_defaults(pipe, &me->in_frame, IA_CSS_FRAME_FORMAT_RAW); @@ -7135,27 +7107,27 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) if (pipe->pipe_settings.capture.copy_binary.info) { if (raw) { ia_css_pipe_util_set_output_frames(out_frames, 0, out_frame); -#if defined(ISP2401) - if (!continuous) { - ia_css_pipe_get_generic_stage_desc(&stage_desc, - copy_binary, - out_frames, - in_frame, - NULL); + if (IS_ISP2401) { + if (!continuous) { + ia_css_pipe_get_generic_stage_desc(&stage_desc, + copy_binary, + out_frames, + in_frame, + NULL); + } else { + in_frame = pipe->stream->last_pipe->continuous_frames[0]; + ia_css_pipe_get_generic_stage_desc(&stage_desc, + copy_binary, + out_frames, + in_frame, + NULL); + } } else { - in_frame = pipe->stream->last_pipe->continuous_frames[0]; ia_css_pipe_get_generic_stage_desc(&stage_desc, copy_binary, out_frames, - in_frame, - NULL); + NULL, NULL); } -#else - ia_css_pipe_get_generic_stage_desc(&stage_desc, - copy_binary, - out_frames, - NULL, NULL); -#endif } else { ia_css_pipe_util_set_output_frames(out_frames, 0, in_frame); @@ -7185,11 +7157,7 @@ create_host_regular_capture_pipeline(struct ia_css_pipe *pipe) local_in_frame = in_frame; else local_in_frame = NULL; -#ifndef ISP2401 - if (!need_pp && (i == num_primary_stage - 1)) -#else - if (!need_pp && (i == num_primary_stage - 1) && !need_ldc) -#endif + if (!need_pp && (i == num_primary_stage - 1) && (!IS_ISP2401 || !need_ldc)) local_out_frame = out_frame; else local_out_frame = NULL; @@ -7400,23 +7368,14 @@ static int capture_start(struct ia_css_pipe *pipe) return err; } } - -#if !defined(ISP2401) /* old isys: need to send_mipi_frames() in all pipe modes */ - err = send_mipi_frames(pipe); - if (err) { - IA_CSS_LEAVE_ERR_PRIVATE(err); - return err; - } -#else - if (pipe->config.mode != IA_CSS_PIPE_MODE_COPY) { + if (!IS_ISP2401 || (IS_ISP2401 && pipe->config.mode != IA_CSS_PIPE_MODE_COPY)) { err = send_mipi_frames(pipe); if (err) { IA_CSS_LEAVE_ERR_PRIVATE(err); return err; } } -#endif ia_css_pipeline_get_sp_thread_id(ia_css_pipe_get_pipe_num(pipe), &thread_id); copy_ovrd = 1 << thread_id; @@ -8123,24 +8082,22 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config, return err; } -#if !defined(ISP2401) - /* We don't support metadata for JPEG stream, since they both use str2mem */ - if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 && - stream_config->metadata_config.resolution.height > 0) { - err = -EINVAL; - IA_CSS_LEAVE_ERR(err); - return err; + if (!IS_ISP2401) { + /* We don't support metadata for JPEG stream, since they both use str2mem */ + if (stream_config->input_config.format == ATOMISP_INPUT_FORMAT_BINARY_8 && + stream_config->metadata_config.resolution.height > 0) { + err = -EINVAL; + IA_CSS_LEAVE_ERR(err); + return err; + } + } else { + if (stream_config->online && stream_config->pack_raw_pixels) { + IA_CSS_LOG("online and pack raw is invalid on input system 2401"); + err = -EINVAL; + IA_CSS_LEAVE_ERR(err); + return err; + } } -#endif - -#ifdef ISP2401 - if (stream_config->online && stream_config->pack_raw_pixels) { - IA_CSS_LOG("online and pack raw is invalid on input system 2401"); - err = -EINVAL; - IA_CSS_LEAVE_ERR(err); - return err; - } -#endif ia_css_debug_pipe_graph_dump_stream_config(stream_config); @@ -8223,19 +8180,17 @@ ia_css_stream_create(const struct ia_css_stream_config *stream_config, /* take over stream config */ curr_stream->config = *stream_config; -#if defined(ISP2401) - if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR && - stream_config->online) - curr_stream->config.online = false; -#endif + if (IS_ISP2401) { + if (stream_config->mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR && + stream_config->online) + curr_stream->config.online = false; -#ifdef ISP2401 - if (curr_stream->config.online) { - curr_stream->config.source.port.num_lanes = - stream_config->source.port.num_lanes; - curr_stream->config.mode = IA_CSS_INPUT_MODE_BUFFERED_SENSOR; + if (curr_stream->config.online) { + curr_stream->config.source.port.num_lanes = + stream_config->source.port.num_lanes; + curr_stream->config.mode = IA_CSS_INPUT_MODE_BUFFERED_SENSOR; + } } -#endif /* in case driver doesn't configure init number of raw buffers, configure it here */ if (curr_stream->config.target_num_cont_raw_buf == 0) curr_stream->config.target_num_cont_raw_buf = NUM_CONTINUOUS_FRAMES; @@ -9162,11 +9117,10 @@ void ia_css_pipe_map_queue(struct ia_css_pipe *pipe, bool map) ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); -#if defined(ISP2401) - need_input_queue = true; -#else - need_input_queue = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; -#endif + if (IS_ISP2401) + need_input_queue = true; + else + need_input_queue = pipe->stream->config.mode == IA_CSS_INPUT_MODE_MEMORY; /* map required buffer queues to resources */ /* TODO: to be improved */ From 5925dc0f30c2294f0015ee7060ef844b93000289 Mon Sep 17 00:00:00 2001 From: Kate Hsuan Date: Mon, 8 May 2023 07:26:29 +0100 Subject: [PATCH 134/253] media: atomisp: runtime: frame: remove #ifdef ISP2401 The actions of ISP2401 and 2400 are determined at the runtime. Link: https://lore.kernel.org/r/20230508062632.34537-2-hpa@redhat.com Signed-off-by: Kate Hsuan Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/runtime/frame/src/frame.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c b/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c index 83bb42e05421..1e374ae848e3 100644 --- a/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c +++ b/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c @@ -601,9 +601,6 @@ static void frame_init_qplane6_planes(struct ia_css_frame *frame) static int frame_allocate_buffer_data(struct ia_css_frame *frame) { -#ifdef ISP2401 - IA_CSS_ENTER_LEAVE_PRIVATE("frame->data_bytes=%d\n", frame->data_bytes); -#endif frame->data = hmm_alloc(frame->data_bytes); if (frame->data == mmgr_NULL) return -ENOMEM; @@ -635,15 +632,11 @@ static int frame_allocate_with_data(struct ia_css_frame **frame, if (err) { kvfree(me); -#ifndef ISP2401 - return err; -#else - me = NULL; -#endif + *frame = NULL; + } else { + *frame = me; } - *frame = me; - return err; } From 72c1c48553093f63be9518b5d7541a66dafad83a Mon Sep 17 00:00:00 2001 From: Kate Hsuan Date: Mon, 8 May 2023 07:26:30 +0100 Subject: [PATCH 135/253] media: atomisp: sh_css_sp: Remove #ifdef ISP2401 The actions of ISP2401 and 2400 will be determined at the runtime. Link: https://lore.kernel.org/r/20230508062632.34537-3-hpa@redhat.com Signed-off-by: Kate Hsuan Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/sh_css_sp.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css_sp.c b/drivers/staging/media/atomisp/pci/sh_css_sp.c index 0dd58a7fe2cc..297e1b981720 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_sp.c +++ b/drivers/staging/media/atomisp/pci/sh_css_sp.c @@ -952,12 +952,10 @@ sh_css_sp_init_stage(struct ia_css_binary *binary, return 0; } -#if defined(ISP2401) - (void)continuous; - sh_css_sp_stage.deinterleaved = 0; -#else - sh_css_sp_stage.deinterleaved = ((stage == 0) && continuous); -#endif + if (IS_ISP2401) + sh_css_sp_stage.deinterleaved = 0; + else + sh_css_sp_stage.deinterleaved = ((stage == 0) && continuous); initialize_stage_frames(&sh_css_sp_stage.frames); /* From 08b9c820878f387b903c28962703337e42cfc4a5 Mon Sep 17 00:00:00 2001 From: Kate Hsuan Date: Mon, 8 May 2023 07:26:31 +0100 Subject: [PATCH 136/253] media: atomisp: sh_css_firmware: determine firmware version at runtime The firmware version of ISP2401 and 2400 is determined at runtime. Link: https://lore.kernel.org/r/20230508062632.34537-4-hpa@redhat.com Signed-off-by: Kate Hsuan Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/sh_css_firmware.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css_firmware.c b/drivers/staging/media/atomisp/pci/sh_css_firmware.c index e7ef578db8ab..49ee88fe151d 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_firmware.c +++ b/drivers/staging/media/atomisp/pci/sh_css_firmware.c @@ -56,11 +56,8 @@ static struct firmware_header *firmware_header; * which will be replaced with the actual RELEASE_VERSION * during package generation. Please do not modify */ -#ifdef ISP2401 -static const char *release_version = STR(irci_stable_candrpv_0415_20150521_0458); -#else -static const char *release_version = STR(irci_stable_candrpv_0415_20150423_1753); -#endif +static const char *release_version_2401 = STR(irci_stable_candrpv_0415_20150521_0458); +static const char *release_version_2400 = STR(irci_stable_candrpv_0415_20150423_1753); #define MAX_FW_REL_VER_NAME 300 static char FW_rel_ver_name[MAX_FW_REL_VER_NAME] = "---"; @@ -191,8 +188,14 @@ sh_css_load_blob_info(const char *fw, const struct ia_css_fw_info *bi, bool sh_css_check_firmware_version(struct device *dev, const char *fw_data) { + const char *release_version; struct sh_css_fw_bi_file_h *file_header; + if (IS_ISP2401) + release_version = release_version_2401; + else + release_version = release_version_2400; + firmware_header = (struct firmware_header *)fw_data; file_header = &firmware_header->file_header; @@ -225,6 +228,7 @@ sh_css_load_firmware(struct device *dev, const char *fw_data, unsigned int fw_size) { unsigned int i; + const char *release_version; struct ia_css_fw_info *binaries; struct sh_css_fw_bi_file_h *file_header; int ret; @@ -234,6 +238,10 @@ sh_css_load_firmware(struct device *dev, const char *fw_data, binaries = &firmware_header->binary_header; strscpy(FW_rel_ver_name, file_header->version, min(sizeof(FW_rel_ver_name), sizeof(file_header->version))); + if (IS_ISP2401) + release_version = release_version_2401; + else + release_version = release_version_2400; ret = sh_css_check_firmware_version(dev, fw_data); if (ret) { IA_CSS_ERROR("CSS code version (%s) and firmware version (%s) mismatch!", From 5c3213e9e2dd5dee0ba54a65a491ad4e43b615d0 Mon Sep 17 00:00:00 2001 From: Kate Hsuan Date: Mon, 8 May 2023 07:26:32 +0100 Subject: [PATCH 137/253] media: atomisp: sh_css_mipi: Remove #ifdef ISP2401 The actions of ISP2401 and 2400 are determined at the runtime. Link: https://lore.kernel.org/r/20230508062632.34537-5-hpa@redhat.com Signed-off-by: Kate Hsuan Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/sh_css_mipi.c | 56 ++++++------------- 1 file changed, 17 insertions(+), 39 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css_mipi.c b/drivers/staging/media/atomisp/pci/sh_css_mipi.c index bc6e8598a776..b20acaab0595 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_mipi.c +++ b/drivers/staging/media/atomisp/pci/sh_css_mipi.c @@ -67,13 +67,12 @@ ia_css_mipi_frame_calculate_size(const unsigned int width, unsigned int mem_words = 0; unsigned int width_padded = width; -#if defined(ISP2401) /* The changes will be reverted as soon as RAW * Buffers are deployed by the 2401 Input System * in the non-continuous use scenario. */ - width_padded += (2 * ISP_VEC_NELEMS); -#endif + if (IS_ISP2401) + width_padded += (2 * ISP_VEC_NELEMS); IA_CSS_ENTER("padded_width=%d, height=%d, format=%d, hasSOLandEOL=%d, embedded_data_size_words=%d\n", width_padded, height, format, hasSOLandEOL, embedded_data_size_words); @@ -235,7 +234,6 @@ bool mipi_is_free(void) return true; } -#if defined(ISP2401) /* * @brief Calculate the required MIPI buffer sizes. * Based on the stream configuration, calculate the @@ -342,7 +340,6 @@ static int calculate_mipi_buff_size(struct ia_css_stream_config *stream_cfg, IA_CSS_LEAVE_ERR(err); return err; } -#endif int allocate_mipi_frames(struct ia_css_pipe *pipe, @@ -363,15 +360,13 @@ allocate_mipi_frames(struct ia_css_pipe *pipe, return -EINVAL; } -#ifdef ISP2401 - if (pipe->stream->config.online) { + if (IS_ISP2401 && pipe->stream->config.online) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "allocate_mipi_frames(%p) exit: no buffers needed for 2401 pipe mode.\n", pipe); return 0; } -#endif if (pipe->stream->config.mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "allocate_mipi_frames(%p) exit: no buffers needed for pipe mode.\n", @@ -386,9 +381,10 @@ allocate_mipi_frames(struct ia_css_pipe *pipe, return -EINVAL; } -#ifdef ISP2401 - err = calculate_mipi_buff_size(&pipe->stream->config, - &my_css.mipi_frame_size[port]); + if (IS_ISP2401) + err = calculate_mipi_buff_size(&pipe->stream->config, + &my_css.mipi_frame_size[port]); + /* * 2401 system allows multiple streams to use same physical port. This is not * true for 2400 system. Currently 2401 uses MIPI buffers as a temporary solution. @@ -396,20 +392,14 @@ allocate_mipi_frames(struct ia_css_pipe *pipe, * In that case only 2400 related code should remain. */ if (ref_count_mipi_allocation[port] != 0) { - ref_count_mipi_allocation[port]++; + if (IS_ISP2401) + ref_count_mipi_allocation[port]++; + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "allocate_mipi_frames(%p) leave: nothing to do, already allocated for this port (port=%d).\n", pipe, port); return 0; } -#else - if (ref_count_mipi_allocation[port] != 0) { - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "allocate_mipi_frames(%p) exit: already allocated for this port (port=%d).\n", - pipe, port); - return 0; - } -#endif ref_count_mipi_allocation[port]++; @@ -503,14 +493,14 @@ free_mipi_frames(struct ia_css_pipe *pipe) } if (ref_count_mipi_allocation[port] > 0) { -#if !defined(ISP2401) - assert(ref_count_mipi_allocation[port] == 1); - if (ref_count_mipi_allocation[port] != 1) { - IA_CSS_ERROR("free_mipi_frames(%p) exit: wrong ref_count (ref_count=%d).", - pipe, ref_count_mipi_allocation[port]); - return err; + if (!IS_ISP2401) { + assert(ref_count_mipi_allocation[port] == 1); + if (ref_count_mipi_allocation[port] != 1) { + IA_CSS_ERROR("free_mipi_frames(%p) exit: wrong ref_count (ref_count=%d).", + pipe, ref_count_mipi_allocation[port]); + return err; + } } -#endif ref_count_mipi_allocation[port]--; @@ -534,18 +524,6 @@ free_mipi_frames(struct ia_css_pipe *pipe) ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "free_mipi_frames(%p) exit (deallocated).\n", pipe); } -#if defined(ISP2401) - else { - /* 2401 system allows multiple streams to use same physical port. This is not - * true for 2400 system. Currently 2401 uses MIPI buffers as a temporary solution. - * TODO AM: Once that is changed (removed) this code should be removed as well. - * In that case only 2400 related code should remain. - */ - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, - "free_mipi_frames(%p) leave: nothing to do, other streams still use this port (port=%d).\n", - pipe, port); - } -#endif } } else { /* pipe ==NULL */ /* AM TEMP: free-ing all mipi buffers just like a legacy code. */ From 649920afc4269fe3db74feadffb8f18dea057dc1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 6 May 2023 19:56:05 +0100 Subject: [PATCH 138/253] media: atomisp: Remove res_overflow parameter from atomisp_try_fmt() The only remaining caller of atomisp_try_fmt() always passes NULL for the res_overflow parameter. Drop it and simplify atomisp_try_fmt(). Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 21 ++++--------------- .../staging/media/atomisp/pci/atomisp_cmd.h | 3 +-- .../staging/media/atomisp/pci/atomisp_ioctl.c | 2 +- 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index aa790ae746f3..bb49d6f2e67f 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -3881,8 +3881,7 @@ static void __atomisp_init_stream_info(u16 stream_index, } /* This function looks up the closest available resolution. */ -int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f, - bool *res_overflow) +int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f) { struct atomisp_device *isp = video_get_drvdata(vdev); struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; @@ -3940,6 +3939,8 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f, } f->pixelformat = fmt->pixelformat; + f->width = format.format.width; + f->height = format.format.height; /* * If the format is jpeg or custom RAW, then the width and height will @@ -3948,22 +3949,8 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f, * the sensor driver. */ if (f->pixelformat == V4L2_PIX_FMT_JPEG || - f->pixelformat == V4L2_PIX_FMT_CUSTOM_M10MO_RAW) { - f->width = format.format.width; - f->height = format.format.height; + f->pixelformat == V4L2_PIX_FMT_CUSTOM_M10MO_RAW) return 0; - } - - if (!res_overflow || (format.format.width < f->width && - format.format.height < f->height)) { - f->width = format.format.width; - f->height = format.format.height; - /* Set the flag when resolution requested is - * beyond the max value supported by sensor - */ - if (res_overflow) - *res_overflow = true; - } /* app vs isp */ f->width = rounddown(clamp_t(u32, f->width, ATOM_ISP_MIN_WIDTH, diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.h b/drivers/staging/media/atomisp/pci/atomisp_cmd.h index 399b549bcf83..3cf086eba06d 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.h +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.h @@ -259,8 +259,7 @@ int atomisp_compare_grid(struct atomisp_sub_device *asd, struct atomisp_grid_info *atomgrid); /* This function looks up the closest available resolution. */ -int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f, - bool *res_overflow); +int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f); int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f); diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 384f31fc66c5..4d927799f53b 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -896,7 +896,7 @@ static int atomisp_try_fmt_cap(struct file *file, void *fh, f->fmt.pix.width += pad_w; f->fmt.pix.height += pad_h; - ret = atomisp_try_fmt(vdev, &f->fmt.pix, NULL); + ret = atomisp_try_fmt(vdev, &f->fmt.pix); if (ret) return ret; From 7943916bd4e5952a535ae8b3f7513866a33b302b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 May 2023 16:16:06 +0100 Subject: [PATCH 139/253] media: atomisp: Remove Continuous capture and SDV run-modes Since we no longer support Continuous mode, setting the run_mode to ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE no longer make sense, so remove this. While at it, also remove ATOMISP_RUN_MODE_SDV, which was never exposed to userspace in the first place. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/include/linux/atomisp.h | 7 +- .../media/atomisp/pci/atomisp_compat_css20.c | 12 --- .../staging/media/atomisp/pci/atomisp_ioctl.c | 3 - .../media/atomisp/pci/atomisp_subdev.c | 16 ++-- .../staging/media/atomisp/pci/atomisp_v4l2.c | 91 ------------------- 5 files changed, 10 insertions(+), 119 deletions(-) diff --git a/drivers/staging/media/atomisp/include/linux/atomisp.h b/drivers/staging/media/atomisp/include/linux/atomisp.h index c7ec56a1c064..bada4c9911fd 100644 --- a/drivers/staging/media/atomisp/include/linux/atomisp.h +++ b/drivers/staging/media/atomisp/include/linux/atomisp.h @@ -38,7 +38,6 @@ #define CI_MODE_PREVIEW 0x8000 #define CI_MODE_VIDEO 0x4000 #define CI_MODE_STILL_CAPTURE 0x2000 -#define CI_MODE_CONTINUOUS 0x1000 #define CI_MODE_NONE 0x0000 #define OUTPUT_MODE_FILE 0x0100 @@ -1059,9 +1058,9 @@ struct atomisp_sensor_ae_bracketing_lut { #define V4L2_CID_RUN_MODE (V4L2_CID_CAMERA_LASTP1 + 20) #define ATOMISP_RUN_MODE_VIDEO 1 #define ATOMISP_RUN_MODE_STILL_CAPTURE 2 -#define ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE 3 -#define ATOMISP_RUN_MODE_PREVIEW 4 -#define ATOMISP_RUN_MODE_SDV 5 +#define ATOMISP_RUN_MODE_PREVIEW 3 +#define ATOMISP_RUN_MODE_MIN 1 +#define ATOMISP_RUN_MODE_MAX 3 #define V4L2_CID_ENABLE_VFPP (V4L2_CID_CAMERA_LASTP1 + 21) #define V4L2_CID_ATOMISP_CONTINUOUS_MODE (V4L2_CID_CAMERA_LASTP1 + 22) diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index 1dae2a7cfdd9..e8c26e66ae7e 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -649,23 +649,11 @@ static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd, if (pipe_id == IA_CSS_PIPE_ID_PREVIEW) return true; - return false; - case ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE: - if (pipe_id == IA_CSS_PIPE_ID_CAPTURE || - pipe_id == IA_CSS_PIPE_ID_PREVIEW) - return true; - return false; case ATOMISP_RUN_MODE_VIDEO: if (pipe_id == IA_CSS_PIPE_ID_VIDEO || pipe_id == IA_CSS_PIPE_ID_YUVPP) return true; - return false; - case ATOMISP_RUN_MODE_SDV: - if (pipe_id == IA_CSS_PIPE_ID_CAPTURE || - pipe_id == IA_CSS_PIPE_ID_VIDEO) - return true; - return false; } diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 4d927799f53b..7f031db28476 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -1902,9 +1902,6 @@ static int atomisp_s_parm(struct file *file, void *fh, case CI_MODE_STILL_CAPTURE: mode = ATOMISP_RUN_MODE_STILL_CAPTURE; break; - case CI_MODE_CONTINUOUS: - mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE; - break; case CI_MODE_PREVIEW: mode = ATOMISP_RUN_MODE_PREVIEW; break; diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c index a0acfdb87177..42f8accf57fc 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c @@ -755,11 +755,9 @@ static const struct v4l2_ctrl_ops ctrl_ops = { }; static const char *const ctrl_run_mode_menu[] = { - NULL, - "Video", - "Still capture", - "Continuous capture", - "Preview", + [ATOMISP_RUN_MODE_VIDEO] = "Video", + [ATOMISP_RUN_MODE_STILL_CAPTURE] = "Still capture", + [ATOMISP_RUN_MODE_PREVIEW] = "Preview", }; static const struct v4l2_ctrl_config ctrl_run_mode = { @@ -767,9 +765,9 @@ static const struct v4l2_ctrl_config ctrl_run_mode = { .id = V4L2_CID_RUN_MODE, .name = "Atomisp run mode", .type = V4L2_CTRL_TYPE_MENU, - .min = 1, - .def = 1, - .max = 4, + .min = ATOMISP_RUN_MODE_MIN, + .def = ATOMISP_RUN_MODE_PREVIEW, + .max = ATOMISP_RUN_MODE_MAX, .qmenu = ctrl_run_mode_menu, }; @@ -971,7 +969,7 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd) return ret; ret = atomisp_video_init(&asd->video_out_vf, "VIEWFINDER", - ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE); + ATOMISP_RUN_MODE_STILL_CAPTURE); if (ret < 0) return ret; diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index 3f315dabbeeb..4370d560308e 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -119,13 +119,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_merr[] = { .isp_freq = ISP_FREQ_400MHZ, .run_mode = ATOMISP_RUN_MODE_STILL_CAPTURE, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_400MHZ, - .run_mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE, - }, { .width = ISP_FREQ_RULE_ANY, .height = ISP_FREQ_RULE_ANY, @@ -133,13 +126,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_merr[] = { .isp_freq = ISP_FREQ_400MHZ, .run_mode = ATOMISP_RUN_MODE_PREVIEW, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_457MHZ, - .run_mode = ATOMISP_RUN_MODE_SDV, - }, }; /* Merrifield and Moorefield DFS rules */ @@ -166,13 +152,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_merr_1179[] = { .isp_freq = ISP_FREQ_400MHZ, .run_mode = ATOMISP_RUN_MODE_STILL_CAPTURE, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_400MHZ, - .run_mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE, - }, { .width = ISP_FREQ_RULE_ANY, .height = ISP_FREQ_RULE_ANY, @@ -180,13 +159,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_merr_1179[] = { .isp_freq = ISP_FREQ_400MHZ, .run_mode = ATOMISP_RUN_MODE_PREVIEW, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_400MHZ, - .run_mode = ATOMISP_RUN_MODE_SDV, - }, }; static const struct atomisp_dfs_config dfs_config_merr_1179 = { @@ -247,13 +219,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_merr_117a[] = { .isp_freq = ISP_FREQ_400MHZ, .run_mode = ATOMISP_RUN_MODE_STILL_CAPTURE, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_400MHZ, - .run_mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE, - }, { .width = ISP_FREQ_RULE_ANY, .height = ISP_FREQ_RULE_ANY, @@ -261,13 +226,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_merr_117a[] = { .isp_freq = ISP_FREQ_200MHZ, .run_mode = ATOMISP_RUN_MODE_PREVIEW, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_400MHZ, - .run_mode = ATOMISP_RUN_MODE_SDV, - }, }; static struct atomisp_dfs_config dfs_config_merr_117a = { @@ -293,13 +251,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_byt[] = { .isp_freq = ISP_FREQ_400MHZ, .run_mode = ATOMISP_RUN_MODE_STILL_CAPTURE, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_400MHZ, - .run_mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE, - }, { .width = ISP_FREQ_RULE_ANY, .height = ISP_FREQ_RULE_ANY, @@ -307,13 +258,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_byt[] = { .isp_freq = ISP_FREQ_400MHZ, .run_mode = ATOMISP_RUN_MODE_PREVIEW, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_400MHZ, - .run_mode = ATOMISP_RUN_MODE_SDV, - }, }; static const struct atomisp_dfs_config dfs_config_byt = { @@ -339,13 +283,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_cht[] = { .isp_freq = ISP_FREQ_356MHZ, .run_mode = ATOMISP_RUN_MODE_STILL_CAPTURE, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_320MHZ, - .run_mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE, - }, { .width = ISP_FREQ_RULE_ANY, .height = ISP_FREQ_RULE_ANY, @@ -353,20 +290,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_cht[] = { .isp_freq = ISP_FREQ_320MHZ, .run_mode = ATOMISP_RUN_MODE_PREVIEW, }, - { - .width = 1280, - .height = 720, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_320MHZ, - .run_mode = ATOMISP_RUN_MODE_SDV, - }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_356MHZ, - .run_mode = ATOMISP_RUN_MODE_SDV, - }, }; static const struct atomisp_freq_scaling_rule dfs_rules_cht_soc[] = { @@ -384,13 +307,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_cht_soc[] = { .isp_freq = ISP_FREQ_356MHZ, .run_mode = ATOMISP_RUN_MODE_STILL_CAPTURE, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_320MHZ, - .run_mode = ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE, - }, { .width = ISP_FREQ_RULE_ANY, .height = ISP_FREQ_RULE_ANY, @@ -398,13 +314,6 @@ static const struct atomisp_freq_scaling_rule dfs_rules_cht_soc[] = { .isp_freq = ISP_FREQ_320MHZ, .run_mode = ATOMISP_RUN_MODE_PREVIEW, }, - { - .width = ISP_FREQ_RULE_ANY, - .height = ISP_FREQ_RULE_ANY, - .fps = ISP_FREQ_RULE_ANY, - .isp_freq = ISP_FREQ_356MHZ, - .run_mode = ATOMISP_RUN_MODE_SDV, - }, }; static const struct atomisp_dfs_config dfs_config_cht = { From 1b9a80a47dbfc871867845350fcc519ea5181418 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 May 2023 16:23:48 +0100 Subject: [PATCH 140/253] media: atomisp: Remove isp->need_gfx_throttle field Remove the isp->need_gfx_throttle field it is only ever set and never read. Also the code setting it is broken, comparing run_mode->val to ATOMISP_SUBDEV_PAD_SOURCE_VIDEO which are not of the same type / not part of the same enum. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 10 ---------- drivers/staging/media/atomisp/pci/atomisp_fops.c | 1 - drivers/staging/media/atomisp/pci/atomisp_internal.h | 2 -- 3 files changed, 13 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index bb49d6f2e67f..ed1a534b7c05 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -4693,16 +4693,6 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) f->fmt.pix = pipe->pix; f->fmt.pix.priv = PAGE_ALIGN(pipe->pix.width * pipe->pix.height * 2); - - /* - * If in video 480P case, no GFX throttle - */ - if (asd->run_mode->val == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO && - f->fmt.pix.width == 720 && f->fmt.pix.height == 480) - isp->need_gfx_throttle = false; - else - isp->need_gfx_throttle = true; - /* Report the needed sizes */ f->fmt.pix.sizeimage = pipe->pix.sizeimage; f->fmt.pix.bytesperline = pipe->pix.bytesperline; diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index fa362c8a37e8..a95c41d084c2 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -539,7 +539,6 @@ static void atomisp_dev_init_struct(struct atomisp_device *isp) { unsigned int i; - isp->need_gfx_throttle = true; isp->isp_fatal_error = false; isp->mipi_frame_size = 0; diff --git a/drivers/staging/media/atomisp/pci/atomisp_internal.h b/drivers/staging/media/atomisp/pci/atomisp_internal.h index 1fac99f4e2b0..e531f0c71a15 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_internal.h +++ b/drivers/staging/media/atomisp/pci/atomisp_internal.h @@ -211,8 +211,6 @@ struct atomisp_device { spinlock_t lock; /* Protects asd.streaming */ - bool need_gfx_throttle; - unsigned int mipi_frame_size; const struct atomisp_dfs_config *dfs; unsigned int hpll_freq; From 006f27897cbdbe02bb3b307118e7a6e25543b516 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 May 2023 18:38:10 +0100 Subject: [PATCH 141/253] media: atomisp: Drop atomisp_get_css_buf_type() Since continuous mode has been removed, there no longer is the option for separate capture output + viewfinder output streams at the same time. So all buffers queued by userspace are now for the normal output stream, remove atomisp_get_css_buf_type() and always use IA_CSS_BUFFER_TYPE_OUTPUT_FRAME for buffers queued by userspace. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_fops.c | 29 +------------------ 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index a95c41d084c2..143ab78b003b 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -342,24 +342,10 @@ static int atomisp_q_video_buffers_to_css(struct atomisp_sub_device *asd, return 0; } -static int atomisp_get_css_buf_type(struct atomisp_sub_device *asd, - enum ia_css_pipe_id pipe_id, - uint16_t source_pad) -{ - if (pipe_id == IA_CSS_PIPE_ID_COPY || - source_pad == ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE || - source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO || - (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW && - asd->run_mode->val != ATOMISP_RUN_MODE_VIDEO)) - return IA_CSS_BUFFER_TYPE_OUTPUT_FRAME; - else - return IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME; -} - /* queue all available buffers to css */ int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd) { - enum ia_css_buffer_type buf_type; + const enum ia_css_buffer_type buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME; enum ia_css_pipe_id css_capture_pipe_id = IA_CSS_PIPE_ID_NUM; enum ia_css_pipe_id css_preview_pipe_id = IA_CSS_PIPE_ID_NUM; enum ia_css_pipe_id css_video_pipe_id = IA_CSS_PIPE_ID_NUM; @@ -400,9 +386,6 @@ int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd) } if (capture_pipe) { - buf_type = atomisp_get_css_buf_type( - asd, css_capture_pipe_id, - atomisp_subdev_source_pad(&capture_pipe->vdev)); input_stream_id = ATOMISP_INPUT_STREAM_GENERAL; atomisp_q_video_buffers_to_css(asd, capture_pipe, @@ -411,9 +394,6 @@ int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd) } if (vf_pipe) { - buf_type = atomisp_get_css_buf_type( - asd, css_capture_pipe_id, - atomisp_subdev_source_pad(&vf_pipe->vdev)); if (asd->stream_env[ATOMISP_INPUT_STREAM_POSTVIEW].stream) input_stream_id = ATOMISP_INPUT_STREAM_POSTVIEW; else @@ -425,10 +405,6 @@ int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd) } if (preview_pipe) { - buf_type = atomisp_get_css_buf_type( - asd, css_preview_pipe_id, - atomisp_subdev_source_pad(&preview_pipe->vdev)); - if (css_preview_pipe_id == IA_CSS_PIPE_ID_YUVPP) input_stream_id = ATOMISP_INPUT_STREAM_VIDEO; else if (asd->stream_env[ATOMISP_INPUT_STREAM_PREVIEW].stream) @@ -442,9 +418,6 @@ int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd) } if (video_pipe) { - buf_type = atomisp_get_css_buf_type( - asd, css_video_pipe_id, - atomisp_subdev_source_pad(&video_pipe->vdev)); if (asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO].stream) input_stream_id = ATOMISP_INPUT_STREAM_VIDEO; else From ea3600379e0f38f7c25263a0ab01cc3efc6cd3fe Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 May 2023 19:11:48 +0100 Subject: [PATCH 142/253] media: atomisp: Replace source-pad checks with run-mode checks Currently atomisp behavior is determined by a mix of which /dev/video# node (which isp-subdev source-pad) is opened + which run-mode is set. With various combinations not being allowed and likely leading to crashes due to lack of error checking. Now that we no longer support continuous mode and thus no longer support streaming from 2 /dev/video# nodes at the same time, there is no need to have a separate /dev/video# node for each run-mode. Instead the plan is to support the 3 different run-modes on a single /dev/video# node. Since we are moving to a single isp-subdev source-pad, the behavior should then be solely and consistently be defined by the run-mode. Replace various source-pad checks with run-mode checks in preparation for moving to a single source-pad. In some places the new run-mode checks overlap with existing run-mode checks and the checks are folded together into a single check. This removes handling of the ATOMISP_SUBDEV_PAD_SOURCE_VF source-pad, this source-pad was only useful for continuous mode, for which support has been removed. Note that currently the only run-mode which we actually have been able to get to work is the video-capture with scaler aka preview mode and as such that is also the only run-mode tested. This patch is intended to preserve the current (known to not work 100%) behavior of the other run-modes, so that those maybe can be enabled later. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 37 +++------- .../media/atomisp/pci/atomisp_compat_css20.c | 72 ++++--------------- .../media/atomisp/pci/atomisp_subdev.c | 23 ++---- 3 files changed, 29 insertions(+), 103 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index ed1a534b7c05..710e97a492c6 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -4215,21 +4215,12 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, ATOMISP_SUBDEV_PAD_SOURCE_VF, &vf_ffmt); asd->video_out_vf.sh_fmt = IA_CSS_FRAME_FORMAT_NV12; - if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { + if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO || + asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { atomisp_css_video_configure_viewfinder(asd, vf_size.width, vf_size.height, 0, asd->video_out_vf.sh_fmt); - } else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { - if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW || - source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO) - atomisp_css_video_configure_viewfinder(asd, - vf_size.width, vf_size.height, 0, - asd->video_out_vf.sh_fmt); - else - atomisp_css_capture_configure_viewfinder(asd, - vf_size.width, vf_size.height, 0, - asd->video_out_vf.sh_fmt); - } else if (source_pad != ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW || + } else if (asd->run_mode->val == ATOMISP_RUN_MODE_STILL_CAPTURE || asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) { atomisp_css_capture_configure_viewfinder(asd, vf_size.width, vf_size.height, 0, @@ -4255,7 +4246,7 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, configure_output = atomisp_css_video_configure_output; get_frame_info = atomisp_css_video_get_output_frame_info; pipe_id = IA_CSS_PIPE_ID_VIDEO; - } else if (source_pad == ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW) { + } else if (asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) { configure_output = atomisp_css_preview_configure_output; get_frame_info = atomisp_css_preview_get_output_frame_info; configure_pp_input = atomisp_css_preview_configure_pp_input; @@ -4386,7 +4377,6 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p struct atomisp_device *isp; struct atomisp_input_stream_info *stream_info = (struct atomisp_input_stream_info *)ffmt->reserved; - int source_pad = atomisp_subdev_source_pad(vdev); struct v4l2_subdev_fh fh; int ret; @@ -4417,8 +4407,7 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p req_ffmt = ffmt; /* Disable dvs if resolution can't be supported by sensor */ - if (asd->params.video_dis_en && - source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO) { + if (asd->params.video_dis_en && asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { vformat.which = V4L2_SUBDEV_FORMAT_TRY; ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, pad, set_fmt, &pad_state, &vformat); @@ -4453,8 +4442,7 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p ffmt->height < ATOM_ISP_STEP_HEIGHT) return -EINVAL; - if (asd->params.video_dis_en && - source_pad == ATOMISP_SUBDEV_PAD_SOURCE_VIDEO && + if (asd->params.video_dis_en && asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO && (ffmt->width < req_ffmt->width || ffmt->height < req_ffmt->height)) { dev_warn(isp->dev, "can not enable video dis due to sensor limitation."); @@ -5005,16 +4993,11 @@ static int atomisp_get_pipe_id(struct atomisp_video_pipe *pipe) return IA_CSS_PIPE_ID_VIDEO; } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) { return IA_CSS_PIPE_ID_CAPTURE; - } else if (pipe == &asd->video_out_video_capture) { + } else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { return IA_CSS_PIPE_ID_VIDEO; - } else if (pipe == &asd->video_out_vf) { - return IA_CSS_PIPE_ID_CAPTURE; - } else if (pipe == &asd->video_out_preview) { - if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) - return IA_CSS_PIPE_ID_VIDEO; - else - return IA_CSS_PIPE_ID_PREVIEW; - } else if (pipe == &asd->video_out_capture) { + } else if (asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) { + return IA_CSS_PIPE_ID_PREVIEW; + } else if (asd->run_mode->val == ATOMISP_RUN_MODE_STILL_CAPTURE) { if (asd->copy_mode) return IA_CSS_PIPE_ID_COPY; else diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index e8c26e66ae7e..dfed7f1fbf6b 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -2416,41 +2416,21 @@ get_info_err: return -EINVAL; } -static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd, - uint16_t source_pad) +static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd) { - struct atomisp_device *isp = asd->isp; - - switch (source_pad) { - case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: - if (asd->copy_mode) - return IA_CSS_PIPE_ID_COPY; - if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO - || asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) - return IA_CSS_PIPE_ID_VIDEO; + if (asd->copy_mode) + return IA_CSS_PIPE_ID_COPY; + switch (asd->run_mode->val) { + case ATOMISP_RUN_MODE_VIDEO: + return IA_CSS_PIPE_ID_VIDEO; + case ATOMISP_RUN_MODE_STILL_CAPTURE: return IA_CSS_PIPE_ID_CAPTURE; - case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE: - if (asd->copy_mode) - return IA_CSS_PIPE_ID_COPY; - - return IA_CSS_PIPE_ID_CAPTURE; - case ATOMISP_SUBDEV_PAD_SOURCE_VF: - if (!atomisp_is_mbuscode_raw(asd->fmt[asd->capture_pad].fmt.code)) { - return IA_CSS_PIPE_ID_CAPTURE; - } - fallthrough; - case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW: - if (asd->copy_mode) - return IA_CSS_PIPE_ID_COPY; - if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) - return IA_CSS_PIPE_ID_VIDEO; - + case ATOMISP_RUN_MODE_PREVIEW: return IA_CSS_PIPE_ID_PREVIEW; } - dev_warn(isp->dev, - "invalid source pad:%d, return default preview pipe index.\n", - source_pad); + + dev_warn(asd->isp->dev, "cannot determine pipe-index return default preview pipe\n"); return IA_CSS_PIPE_ID_PREVIEW; } @@ -2459,7 +2439,7 @@ int atomisp_get_css_frame_info(struct atomisp_sub_device *asd, struct ia_css_frame_info *frame_info) { struct ia_css_pipe_info info; - int pipe_index = atomisp_get_pipe_index(asd, source_pad); + int pipe_index = atomisp_get_pipe_index(asd); int stream_index; struct atomisp_device *isp = asd->isp; @@ -2473,34 +2453,8 @@ int atomisp_get_css_frame_info(struct atomisp_sub_device *asd, return -EINVAL; } - switch (source_pad) { - case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE: - *frame_info = info.output_info[0]; - break; - case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: - *frame_info = info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX]; - break; - case ATOMISP_SUBDEV_PAD_SOURCE_VF: - if (stream_index == ATOMISP_INPUT_STREAM_POSTVIEW) - *frame_info = info.output_info[0]; - else - *frame_info = info.vf_output_info[0]; - break; - case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW: - if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO && - (pipe_index == IA_CSS_PIPE_ID_VIDEO || - pipe_index == IA_CSS_PIPE_ID_YUVPP)) - *frame_info = info.vf_output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX]; - else - *frame_info = - info.output_info[ATOMISP_CSS_OUTPUT_DEFAULT_INDEX]; - - break; - default: - frame_info = NULL; - break; - } - return frame_info ? 0 : -EINVAL; + *frame_info = info.output_info[0]; + return 0; } int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd, diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c index 42f8accf57fc..92cf0e845a4f 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c @@ -393,8 +393,7 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, r->width = rounddown(r->width, ATOM_ISP_STEP_WIDTH); r->height = rounddown(r->height, ATOM_ISP_STEP_HEIGHT); - switch (pad) { - case ATOMISP_SUBDEV_PAD_SINK: { + if (pad == ATOMISP_SUBDEV_PAD_SINK) { /* Only crop target supported on sink pad. */ unsigned int dvs_w, dvs_h; @@ -445,7 +444,7 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, } if (which == V4L2_SUBDEV_FORMAT_TRY) - break; + goto get_rect; if (isp_sd->params.video_dis_en && isp_sd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { @@ -468,12 +467,8 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, ATOMISP_INPUT_STREAM_GENERAL, crop[pad]->width, crop[pad]->height); - break; - } - case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE: - case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: { + } else if (isp_sd->run_mode->val != ATOMISP_RUN_MODE_PREVIEW) { /* Only compose target is supported on source pads. */ - if (isp_sd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) { /* Scaling is disabled in this mode */ r->width = crop[ATOMISP_SUBDEV_PAD_SINK]->width; @@ -492,7 +487,7 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, if (r->width == 0 || r->height == 0 || crop[ATOMISP_SUBDEV_PAD_SINK]->width == 0 || crop[ATOMISP_SUBDEV_PAD_SINK]->height == 0) - break; + goto get_rect; /* * do cropping on sensor input if ratio of required resolution * is different with sensor output resolution ratio: @@ -522,18 +517,12 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, rounddown(crop[ATOMISP_SUBDEV_PAD_SINK]-> width * r->height / r->width, ATOM_ISP_STEP_WIDTH)); - - break; - } - case ATOMISP_SUBDEV_PAD_SOURCE_VF: - case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW: + } else { comp[pad]->width = r->width; comp[pad]->height = r->height; - break; - default: - return -EINVAL; } +get_rect: /* Set format dimensions on non-sink pads as well. */ if (pad != ATOMISP_SUBDEV_PAD_SINK) { ffmt[pad]->width = comp[pad]->width; From d957824bf8e43f052e339c16032a4dccf52b0ed0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 May 2023 12:54:26 +0100 Subject: [PATCH 143/253] media: atomisp: Register only 1 /dev/video# node Now that we no longer support continuous mode and thus no longer support streaming from 2 /dev/video# nodes at the same time, there is no need to have a separate /dev/video# node (+ matching v4l2-subdev pads) for each run-mode. Keep the video_out_preview /dev/video0 device and remove the video_out_video_capture / video_out_vf / video_out_capture video-devices (atomisp_pipe-s) and also remove the matching ATOMISP_SUBDEV_PAD_SOURCE_VIDEO / ATOMISP_SUBDEV_PAD_SOURCE_VF / ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE source-pads. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 44 ++------ .../media/atomisp/pci/atomisp_compat_css20.c | 3 - .../staging/media/atomisp/pci/atomisp_fops.c | 92 +++------------- .../staging/media/atomisp/pci/atomisp_ioctl.c | 5 +- .../media/atomisp/pci/atomisp_subdev.c | 102 +----------------- .../media/atomisp/pci/atomisp_subdev.h | 15 +-- 6 files changed, 30 insertions(+), 231 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 710e97a492c6..faaa4f1c5c7c 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -643,10 +643,7 @@ void atomisp_flush_video_pipe(struct atomisp_video_pipe *pipe, enum vb2_buffer_s /* Returns queued buffers back to video-core */ void atomisp_flush_bufs_and_wakeup(struct atomisp_sub_device *asd) { - atomisp_flush_video_pipe(&asd->video_out_capture, VB2_BUF_STATE_ERROR, false); - atomisp_flush_video_pipe(&asd->video_out_vf, VB2_BUF_STATE_ERROR, false); atomisp_flush_video_pipe(&asd->video_out_preview, VB2_BUF_STATE_ERROR, false); - atomisp_flush_video_pipe(&asd->video_out_video_capture, VB2_BUF_STATE_ERROR, false); } /* clean out the parameters that did not apply */ @@ -1035,9 +1032,7 @@ static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout) atomisp_flush_bufs_and_wakeup(&isp->asd); /* Requeue unprocessed per-frame parameters. */ - atomisp_recover_params_queue(&isp->asd.video_out_capture); atomisp_recover_params_queue(&isp->asd.video_out_preview); - atomisp_recover_params_queue(&isp->asd.video_out_video_capture); ret = v4l2_subdev_call( isp->inputs[isp->asd.input_curr].camera, video, @@ -1298,7 +1293,7 @@ static void atomisp_update_capture_mode(struct atomisp_sub_device *asd) atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_ADVANCED); else if (asd->params.low_light) atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_LOW_LIGHT); - else if (asd->video_out_capture.sh_fmt == IA_CSS_FRAME_FORMAT_RAW) + else if (asd->video_out_preview.sh_fmt == IA_CSS_FRAME_FORMAT_RAW) atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_RAW); else atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_PRIMARY); @@ -4191,40 +4186,24 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, * CSS still requires viewfinder configuration. */ { - struct v4l2_rect vf_size = {0}; - struct v4l2_mbus_framefmt vf_ffmt = {0}; + u32 width, height; if (pix->width < 640 || pix->height < 480) { - vf_size.width = pix->width; - vf_size.height = pix->height; + width = pix->width; + height = pix->height; } else { - vf_size.width = 640; - vf_size.height = 480; + width = 640; + height = 480; } - /* FIXME: proper format name for this one. See - atomisp_output_fmts[] in atomisp_v4l2.c */ - vf_ffmt.code = V4L2_MBUS_FMT_CUSTOM_YUV420; - - atomisp_subdev_set_selection(&asd->subdev, fh.state, - V4L2_SUBDEV_FORMAT_ACTIVE, - ATOMISP_SUBDEV_PAD_SOURCE_VF, - V4L2_SEL_TGT_COMPOSE, 0, &vf_size); - atomisp_subdev_set_ffmt(&asd->subdev, fh.state, - V4L2_SUBDEV_FORMAT_ACTIVE, - ATOMISP_SUBDEV_PAD_SOURCE_VF, &vf_ffmt); - asd->video_out_vf.sh_fmt = IA_CSS_FRAME_FORMAT_NV12; - if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO || asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { - atomisp_css_video_configure_viewfinder(asd, - vf_size.width, vf_size.height, 0, - asd->video_out_vf.sh_fmt); + atomisp_css_video_configure_viewfinder(asd, width, height, 0, + IA_CSS_FRAME_FORMAT_NV12); } else if (asd->run_mode->val == ATOMISP_RUN_MODE_STILL_CAPTURE || asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) { - atomisp_css_capture_configure_viewfinder(asd, - vf_size.width, vf_size.height, 0, - asd->video_out_vf.sh_fmt); + atomisp_css_capture_configure_viewfinder(asd, width, height, 0, + IA_CSS_FRAME_FORMAT_NV12); } } @@ -4811,9 +4790,6 @@ bool atomisp_is_vf_pipe(struct atomisp_video_pipe *pipe) return false; } - if (pipe == &asd->video_out_vf) - return true; - if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO && pipe == &asd->video_out_preview) return true; diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index dfed7f1fbf6b..8e8caa99ce72 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -1958,10 +1958,7 @@ void atomisp_css_stop(struct atomisp_sub_device *asd, list_splice_init(&asd->metadata_ready[i], &asd->metadata[i]); } - atomisp_flush_params_queue(&asd->video_out_capture); - atomisp_flush_params_queue(&asd->video_out_vf); atomisp_flush_params_queue(&asd->video_out_preview); - atomisp_flush_params_queue(&asd->video_out_video_capture); atomisp_free_css_parameters(&asd->params.css_param); memset(&asd->params.css_param, 0, sizeof(asd->params.css_param)); } diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index 143ab78b003b..3adeeb97e570 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -345,89 +345,26 @@ static int atomisp_q_video_buffers_to_css(struct atomisp_sub_device *asd, /* queue all available buffers to css */ int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd) { - const enum ia_css_buffer_type buf_type = IA_CSS_BUFFER_TYPE_OUTPUT_FRAME; - enum ia_css_pipe_id css_capture_pipe_id = IA_CSS_PIPE_ID_NUM; - enum ia_css_pipe_id css_preview_pipe_id = IA_CSS_PIPE_ID_NUM; - enum ia_css_pipe_id css_video_pipe_id = IA_CSS_PIPE_ID_NUM; - enum atomisp_input_stream_id input_stream_id; - struct atomisp_video_pipe *capture_pipe = NULL; - struct atomisp_video_pipe *vf_pipe = NULL; - struct atomisp_video_pipe *preview_pipe = NULL; - struct atomisp_video_pipe *video_pipe = NULL; - bool raw_mode = atomisp_is_mbuscode_raw( - asd->fmt[asd->capture_pad].fmt.code); + enum ia_css_pipe_id pipe_id; - if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { - video_pipe = &asd->video_out_video_capture; - css_video_pipe_id = IA_CSS_PIPE_ID_VIDEO; + if (asd->copy_mode) { + pipe_id = IA_CSS_PIPE_ID_COPY; + } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { + pipe_id = IA_CSS_PIPE_ID_VIDEO; } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) { - preview_pipe = &asd->video_out_capture; - css_preview_pipe_id = IA_CSS_PIPE_ID_CAPTURE; + pipe_id = IA_CSS_PIPE_ID_CAPTURE; } else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { - video_pipe = &asd->video_out_video_capture; - preview_pipe = &asd->video_out_preview; - css_video_pipe_id = IA_CSS_PIPE_ID_VIDEO; - css_preview_pipe_id = IA_CSS_PIPE_ID_VIDEO; + pipe_id = IA_CSS_PIPE_ID_VIDEO; } else if (asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) { - preview_pipe = &asd->video_out_preview; - css_preview_pipe_id = IA_CSS_PIPE_ID_PREVIEW; + pipe_id = IA_CSS_PIPE_ID_PREVIEW; } else { /* ATOMISP_RUN_MODE_STILL_CAPTURE */ - capture_pipe = &asd->video_out_capture; - if (!raw_mode) - vf_pipe = &asd->video_out_vf; - css_capture_pipe_id = IA_CSS_PIPE_ID_CAPTURE; - } - - if (IS_ISP2401 && asd->copy_mode) { - css_capture_pipe_id = IA_CSS_PIPE_ID_COPY; - css_preview_pipe_id = IA_CSS_PIPE_ID_COPY; - css_video_pipe_id = IA_CSS_PIPE_ID_COPY; - } - - if (capture_pipe) { - input_stream_id = ATOMISP_INPUT_STREAM_GENERAL; - - atomisp_q_video_buffers_to_css(asd, capture_pipe, - input_stream_id, - buf_type, css_capture_pipe_id); - } - - if (vf_pipe) { - if (asd->stream_env[ATOMISP_INPUT_STREAM_POSTVIEW].stream) - input_stream_id = ATOMISP_INPUT_STREAM_POSTVIEW; - else - input_stream_id = ATOMISP_INPUT_STREAM_GENERAL; - - atomisp_q_video_buffers_to_css(asd, vf_pipe, - input_stream_id, - buf_type, css_capture_pipe_id); - } - - if (preview_pipe) { - if (css_preview_pipe_id == IA_CSS_PIPE_ID_YUVPP) - input_stream_id = ATOMISP_INPUT_STREAM_VIDEO; - else if (asd->stream_env[ATOMISP_INPUT_STREAM_PREVIEW].stream) - input_stream_id = ATOMISP_INPUT_STREAM_PREVIEW; - else - input_stream_id = ATOMISP_INPUT_STREAM_GENERAL; - - atomisp_q_video_buffers_to_css(asd, preview_pipe, - input_stream_id, - buf_type, css_preview_pipe_id); - } - - if (video_pipe) { - if (asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO].stream) - input_stream_id = ATOMISP_INPUT_STREAM_VIDEO; - else - input_stream_id = ATOMISP_INPUT_STREAM_GENERAL; - - atomisp_q_video_buffers_to_css(asd, video_pipe, - input_stream_id, - buf_type, css_video_pipe_id); + pipe_id = IA_CSS_PIPE_ID_CAPTURE; } + atomisp_q_video_buffers_to_css(asd, &asd->video_out_preview, + ATOMISP_INPUT_STREAM_GENERAL, + IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, pipe_id); return 0; } @@ -558,10 +495,7 @@ static void atomisp_subdev_init_struct(struct atomisp_sub_device *asd) */ static unsigned int atomisp_subdev_users(struct atomisp_sub_device *asd) { - return asd->video_out_preview.users + - asd->video_out_vf.users + - asd->video_out_capture.users + - asd->video_out_video_capture.users; + return asd->video_out_preview.users; } unsigned int atomisp_dev_users(struct atomisp_device *isp) diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 7f031db28476..392c0ed56fb4 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -618,10 +618,7 @@ static int atomisp_enum_input(struct file *file, void *fh, static unsigned int atomisp_subdev_streaming_count(struct atomisp_sub_device *asd) { - return vb2_start_streaming_called(&asd->video_out_preview.vb_queue) + - vb2_start_streaming_called(&asd->video_out_capture.vb_queue) + - vb2_start_streaming_called(&asd->video_out_video_capture.vb_queue) + - vb2_start_streaming_called(&asd->video_out_vf.vb_queue); + return vb2_start_streaming_called(&asd->video_out_preview.vb_queue); } unsigned int atomisp_streaming_count(struct atomisp_device *isp) diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c index 92cf0e845a4f..d7da8d076529 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c @@ -355,10 +355,7 @@ static const char *atomisp_pad_str(unsigned int pad) { static const char *const pad_str[] = { "ATOMISP_SUBDEV_PAD_SINK", - "ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE", - "ATOMISP_SUBDEV_PAD_SOURCE_VF", "ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW", - "ATOMISP_SUBDEV_PAD_SOURCE_VIDEO", }; if (pad >= ARRAY_SIZE(pad_str)) @@ -376,7 +373,6 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *ffmt[ATOMISP_SUBDEV_PADS_NUM]; struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM], *comp[ATOMISP_SUBDEV_PADS_NUM]; - unsigned int i; unsigned int padding_w = pad_w; unsigned int padding_h = pad_h; @@ -432,15 +428,11 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, crop[pad]->height = min(crop[pad]->height, r->height); if (!(flags & V4L2_SEL_FLAG_KEEP_CONFIG)) { - for (i = ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE; - i < ATOMISP_SUBDEV_PADS_NUM; i++) { - struct v4l2_rect tmp = *crop[pad]; + struct v4l2_rect tmp = *crop[pad]; - atomisp_subdev_set_selection( - sd, sd_state, which, i, - V4L2_SEL_TGT_COMPOSE, - flags, &tmp); - } + atomisp_subdev_set_selection(sd, sd_state, which, + ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW, + V4L2_SEL_TGT_COMPOSE, flags, &tmp); } if (which == V4L2_SUBDEV_FORMAT_TRY) @@ -601,10 +593,7 @@ void atomisp_subdev_set_ffmt(struct v4l2_subdev *sd, break; } - case ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE: case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW: - case ATOMISP_SUBDEV_PAD_SOURCE_VF: - case ATOMISP_SUBDEV_PAD_SOURCE_VIDEO: __ffmt->code = ffmt->code; break; } @@ -911,20 +900,11 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd) pads[ATOMISP_SUBDEV_PAD_SINK].flags = MEDIA_PAD_FL_SINK; pads[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].flags = MEDIA_PAD_FL_SOURCE; - pads[ATOMISP_SUBDEV_PAD_SOURCE_VF].flags = MEDIA_PAD_FL_SOURCE; - pads[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].flags = MEDIA_PAD_FL_SOURCE; - pads[ATOMISP_SUBDEV_PAD_SOURCE_VIDEO].flags = MEDIA_PAD_FL_SOURCE; asd->fmt[ATOMISP_SUBDEV_PAD_SINK].fmt.code = MEDIA_BUS_FMT_SBGGR10_1X10; asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].fmt.code = MEDIA_BUS_FMT_SBGGR10_1X10; - asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VF].fmt.code = - MEDIA_BUS_FMT_SBGGR10_1X10; - asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE].fmt.code = - MEDIA_BUS_FMT_SBGGR10_1X10; - asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_VIDEO].fmt.code = - MEDIA_BUS_FMT_SBGGR10_1X10; me->ops = &isp_subdev_media_ops; me->function = MEDIA_ENT_F_PROC_VIDEO_ISP; @@ -937,41 +917,11 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd) if (ret) return ret; - ret = atomisp_init_subdev_pipe(asd, &asd->video_out_vf, - V4L2_BUF_TYPE_VIDEO_CAPTURE); - if (ret) - return ret; - - ret = atomisp_init_subdev_pipe(asd, &asd->video_out_capture, - V4L2_BUF_TYPE_VIDEO_CAPTURE); - if (ret) - return ret; - - ret = atomisp_init_subdev_pipe(asd, &asd->video_out_video_capture, - V4L2_BUF_TYPE_VIDEO_CAPTURE); - if (ret) - return ret; - - ret = atomisp_video_init(&asd->video_out_capture, "CAPTURE", - ATOMISP_RUN_MODE_STILL_CAPTURE); - if (ret < 0) - return ret; - - ret = atomisp_video_init(&asd->video_out_vf, "VIEWFINDER", - ATOMISP_RUN_MODE_STILL_CAPTURE); - if (ret < 0) - return ret; - ret = atomisp_video_init(&asd->video_out_preview, "PREVIEW", ATOMISP_RUN_MODE_PREVIEW); if (ret < 0) return ret; - ret = atomisp_video_init(&asd->video_out_video_capture, "VIDEO", - ATOMISP_RUN_MODE_VIDEO); - if (ret < 0) - return ret; - ret = v4l2_ctrl_handler_init(&asd->ctrl_handler, 1); if (ret) return ret; @@ -1035,21 +985,6 @@ int atomisp_create_pads_links(struct atomisp_device *isp) &isp->asd.video_out_preview.vdev.entity, 0, 0); if (ret < 0) return ret; - ret = media_create_pad_link(&isp->asd.subdev.entity, - ATOMISP_SUBDEV_PAD_SOURCE_VF, - &isp->asd.video_out_vf.vdev.entity, 0, 0); - if (ret < 0) - return ret; - ret = media_create_pad_link(&isp->asd.subdev.entity, - ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE, - &isp->asd.video_out_capture.vdev.entity, 0, 0); - if (ret < 0) - return ret; - ret = media_create_pad_link(&isp->asd.subdev.entity, - ATOMISP_SUBDEV_PAD_SOURCE_VIDEO, - &isp->asd.video_out_video_capture.vdev.entity, 0, 0); - if (ret < 0) - return ret; return 0; } @@ -1080,9 +1015,6 @@ void atomisp_subdev_unregister_entities(struct atomisp_sub_device *asd) atomisp_subdev_cleanup_entities(asd); v4l2_device_unregister_subdev(&asd->subdev); atomisp_video_unregister(&asd->video_out_preview); - atomisp_video_unregister(&asd->video_out_vf); - atomisp_video_unregister(&asd->video_out_capture); - atomisp_video_unregister(&asd->video_out_video_capture); } int atomisp_subdev_register_subdev(struct atomisp_sub_device *asd, @@ -1096,11 +1028,6 @@ int atomisp_subdev_register_video_nodes(struct atomisp_sub_device *asd, { int ret; - /* - * FIXME: check if all device caps are properly initialized. - * Should any of those use V4L2_CAP_META_CAPTURE? Probably yes. - */ - asd->video_out_preview.vdev.v4l2_dev = vdev; asd->video_out_preview.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; ret = video_register_device(&asd->video_out_preview.vdev, @@ -1108,27 +1035,6 @@ int atomisp_subdev_register_video_nodes(struct atomisp_sub_device *asd, if (ret < 0) goto error; - asd->video_out_capture.vdev.v4l2_dev = vdev; - asd->video_out_capture.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - ret = video_register_device(&asd->video_out_capture.vdev, - VFL_TYPE_VIDEO, -1); - if (ret < 0) - goto error; - - asd->video_out_vf.vdev.v4l2_dev = vdev; - asd->video_out_vf.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - ret = video_register_device(&asd->video_out_vf.vdev, - VFL_TYPE_VIDEO, -1); - if (ret < 0) - goto error; - - asd->video_out_video_capture.vdev.v4l2_dev = vdev; - asd->video_out_video_capture.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - ret = video_register_device(&asd->video_out_video_capture.vdev, - VFL_TYPE_VIDEO, -1); - if (ret < 0) - goto error; - return 0; error: diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.h b/drivers/staging/media/atomisp/pci/atomisp_subdev.h index fee663bc415a..2be594a8e733 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.h +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.h @@ -32,15 +32,8 @@ #define ATOMISP_MAX_EXP_ID (250) #define ATOMISP_SUBDEV_PAD_SINK 0 -/* capture output for still frames */ -#define ATOMISP_SUBDEV_PAD_SOURCE_CAPTURE 1 -/* viewfinder output for downscaled capture output */ -#define ATOMISP_SUBDEV_PAD_SOURCE_VF 2 -/* preview output for display */ -#define ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW 3 -/* main output for video pipeline */ -#define ATOMISP_SUBDEV_PAD_SOURCE_VIDEO 4 -#define ATOMISP_SUBDEV_PADS_NUM 5 +#define ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW 1 +#define ATOMISP_SUBDEV_PADS_NUM 2 struct atomisp_in_fmt_conv { u32 code; @@ -251,11 +244,7 @@ struct atomisp_sub_device { u16 capture_pad; /* main capture pad; defines much of isp config */ unsigned int output; - struct atomisp_video_pipe video_out_capture; /* capture output */ - struct atomisp_video_pipe video_out_vf; /* viewfinder output */ struct atomisp_video_pipe video_out_preview; /* preview output */ - /* video pipe main output */ - struct atomisp_video_pipe video_out_video_capture; /* struct isp_subdev_params params; */ struct atomisp_device *isp; struct v4l2_ctrl_handler ctrl_handler; From 26dcabc0dd1bcbcb23464362a5ddc917df8ceb74 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 May 2023 15:20:22 +0100 Subject: [PATCH 144/253] media: atomisp: Drop atomisp_is_vf_pipe() Since there only is one /dev/video# node now (no more continuous mode), there are now no longer separate main capture + view-finder pipes. We are now always on the main pipe, so atomisp_is_vf_pipe() should always return false now. Drop any checks using it, replacing them with the code-path for a false return. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 32 ++----------------- .../staging/media/atomisp/pci/atomisp_cmd.h | 2 -- .../staging/media/atomisp/pci/atomisp_fops.c | 5 ++- .../staging/media/atomisp/pci/atomisp_ioctl.c | 3 +- 4 files changed, 5 insertions(+), 37 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index faaa4f1c5c7c..3d6e0d0c7eaa 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -3216,9 +3216,6 @@ void atomisp_handle_parameter_and_buffer(struct atomisp_video_pipe *pipe) lockdep_assert_held(&asd->isp->mutex); - if (atomisp_is_vf_pipe(pipe)) - return; - /* * CSS/FW requires set parameter and enqueue buffer happen after ISP * is streamon. @@ -3294,15 +3291,7 @@ int atomisp_set_parameters(struct video_device *vdev, dev_dbg(asd->isp->dev, "set parameter(per_frame_setting %d) isp_config_id %d of %s\n", arg->per_frame_setting, arg->isp_config_id, vdev->name); - if (IS_ISP2401) { - if (atomisp_is_vf_pipe(pipe) && arg->per_frame_setting) { - dev_err(asd->isp->dev, "%s: vf pipe not support per_frame_setting", - __func__); - return -EINVAL; - } - } - - if (arg->per_frame_setting && !atomisp_is_vf_pipe(pipe)) { + if (arg->per_frame_setting) { /* * Per-frame setting enabled, we allocate a new parameter * buffer to cache the parameters and only when frame buffers @@ -3341,7 +3330,7 @@ int atomisp_set_parameters(struct video_device *vdev, if (ret) goto apply_parameter_failed; - if (!(arg->per_frame_setting && !atomisp_is_vf_pipe(pipe))) { + if (!arg->per_frame_setting) { /* indicate to CSS that we have parameters to be updated */ asd->params.css_update_params_needed = true; } else { @@ -4780,23 +4769,6 @@ int atomisp_flash_enable(struct atomisp_sub_device *asd, int num_frames) return 0; } -bool atomisp_is_vf_pipe(struct atomisp_video_pipe *pipe) -{ - struct atomisp_sub_device *asd = pipe->asd; - - if (!asd) { - dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", - __func__, pipe->vdev.name); - return false; - } - - if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO && - pipe == &asd->video_out_preview) - return true; - - return false; -} - static int __checking_exp_id(struct atomisp_sub_device *asd, int exp_id) { struct atomisp_device *isp = asd->isp; diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.h b/drivers/staging/media/atomisp/pci/atomisp_cmd.h index 3cf086eba06d..cbe2f48d3dfa 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.h +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.h @@ -291,8 +291,6 @@ void atomisp_eof_event(struct atomisp_sub_device *asd, uint8_t exp_id); enum mipi_port_id __get_mipi_port(struct atomisp_device *isp, enum atomisp_camera_port port); -bool atomisp_is_vf_pipe(struct atomisp_video_pipe *pipe); - void atomisp_apply_css_parameters( struct atomisp_sub_device *asd, struct atomisp_css_params *css_param); diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index 3adeeb97e570..99152db236a1 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -403,9 +403,8 @@ static void atomisp_buf_queue(struct vb2_buffer *vb) * is put to waiting list until previous per-frame parameter buffers * get enqueued. */ - if (!atomisp_is_vf_pipe(pipe) && - (pipe->frame_request_config_id[vb->index] || - !list_empty(&pipe->buffers_waiting_for_param))) + if (pipe->frame_request_config_id[vb->index] || + !list_empty(&pipe->buffers_waiting_for_param)) list_add_tail(&frame->queue, &pipe->buffers_waiting_for_param); else list_add_tail(&frame->queue, &pipe->activeq); diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 392c0ed56fb4..3068f1a317f3 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -1045,8 +1045,7 @@ static int atomisp_qbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer if (buf->index >= vdev->queue->num_buffers) return -EINVAL; - if (!atomisp_is_vf_pipe(pipe) && - (buf->reserved2 & ATOMISP_BUFFER_HAS_PER_FRAME_SETTING)) { + if (buf->reserved2 & ATOMISP_BUFFER_HAS_PER_FRAME_SETTING) { /* this buffer will have a per-frame parameter */ pipe->frame_request_config_id[buf->index] = buf->reserved2 & ~ATOMISP_BUFFER_HAS_PER_FRAME_SETTING; From aca8a1dfb9ee56dcd358e73745c850db7f8a7dca Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 May 2023 20:42:26 +0100 Subject: [PATCH 145/253] media: atomisp: Rename video_out_preview to video_out Now that we have only 1 /dev/video# node for output for all different run-modes (with only 1 run-mode at a time) using video_out_preview for the remaining atomisp_pipe does not properly reflect that this is *the* output pipe. Fo the following renames to fix the naming: s/video_out_preview/video_out/ s/ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW/ATOMISP_SUBDEV_PAD_SOURCE/ Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 6 ++-- .../media/atomisp/pci/atomisp_compat_css20.c | 2 +- .../staging/media/atomisp/pci/atomisp_fops.c | 4 +-- .../staging/media/atomisp/pci/atomisp_ioctl.c | 2 +- .../media/atomisp/pci/atomisp_subdev.c | 34 ++++++++----------- .../media/atomisp/pci/atomisp_subdev.h | 5 ++- 6 files changed, 23 insertions(+), 30 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 3d6e0d0c7eaa..8cd94189052f 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -643,7 +643,7 @@ void atomisp_flush_video_pipe(struct atomisp_video_pipe *pipe, enum vb2_buffer_s /* Returns queued buffers back to video-core */ void atomisp_flush_bufs_and_wakeup(struct atomisp_sub_device *asd) { - atomisp_flush_video_pipe(&asd->video_out_preview, VB2_BUF_STATE_ERROR, false); + atomisp_flush_video_pipe(&asd->video_out, VB2_BUF_STATE_ERROR, false); } /* clean out the parameters that did not apply */ @@ -1032,7 +1032,7 @@ static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout) atomisp_flush_bufs_and_wakeup(&isp->asd); /* Requeue unprocessed per-frame parameters. */ - atomisp_recover_params_queue(&isp->asd.video_out_preview); + atomisp_recover_params_queue(&isp->asd.video_out); ret = v4l2_subdev_call( isp->inputs[isp->asd.input_curr].camera, video, @@ -1293,7 +1293,7 @@ static void atomisp_update_capture_mode(struct atomisp_sub_device *asd) atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_ADVANCED); else if (asd->params.low_light) atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_LOW_LIGHT); - else if (asd->video_out_preview.sh_fmt == IA_CSS_FRAME_FORMAT_RAW) + else if (asd->video_out.sh_fmt == IA_CSS_FRAME_FORMAT_RAW) atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_RAW); else atomisp_css_capture_set_mode(asd, IA_CSS_CAPTURE_MODE_PRIMARY); diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index 8e8caa99ce72..d5b9c0fda69a 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -1958,7 +1958,7 @@ void atomisp_css_stop(struct atomisp_sub_device *asd, list_splice_init(&asd->metadata_ready[i], &asd->metadata[i]); } - atomisp_flush_params_queue(&asd->video_out_preview); + atomisp_flush_params_queue(&asd->video_out); atomisp_free_css_parameters(&asd->params.css_param); memset(&asd->params.css_param, 0, sizeof(asd->params.css_param)); } diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index 99152db236a1..ccd96464ebfa 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -362,7 +362,7 @@ int atomisp_qbuffers_to_css(struct atomisp_sub_device *asd) pipe_id = IA_CSS_PIPE_ID_CAPTURE; } - atomisp_q_video_buffers_to_css(asd, &asd->video_out_preview, + atomisp_q_video_buffers_to_css(asd, &asd->video_out, ATOMISP_INPUT_STREAM_GENERAL, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, pipe_id); return 0; @@ -494,7 +494,7 @@ static void atomisp_subdev_init_struct(struct atomisp_sub_device *asd) */ static unsigned int atomisp_subdev_users(struct atomisp_sub_device *asd) { - return asd->video_out_preview.users; + return asd->video_out.users; } unsigned int atomisp_dev_users(struct atomisp_device *isp) diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 3068f1a317f3..1684ea6ad735 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -618,7 +618,7 @@ static int atomisp_enum_input(struct file *file, void *fh, static unsigned int atomisp_subdev_streaming_count(struct atomisp_sub_device *asd) { - return vb2_start_streaming_called(&asd->video_out_preview.vb_queue); + return vb2_start_streaming_called(&asd->video_out.vb_queue); } unsigned int atomisp_streaming_count(struct atomisp_device *isp) diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c index d7da8d076529..a9da3662e2ec 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c @@ -355,7 +355,7 @@ static const char *atomisp_pad_str(unsigned int pad) { static const char *const pad_str[] = { "ATOMISP_SUBDEV_PAD_SINK", - "ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW", + "ATOMISP_SUBDEV_PAD_SOURCE", }; if (pad >= ARRAY_SIZE(pad_str)) @@ -431,7 +431,7 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, struct v4l2_rect tmp = *crop[pad]; atomisp_subdev_set_selection(sd, sd_state, which, - ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW, + ATOMISP_SUBDEV_PAD_SOURCE, V4L2_SEL_TGT_COMPOSE, flags, &tmp); } @@ -593,7 +593,7 @@ void atomisp_subdev_set_ffmt(struct v4l2_subdev *sd, break; } - case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW: + case ATOMISP_SUBDEV_PAD_SOURCE: __ffmt->code = ffmt->code; break; } @@ -899,12 +899,10 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd) sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; pads[ATOMISP_SUBDEV_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - pads[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].flags = MEDIA_PAD_FL_SOURCE; + pads[ATOMISP_SUBDEV_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - asd->fmt[ATOMISP_SUBDEV_PAD_SINK].fmt.code = - MEDIA_BUS_FMT_SBGGR10_1X10; - asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW].fmt.code = - MEDIA_BUS_FMT_SBGGR10_1X10; + asd->fmt[ATOMISP_SUBDEV_PAD_SINK].fmt.code = MEDIA_BUS_FMT_SBGGR10_1X10; + asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE].fmt.code = MEDIA_BUS_FMT_SBGGR10_1X10; me->ops = &isp_subdev_media_ops; me->function = MEDIA_ENT_F_PROC_VIDEO_ISP; @@ -912,13 +910,11 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd) if (ret < 0) return ret; - ret = atomisp_init_subdev_pipe(asd, &asd->video_out_preview, - V4L2_BUF_TYPE_VIDEO_CAPTURE); + ret = atomisp_init_subdev_pipe(asd, &asd->video_out, V4L2_BUF_TYPE_VIDEO_CAPTURE); if (ret) return ret; - ret = atomisp_video_init(&asd->video_out_preview, "PREVIEW", - ATOMISP_RUN_MODE_PREVIEW); + ret = atomisp_video_init(&asd->video_out, "PREVIEW", ATOMISP_RUN_MODE_PREVIEW); if (ret < 0) return ret; @@ -980,9 +976,8 @@ int atomisp_create_pads_links(struct atomisp_device *isp) return ret; } - ret = media_create_pad_link(&isp->asd.subdev.entity, - ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW, - &isp->asd.video_out_preview.vdev.entity, 0, 0); + ret = media_create_pad_link(&isp->asd.subdev.entity, ATOMISP_SUBDEV_PAD_SOURCE, + &isp->asd.video_out.vdev.entity, 0, 0); if (ret < 0) return ret; @@ -1014,7 +1009,7 @@ void atomisp_subdev_unregister_entities(struct atomisp_sub_device *asd) { atomisp_subdev_cleanup_entities(asd); v4l2_device_unregister_subdev(&asd->subdev); - atomisp_video_unregister(&asd->video_out_preview); + atomisp_video_unregister(&asd->video_out); } int atomisp_subdev_register_subdev(struct atomisp_sub_device *asd, @@ -1028,10 +1023,9 @@ int atomisp_subdev_register_video_nodes(struct atomisp_sub_device *asd, { int ret; - asd->video_out_preview.vdev.v4l2_dev = vdev; - asd->video_out_preview.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - ret = video_register_device(&asd->video_out_preview.vdev, - VFL_TYPE_VIDEO, -1); + asd->video_out.vdev.v4l2_dev = vdev; + asd->video_out.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + ret = video_register_device(&asd->video_out.vdev, VFL_TYPE_VIDEO, -1); if (ret < 0) goto error; diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.h b/drivers/staging/media/atomisp/pci/atomisp_subdev.h index 2be594a8e733..c4f312c55a4a 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.h +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.h @@ -32,7 +32,7 @@ #define ATOMISP_MAX_EXP_ID (250) #define ATOMISP_SUBDEV_PAD_SINK 0 -#define ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW 1 +#define ATOMISP_SUBDEV_PAD_SOURCE 1 #define ATOMISP_SUBDEV_PADS_NUM 2 struct atomisp_in_fmt_conv { @@ -244,8 +244,7 @@ struct atomisp_sub_device { u16 capture_pad; /* main capture pad; defines much of isp config */ unsigned int output; - struct atomisp_video_pipe video_out_preview; /* preview output */ - /* struct isp_subdev_params params; */ + struct atomisp_video_pipe video_out; struct atomisp_device *isp; struct v4l2_ctrl_handler ctrl_handler; struct v4l2_ctrl *run_mode; From e4454e06e55d78852693641bebb041b6a0cebe79 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 May 2023 21:11:42 +0100 Subject: [PATCH 146/253] media: atomisp: Remove source_pad parameter from functions and structs Now that there is only 1 source-pad for an asd there is no need to have a parameter for this in various places. Remove the source_pad function parameter and atomisp_sub_device.capture_pad data member. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 44 ++++++++----------- .../media/atomisp/pci/atomisp_compat.h | 4 +- .../media/atomisp/pci/atomisp_compat_css20.c | 4 +- .../staging/media/atomisp/pci/atomisp_fops.c | 7 ++- .../staging/media/atomisp/pci/atomisp_ioctl.c | 13 +++--- .../media/atomisp/pci/atomisp_subdev.c | 25 ++--------- .../media/atomisp/pci/atomisp_subdev.h | 5 +-- 7 files changed, 33 insertions(+), 69 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 8cd94189052f..3dcf81e431cb 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -229,8 +229,8 @@ int atomisp_freq_scaling(struct atomisp_device *isp, goto done; } - curr_rules.width = isp->asd.fmt[isp->asd.capture_pad].fmt.width; - curr_rules.height = isp->asd.fmt[isp->asd.capture_pad].fmt.height; + curr_rules.width = isp->asd.fmt[ATOMISP_SUBDEV_PAD_SOURCE].fmt.width; + curr_rules.height = isp->asd.fmt[ATOMISP_SUBDEV_PAD_SOURCE].fmt.height; curr_rules.fps = fps; curr_rules.run_mode = isp->asd.run_mode->val; @@ -1548,13 +1548,12 @@ void atomisp_free_internal_buffers(struct atomisp_sub_device *asd) } static void atomisp_update_grid_info(struct atomisp_sub_device *asd, - enum ia_css_pipe_id pipe_id, - int source_pad) + enum ia_css_pipe_id pipe_id) { struct atomisp_device *isp = asd->isp; int err; - if (atomisp_css_get_grid_info(asd, pipe_id, source_pad)) + if (atomisp_css_get_grid_info(asd, pipe_id)) return; /* We must free all buffers because they no longer match @@ -4105,8 +4104,7 @@ static int css_input_resolution_changed(struct atomisp_sub_device *asd, static int atomisp_set_fmt_to_isp(struct video_device *vdev, struct ia_css_frame_info *output_info, - struct v4l2_pix_format *pix, - unsigned int source_pad) + struct v4l2_pix_format *pix) { struct camera_mipi_info *mipi_info; struct atomisp_device *isp = video_get_drvdata(vdev); @@ -4279,7 +4277,7 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, return ret; } - atomisp_update_grid_info(asd, pipe_id, source_pad); + atomisp_update_grid_info(asd, pipe_id); return 0; } @@ -4303,7 +4301,7 @@ static void atomisp_get_dis_envelop(struct atomisp_sub_device *asd, } static void atomisp_check_copy_mode(struct atomisp_sub_device *asd, - int source_pad, const struct v4l2_pix_format *f) + const struct v4l2_pix_format *f) { struct v4l2_mbus_framefmt *sink, *src; @@ -4316,7 +4314,7 @@ static void atomisp_check_copy_mode(struct atomisp_sub_device *asd, sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SINK); src = atomisp_subdev_get_ffmt(&asd->subdev, NULL, - V4L2_SUBDEV_FORMAT_ACTIVE, source_pad); + V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SOURCE); if (sink->code == src->code && sink->width == f->width && sink->height == f->height) asd->copy_mode = true; @@ -4439,7 +4437,6 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) .which = V4L2_SUBDEV_FORMAT_ACTIVE, }; struct v4l2_rect isp_sink_crop; - u16 source_pad = atomisp_subdev_source_pad(vdev); struct v4l2_subdev_fh fh; int ret; @@ -4447,12 +4444,9 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) if (ret) return ret; - if (source_pad >= ATOMISP_SUBDEV_PADS_NUM) - return -EINVAL; - dev_dbg(isp->dev, - "setting resolution %ux%u on pad %u bytesperline %u\n", - f->fmt.pix.width, f->fmt.pix.height, source_pad, f->fmt.pix.bytesperline); + "setting resolution %ux%u bytesperline %u\n", + f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.bytesperline); v4l2_fh_init(&fh.vfh, vdev); @@ -4501,9 +4495,9 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) isp_source_fmt.code = format_bridge->mbus_code; atomisp_subdev_set_ffmt(&asd->subdev, fh.state, V4L2_SUBDEV_FORMAT_ACTIVE, - source_pad, &isp_source_fmt); + ATOMISP_SUBDEV_PAD_SOURCE, &isp_source_fmt); - if (!atomisp_subdev_format_conversion(asd, source_pad)) { + if (!atomisp_subdev_format_conversion(asd)) { padding_w = 0; padding_h = 0; } @@ -4511,8 +4505,6 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) atomisp_get_dis_envelop(asd, f->fmt.pix.width, f->fmt.pix.height, &dvs_env_w, &dvs_env_h); - asd->capture_pad = source_pad; - ret = atomisp_set_fmt_to_snr(vdev, &f->fmt.pix, padding_w, padding_h, dvs_env_w, dvs_env_h); if (ret) { @@ -4523,7 +4515,7 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) atomisp_csi_lane_config(isp); - atomisp_check_copy_mode(asd, source_pad, &f->fmt.pix); + atomisp_check_copy_mode(asd, &f->fmt.pix); isp_sink_crop = *atomisp_subdev_get_rect(&asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, @@ -4534,7 +4526,7 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) * width or height) bigger than the desired result. */ if (isp_sink_crop.width * 9 / 10 < f->fmt.pix.width || isp_sink_crop.height * 9 / 10 < f->fmt.pix.height || - (atomisp_subdev_format_conversion(asd, source_pad) && + (atomisp_subdev_format_conversion(asd) && (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO || asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER))) { isp_sink_crop.width = f->fmt.pix.width; @@ -4548,7 +4540,7 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) &isp_sink_crop); atomisp_subdev_set_selection(&asd->subdev, fh.state, V4L2_SUBDEV_FORMAT_ACTIVE, - source_pad, V4L2_SEL_TGT_COMPOSE, + ATOMISP_SUBDEV_PAD_SOURCE, V4L2_SEL_TGT_COMPOSE, 0, &isp_sink_crop); } else if (IS_MOFD) { struct v4l2_rect main_compose = {0}; @@ -4567,7 +4559,7 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) atomisp_subdev_set_selection(&asd->subdev, fh.state, V4L2_SUBDEV_FORMAT_ACTIVE, - source_pad, + ATOMISP_SUBDEV_PAD_SOURCE, V4L2_SEL_TGT_COMPOSE, 0, &main_compose); } else { @@ -4605,12 +4597,12 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) atomisp_subdev_set_selection(&asd->subdev, fh.state, V4L2_SUBDEV_FORMAT_ACTIVE, - source_pad, + ATOMISP_SUBDEV_PAD_SOURCE, V4L2_SEL_TGT_COMPOSE, 0, &main_compose); } - ret = atomisp_set_fmt_to_isp(vdev, &output_info, &f->fmt.pix, source_pad); + ret = atomisp_set_fmt_to_isp(vdev, &output_info, &f->fmt.pix); if (ret) { dev_warn(isp->dev, "Can't set format on ISP. Error %d\n", ret); return -EINVAL; diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat.h b/drivers/staging/media/atomisp/pci/atomisp_compat.h index 218e8ac276c8..168c42956c29 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat.h +++ b/drivers/staging/media/atomisp/pci/atomisp_compat.h @@ -113,8 +113,7 @@ void atomisp_css_free_metadata_buffer(struct atomisp_metadata_buf *metadata_buf); int atomisp_css_get_grid_info(struct atomisp_sub_device *asd, - enum ia_css_pipe_id pipe_id, - int source_pad); + enum ia_css_pipe_id pipe_id); int atomisp_alloc_3a_output_buf(struct atomisp_sub_device *asd); @@ -276,7 +275,6 @@ int atomisp_css_video_configure_output(struct atomisp_sub_device *asd, enum ia_css_frame_format format); int atomisp_get_css_frame_info(struct atomisp_sub_device *asd, - u16 source_pad, struct ia_css_frame_info *frame_info); int atomisp_css_video_configure_viewfinder(struct atomisp_sub_device *asd, diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index d5b9c0fda69a..416cc45bd472 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -1328,8 +1328,7 @@ void atomisp_css_free_stat_buffers(struct atomisp_sub_device *asd) } int atomisp_css_get_grid_info(struct atomisp_sub_device *asd, - enum ia_css_pipe_id pipe_id, - int source_pad) + enum ia_css_pipe_id pipe_id) { struct ia_css_pipe_info p_info; struct ia_css_grid_info old_info; @@ -2432,7 +2431,6 @@ static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd) } int atomisp_get_css_frame_info(struct atomisp_sub_device *asd, - u16 source_pad, struct ia_css_frame_info *frame_info) { struct ia_css_pipe_info info; diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index ccd96464ebfa..39eba99feee0 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -47,7 +47,6 @@ static int atomisp_queue_setup(struct vb2_queue *vq, unsigned int sizes[], struct device *alloc_devs[]) { struct atomisp_video_pipe *pipe = container_of(vq, struct atomisp_video_pipe, vb_queue); - u16 source_pad = atomisp_subdev_source_pad(&pipe->vdev); int ret; mutex_lock(&pipe->asd->isp->mutex); /* for get_css_frame_info() / set_fmt() */ @@ -56,7 +55,7 @@ static int atomisp_queue_setup(struct vb2_queue *vq, * When VIDIOC_S_FMT has not been called before VIDIOC_REQBUFS, then * this will fail. Call atomisp_set_fmt() ourselves and try again. */ - ret = atomisp_get_css_frame_info(pipe->asd, source_pad, &pipe->frame_info); + ret = atomisp_get_css_frame_info(pipe->asd, &pipe->frame_info); if (ret) { struct v4l2_format f = { .fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420, @@ -68,7 +67,7 @@ static int atomisp_queue_setup(struct vb2_queue *vq, if (ret) goto out; - ret = atomisp_get_css_frame_info(pipe->asd, source_pad, &pipe->frame_info); + ret = atomisp_get_css_frame_info(pipe->asd, &pipe->frame_info); if (ret) goto out; } @@ -654,7 +653,7 @@ static int atomisp_release(struct file *file) done: atomisp_subdev_set_selection(&asd->subdev, fh.state, V4L2_SUBDEV_FORMAT_ACTIVE, - atomisp_subdev_source_pad(vdev), + ATOMISP_SUBDEV_PAD_SOURCE, V4L2_SEL_TGT_COMPOSE, 0, &clear_compose); mutex_unlock(&isp->mutex); diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 1684ea6ad735..8e2b5b647670 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -1131,7 +1131,7 @@ static unsigned int atomisp_sensor_start_stream(struct atomisp_sub_device *asd) if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO || (asd->run_mode->val == ATOMISP_RUN_MODE_STILL_CAPTURE && - !atomisp_is_mbuscode_raw(asd->fmt[asd->capture_pad].fmt.code))) + !atomisp_is_mbuscode_raw(asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE].fmt.code))) return 2; else return 1; @@ -1159,7 +1159,6 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) { struct atomisp_video_pipe *pipe = vq_to_pipe(vq); struct atomisp_sub_device *asd = pipe->asd; - struct video_device *vdev = &pipe->vdev; struct atomisp_device *isp = asd->isp; struct pci_dev *pdev = to_pci_dev(isp->dev); enum ia_css_pipe_id css_pipe_id; @@ -1167,9 +1166,9 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) unsigned long irqflags; int ret; - mutex_lock(&isp->mutex); + dev_dbg(isp->dev, "Start stream\n"); - dev_dbg(isp->dev, "Start stream on pad %d\n", atomisp_subdev_source_pad(vdev)); + mutex_lock(&isp->mutex); ret = atomisp_pipe_check(pipe, false); if (ret) @@ -1291,7 +1290,6 @@ void atomisp_stop_streaming(struct vb2_queue *vq) { struct atomisp_video_pipe *pipe = vq_to_pipe(vq); struct atomisp_sub_device *asd = pipe->asd; - struct video_device *vdev = &pipe->vdev; struct atomisp_device *isp = asd->isp; struct pci_dev *pdev = to_pci_dev(isp->dev); enum ia_css_pipe_id css_pipe_id; @@ -1300,10 +1298,9 @@ void atomisp_stop_streaming(struct vb2_queue *vq) unsigned long flags; int ret; + dev_dbg(isp->dev, "Stop stream\n"); + mutex_lock(&isp->mutex); - - dev_dbg(isp->dev, "Stop stream on pad %d\n", atomisp_subdev_source_pad(vdev)); - /* * There is no guarantee that the buffers queued to / owned by the ISP * will properly be returned to the queue when stopping. Set a flag to diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c index a9da3662e2ec..28554ee4ff67 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c @@ -117,35 +117,19 @@ const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv_by_atomisp_in_fmt( return NULL; } -bool atomisp_subdev_format_conversion(struct atomisp_sub_device *asd, - unsigned int source_pad) +bool atomisp_subdev_format_conversion(struct atomisp_sub_device *asd) { struct v4l2_mbus_framefmt *sink, *src; sink = atomisp_subdev_get_ffmt(&asd->subdev, NULL, - V4L2_SUBDEV_FORMAT_ACTIVE, - ATOMISP_SUBDEV_PAD_SINK); + V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SINK); src = atomisp_subdev_get_ffmt(&asd->subdev, NULL, - V4L2_SUBDEV_FORMAT_ACTIVE, source_pad); + V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SOURCE); return atomisp_is_mbuscode_raw(sink->code) && !atomisp_is_mbuscode_raw(src->code); } -uint16_t atomisp_subdev_source_pad(struct video_device *vdev) -{ - struct media_link *link; - u16 ret = 0; - - list_for_each_entry(link, &vdev->entity.links, list) { - if (link->source) { - ret = link->source->index; - break; - } - } - return ret; -} - /* * V4L2 subdev operations */ @@ -404,8 +388,7 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, padding_h = 12; } - if (atomisp_subdev_format_conversion(isp_sd, - isp_sd->capture_pad) + if (atomisp_subdev_format_conversion(isp_sd) && crop[pad]->width && crop[pad]->height) { crop[pad]->width -= padding_w; crop[pad]->height -= padding_h; diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.h b/drivers/staging/media/atomisp/pci/atomisp_subdev.h index c4f312c55a4a..ee7d0ee5d6e4 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.h +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.h @@ -241,7 +241,6 @@ struct atomisp_sub_device { struct v4l2_subdev subdev; struct media_pad pads[ATOMISP_SUBDEV_PADS_NUM]; struct atomisp_pad_format fmt[ATOMISP_SUBDEV_PADS_NUM]; - u16 capture_pad; /* main capture pad; defines much of isp config */ unsigned int output; struct atomisp_video_pipe video_out; @@ -340,9 +339,7 @@ const struct atomisp_in_fmt_conv atomisp_in_fmt); const struct atomisp_in_fmt_conv *atomisp_find_in_fmt_conv_compressed(u32 code); -bool atomisp_subdev_format_conversion(struct atomisp_sub_device *asd, - unsigned int source_pad); -uint16_t atomisp_subdev_source_pad(struct video_device *vdev); +bool atomisp_subdev_format_conversion(struct atomisp_sub_device *asd); /* Get pointer to appropriate format */ struct v4l2_mbus_framefmt From 8fd3c9a468c044e25b2ddaaa53d10414906b83af Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 May 2023 21:14:47 +0100 Subject: [PATCH 147/253] media: atomisp: Remove 1 line atomisp_flush_bufs_and_wakeup() helper After recent changes this now is just a wrapper around atomisp_flush_video_pipe(). Make its single caller call atomisp_flush_video_pipe() directly and drop the helper. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 8 +------- drivers/staging/media/atomisp/pci/atomisp_cmd.h | 1 - 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 3dcf81e431cb..42a2a8f0da06 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -640,12 +640,6 @@ void atomisp_flush_video_pipe(struct atomisp_video_pipe *pipe, enum vb2_buffer_s spin_unlock_irqrestore(&pipe->irq_lock, irqflags); } -/* Returns queued buffers back to video-core */ -void atomisp_flush_bufs_and_wakeup(struct atomisp_sub_device *asd) -{ - atomisp_flush_video_pipe(&asd->video_out, VB2_BUF_STATE_ERROR, false); -} - /* clean out the parameters that did not apply */ void atomisp_flush_params_queue(struct atomisp_video_pipe *pipe) { @@ -1029,7 +1023,7 @@ static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout) * dequeueing buffers is not needed. CSS will recycle * buffers that it has. */ - atomisp_flush_bufs_and_wakeup(&isp->asd); + atomisp_flush_video_pipe(&isp->asd.video_out, VB2_BUF_STATE_ERROR, false); /* Requeue unprocessed per-frame parameters. */ atomisp_recover_params_queue(&isp->asd.video_out); diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.h b/drivers/staging/media/atomisp/pci/atomisp_cmd.h index cbe2f48d3dfa..1cb973ddf2dc 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.h +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.h @@ -59,7 +59,6 @@ int atomisp_buffers_in_css(struct atomisp_video_pipe *pipe); void atomisp_buffer_done(struct ia_css_frame *frame, enum vb2_buffer_state state); void atomisp_flush_video_pipe(struct atomisp_video_pipe *pipe, enum vb2_buffer_state state, bool warn_on_css_frames); -void atomisp_flush_bufs_and_wakeup(struct atomisp_sub_device *asd); void atomisp_clear_css_buffer_counters(struct atomisp_sub_device *asd); /* Interrupt functions */ From 28714506c3b775702dd6738a0a44b9ff0d7bf0ac Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 May 2023 21:19:33 +0100 Subject: [PATCH 148/253] media: atomisp: Remove atomisp_subdev_register_video_nodes() helper Now that there is only 1 /dev/video# node left there is no need to do this in a helper. Just make atomisp_register_device_nodes() call video_register_device() directly. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_subdev.c | 18 ------------------ .../staging/media/atomisp/pci/atomisp_subdev.h | 2 -- .../staging/media/atomisp/pci/atomisp_v4l2.c | 4 +++- 3 files changed, 3 insertions(+), 21 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c index 28554ee4ff67..32fc4d25c663 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c @@ -1001,24 +1001,6 @@ int atomisp_subdev_register_subdev(struct atomisp_sub_device *asd, return v4l2_device_register_subdev(vdev, &asd->subdev); } -int atomisp_subdev_register_video_nodes(struct atomisp_sub_device *asd, - struct v4l2_device *vdev) -{ - int ret; - - asd->video_out.vdev.v4l2_dev = vdev; - asd->video_out.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - ret = video_register_device(&asd->video_out.vdev, VFL_TYPE_VIDEO, -1); - if (ret < 0) - goto error; - - return 0; - -error: - atomisp_subdev_unregister_entities(asd); - return ret; -} - /* * atomisp_subdev_init - ISP Subdevice initialization. * @dev: Device pointer specific to the ATOM ISP. diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.h b/drivers/staging/media/atomisp/pci/atomisp_subdev.h index ee7d0ee5d6e4..28afcdd41ef3 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.h +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.h @@ -367,8 +367,6 @@ void atomisp_subdev_cleanup_pending_events(struct atomisp_sub_device *asd); void atomisp_subdev_unregister_entities(struct atomisp_sub_device *asd); int atomisp_subdev_register_subdev(struct atomisp_sub_device *asd, struct v4l2_device *vdev); -int atomisp_subdev_register_video_nodes(struct atomisp_sub_device *asd, - struct v4l2_device *vdev); int atomisp_subdev_init(struct atomisp_device *isp); void atomisp_subdev_cleanup(struct atomisp_device *isp); int atomisp_create_pads_links(struct atomisp_device *isp); diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index 4370d560308e..f914ab9068c1 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -1016,7 +1016,9 @@ static int atomisp_register_device_nodes(struct atomisp_device *isp) { int err; - err = atomisp_subdev_register_video_nodes(&isp->asd, &isp->v4l2_dev); + isp->asd.video_out.vdev.v4l2_dev = &isp->v4l2_dev; + isp->asd.video_out.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + err = video_register_device(&isp->asd.video_out.vdev, VFL_TYPE_VIDEO, -1); if (err) return err; From 6f48bc9e49f9ff343badeee9b87b258826c9bdc6 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 May 2023 21:21:30 +0100 Subject: [PATCH 149/253] media: atomisp: Remove a bunch of unused atomisp_css_*() functions Remove various unused atomisp_css_*() functions from atomisp_compat_css20.c. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/atomisp_compat.h | 29 ------ .../media/atomisp/pci/atomisp_compat_css20.c | 99 ------------------- 2 files changed, 128 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat.h b/drivers/staging/media/atomisp/pci/atomisp_compat.h index 168c42956c29..850b354cc160 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat.h +++ b/drivers/staging/media/atomisp/pci/atomisp_compat.h @@ -150,10 +150,6 @@ int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd, enum atomisp_input_stream_id stream_id, struct v4l2_mbus_framefmt *ffmt); -int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - enum atomisp_input_format input_format); - void atomisp_css_isys_two_stream_cfg_update_stream1( struct atomisp_sub_device *asd, enum atomisp_input_stream_id stream_id, @@ -209,15 +205,6 @@ void atomisp_css_capture_enable_online(struct atomisp_sub_device *asd, void atomisp_css_preview_enable_online(struct atomisp_sub_device *asd, unsigned short stream_index, bool enable); -void atomisp_css_video_enable_online(struct atomisp_sub_device *asd, - bool enable); - -void atomisp_css_enable_continuous(struct atomisp_sub_device *asd, - bool enable); - -void atomisp_css_enable_cvf(struct atomisp_sub_device *asd, - bool enable); - int atomisp_css_input_configure_port(struct atomisp_sub_device *asd, enum mipi_port_id port, unsigned int num_lanes, @@ -243,22 +230,6 @@ int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd, unsigned int padded_width, enum ia_css_frame_format format); -int atomisp_css_yuvpp_configure_output(struct atomisp_sub_device *asd, - unsigned int stream_index, - unsigned int width, unsigned int height, - unsigned int padded_width, - enum ia_css_frame_format format); - -int atomisp_css_yuvpp_get_output_frame_info( - struct atomisp_sub_device *asd, - unsigned int stream_index, - struct ia_css_frame_info *info); - -int atomisp_css_yuvpp_get_viewfinder_frame_info( - struct atomisp_sub_device *asd, - unsigned int stream_index, - struct ia_css_frame_info *info); - int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd, unsigned int width, unsigned int height, unsigned int min_width, diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index 416cc45bd472..43760fcc0d43 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -1611,29 +1611,6 @@ int atomisp_css_set_default_isys_config(struct atomisp_sub_device *asd, return 0; } -int atomisp_css_isys_two_stream_cfg(struct atomisp_sub_device *asd, - enum atomisp_input_stream_id stream_id, - enum atomisp_input_format input_format) -{ - struct ia_css_stream_config *s_config = - &asd->stream_env[stream_id].stream_config; - - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.width = - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.width; - - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].input_res.height = - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].input_res.height / 2; - - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].linked_isys_stream_id - = IA_CSS_STREAM_ISYS_STREAM_0; - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_0].format = - ATOMISP_INPUT_FORMAT_USER_DEF1; - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].format = - ATOMISP_INPUT_FORMAT_USER_DEF2; - s_config->isys_config[IA_CSS_STREAM_ISYS_STREAM_1].valid = true; - return 0; -} - void atomisp_css_isys_two_stream_cfg_update_stream1( struct atomisp_sub_device *asd, enum atomisp_input_stream_id stream_id, @@ -1819,49 +1796,6 @@ void atomisp_css_preview_enable_online(struct atomisp_sub_device *asd, } } -void atomisp_css_video_enable_online(struct atomisp_sub_device *asd, - bool enable) -{ - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_VIDEO]; - int i; - - if (stream_env->stream_config.online != enable) { - stream_env->stream_config.online = enable; - for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) - stream_env->update_pipe[i] = true; - } -} - -void atomisp_css_enable_continuous(struct atomisp_sub_device *asd, - bool enable) -{ - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; - int i; - - if (stream_env->stream_config.continuous != !!enable) { - stream_env->stream_config.continuous = !!enable; - stream_env->stream_config.pack_raw_pixels = true; - for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) - stream_env->update_pipe[i] = true; - } -} - -void atomisp_css_enable_cvf(struct atomisp_sub_device *asd, - bool enable) -{ - struct atomisp_stream_env *stream_env = - &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]; - int i; - - if (stream_env->stream_config.disable_cont_viewfinder != !enable) { - stream_env->stream_config.disable_cont_viewfinder = !enable; - for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) - stream_env->update_pipe[i] = true; - } -} - int atomisp_css_input_configure_port( struct atomisp_sub_device *asd, enum mipi_port_id port, @@ -2467,39 +2401,6 @@ int atomisp_css_copy_configure_output(struct atomisp_sub_device *asd, return 0; } -int atomisp_css_yuvpp_configure_output(struct atomisp_sub_device *asd, - unsigned int stream_index, - unsigned int width, unsigned int height, - unsigned int padded_width, - enum ia_css_frame_format format) -{ - asd->stream_env[stream_index].pipe_configs[IA_CSS_PIPE_ID_YUVPP]. - default_capture_config.mode = - IA_CSS_CAPTURE_MODE_RAW; - - __configure_output(asd, stream_index, width, height, padded_width, - format, IA_CSS_PIPE_ID_YUVPP); - return 0; -} - -int atomisp_css_yuvpp_get_output_frame_info( - struct atomisp_sub_device *asd, - unsigned int stream_index, - struct ia_css_frame_info *info) -{ - return __get_frame_info(asd, stream_index, info, - ATOMISP_CSS_OUTPUT_FRAME, IA_CSS_PIPE_ID_YUVPP); -} - -int atomisp_css_yuvpp_get_viewfinder_frame_info( - struct atomisp_sub_device *asd, - unsigned int stream_index, - struct ia_css_frame_info *info) -{ - return __get_frame_info(asd, stream_index, info, - ATOMISP_CSS_VF_FRAME, IA_CSS_PIPE_ID_YUVPP); -} - int atomisp_css_preview_configure_output(struct atomisp_sub_device *asd, unsigned int width, unsigned int height, unsigned int min_width, From fb86cf8bd8a94981be5c0f4263f31e43e1aaf445 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 10 May 2023 21:21:51 +0100 Subject: [PATCH 150/253] media: atomisp: Remove unused mipi_frame_size field from atomisp_[sub_]device Both the atomisp_device and the atomisp_sub_device structs have an unused mipi_frame_size field, remove the field from both. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_fops.c | 2 -- drivers/staging/media/atomisp/pci/atomisp_internal.h | 1 - drivers/staging/media/atomisp/pci/atomisp_subdev.h | 2 -- 3 files changed, 5 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index 39eba99feee0..37d8c8af3e8c 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -448,7 +448,6 @@ static void atomisp_dev_init_struct(struct atomisp_device *isp) unsigned int i; isp->isp_fatal_error = false; - isp->mipi_frame_size = 0; for (i = 0; i < isp->input_cnt; i++) isp->inputs[i].asd = NULL; @@ -478,7 +477,6 @@ static void atomisp_subdev_init_struct(struct atomisp_sub_device *asd) /* Add for channel */ asd->input_curr = 0; - asd->mipi_frame_size = 0; asd->copy_mode = false; asd->stream_prepared = false; diff --git a/drivers/staging/media/atomisp/pci/atomisp_internal.h b/drivers/staging/media/atomisp/pci/atomisp_internal.h index e531f0c71a15..cec0ac92726e 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_internal.h +++ b/drivers/staging/media/atomisp/pci/atomisp_internal.h @@ -211,7 +211,6 @@ struct atomisp_device { spinlock_t lock; /* Protects asd.streaming */ - unsigned int mipi_frame_size; const struct atomisp_dfs_config *dfs; unsigned int hpll_freq; unsigned int running_freq; diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.h b/drivers/staging/media/atomisp/pci/atomisp_subdev.h index 28afcdd41ef3..a702890003f9 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.h +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.h @@ -304,8 +304,6 @@ struct atomisp_sub_device { unsigned int latest_preview_exp_id; /* CSS ZSL/SDV raw buffer id */ - unsigned int mipi_frame_size; - bool copy_mode; /* CSI2+ use copy mode */ int raw_buffer_bitmap[ATOMISP_MAX_EXP_ID / 32 + From 820a1338d6a14bde0de7ed57cf486c31798a9619 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 11 May 2023 15:51:21 +0100 Subject: [PATCH 151/253] media: atomisp: Remove isp_timeout flag isp_timeout only ever gets set in __atomisp_css_recover() and then immediately gets cleared again after calling atomisp_reset(). All this happens with isp->mutex held. The only consumer of isp->isp_timeout is atomisp_stop_streaming(), which also holds isp->mutex and which is *not* called by atomisp_reset(). Since both hold isp->mutex and since __atomisp_css_recover() clears isp_timeout before releasing the mutex, atomisp_stop_streaming() can never see isp_timeout being true, so just remove the flag. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 8 +++----- drivers/staging/media/atomisp/pci/atomisp_internal.h | 2 -- drivers/staging/media/atomisp/pci/atomisp_ioctl.c | 7 +------ 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 42a2a8f0da06..ea07ddcdd7f1 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -935,7 +935,7 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error, atomisp_qbuffers_to_css(asd); } -static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout) +static void __atomisp_css_recover(struct atomisp_device *isp) { struct pci_dev *pdev = to_pci_dev(isp->dev); enum ia_css_pipe_id css_pipe_id; @@ -992,9 +992,7 @@ static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout) isp->saved_regs.i_control | MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK); /* reset ISP and restore its state */ - isp->isp_timeout = true; atomisp_reset(isp); - isp->isp_timeout = false; if (stream_restart) { atomisp_css_input_set_mode(&isp->asd, IA_CSS_INPUT_MODE_BUFFERED_SENSOR); @@ -1043,14 +1041,14 @@ void atomisp_assert_recovery_work(struct work_struct *work) assert_recovery_work); mutex_lock(&isp->mutex); - __atomisp_css_recover(isp, true); + __atomisp_css_recover(isp); mutex_unlock(&isp->mutex); } void atomisp_css_flush(struct atomisp_device *isp) { /* Start recover */ - __atomisp_css_recover(isp, false); + __atomisp_css_recover(isp); dev_dbg(isp->dev, "atomisp css flush done\n"); } diff --git a/drivers/staging/media/atomisp/pci/atomisp_internal.h b/drivers/staging/media/atomisp/pci/atomisp_internal.h index cec0ac92726e..3d4f0f632f44 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_internal.h +++ b/drivers/staging/media/atomisp/pci/atomisp_internal.h @@ -204,8 +204,6 @@ struct atomisp_device { struct atomisp_regs saved_regs; struct atomisp_css_env css_env; - /* isp timeout status flag */ - bool isp_timeout; bool isp_fatal_error; struct work_struct assert_recovery_work; diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 8e2b5b647670..e0a8616ecf05 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -1369,11 +1369,7 @@ stopsensor: /* * ISP work around, need to reset isp * Is it correct time to reset ISP when first node does streamoff? - */ - if (isp->isp_timeout) - dev_err(isp->dev, "%s: Resetting with WA activated", - __func__); - /* + * * It is possible that the other asd stream is in the stage * that v4l2_setfmt is just get called on it, which will * create css stream on that stream. But at this point, there @@ -1403,7 +1399,6 @@ stopsensor: } } - isp->isp_timeout = false; out_unlock: mutex_unlock(&isp->mutex); } From 1ae393ea3dbc0a75f1eb460d32d56a4f18dfd684 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 9 May 2023 22:12:16 +0100 Subject: [PATCH 152/253] media: atomisp: Remove atomisp_sensor_start_stream() Now that we no longer have continuous mode we always want to start the sensor on the first atomisp_start_streaming() call and stop it on the first atomisp_stop_streaming() call. Remove atomisp_sensor_start_stream() which returned the number of streams which should be active before starting the sensor and always start/stop the sensor directly. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_ioctl.c | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index e0a8616ecf05..13e00a2af8e1 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -1123,20 +1123,6 @@ enum ia_css_pipe_id atomisp_get_css_pipe_id(struct atomisp_sub_device *asd) } } -static unsigned int atomisp_sensor_start_stream(struct atomisp_sub_device *asd) -{ - if (asd->vfpp->val != ATOMISP_VFPP_ENABLE || - asd->copy_mode) - return 1; - - if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO || - (asd->run_mode->val == ATOMISP_RUN_MODE_STILL_CAPTURE && - !atomisp_is_mbuscode_raw(asd->fmt[ATOMISP_SUBDEV_PAD_SOURCE].fmt.code))) - return 2; - else - return 1; -} - /* Input system HW workaround */ /* Input system address translation corrupts burst during */ /* invalidate. SW workaround for this is to set burst length */ @@ -1162,7 +1148,6 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) struct atomisp_device *isp = asd->isp; struct pci_dev *pdev = to_pci_dev(isp->dev); enum ia_css_pipe_id css_pipe_id; - unsigned int sensor_start_stream; unsigned long irqflags; int ret; @@ -1177,18 +1162,6 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) /* Input system HW workaround */ atomisp_dma_burst_len_cfg(asd); - /* - * The number of streaming video nodes is based on which - * binary is going to be run. - */ - sensor_start_stream = atomisp_sensor_start_stream(asd); - - if (atomisp_subdev_streaming_count(asd) > sensor_start_stream) { - atomisp_qbuffers_to_css(asd); - ret = 0; - goto out_unlock; - } - if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED) { atomisp_qbuffers_to_css(asd); goto start_sensor; @@ -1233,12 +1206,6 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) atomisp_qbuffers_to_css(asd); - /* Only start sensor when the last streaming instance started */ - if (atomisp_subdev_streaming_count(asd) < sensor_start_stream) { - ret = 0; - goto out_unlock; - } - start_sensor: if (isp->flash) { asd->params.num_flash_frames = 0; @@ -1340,9 +1307,6 @@ void atomisp_stop_streaming(struct vb2_queue *vq) atomisp_subdev_cleanup_pending_events(asd); stopsensor: - if (atomisp_subdev_streaming_count(asd) != atomisp_sensor_start_stream(asd)) - goto out_unlock; - ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, video, s_stream, 0); From 3f3ee94c89b79c9addaf83b029edec9b720ec1f7 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 11 May 2023 16:03:38 +0100 Subject: [PATCH 153/253] media: atomisp: Simplify atomisp_[start|stop]_streaming() Now that continuous mode is gone and we only have 1 /dev/video# node, the videobuf2 core guarantees that atomisp_[start|stop]_streaming() will only be called one at a time. So there is no need to check for things like the isp is already streaming when starting, or other streams still being active while stopping. Remove checks for these from atomisp_[start|stop]_streaming(). While at it also improve the logging a bit: 1. Remove the dev_err(isp->dev, "atomisp_reset") logged on every stream stop (even though everything is fine. 2. Log a message when starting/stopping the sensor stream fails Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_ioctl.c | 89 ++++--------------- 1 file changed, 17 insertions(+), 72 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 13e00a2af8e1..087ec5120bce 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -615,12 +615,6 @@ static int atomisp_enum_input(struct file *file, void *fh, return 0; } -static unsigned int -atomisp_subdev_streaming_count(struct atomisp_sub_device *asd) -{ - return vb2_start_streaming_called(&asd->video_out.vb_queue); -} - unsigned int atomisp_streaming_count(struct atomisp_device *isp) { return isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED; @@ -1162,11 +1156,6 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) /* Input system HW workaround */ atomisp_dma_burst_len_cfg(asd); - if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED) { - atomisp_qbuffers_to_css(asd); - goto start_sensor; - } - css_pipe_id = atomisp_get_css_pipe_id(asd); /* Invalidate caches. FIXME: should flush only necessary buffers */ @@ -1206,7 +1195,6 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) atomisp_qbuffers_to_css(asd); -start_sensor: if (isp->flash) { asd->params.num_flash_frames = 0; asd->params.flash_state = ATOMISP_FLASH_IDLE; @@ -1216,19 +1204,9 @@ start_sensor: atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, atomisp_css_valid_sof(isp)); atomisp_csi2_configure(asd); - /* - * set freq to max when streaming count > 1 which indicate - * dual camera would run - */ - if (atomisp_streaming_count(isp) > 1) { - if (atomisp_freq_scaling(isp, - ATOMISP_DFS_MODE_MAX, false) < 0) - dev_dbg(isp->dev, "DFS max mode failed!\n"); - } else { - if (atomisp_freq_scaling(isp, - ATOMISP_DFS_MODE_AUTO, false) < 0) - dev_dbg(isp->dev, "DFS auto mode failed!\n"); - } + + if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_AUTO, false) < 0) + dev_dbg(isp->dev, "DFS auto mode failed!\n"); /* Enable the CSI interface on ANN B0/K0 */ if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 << @@ -1241,6 +1219,7 @@ start_sensor: ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, video, s_stream, 1); if (ret) { + dev_err(isp->dev, "Starting sensor stream failed: %d\n", ret); spin_lock_irqsave(&isp->lock, irqflags); asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED; spin_unlock_irqrestore(&isp->lock, irqflags); @@ -1260,8 +1239,6 @@ void atomisp_stop_streaming(struct vb2_queue *vq) struct atomisp_device *isp = asd->isp; struct pci_dev *pdev = to_pci_dev(isp->dev); enum ia_css_pipe_id css_pipe_id; - bool recreate_stream = false; - bool first_streamoff = false; unsigned long flags; int ret; @@ -1284,19 +1261,10 @@ void atomisp_stop_streaming(struct vb2_queue *vq) if (ret == 0) dev_warn(isp->dev, "Warning timeout waiting for CSS to return buffers\n"); - if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED) - first_streamoff = true; - spin_lock_irqsave(&isp->lock, flags); - if (atomisp_subdev_streaming_count(asd) == 1) - asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED; - else - asd->streaming = ATOMISP_DEVICE_STREAMING_STOPPING; + asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED; spin_unlock_irqrestore(&isp->lock, flags); - if (!first_streamoff) - goto stopsensor; - atomisp_clear_css_buffer_counters(asd); atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false); @@ -1306,21 +1274,17 @@ void atomisp_stop_streaming(struct vb2_queue *vq) atomisp_flush_video_pipe(pipe, VB2_BUF_STATE_ERROR, true); atomisp_subdev_cleanup_pending_events(asd); -stopsensor: + ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, video, s_stream, 0); + if (ret) + dev_warn(isp->dev, "Stopping sensor stream failed: %d\n", ret); if (isp->flash) { asd->params.num_flash_frames = 0; asd->params.flash_state = ATOMISP_FLASH_IDLE; } - /* if other streams are running, isp should not be powered off */ - if (atomisp_streaming_count(isp)) { - atomisp_css_flush(isp); - goto out_unlock; - } - /* Disable the CSI interface on ANN B0/K0 */ if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT) | ATOMISP_HW_STEPPING_B0)) { @@ -1330,40 +1294,21 @@ stopsensor: if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_LOW, false)) dev_warn(isp->dev, "DFS failed.\n"); - /* - * ISP work around, need to reset isp - * Is it correct time to reset ISP when first node does streamoff? - * - * It is possible that the other asd stream is in the stage - * that v4l2_setfmt is just get called on it, which will - * create css stream on that stream. But at this point, there - * is no way to destroy the css stream created on that stream. - * - * So force stream destroy here. - */ - if (isp->asd.stream_prepared) { - atomisp_destroy_pipes_stream_force(&isp->asd); - recreate_stream = true; - } - /* disable PUNIT/ISP acknowlede/handshake - SRSE=3 */ + /* + * ISP work around, need to reset ISP to allow next stream on to work. + * Streams have already been destroyed by atomisp_css_stop(). + * Disable PUNIT/ISP acknowlede/handshake - SRSE=3 and then reset. + */ pci_write_config_dword(pdev, PCI_I_CONTROL, isp->saved_regs.i_control | MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK); - dev_err(isp->dev, "atomisp_reset"); atomisp_reset(isp); - if (recreate_stream) { - int ret2; + /* Streams were destroyed by atomisp_css_stop(), recreate them. */ + ret = atomisp_create_pipes_stream(&isp->asd); + if (ret) + dev_warn(isp->dev, "Recreating streams failed: %d\n", ret); - ret2 = atomisp_create_pipes_stream(&isp->asd); - if (ret2) { - dev_err(isp->dev, "%s error re-creating streams: %d\n", __func__, ret2); - if (!ret) - ret = ret2; - } - } - -out_unlock: mutex_unlock(&isp->mutex); } From 71a85e054f3237595c50b1a74919185597fa2fba Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 11 May 2023 19:27:24 +0100 Subject: [PATCH 154/253] media: atomisp: Simplify atomisp_css_[start|stop]() Now that continuous mode is gone and we only have 1 /dev/video# node, the videobuf2 core guarantees that atomisp_css_[start|stop]() will only be called one at a time. So there is no need for atomisp_streaming_count() counts. When reqbufs has been done then the streams are guaranteed to be created, and streaming cannot be started without reqbufs so there is no need for atomisp_css_start() to check if it needs to create the streams. Use this to clean-up atomisp_css_[start|stop](). While at it also fix atomisp_css_start() not re-creating the streams on an error, breaking the guarantee that the streams are always there after a succesfull reqbufs call. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/atomisp_compat_css20.c | 68 ++++++------------- 1 file changed, 20 insertions(+), 48 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index 43760fcc0d43..092262e1b7ec 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -1001,42 +1001,17 @@ int atomisp_css_start(struct atomisp_sub_device *asd, wbinvd(); } - /* - * For dual steam case, it is possible that: - * 1: for this stream, it is at the stage that: - * - after set_fmt is called - * - before stream on is called - * 2: for the other stream, the stream off is called which css reset - * has been done. - * - * Thus the stream created in set_fmt get destroyed and need to be - * recreated in the next stream on. - */ - if (!asd->stream_prepared) { - ret = atomisp_create_pipes_stream(asd); - if (ret) - return ret; - } - /* - * SP can only be started one time - * if atomisp_subdev_streaming_count() tell there already has some - * subdev at streamming, then SP should already be started previously, - * so need to skip start sp procedure - */ - if (atomisp_streaming_count(isp)) { - dev_dbg(isp->dev, "skip start sp\n"); - } else { - if (!sh_css_hrt_system_is_idle()) - dev_err(isp->dev, "CSS HW not idle before starting SP\n"); - if (ia_css_start_sp()) { - dev_err(isp->dev, "start sp error.\n"); - ret = -EINVAL; - goto start_err; - } else { - sp_is_started = true; - } + if (!sh_css_hrt_system_is_idle()) + dev_err(isp->dev, "CSS HW not idle before starting SP\n"); + + if (ia_css_start_sp()) { + dev_err(isp->dev, "start sp error.\n"); + ret = -EINVAL; + goto start_err; } + sp_is_started = true; + for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { if (asd->stream_env[i].stream) { if (ia_css_stream_start(asd->stream_env[i] @@ -1054,16 +1029,15 @@ int atomisp_css_start(struct atomisp_sub_device *asd, return 0; start_err: - atomisp_destroy_pipes_stream_force(asd); - - /* css 2.0 API limitation: ia_css_stop_sp() could be only called after - * destroy all pipes - */ /* - * SP can not be stop if other streams are in use + * CSS 2.0 API limitation: ia_css_stop_sp() can only be called after + * destroying all pipes. */ - if ((atomisp_streaming_count(isp) == 0) && sp_is_started) + if (sp_is_started) { + atomisp_destroy_pipes_stream_force(asd); ia_css_stop_sp(); + atomisp_create_pipes_stream(asd); + } return ret; } @@ -1843,20 +1817,18 @@ int atomisp_css_input_configure_port( void atomisp_css_stop(struct atomisp_sub_device *asd, enum ia_css_pipe_id pipe_id, bool in_reset) { - struct atomisp_device *isp = asd->isp; unsigned long irqflags; unsigned int i; - /* if is called in atomisp_reset(), force destroy streams and pipes */ + /* + * CSS 2.0 API limitation: ia_css_stop_sp() can only be called after + * destroying all pipes. + */ atomisp_destroy_pipes_stream_force(asd); atomisp_init_raw_buffer_bitmap(asd); - /* - * SP can not be stop if other streams are in use - */ - if (atomisp_streaming_count(isp) == 0) - ia_css_stop_sp(); + ia_css_stop_sp(); if (!in_reset) { struct atomisp_stream_env *stream_env; From 347f2e56b94e1ed197daa6697b22af049a82157d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 11 May 2023 16:39:37 +0100 Subject: [PATCH 155/253] media: atomisp: Simplify atomisp_open() and atomisp_release() Now that continuous mode is gone and we only have 1 /dev/video# node, combined with only allowing 1 open of that /dev/video# node for now, there is no need to check for other (sub)dev / pipe users. Remove the unnecessary checks for a nice cleanup. Note we also don't need to set asd->streaming to disabled since the vb2_fop_release() call done by atomisp_release() will have called atomisp_stop_streaming() already at this point (if necessary) and that will have already done this. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_fops.c | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index 37d8c8af3e8c..ef1a5ad30ace 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -532,11 +532,6 @@ static int atomisp_open(struct file *file) return -EBUSY; } - if (atomisp_dev_users(isp)) { - dev_dbg(isp->dev, "skip init isp in open\n"); - goto init_subdev; - } - /* runtime power management, turn on ISP */ ret = pm_runtime_resume_and_get(vdev->v4l2_dev->dev); if (ret < 0) { @@ -552,19 +547,12 @@ static int atomisp_open(struct file *file) goto css_error; } -init_subdev: - if (atomisp_subdev_users(asd)) - goto done; - atomisp_subdev_init_struct(asd); /* Ensure that a mode is set */ v4l2_ctrl_s_ctrl(asd->run_mode, pipe->default_run_mode); -done: pipe->users++; mutex_unlock(&isp->mutex); - - return 0; css_error: @@ -583,7 +571,6 @@ static int atomisp_release(struct file *file) struct atomisp_sub_device *asd = pipe->asd; struct v4l2_subdev_fh fh; struct v4l2_rect clear_compose = {0}; - unsigned long flags; int ret; v4l2_fh_init(&fh.vfh, vdev); @@ -598,8 +585,6 @@ static int atomisp_release(struct file *file) mutex_lock(&isp->mutex); pipe->users--; - if (pipe->users) - goto done; /* * A little trick here: @@ -616,9 +601,6 @@ static int atomisp_release(struct file *file) ATOMISP_SUBDEV_PAD_SINK, &isp_sink_fmt); } - if (atomisp_subdev_users(asd)) - goto done; - atomisp_css_free_stat_buffers(asd); atomisp_free_internal_buffers(asd); @@ -632,13 +614,6 @@ static int atomisp_release(struct file *file) isp->inputs[asd->input_curr].asd = NULL; } - spin_lock_irqsave(&isp->lock, flags); - asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED; - spin_unlock_irqrestore(&isp->lock, flags); - - if (atomisp_dev_users(isp)) - goto done; - atomisp_destroy_pipes_stream_force(asd); ret = v4l2_subdev_call(isp->flash, core, s_power, 0); @@ -648,7 +623,6 @@ static int atomisp_release(struct file *file) if (pm_runtime_put_sync(vdev->v4l2_dev->dev) < 0) dev_err(isp->dev, "Failed to power off device\n"); -done: atomisp_subdev_set_selection(&asd->subdev, fh.state, V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SOURCE, From e1278e6187b804566b789bdfd5339cceed035d71 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 11 May 2023 18:18:24 +0100 Subject: [PATCH 156/253] media: atomisp: Simplify atomisp_pipe_check() All switch (pipe->asd->streaming) cases in atomisp_pipe_check() are either no-ops or never happen: 1. ATOMISP_DEVICE_STREAMING_DISABLED already is a no-op 2. The videobuf2 core guarantees that when we are streaming vb2_is_busy() returns true. So the ATOMISP_DEVICE_STREAMING_ENABLED case is already handled by the if above the switch (pipe->asd->streaming). 3. After recent changes pipe->asd->streaming is only ever set to ATOMISP_DEVICE_STREAMING_STOPPING in atomisp_assert_recovery_work() and that function holds isp->mutex and always transitions the streaming state to ATOMISP_DEVICE_STREAMING_DISABLED or ATOMISP_DEVICE_STREAMING_ENABLED before releasing the mutex. So atomisp_pipe_check() never sees ATOMISP_DEVICE_STREAMING_STOPPING. Remove the entire switch-case. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_ioctl.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 087ec5120bce..08a3d98794df 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -528,22 +528,6 @@ int atomisp_pipe_check(struct atomisp_video_pipe *pipe, bool settings_change) return -EBUSY; } - switch (pipe->asd->streaming) { - case ATOMISP_DEVICE_STREAMING_DISABLED: - break; - case ATOMISP_DEVICE_STREAMING_ENABLED: - if (settings_change) { - dev_err(pipe->isp->dev, "Set fmt/input IOCTL while streaming\n"); - return -EBUSY; - } - break; - case ATOMISP_DEVICE_STREAMING_STOPPING: - dev_err(pipe->isp->dev, "IOCTL issued while stopping\n"); - return -EBUSY; - default: - return -EINVAL; - } - return 0; } From 0f072c1e2453e6c56b233b15a2f5d50606f02d85 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 11 May 2023 18:33:06 +0100 Subject: [PATCH 157/253] media: atomisp: Turn asd->streaming state tracker into a bool The ATOMISP_DEVICE_STREAMING_STOPPING pipe state comes from when we still had continuous mode. This would be set when streaming from both capture + preview devnodes when 1 of the 2 streams has been stopped and the driver was waiting for the other stream to get stopped too. With continuous mode gone the stopping state is no longer necessary and asd->streaming can be changed to a bool. Note that atomisp_assert_recovery_work() would still temporarily set streaming to stopping, but it does so with the isp->mutex held and changes streaming to either enabled or disabled before releasing the mutex, so none of the consumers which care about the difference ever see the stopping state. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 21 +++++++------------ .../media/atomisp/pci/atomisp_compat_css20.c | 4 ++-- .../staging/media/atomisp/pci/atomisp_fops.c | 2 +- .../media/atomisp/pci/atomisp_internal.h | 4 ---- .../staging/media/atomisp/pci/atomisp_ioctl.c | 8 +++---- .../media/atomisp/pci/atomisp_subdev.h | 2 +- .../staging/media/atomisp/pci/atomisp_v4l2.c | 2 +- 7 files changed, 17 insertions(+), 26 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index ea07ddcdd7f1..26a194251a76 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -475,7 +475,7 @@ irqreturn_t atomisp_isr(int irq, void *dev) if (!atomisp_streaming_count(isp)) goto out_nowake; - if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED) { + if (isp->asd.streaming) { if (irq_infos & IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF) { atomic_inc(&isp->asd.sof_count); atomisp_sof_event(&isp->asd); @@ -950,12 +950,11 @@ static void __atomisp_css_recover(struct atomisp_device *isp) atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false); - if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED || - isp->asd.stream_prepared) { + if (isp->asd.streaming || isp->asd.stream_prepared) { stream_restart = true; spin_lock_irqsave(&isp->lock, flags); - isp->asd.streaming = ATOMISP_DEVICE_STREAMING_STOPPING; + isp->asd.streaming = false; spin_unlock_irqrestore(&isp->lock, flags); /* stream off sensor */ @@ -971,10 +970,6 @@ static void __atomisp_css_recover(struct atomisp_device *isp) css_pipe_id = atomisp_get_css_pipe_id(&isp->asd); atomisp_css_stop(&isp->asd, css_pipe_id, true); - spin_lock_irqsave(&isp->lock, flags); - isp->asd.streaming = ATOMISP_DEVICE_STREAMING_DISABLED; - spin_unlock_irqrestore(&isp->lock, flags); - isp->asd.preview_exp_id = 1; isp->asd.postview_exp_id = 1; /* notify HAL the CSS reset */ @@ -1003,7 +998,7 @@ static void __atomisp_css_recover(struct atomisp_device *isp) "start SP failed, so do not set streaming to be enable!\n"); } else { spin_lock_irqsave(&isp->lock, flags); - isp->asd.streaming = ATOMISP_DEVICE_STREAMING_ENABLED; + isp->asd.streaming = true; spin_unlock_irqrestore(&isp->lock, flags); } @@ -1128,7 +1123,7 @@ irqreturn_t atomisp_isr_thread(int irq, void *isp_ptr) if (atomisp_css_isr_thread(isp)) goto out; - if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED) + if (isp->asd.streaming) atomisp_setup_flash(&isp->asd); out: mutex_unlock(&isp->mutex); @@ -3211,7 +3206,7 @@ void atomisp_handle_parameter_and_buffer(struct atomisp_video_pipe *pipe) * CSS/FW requires set parameter and enqueue buffer happen after ISP * is streamon. */ - if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) + if (!asd->streaming) return; if (list_empty(&pipe->per_frame_params) || @@ -4761,7 +4756,7 @@ static int __checking_exp_id(struct atomisp_sub_device *asd, int exp_id) dev_warn(isp->dev, "%s Raw Buffer Lock is disable.\n", __func__); return -EINVAL; } - if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) { + if (!asd->streaming) { dev_err(isp->dev, "%s streaming %d invalid exp_id %d.\n", __func__, exp_id, asd->streaming); return -EINVAL; @@ -4883,7 +4878,7 @@ int atomisp_enable_dz_capt_pipe(struct atomisp_sub_device *asd, int atomisp_inject_a_fake_event(struct atomisp_sub_device *asd, int *event) { - if (!event || asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) + if (!event || !asd->streaming) return -EINVAL; lockdep_assert_held(&asd->isp->mutex); diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index 092262e1b7ec..cecdf111e14f 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -3081,7 +3081,7 @@ int atomisp_css_get_dis_stat(struct atomisp_sub_device *asd, return -EINVAL; /* isp needs to be streaming to get DIS statistics */ - if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED) + if (!asd->streaming) return -EINVAL; if (atomisp_compare_dvs_grid(asd, &stats->dvs2_stat.grid_info) != 0) @@ -3210,7 +3210,7 @@ static bool atomisp_css_isr_get_stream_id(struct ia_css_pipe *css_pipe, struct atomisp_stream_env *stream_env; int i, j; - if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_DISABLED) + if (!isp->asd.streaming) return false; for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) { diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index ef1a5ad30ace..c7da5bfd93ae 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -411,7 +411,7 @@ static void atomisp_buf_queue(struct vb2_buffer *vb) spin_unlock_irqrestore(&pipe->irq_lock, irqflags); /* TODO: do this better, not best way to queue to css */ - if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED) { + if (asd->streaming) { if (!list_empty(&pipe->buffers_waiting_for_param)) atomisp_handle_parameter_and_buffer(pipe); else diff --git a/drivers/staging/media/atomisp/pci/atomisp_internal.h b/drivers/staging/media/atomisp/pci/atomisp_internal.h index 3d4f0f632f44..feaf4037a389 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_internal.h +++ b/drivers/staging/media/atomisp/pci/atomisp_internal.h @@ -168,10 +168,6 @@ struct atomisp_regs { u32 csi_access_viol; }; -#define ATOMISP_DEVICE_STREAMING_DISABLED 0 -#define ATOMISP_DEVICE_STREAMING_ENABLED 1 -#define ATOMISP_DEVICE_STREAMING_STOPPING 2 - /* * ci device struct */ diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 08a3d98794df..020d4184375f 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -601,7 +601,7 @@ static int atomisp_enum_input(struct file *file, void *fh, unsigned int atomisp_streaming_count(struct atomisp_device *isp) { - return isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED; + return isp->asd.streaming; } /* @@ -1163,7 +1163,7 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) } spin_lock_irqsave(&isp->lock, irqflags); - asd->streaming = ATOMISP_DEVICE_STREAMING_ENABLED; + asd->streaming = true; spin_unlock_irqrestore(&isp->lock, irqflags); atomic_set(&asd->sof_count, -1); atomic_set(&asd->sequence, -1); @@ -1205,7 +1205,7 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) if (ret) { dev_err(isp->dev, "Starting sensor stream failed: %d\n", ret); spin_lock_irqsave(&isp->lock, irqflags); - asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED; + asd->streaming = false; spin_unlock_irqrestore(&isp->lock, irqflags); ret = -EINVAL; goto out_unlock; @@ -1246,7 +1246,7 @@ void atomisp_stop_streaming(struct vb2_queue *vq) dev_warn(isp->dev, "Warning timeout waiting for CSS to return buffers\n"); spin_lock_irqsave(&isp->lock, flags); - asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED; + asd->streaming = false; spin_unlock_irqrestore(&isp->lock, flags); atomisp_clear_css_buffer_counters(asd); diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.h b/drivers/staging/media/atomisp/pci/atomisp_subdev.h index a702890003f9..49177386d57f 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.h +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.h @@ -299,7 +299,7 @@ struct atomisp_sub_device { * Writers of streaming must hold both isp->mutex and isp->lock. * Readers of streaming need to hold only one of the two locks. */ - unsigned int streaming; + bool streaming; bool stream_prepared; /* whether css stream is created */ unsigned int latest_preview_exp_id; /* CSS ZSL/SDV raw buffer id */ diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index f914ab9068c1..c68e9062743d 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -672,7 +672,7 @@ static int atomisp_suspend(struct device *dev) return -EBUSY; spin_lock_irqsave(&isp->lock, flags); - if (isp->asd.streaming != ATOMISP_DEVICE_STREAMING_DISABLED) { + if (isp->asd.streaming) { spin_unlock_irqrestore(&isp->lock, flags); dev_err(isp->dev, "atomisp cannot suspend at this time.\n"); return -EINVAL; From b19f8ef5bd3957e6269f1cb9647054de2e1bf217 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 11 May 2023 16:14:21 +0100 Subject: [PATCH 158/253] media: atomisp: Remove no longer used atomisp_css_flush() Remove the no longer used atomisp_css_flush() function and merge atomisp_assert_recovery_work() and __atomisp_css_recover() into a single function. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 25 +++++-------------- .../staging/media/atomisp/pci/atomisp_cmd.h | 2 -- 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 26a194251a76..1482184a9ea5 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -935,18 +935,20 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error, atomisp_qbuffers_to_css(asd); } -static void __atomisp_css_recover(struct atomisp_device *isp) +void atomisp_assert_recovery_work(struct work_struct *work) { + struct atomisp_device *isp = container_of(work, struct atomisp_device, + assert_recovery_work); struct pci_dev *pdev = to_pci_dev(isp->dev); enum ia_css_pipe_id css_pipe_id; bool stream_restart = false; unsigned long flags; int ret; - lockdep_assert_held(&isp->mutex); + mutex_lock(&isp->mutex); if (!atomisp_streaming_count(isp)) - return; + goto out_unlock; atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false); @@ -1028,26 +1030,11 @@ static void __atomisp_css_recover(struct atomisp_device *isp) dev_warn(isp->dev, "can't start streaming on sensor!\n"); } -} -void atomisp_assert_recovery_work(struct work_struct *work) -{ - struct atomisp_device *isp = container_of(work, struct atomisp_device, - assert_recovery_work); - - mutex_lock(&isp->mutex); - __atomisp_css_recover(isp); +out_unlock: mutex_unlock(&isp->mutex); } -void atomisp_css_flush(struct atomisp_device *isp) -{ - /* Start recover */ - __atomisp_css_recover(isp); - - dev_dbg(isp->dev, "atomisp css flush done\n"); -} - void atomisp_setup_flash(struct atomisp_sub_device *asd) { struct atomisp_device *isp = asd->isp; diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.h b/drivers/staging/media/atomisp/pci/atomisp_cmd.h index 1cb973ddf2dc..783fb1e6f4f9 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.h +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.h @@ -282,8 +282,6 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error, enum ia_css_pipe_id css_pipe_id, bool q_buffers, enum atomisp_input_stream_id stream_id); -void atomisp_css_flush(struct atomisp_device *isp); - /* Events. Only one event has to be exported for now. */ void atomisp_eof_event(struct atomisp_sub_device *asd, uint8_t exp_id); From 3fb3cd02d25b391a507cbc480361d4d27cbdfc21 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 11 May 2023 19:35:43 +0100 Subject: [PATCH 159/253] media: atomisp: Remove atomisp_streaming_count() atomisp_streaming_count() is just an alias for isp->asd.streaming now, replace it with directly checking that and remove the helper. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 6 +++--- drivers/staging/media/atomisp/pci/atomisp_drvfs.c | 2 +- drivers/staging/media/atomisp/pci/atomisp_ioctl.c | 5 ----- drivers/staging/media/atomisp/pci/atomisp_ioctl.h | 2 -- 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 1482184a9ea5..b2bc9bc050ba 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -472,7 +472,7 @@ irqreturn_t atomisp_isr(int irq, void *dev) clear_irq_reg(isp); - if (!atomisp_streaming_count(isp)) + if (!isp->asd.streaming) goto out_nowake; if (isp->asd.streaming) { @@ -947,7 +947,7 @@ void atomisp_assert_recovery_work(struct work_struct *work) mutex_lock(&isp->mutex); - if (!atomisp_streaming_count(isp)) + if (!isp->asd.streaming) goto out_unlock; atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false); @@ -1074,7 +1074,7 @@ irqreturn_t atomisp_isr_thread(int irq, void *isp_ptr) spin_lock_irqsave(&isp->lock, flags); - if (!atomisp_streaming_count(isp)) { + if (!isp->asd.streaming) { spin_unlock_irqrestore(&isp->lock, flags); return IRQ_HANDLED; } diff --git a/drivers/staging/media/atomisp/pci/atomisp_drvfs.c b/drivers/staging/media/atomisp/pci/atomisp_drvfs.c index 3ddc935ec01d..1df534bf54d3 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_drvfs.c +++ b/drivers/staging/media/atomisp/pci/atomisp_drvfs.c @@ -69,7 +69,7 @@ static inline int iunit_dump_dbgopt(struct atomisp_device *isp, } if (opt & OPTION_BIN_RUN) { - if (atomisp_streaming_count(isp)) { + if (isp->asd.streaming) { atomisp_css_dump_sp_raw_copy_linecount(true); atomisp_css_debug_dump_isp_binary(); } else { diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 020d4184375f..6a062b86d18a 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -599,11 +599,6 @@ static int atomisp_enum_input(struct file *file, void *fh, return 0; } -unsigned int atomisp_streaming_count(struct atomisp_device *isp) -{ - return isp->asd.streaming; -} - /* * get input are used to get current primary/secondary camera */ diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.h b/drivers/staging/media/atomisp/pci/atomisp_ioctl.h index db6da77df06b..997fa61589ab 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.h +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.h @@ -47,8 +47,6 @@ enum ia_css_pipe_id atomisp_get_css_pipe_id(struct atomisp_sub_device extern const struct v4l2_ioctl_ops atomisp_ioctl_ops; -unsigned int atomisp_streaming_count(struct atomisp_device *isp); - /* compat_ioctl for 32bit userland app and 64bit kernel */ long atomisp_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg); From bcc90bb31c819a7428ecd0604ce50553371fa278 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 11 May 2023 19:53:16 +0100 Subject: [PATCH 160/253] media: atomisp: Simplify atomisp_isr() and recovery_work() Both atomisp_isr() and recovery_work() now have a combination of: 1. "if (!isp->asd.streaming) goto out;" code at the top 2. "if (sp->asd.streaming) {}" blocks in the body which are jumped over by the goto out. This means that the "if (sp->asd.streaming) {}" blocks are always executed if they are not jumped over by the goto. Remove the unnecessary "if (sp->asd.streaming)" checks and re-indent the code. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 128 +++++++----------- 1 file changed, 50 insertions(+), 78 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index b2bc9bc050ba..c0c2247f02a4 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -475,36 +475,28 @@ irqreturn_t atomisp_isr(int irq, void *dev) if (!isp->asd.streaming) goto out_nowake; - if (isp->asd.streaming) { - if (irq_infos & IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF) { - atomic_inc(&isp->asd.sof_count); - atomisp_sof_event(&isp->asd); - - /* If sequence_temp and sequence are the same - * there where no frames lost so we can increase - * sequence_temp. - * If not then processing of frame is still in progress - * and driver needs to keep old sequence_temp value. - * NOTE: There is assumption here that ISP will not - * start processing next frame from sensor before old - * one is completely done. */ - if (atomic_read(&isp->asd.sequence) == - atomic_read(&isp->asd.sequence_temp)) - atomic_set(&isp->asd.sequence_temp, - atomic_read(&isp->asd.sof_count)); - } - if (irq_infos & IA_CSS_IRQ_INFO_EVENTS_READY) - atomic_set(&isp->asd.sequence, - atomic_read(&isp->asd.sequence_temp)); - } - if (irq_infos & IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF) { - dev_dbg_ratelimited(isp->dev, - "irq:0x%x (SOF)\n", - irq_infos); + atomic_inc(&isp->asd.sof_count); + atomisp_sof_event(&isp->asd); + + /* + * If sequence_temp and sequence are the same there where no frames + * lost so we can increase sequence_temp. + * If not then processing of frame is still in progress and driver + * needs to keep old sequence_temp value. + * NOTE: There is assumption here that ISP will not start processing + * next frame from sensor before old one is completely done. + */ + if (atomic_read(&isp->asd.sequence) == atomic_read(&isp->asd.sequence_temp)) + atomic_set(&isp->asd.sequence_temp, atomic_read(&isp->asd.sof_count)); + + dev_dbg_ratelimited(isp->dev, "irq:0x%x (SOF)\n", irq_infos); irq_infos &= ~IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF; } + if (irq_infos & IA_CSS_IRQ_INFO_EVENTS_READY) + atomic_set(&isp->asd.sequence, atomic_read(&isp->asd.sequence_temp)); + if ((irq_infos & IA_CSS_IRQ_INFO_INPUT_SYSTEM_ERROR) || (irq_infos & IA_CSS_IRQ_INFO_IF_ERROR)) { /* handle mipi receiver error */ @@ -941,7 +933,6 @@ void atomisp_assert_recovery_work(struct work_struct *work) assert_recovery_work); struct pci_dev *pdev = to_pci_dev(isp->dev); enum ia_css_pipe_id css_pipe_id; - bool stream_restart = false; unsigned long flags; int ret; @@ -952,33 +943,25 @@ void atomisp_assert_recovery_work(struct work_struct *work) atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false); - if (isp->asd.streaming || isp->asd.stream_prepared) { - stream_restart = true; + spin_lock_irqsave(&isp->lock, flags); + isp->asd.streaming = false; + spin_unlock_irqrestore(&isp->lock, flags); - spin_lock_irqsave(&isp->lock, flags); - isp->asd.streaming = false; - spin_unlock_irqrestore(&isp->lock, flags); + /* stream off sensor */ + ret = v4l2_subdev_call(isp->inputs[isp->asd.input_curr].camera, video, s_stream, 0); + if (ret) + dev_warn(isp->dev, "Stopping sensor stream failed: %d\n", ret); - /* stream off sensor */ - ret = v4l2_subdev_call( - isp->inputs[isp->asd.input_curr]. - camera, video, s_stream, 0); - if (ret) - dev_warn(isp->dev, - "can't stop streaming on sensor!\n"); + atomisp_clear_css_buffer_counters(&isp->asd); - atomisp_clear_css_buffer_counters(&isp->asd); + css_pipe_id = atomisp_get_css_pipe_id(&isp->asd); + atomisp_css_stop(&isp->asd, css_pipe_id, true); - css_pipe_id = atomisp_get_css_pipe_id(&isp->asd); - atomisp_css_stop(&isp->asd, css_pipe_id, true); - - isp->asd.preview_exp_id = 1; - isp->asd.postview_exp_id = 1; - /* notify HAL the CSS reset */ - dev_dbg(isp->dev, - "send reset event to %s\n", isp->asd.subdev.devnode->name); - atomisp_reset_event(&isp->asd); - } + isp->asd.preview_exp_id = 1; + isp->asd.postview_exp_id = 1; + /* notify HAL the CSS reset */ + dev_dbg(isp->dev, "send reset event to %s\n", isp->asd.subdev.devnode->name); + atomisp_reset_event(&isp->asd); /* clear irq */ disable_isp_irq(hrt_isp_css_irq_sp); @@ -991,45 +974,34 @@ void atomisp_assert_recovery_work(struct work_struct *work) /* reset ISP and restore its state */ atomisp_reset(isp); - if (stream_restart) { - atomisp_css_input_set_mode(&isp->asd, IA_CSS_INPUT_MODE_BUFFERED_SENSOR); + atomisp_css_input_set_mode(&isp->asd, IA_CSS_INPUT_MODE_BUFFERED_SENSOR); - css_pipe_id = atomisp_get_css_pipe_id(&isp->asd); - if (atomisp_css_start(&isp->asd, css_pipe_id, true)) { - dev_warn(isp->dev, - "start SP failed, so do not set streaming to be enable!\n"); - } else { - spin_lock_irqsave(&isp->lock, flags); - isp->asd.streaming = true; - spin_unlock_irqrestore(&isp->lock, flags); - } - - atomisp_csi2_configure(&isp->asd); + css_pipe_id = atomisp_get_css_pipe_id(&isp->asd); + if (atomisp_css_start(&isp->asd, css_pipe_id, true)) { + dev_warn(isp->dev, "start SP failed, so do not set streaming to be enable!\n"); + } else { + spin_lock_irqsave(&isp->lock, flags); + isp->asd.streaming = true; + spin_unlock_irqrestore(&isp->lock, flags); } + atomisp_csi2_configure(&isp->asd); + atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, atomisp_css_valid_sof(isp)); if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_AUTO, true) < 0) dev_dbg(isp->dev, "DFS auto failed while recovering!\n"); - if (stream_restart) { - /* - * dequeueing buffers is not needed. CSS will recycle - * buffers that it has. - */ - atomisp_flush_video_pipe(&isp->asd.video_out, VB2_BUF_STATE_ERROR, false); + /* Dequeueing buffers is not needed, CSS will recycle buffers that it has */ + atomisp_flush_video_pipe(&isp->asd.video_out, VB2_BUF_STATE_ERROR, false); - /* Requeue unprocessed per-frame parameters. */ - atomisp_recover_params_queue(&isp->asd.video_out); + /* Requeue unprocessed per-frame parameters. */ + atomisp_recover_params_queue(&isp->asd.video_out); - ret = v4l2_subdev_call( - isp->inputs[isp->asd.input_curr].camera, video, - s_stream, 1); - if (ret) - dev_warn(isp->dev, - "can't start streaming on sensor!\n"); - } + ret = v4l2_subdev_call(isp->inputs[isp->asd.input_curr].camera, video, s_stream, 1); + if (ret) + dev_err(isp->dev, "Starting sensor stream failed: %d\n", ret); out_unlock: mutex_unlock(&isp->mutex); From 2cb61011bfed4344185fcfe64adf2c9f2353eaa3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 12 May 2023 16:17:54 +0100 Subject: [PATCH 161/253] media: atomisp: Rename atomisp_destroy_pipes_stream_force() to atomisp_destroy_pipes_stream() There now no longer is a non force version of atomisp_destroy_pipes_stream_force() so having the _force postfix no longer makes sense rename it to atomisp_destroy_pipes_stream(). Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_compat.h | 2 +- .../staging/media/atomisp/pci/atomisp_compat_css20.c | 10 +++++----- drivers/staging/media/atomisp/pci/atomisp_fops.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat.h b/drivers/staging/media/atomisp/pci/atomisp_compat.h index 850b354cc160..89ed1f7209f0 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat.h +++ b/drivers/staging/media/atomisp/pci/atomisp_compat.h @@ -215,7 +215,7 @@ int atomisp_css_input_configure_port(struct atomisp_sub_device *asd, unsigned int metadata_height); int atomisp_create_pipes_stream(struct atomisp_sub_device *asd); -void atomisp_destroy_pipes_stream_force(struct atomisp_sub_device *asd); +void atomisp_destroy_pipes_stream(struct atomisp_sub_device *asd); void atomisp_css_stop(struct atomisp_sub_device *asd, enum ia_css_pipe_id pipe_id, bool in_reset); diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index cecdf111e14f..a04c16502cac 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -548,7 +548,7 @@ static int __destroy_pipes(struct atomisp_sub_device *asd) return 0; } -void atomisp_destroy_pipes_stream_force(struct atomisp_sub_device *asd) +void atomisp_destroy_pipes_stream(struct atomisp_sub_device *asd) { if (__destroy_streams(asd)) dev_warn(asd->isp->dev, "destroy stream failed.\n"); @@ -746,7 +746,7 @@ int atomisp_create_pipes_stream(struct atomisp_sub_device *asd) int atomisp_css_update_stream(struct atomisp_sub_device *asd) { - atomisp_destroy_pipes_stream_force(asd); + atomisp_destroy_pipes_stream(asd); return atomisp_create_pipes_stream(asd); } @@ -1034,7 +1034,7 @@ start_err: * destroying all pipes. */ if (sp_is_started) { - atomisp_destroy_pipes_stream_force(asd); + atomisp_destroy_pipes_stream(asd); ia_css_stop_sp(); atomisp_create_pipes_stream(asd); } @@ -1824,7 +1824,7 @@ void atomisp_css_stop(struct atomisp_sub_device *asd, * CSS 2.0 API limitation: ia_css_stop_sp() can only be called after * destroying all pipes. */ - atomisp_destroy_pipes_stream_force(asd); + atomisp_destroy_pipes_stream(asd); atomisp_init_raw_buffer_bitmap(asd); @@ -2314,7 +2314,7 @@ static int __get_frame_info(struct atomisp_sub_device *asd, return 0; get_info_err: - atomisp_destroy_pipes_stream_force(asd); + atomisp_destroy_pipes_stream(asd); return -EINVAL; } diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index c7da5bfd93ae..223c5be072cc 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -614,7 +614,7 @@ static int atomisp_release(struct file *file) isp->inputs[asd->input_curr].asd = NULL; } - atomisp_destroy_pipes_stream_force(asd); + atomisp_destroy_pipes_stream(asd); ret = v4l2_subdev_call(isp->flash, core, s_power, 0); if (ret < 0 && ret != -ENODEV && ret != -ENOIOCTLCMD) From 4d141d3fae3e3d8b85817bde3b6b6a0e7b08eb3b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 12 May 2023 16:24:32 +0100 Subject: [PATCH 162/253] media: atomisp: Allow system suspend to continue with open /dev/video# nodes Just having a /dev/video# node open is not a reason to block system suspend. At least when userspace is not streaming. In that case the worst case scenario is that streams have been created, but we can just destroy those before powering off the ISP and recreate the streams on resume. Fixing suspend when streaming is left as a FIXME item for later. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/atomisp_subdev.h | 1 + .../staging/media/atomisp/pci/atomisp_v4l2.c | 23 ++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.h b/drivers/staging/media/atomisp/pci/atomisp_subdev.h index 49177386d57f..dc6970b48633 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.h +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.h @@ -301,6 +301,7 @@ struct atomisp_sub_device { */ bool streaming; bool stream_prepared; /* whether css stream is created */ + bool recreate_streams_on_resume; unsigned int latest_preview_exp_id; /* CSS ZSL/SDV raw buffer id */ diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index c68e9062743d..a76b60f8b411 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -664,13 +664,7 @@ static int atomisp_suspend(struct device *dev) dev_get_drvdata(dev); unsigned long flags; - /* - * FIXME: Suspend is not supported by sensors. Abort if any video - * node was opened. - */ - if (atomisp_dev_users(isp)) - return -EBUSY; - + /* FIXME: Suspend is not supported by sensors. Abort if streaming. */ spin_lock_irqsave(&isp->lock, flags); if (isp->asd.streaming) { spin_unlock_irqrestore(&isp->lock, flags); @@ -681,12 +675,25 @@ static int atomisp_suspend(struct device *dev) pm_runtime_resume(dev); + isp->asd.recreate_streams_on_resume = isp->asd.stream_prepared; + atomisp_destroy_pipes_stream(&isp->asd); + return atomisp_power_off(dev); } static int atomisp_resume(struct device *dev) { - return atomisp_power_on(dev); + struct atomisp_device *isp = dev_get_drvdata(dev); + int ret; + + ret = atomisp_power_on(dev); + if (ret) + return ret; + + if (isp->asd.recreate_streams_on_resume) + ret = atomisp_create_pipes_stream(&isp->asd); + + return ret; } int atomisp_csi_lane_config(struct atomisp_device *isp) From 5ab97df8642e93559edfcbf2d9f7b8478b683c96 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 12 May 2023 16:27:46 +0100 Subject: [PATCH 163/253] media: atomisp: Remove atomisp_[sub]dev_users() The atomisp_[sub]dev_users() functions are not used anymore, remove them. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_fops.c | 10 ---------- drivers/staging/media/atomisp/pci/atomisp_fops.h | 3 --- 2 files changed, 13 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index 223c5be072cc..179c23ea7700 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -489,16 +489,6 @@ static void atomisp_subdev_init_struct(struct atomisp_sub_device *asd) /* * file operation functions */ -static unsigned int atomisp_subdev_users(struct atomisp_sub_device *asd) -{ - return asd->video_out.users; -} - -unsigned int atomisp_dev_users(struct atomisp_device *isp) -{ - return atomisp_subdev_users(&isp->asd); -} - static int atomisp_open(struct file *file) { struct video_device *vdev = video_devdata(file); diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.h b/drivers/staging/media/atomisp/pci/atomisp_fops.h index 883c1851c1c9..ad1cb1ac8aa4 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.h +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.h @@ -22,9 +22,6 @@ #define __ATOMISP_FOPS_H__ #include "atomisp_subdev.h" -unsigned int atomisp_dev_users(struct atomisp_device *isp); -unsigned int atomisp_sub_dev_users(struct atomisp_sub_device *asd); - /* * Memory help functions for image frame and private parameters */ From e5fab487eac8bb3ec784c2523f128ceaeb8feba4 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 12 May 2023 17:26:11 +0100 Subject: [PATCH 164/253] media: atomisp: Remove unused css_pipe_id argument from atomisp_css_[start|stop]() The css_pipe_id argument pass to atomisp_css_[start|stop]() is not used, drop it. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 7 ++----- drivers/staging/media/atomisp/pci/atomisp_compat.h | 6 ++---- drivers/staging/media/atomisp/pci/atomisp_compat_css20.c | 6 ++---- drivers/staging/media/atomisp/pci/atomisp_ioctl.c | 9 ++------- 4 files changed, 8 insertions(+), 20 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index c0c2247f02a4..d9139e67c94f 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -932,7 +932,6 @@ void atomisp_assert_recovery_work(struct work_struct *work) struct atomisp_device *isp = container_of(work, struct atomisp_device, assert_recovery_work); struct pci_dev *pdev = to_pci_dev(isp->dev); - enum ia_css_pipe_id css_pipe_id; unsigned long flags; int ret; @@ -954,8 +953,7 @@ void atomisp_assert_recovery_work(struct work_struct *work) atomisp_clear_css_buffer_counters(&isp->asd); - css_pipe_id = atomisp_get_css_pipe_id(&isp->asd); - atomisp_css_stop(&isp->asd, css_pipe_id, true); + atomisp_css_stop(&isp->asd, true); isp->asd.preview_exp_id = 1; isp->asd.postview_exp_id = 1; @@ -976,8 +974,7 @@ void atomisp_assert_recovery_work(struct work_struct *work) atomisp_css_input_set_mode(&isp->asd, IA_CSS_INPUT_MODE_BUFFERED_SENSOR); - css_pipe_id = atomisp_get_css_pipe_id(&isp->asd); - if (atomisp_css_start(&isp->asd, css_pipe_id, true)) { + if (atomisp_css_start(&isp->asd, true)) { dev_warn(isp->dev, "start SP failed, so do not set streaming to be enable!\n"); } else { spin_lock_irqsave(&isp->lock, flags); diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat.h b/drivers/staging/media/atomisp/pci/atomisp_compat.h index 89ed1f7209f0..7e99c9853532 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat.h +++ b/drivers/staging/media/atomisp/pci/atomisp_compat.h @@ -78,8 +78,7 @@ int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd, void ia_css_mmu_invalidate_cache(void); -int atomisp_css_start(struct atomisp_sub_device *asd, - enum ia_css_pipe_id pipe_id, bool in_reset); +int atomisp_css_start(struct atomisp_sub_device *asd, bool in_reset); void atomisp_css_update_isp_params(struct atomisp_sub_device *asd); void atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device *asd, @@ -217,8 +216,7 @@ int atomisp_css_input_configure_port(struct atomisp_sub_device *asd, int atomisp_create_pipes_stream(struct atomisp_sub_device *asd); void atomisp_destroy_pipes_stream(struct atomisp_sub_device *asd); -void atomisp_css_stop(struct atomisp_sub_device *asd, - enum ia_css_pipe_id pipe_id, bool in_reset); +void atomisp_css_stop(struct atomisp_sub_device *asd, bool in_reset); void atomisp_css_continuous_set_num_raw_frames( struct atomisp_sub_device *asd, diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index a04c16502cac..4e004464ac4c 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -985,8 +985,7 @@ int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd, return 0; } -int atomisp_css_start(struct atomisp_sub_device *asd, - enum ia_css_pipe_id pipe_id, bool in_reset) +int atomisp_css_start(struct atomisp_sub_device *asd, bool in_reset) { struct atomisp_device *isp = asd->isp; bool sp_is_started = false; @@ -1814,8 +1813,7 @@ int atomisp_css_input_configure_port( return 0; } -void atomisp_css_stop(struct atomisp_sub_device *asd, - enum ia_css_pipe_id pipe_id, bool in_reset) +void atomisp_css_stop(struct atomisp_sub_device *asd, bool in_reset) { unsigned long irqflags; unsigned int i; diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 6a062b86d18a..6bae107682c1 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -1120,7 +1120,6 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) struct atomisp_sub_device *asd = pipe->asd; struct atomisp_device *isp = asd->isp; struct pci_dev *pdev = to_pci_dev(isp->dev); - enum ia_css_pipe_id css_pipe_id; unsigned long irqflags; int ret; @@ -1135,8 +1134,6 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) /* Input system HW workaround */ atomisp_dma_burst_len_cfg(asd); - css_pipe_id = atomisp_get_css_pipe_id(asd); - /* Invalidate caches. FIXME: should flush only necessary buffers */ wbinvd(); @@ -1151,7 +1148,7 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) } asd->params.dvs_6axis = NULL; - ret = atomisp_css_start(asd, css_pipe_id, false); + ret = atomisp_css_start(asd, false); if (ret) { atomisp_flush_video_pipe(pipe, VB2_BUF_STATE_QUEUED, true); goto out_unlock; @@ -1217,7 +1214,6 @@ void atomisp_stop_streaming(struct vb2_queue *vq) struct atomisp_sub_device *asd = pipe->asd; struct atomisp_device *isp = asd->isp; struct pci_dev *pdev = to_pci_dev(isp->dev); - enum ia_css_pipe_id css_pipe_id; unsigned long flags; int ret; @@ -1247,8 +1243,7 @@ void atomisp_stop_streaming(struct vb2_queue *vq) atomisp_clear_css_buffer_counters(asd); atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false); - css_pipe_id = atomisp_get_css_pipe_id(asd); - atomisp_css_stop(asd, css_pipe_id, false); + atomisp_css_stop(asd, false); atomisp_flush_video_pipe(pipe, VB2_BUF_STATE_ERROR, true); From 1180d072e05cb40fdd65725b9235e23c008411f9 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 12 May 2023 17:27:10 +0100 Subject: [PATCH 165/253] media: atomisp: Remove unused atomisp_get_css_pipe_id() function Remove no longer user atomisp_get_css_pipe_id() function. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_ioctl.c | 28 ------------------- .../staging/media/atomisp/pci/atomisp_ioctl.h | 3 -- 2 files changed, 31 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 6bae107682c1..1deeb7c28379 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -1068,34 +1068,6 @@ static int atomisp_dqbuf_wrapper(struct file *file, void *fh, struct v4l2_buffer return 0; } -enum ia_css_pipe_id atomisp_get_css_pipe_id(struct atomisp_sub_device *asd) -{ - /* - * Disable vf_pp and run CSS in video mode. This allows using ISP - * scaling but it has one frame delay due to CSS internal buffering. - */ - if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) - return IA_CSS_PIPE_ID_VIDEO; - - /* - * Disable vf_pp and run CSS in still capture mode. In this mode - * CSS does not cause extra latency with buffering, but scaling - * is not available. - */ - if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) - return IA_CSS_PIPE_ID_CAPTURE; - - switch (asd->run_mode->val) { - case ATOMISP_RUN_MODE_PREVIEW: - return IA_CSS_PIPE_ID_PREVIEW; - case ATOMISP_RUN_MODE_VIDEO: - return IA_CSS_PIPE_ID_VIDEO; - case ATOMISP_RUN_MODE_STILL_CAPTURE: - default: - return IA_CSS_PIPE_ID_CAPTURE; - } -} - /* Input system HW workaround */ /* Input system address translation corrupts burst during */ /* invalidate. SW workaround for this is to set burst length */ diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.h b/drivers/staging/media/atomisp/pci/atomisp_ioctl.h index 997fa61589ab..56d3df86c706 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.h +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.h @@ -42,9 +42,6 @@ int atomisp_alloc_css_stat_bufs(struct atomisp_sub_device *asd, int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count); void atomisp_stop_streaming(struct vb2_queue *vq); -enum ia_css_pipe_id atomisp_get_css_pipe_id(struct atomisp_sub_device - *asd); - extern const struct v4l2_ioctl_ops atomisp_ioctl_ops; /* compat_ioctl for 32bit userland app and 64bit kernel */ From ae39964d2c01cb1805fcaa6f0ad0b7b4e8568106 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 12 May 2023 18:31:21 +0100 Subject: [PATCH 166/253] media: atomisp: Remove in_reset argument from atomisp_css_start() The in_reset argument to atomisp_css_start() is only ever true in atomisp_assert_recovery_work(), drop the argument and move the special reset handlig to atomisp_assert_recovery_work(). Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 8 +++++++- drivers/staging/media/atomisp/pci/atomisp_compat.h | 2 +- .../staging/media/atomisp/pci/atomisp_compat_css20.c | 11 +---------- drivers/staging/media/atomisp/pci/atomisp_ioctl.c | 2 +- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index d9139e67c94f..9c44ffba2828 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -974,7 +974,13 @@ void atomisp_assert_recovery_work(struct work_struct *work) atomisp_css_input_set_mode(&isp->asd, IA_CSS_INPUT_MODE_BUFFERED_SENSOR); - if (atomisp_css_start(&isp->asd, true)) { + /* Recreate streams destroyed by atomisp_css_stop() */ + atomisp_create_pipes_stream(&isp->asd); + + /* Invalidate caches. FIXME: should flush only necessary buffers */ + wbinvd(); + + if (atomisp_css_start(&isp->asd)) { dev_warn(isp->dev, "start SP failed, so do not set streaming to be enable!\n"); } else { spin_lock_irqsave(&isp->lock, flags); diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat.h b/drivers/staging/media/atomisp/pci/atomisp_compat.h index 7e99c9853532..e9e4bfb0f5f9 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat.h +++ b/drivers/staging/media/atomisp/pci/atomisp_compat.h @@ -78,7 +78,7 @@ int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd, void ia_css_mmu_invalidate_cache(void); -int atomisp_css_start(struct atomisp_sub_device *asd, bool in_reset); +int atomisp_css_start(struct atomisp_sub_device *asd); void atomisp_css_update_isp_params(struct atomisp_sub_device *asd); void atomisp_css_update_isp_params_on_pipe(struct atomisp_sub_device *asd, diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index 4e004464ac4c..b13d1cb4668d 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -985,21 +985,12 @@ int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd, return 0; } -int atomisp_css_start(struct atomisp_sub_device *asd, bool in_reset) +int atomisp_css_start(struct atomisp_sub_device *asd) { struct atomisp_device *isp = asd->isp; bool sp_is_started = false; int ret = 0, i = 0; - if (in_reset) { - ret = atomisp_css_update_stream(asd); - if (ret) - return ret; - - /* Invalidate caches. FIXME: should flush only necessary buffers */ - wbinvd(); - } - if (!sh_css_hrt_system_is_idle()) dev_err(isp->dev, "CSS HW not idle before starting SP\n"); diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 1deeb7c28379..900e4c79cd78 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -1120,7 +1120,7 @@ int atomisp_start_streaming(struct vb2_queue *vq, unsigned int count) } asd->params.dvs_6axis = NULL; - ret = atomisp_css_start(asd, false); + ret = atomisp_css_start(asd); if (ret) { atomisp_flush_video_pipe(pipe, VB2_BUF_STATE_QUEUED, true); goto out_unlock; From 250781c5a2e6a0335b85f2342415fe6f1180c6e0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 9 May 2023 21:10:34 +0100 Subject: [PATCH 167/253] media: atomisp: Set asd.subdev.devnode once from isp_subdev_init_entities() Now that we have only one /dev/video# node we can set asd.subdev.devnode once from isp_subdev_init_entities(), replacing the hack to set it the last opened/closed /dev/video# node from atomisp_open() / atomisp_release(). Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_fops.c | 4 ---- drivers/staging/media/atomisp/pci/atomisp_subdev.c | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index 179c23ea7700..fb42c2710795 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -505,8 +505,6 @@ static int atomisp_open(struct file *file) mutex_lock(&isp->mutex); - asd->subdev.devnode = vdev; - if (!isp->input_cnt) { dev_err(isp->dev, "no camera attached\n"); ret = -EINVAL; @@ -567,8 +565,6 @@ static int atomisp_release(struct file *file) dev_dbg(isp->dev, "release device %s\n", vdev->name); - asd->subdev.devnode = vdev; - /* Note file must not be used after this! */ vb2_fop_release(file); diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c index 32fc4d25c663..8b99805bcc77 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c @@ -880,6 +880,7 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd) sprintf(sd->name, "ATOMISP_SUBDEV"); v4l2_set_subdevdata(sd, asd); sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; + sd->devnode = &asd->video_out.vdev; pads[ATOMISP_SUBDEV_PAD_SINK].flags = MEDIA_PAD_FL_SINK; pads[ATOMISP_SUBDEV_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; From 76d2d7d6afae2fe5bd7f8e441e9944c6ac8f10dc Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 18 May 2023 13:43:45 +0100 Subject: [PATCH 168/253] media: atomisp: gc0310: Drop XXGC0310 ACPI hardware-id The XXGC0310 ACPI hardware-id does not appear to be used in the DSDTs of any hardware out there, so drop it. Link: https://lore.kernel.org/r/20230518153214.194976-5-hdegoede@redhat.com Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/i2c/atomisp-gc0310.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c index 273155308fe3..c1590ad8f66f 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c @@ -471,7 +471,6 @@ static int gc0310_resume(struct device *dev) static DEFINE_RUNTIME_DEV_PM_OPS(gc0310_pm_ops, gc0310_suspend, gc0310_resume, NULL); static const struct acpi_device_id gc0310_acpi_match[] = { - {"XXGC0310"}, {"INT0310"}, {}, }; From 2746a966f9f05fdb0727f4e1e8f2d51ec79e071d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 18 May 2023 15:15:07 +0100 Subject: [PATCH 169/253] media: atomisp: gc0310: Fix double free in gc0310_remove() gc0310_remove() must not call kfree(dev) since the gc0310_device struct is devm managed so explicitly freeing it causes a double free. While at it add a missing mutex_destroy() call for the input_lock. Link: https://lore.kernel.org/r/20230518153214.194976-6-hdegoede@redhat.com Fixes: 340b4dd6c183 ("media: atomisp: gc0310: Use devm_kzalloc() for data struct") Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/i2c/atomisp-gc0310.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c index c1590ad8f66f..af791cfc9e9a 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c @@ -377,8 +377,8 @@ static void gc0310_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); media_entity_cleanup(&dev->sd.entity); v4l2_ctrl_handler_free(&dev->ctrls.handler); + mutex_destroy(&dev->input_lock); pm_runtime_disable(&client->dev); - kfree(dev); } static int gc0310_probe(struct i2c_client *client) From 63558464ad4dc25dc012d67d5f1e9fad8abcc28a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 18 May 2023 13:48:34 +0100 Subject: [PATCH 170/253] media: atomisp: gc0310: Cleanup includes Remove a bunch of unused includes and sort the remainging includes alphabetically. Link: https://lore.kernel.org/r/20230518153214.194976-7-hdegoede@redhat.com Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-gc0310.c | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c index af791cfc9e9a..b873621b3475 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c @@ -16,26 +16,19 @@ * */ -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include +#include #include -#include #include -#include +#include +#include #include -#include -#include -#include "../include/linux/atomisp_gmin_platform.h" +#include +#include +#include + +#include "../include/linux/atomisp_gmin_platform.h" #include "gc0310.h" /* From f5e381ffb6fdd021f2a1c0172dce486f647746c6 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 18 May 2023 15:19:14 +0100 Subject: [PATCH 171/253] media: atomisp: gc0310: Remove gc0310_s_config() function gc0310_s_config() used to call camera_sensor_platform_data.csi_cfg() back when the gc0310 driver was still using the atomisp_gmin_platform code for power-management. Now it is just a weirdly named wrapper around gc0310_detect(), drop gc0310_s_config() and make probe() call gc0310_detect() directly. Link: https://lore.kernel.org/r/20230518153214.194976-8-hdegoede@redhat.com Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-gc0310.c | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c index b873621b3475..9051b10faab3 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c @@ -172,7 +172,10 @@ static int gc0310_detect(struct i2c_client *client) if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) return -ENODEV; - ret = i2c_smbus_read_word_swapped(client, GC0310_SC_CMMN_CHIP_ID_H); + ret = pm_runtime_get_sync(&client->dev); + if (ret >= 0) + ret = i2c_smbus_read_word_swapped(client, GC0310_SC_CMMN_CHIP_ID_H); + pm_runtime_put(&client->dev); if (ret < 0) { dev_err(&client->dev, "read sensor_id failed: %d\n", ret); return -ENODEV; @@ -261,19 +264,6 @@ error_unlock: return ret; } -static int gc0310_s_config(struct v4l2_subdev *sd) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - int ret; - - ret = pm_runtime_get_sync(&client->dev); - if (ret >= 0) - ret = gc0310_detect(client); - - pm_runtime_put(&client->dev); - return ret; -} - static int gc0310_g_frame_interval(struct v4l2_subdev *sd, struct v4l2_subdev_frame_interval *interval) { @@ -406,7 +396,7 @@ static int gc0310_probe(struct i2c_client *client) pm_runtime_set_autosuspend_delay(&client->dev, 1000); pm_runtime_use_autosuspend(&client->dev); - ret = gc0310_s_config(&dev->sd); + ret = gc0310_detect(client); if (ret) { gc0310_remove(client); return ret; From 1bb2a551e65bf35928432d1837e6d9287361704e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 18 May 2023 15:33:34 +0100 Subject: [PATCH 172/253] media: atomisp: gc0310: Remove gc0310.h Remove the gc0310.h header file, moving most of its content into atomisp-gc0310.c and dropping some unused parts. This brings the gc0310 sensor driver inline with other sensor regular / non atomisp sensor drivers which usually only are one single .c file. Link: https://lore.kernel.org/r/20230518153214.194976-9-hdegoede@redhat.com Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-gc0310.c | 242 +++++++++++++- drivers/staging/media/atomisp/i2c/gc0310.h | 309 ------------------ 2 files changed, 241 insertions(+), 310 deletions(-) delete mode 100644 drivers/staging/media/atomisp/i2c/gc0310.h diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c index 9051b10faab3..77a2bd1fe749 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c @@ -26,10 +26,250 @@ #include #include +#include #include #include "../include/linux/atomisp_gmin_platform.h" -#include "gc0310.h" + +#define GC0310_NATIVE_WIDTH 656 +#define GC0310_NATIVE_HEIGHT 496 + +#define GC0310_FPS 30 +#define GC0310_SKIP_FRAMES 3 + +#define GC0310_FOCAL_LENGTH_NUM 278 /* 2.78mm */ + +#define GC0310_ID 0xa310 + +#define GC0310_RESET_RELATED 0xFE +#define GC0310_REGISTER_PAGE_0 0x0 +#define GC0310_REGISTER_PAGE_3 0x3 + +/* + * GC0310 System control registers + */ +#define GC0310_SW_STREAM 0x10 + +#define GC0310_SC_CMMN_CHIP_ID_H 0xf0 +#define GC0310_SC_CMMN_CHIP_ID_L 0xf1 + +#define GC0310_AEC_PK_EXPO_H 0x03 +#define GC0310_AEC_PK_EXPO_L 0x04 +#define GC0310_AGC_ADJ 0x48 +#define GC0310_DGC_ADJ 0x71 +#define GC0310_GROUP_ACCESS 0x3208 + +#define GC0310_H_CROP_START_H 0x09 +#define GC0310_H_CROP_START_L 0x0A +#define GC0310_V_CROP_START_H 0x0B +#define GC0310_V_CROP_START_L 0x0C +#define GC0310_H_OUTSIZE_H 0x0F +#define GC0310_H_OUTSIZE_L 0x10 +#define GC0310_V_OUTSIZE_H 0x0D +#define GC0310_V_OUTSIZE_L 0x0E +#define GC0310_H_BLANKING_H 0x05 +#define GC0310_H_BLANKING_L 0x06 +#define GC0310_V_BLANKING_H 0x07 +#define GC0310_V_BLANKING_L 0x08 +#define GC0310_SH_DELAY 0x11 + +#define GC0310_START_STREAMING 0x94 /* 8-bit enable */ +#define GC0310_STOP_STREAMING 0x0 /* 8-bit disable */ + +#define to_gc0310_sensor(x) container_of(x, struct gc0310_device, sd) + +struct gc0310_device { + struct v4l2_subdev sd; + struct media_pad pad; + /* Protect against concurrent changes to controls */ + struct mutex input_lock; + bool is_streaming; + + struct gpio_desc *reset; + struct gpio_desc *powerdown; + + struct gc0310_mode { + struct v4l2_mbus_framefmt fmt; + } mode; + + struct gc0310_ctrls { + struct v4l2_ctrl_handler handler; + struct v4l2_ctrl *exposure; + struct v4l2_ctrl *gain; + } ctrls; +}; + +struct gc0310_reg { + u8 reg; + u8 val; +}; + +static const struct gc0310_reg gc0310_reset_register[] = { + /* System registers */ + { 0xfe, 0xf0 }, + { 0xfe, 0xf0 }, + { 0xfe, 0x00 }, + + { 0xfc, 0x0e }, /* 4e */ + { 0xfc, 0x0e }, /* 16//4e // [0]apwd [6]regf_clk_gate */ + { 0xf2, 0x80 }, /* sync output */ + { 0xf3, 0x00 }, /* 1f//01 data output */ + { 0xf7, 0x33 }, /* f9 */ + { 0xf8, 0x05 }, /* 00 */ + { 0xf9, 0x0e }, /* 0x8e //0f */ + { 0xfa, 0x11 }, + + /* MIPI */ + { 0xfe, 0x03 }, + { 0x01, 0x03 }, /* mipi 1lane */ + { 0x02, 0x22 }, /* 0x33 */ + { 0x03, 0x94 }, + { 0x04, 0x01 }, /* fifo_prog */ + { 0x05, 0x00 }, /* fifo_prog */ + { 0x06, 0x80 }, /* b0 //YUV ISP data */ + { 0x11, 0x2a }, /* 1e //LDI set YUV422 */ + { 0x12, 0x90 }, /* 00 //04 //00 //04//00 //LWC[7:0] */ + { 0x13, 0x02 }, /* 05 //05 //LWC[15:8] */ + { 0x15, 0x12 }, /* 0x10 //DPHYY_MODE read_ready */ + { 0x17, 0x01 }, + { 0x40, 0x08 }, + { 0x41, 0x00 }, + { 0x42, 0x00 }, + { 0x43, 0x00 }, + { 0x21, 0x02 }, /* 0x01 */ + { 0x22, 0x02 }, /* 0x01 */ + { 0x23, 0x01 }, /* 0x05 //Nor:0x05 DOU:0x06 */ + { 0x29, 0x00 }, + { 0x2A, 0x25 }, /* 0x05 //data zero 0x7a de */ + { 0x2B, 0x02 }, + + { 0xfe, 0x00 }, + + /* CISCTL */ + { 0x00, 0x2f }, /* 2f//0f//02//01 */ + { 0x01, 0x0f }, /* 06 */ + { 0x02, 0x04 }, + { 0x4f, 0x00 }, /* AEC 0FF */ + { 0x03, 0x01 }, /* 0x03 //04 */ + { 0x04, 0xc0 }, /* 0xe8 //58 */ + { 0x05, 0x00 }, + { 0x06, 0xb2 }, /* 0x0a //HB */ + { 0x07, 0x00 }, + { 0x08, 0x0c }, /* 0x89 //VB */ + { 0x09, 0x00 }, /* row start */ + { 0x0a, 0x00 }, + { 0x0b, 0x00 }, /* col start */ + { 0x0c, 0x00 }, + { 0x0d, 0x01 }, /* height */ + { 0x0e, 0xf2 }, /* 0xf7 //height */ + { 0x0f, 0x02 }, /* width */ + { 0x10, 0x94 }, /* 0xa0 //height */ + { 0x17, 0x14 }, + { 0x18, 0x1a }, /* 0a//[4]double reset */ + { 0x19, 0x14 }, /* AD pipeline */ + { 0x1b, 0x48 }, + { 0x1e, 0x6b }, /* 3b//col bias */ + { 0x1f, 0x28 }, /* 20//00//08//txlow */ + { 0x20, 0x89 }, /* 88//0c//[3:2]DA15 */ + { 0x21, 0x49 }, /* 48//[3] txhigh */ + { 0x22, 0xb0 }, + { 0x23, 0x04 }, /* [1:0]vcm_r */ + { 0x24, 0x16 }, /* 15 */ + { 0x34, 0x20 }, /* [6:4] rsg high//range */ + + /* BLK */ + { 0x26, 0x23 }, /* [1]dark_current_en [0]offset_en */ + { 0x28, 0xff }, /* BLK_limie_value */ + { 0x29, 0x00 }, /* global offset */ + { 0x33, 0x18 }, /* offset_ratio */ + { 0x37, 0x20 }, /* dark_current_ratio */ + { 0x2a, 0x00 }, + { 0x2b, 0x00 }, + { 0x2c, 0x00 }, + { 0x2d, 0x00 }, + { 0x2e, 0x00 }, + { 0x2f, 0x00 }, + { 0x30, 0x00 }, + { 0x31, 0x00 }, + { 0x47, 0x80 }, /* a7 */ + { 0x4e, 0x66 }, /* select_row */ + { 0xa8, 0x02 }, /* win_width_dark, same with crop_win_width */ + { 0xa9, 0x80 }, + + /* ISP */ + { 0x40, 0x06 }, /* 0xff //ff //48 */ + { 0x41, 0x00 }, /* 0x21 //00//[0]curve_en */ + { 0x42, 0x04 }, /* 0xcf //0a//[1]awn_en */ + { 0x44, 0x18 }, /* 0x18 //02 */ + { 0x46, 0x02 }, /* 0x03 //sync */ + { 0x49, 0x03 }, + { 0x4c, 0x20 }, /* 00[5]pretect exp */ + { 0x50, 0x01 }, /* crop enable */ + { 0x51, 0x00 }, + { 0x52, 0x00 }, + { 0x53, 0x00 }, + { 0x54, 0x01 }, + { 0x55, 0x01 }, /* crop window height */ + { 0x56, 0xf0 }, + { 0x57, 0x02 }, /* crop window width */ + { 0x58, 0x90 }, + + /* Gain */ + { 0x70, 0x70 }, /* 70 //80//global gain */ + { 0x71, 0x20 }, /* pregain gain */ + { 0x72, 0x40 }, /* post gain */ + { 0x5a, 0x84 }, /* 84//analog gain 0 */ + { 0x5b, 0xc9 }, /* c9 */ + { 0x5c, 0xed }, /* ed//not use pga gain highest level */ + { 0x77, 0x40 }, /* R gain 0x74 //awb gain */ + { 0x78, 0x40 }, /* G gain */ + { 0x79, 0x40 }, /* B gain 0x5f */ + + { 0x48, 0x00 }, + { 0xfe, 0x01 }, + { 0x0a, 0x45 }, /* [7]col gain mode */ + + { 0x3e, 0x40 }, + { 0x3f, 0x5c }, + { 0x40, 0x7b }, + { 0x41, 0xbd }, + { 0x42, 0xf6 }, + { 0x43, 0x63 }, + { 0x03, 0x60 }, + { 0x44, 0x03 }, + + /* Dark / Sun mode related */ + { 0xfe, 0x01 }, + { 0x45, 0xa4 }, /* 0xf7 */ + { 0x46, 0xf0 }, /* 0xff //f0//sun value th */ + { 0x48, 0x03 }, /* sun mode */ + { 0x4f, 0x60 }, /* sun_clamp */ + { 0xfe, 0x00 }, +}; + +static const struct gc0310_reg gc0310_VGA_30fps[] = { + { 0xfe, 0x00 }, + { 0x0d, 0x01 }, /* height */ + { 0x0e, 0xf2 }, /* 0xf7 //height */ + { 0x0f, 0x02 }, /* width */ + { 0x10, 0x94 }, /* 0xa0 //height */ + + { 0x50, 0x01 }, /* crop enable */ + { 0x51, 0x00 }, + { 0x52, 0x00 }, + { 0x53, 0x00 }, + { 0x54, 0x01 }, + { 0x55, 0x01 }, /* crop window height */ + { 0x56, 0xf0 }, + { 0x57, 0x02 }, /* crop window width */ + { 0x58, 0x90 }, + + { 0xfe, 0x03 }, + { 0x12, 0x90 }, /* 00 //04 //00 //04//00 //LWC[7:0] */ + { 0x13, 0x02 }, /* 05 //05 //LWC[15:8] */ + + { 0xfe, 0x00 }, +}; /* * gc0310_write_reg_array - Initializes a list of GC0310 registers diff --git a/drivers/staging/media/atomisp/i2c/gc0310.h b/drivers/staging/media/atomisp/i2c/gc0310.h deleted file mode 100644 index d40406289598..000000000000 --- a/drivers/staging/media/atomisp/i2c/gc0310.h +++ /dev/null @@ -1,309 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Support for GalaxyCore GC0310 VGA camera sensor. - * - * Copyright (c) 2013 Intel Corporation. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * 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 __GC0310_H__ -#define __GC0310_H__ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../include/linux/atomisp_platform.h" - -#define GC0310_NATIVE_WIDTH 656 -#define GC0310_NATIVE_HEIGHT 496 - -#define GC0310_FPS 30 -#define GC0310_SKIP_FRAMES 3 - -#define GC0310_FOCAL_LENGTH_NUM 278 /* 2.78mm */ - -#define GC0310_ID 0xa310 - -#define GC0310_RESET_RELATED 0xFE -#define GC0310_REGISTER_PAGE_0 0x0 -#define GC0310_REGISTER_PAGE_3 0x3 - -#define GC0310_FINE_INTG_TIME_MIN 0 -#define GC0310_FINE_INTG_TIME_MAX_MARGIN 0 -#define GC0310_COARSE_INTG_TIME_MIN 1 -#define GC0310_COARSE_INTG_TIME_MAX_MARGIN 6 - -/* - * GC0310 System control registers - */ -#define GC0310_SW_STREAM 0x10 - -#define GC0310_SC_CMMN_CHIP_ID_H 0xf0 -#define GC0310_SC_CMMN_CHIP_ID_L 0xf1 - -#define GC0310_AEC_PK_EXPO_H 0x03 -#define GC0310_AEC_PK_EXPO_L 0x04 -#define GC0310_AGC_ADJ 0x48 -#define GC0310_DGC_ADJ 0x71 -#if 0 -#define GC0310_GROUP_ACCESS 0x3208 -#endif - -#define GC0310_H_CROP_START_H 0x09 -#define GC0310_H_CROP_START_L 0x0A -#define GC0310_V_CROP_START_H 0x0B -#define GC0310_V_CROP_START_L 0x0C -#define GC0310_H_OUTSIZE_H 0x0F -#define GC0310_H_OUTSIZE_L 0x10 -#define GC0310_V_OUTSIZE_H 0x0D -#define GC0310_V_OUTSIZE_L 0x0E -#define GC0310_H_BLANKING_H 0x05 -#define GC0310_H_BLANKING_L 0x06 -#define GC0310_V_BLANKING_H 0x07 -#define GC0310_V_BLANKING_L 0x08 -#define GC0310_SH_DELAY 0x11 - -#define GC0310_START_STREAMING 0x94 /* 8-bit enable */ -#define GC0310_STOP_STREAMING 0x0 /* 8-bit disable */ - -/* - * gc0310 device structure. - */ -struct gc0310_device { - struct v4l2_subdev sd; - struct media_pad pad; - struct mutex input_lock; - bool is_streaming; - - struct gpio_desc *reset; - struct gpio_desc *powerdown; - - struct gc0310_mode { - struct v4l2_mbus_framefmt fmt; - } mode; - - struct gc0310_ctrls { - struct v4l2_ctrl_handler handler; - struct v4l2_ctrl *exposure; - struct v4l2_ctrl *gain; - } ctrls; -}; - -/** - * struct gc0310_reg - MI sensor register format - * @reg: 16-bit offset to register - * @val: 8/16/32-bit register value - * - * Define a structure for sensor register initialization values - */ -struct gc0310_reg { - u8 reg; - u8 val; /* @set value for read/mod/write, @mask */ -}; - -#define to_gc0310_sensor(x) container_of(x, struct gc0310_device, sd) - -/* - * Register settings for various resolution - */ -static const struct gc0310_reg gc0310_reset_register[] = { -///////////////////////////////////////////////// -///////////////// system reg ///////////////// -///////////////////////////////////////////////// - { 0xfe, 0xf0 }, - { 0xfe, 0xf0 }, - { 0xfe, 0x00 }, - - { 0xfc, 0x0e }, /* 4e */ - { 0xfc, 0x0e }, /* 16//4e // [0]apwd [6]regf_clk_gate */ - { 0xf2, 0x80 }, /* sync output */ - { 0xf3, 0x00 }, /* 1f//01 data output */ - { 0xf7, 0x33 }, /* f9 */ - { 0xf8, 0x05 }, /* 00 */ - { 0xf9, 0x0e }, /* 0x8e //0f */ - { 0xfa, 0x11 }, - -///////////////////////////////////////////////// -/////////////////// MIPI //////////////////// -///////////////////////////////////////////////// - { 0xfe, 0x03 }, - { 0x01, 0x03 }, /* mipi 1lane */ - { 0x02, 0x22 }, /* 0x33 */ - { 0x03, 0x94 }, - { 0x04, 0x01 }, /* fifo_prog */ - { 0x05, 0x00 }, /* fifo_prog */ - { 0x06, 0x80 }, /* b0 //YUV ISP data */ - { 0x11, 0x2a }, /* 1e //LDI set YUV422 */ - { 0x12, 0x90 }, /* 00 //04 //00 //04//00 //LWC[7:0] */ - { 0x13, 0x02 }, /* 05 //05 //LWC[15:8] */ - { 0x15, 0x12 }, /* 0x10 //DPHYY_MODE read_ready */ - { 0x17, 0x01 }, - { 0x40, 0x08 }, - { 0x41, 0x00 }, - { 0x42, 0x00 }, - { 0x43, 0x00 }, - { 0x21, 0x02 }, /* 0x01 */ - { 0x22, 0x02 }, /* 0x01 */ - { 0x23, 0x01 }, /* 0x05 //Nor:0x05 DOU:0x06 */ - { 0x29, 0x00 }, - { 0x2A, 0x25 }, /* 0x05 //data zero 0x7a de */ - { 0x2B, 0x02 }, - - { 0xfe, 0x00 }, - -///////////////////////////////////////////////// -///////////////// CISCTL reg ///////////////// -///////////////////////////////////////////////// - { 0x00, 0x2f }, /* 2f//0f//02//01 */ - { 0x01, 0x0f }, /* 06 */ - { 0x02, 0x04 }, - { 0x4f, 0x00 }, /* AEC 0FF */ - { 0x03, 0x01 }, /* 0x03 //04 */ - { 0x04, 0xc0 }, /* 0xe8 //58 */ - { 0x05, 0x00 }, - { 0x06, 0xb2 }, /* 0x0a //HB */ - { 0x07, 0x00 }, - { 0x08, 0x0c }, /* 0x89 //VB */ - { 0x09, 0x00 }, /* row start */ - { 0x0a, 0x00 }, - { 0x0b, 0x00 }, /* col start */ - { 0x0c, 0x00 }, - { 0x0d, 0x01 }, /* height */ - { 0x0e, 0xf2 }, /* 0xf7 //height */ - { 0x0f, 0x02 }, /* width */ - { 0x10, 0x94 }, /* 0xa0 //height */ - { 0x17, 0x14 }, - { 0x18, 0x1a }, /* 0a//[4]double reset */ - { 0x19, 0x14 }, /* AD pipeline */ - { 0x1b, 0x48 }, - { 0x1e, 0x6b }, /* 3b//col bias */ - { 0x1f, 0x28 }, /* 20//00//08//txlow */ - { 0x20, 0x89 }, /* 88//0c//[3:2]DA15 */ - { 0x21, 0x49 }, /* 48//[3] txhigh */ - { 0x22, 0xb0 }, - { 0x23, 0x04 }, /* [1:0]vcm_r */ - { 0x24, 0x16 }, /* 15 */ - { 0x34, 0x20 }, /* [6:4] rsg high//range */ - -///////////////////////////////////////////////// -//////////////////// BLK //////////////////// -///////////////////////////////////////////////// - { 0x26, 0x23 }, /* [1]dark_current_en [0]offset_en */ - { 0x28, 0xff }, /* BLK_limie_value */ - { 0x29, 0x00 }, /* global offset */ - { 0x33, 0x18 }, /* offset_ratio */ - { 0x37, 0x20 }, /* dark_current_ratio */ - { 0x2a, 0x00 }, - { 0x2b, 0x00 }, - { 0x2c, 0x00 }, - { 0x2d, 0x00 }, - { 0x2e, 0x00 }, - { 0x2f, 0x00 }, - { 0x30, 0x00 }, - { 0x31, 0x00 }, - { 0x47, 0x80 }, /* a7 */ - { 0x4e, 0x66 }, /* select_row */ - { 0xa8, 0x02 }, /* win_width_dark, same with crop_win_width */ - { 0xa9, 0x80 }, - -///////////////////////////////////////////////// -////////////////// ISP reg /////////////////// -///////////////////////////////////////////////// - { 0x40, 0x06 }, /* 0xff //ff //48 */ - { 0x41, 0x00 }, /* 0x21 //00//[0]curve_en */ - { 0x42, 0x04 }, /* 0xcf //0a//[1]awn_en */ - { 0x44, 0x18 }, /* 0x18 //02 */ - { 0x46, 0x02 }, /* 0x03 //sync */ - { 0x49, 0x03 }, - { 0x4c, 0x20 }, /* 00[5]pretect exp */ - { 0x50, 0x01 }, /* crop enable */ - { 0x51, 0x00 }, - { 0x52, 0x00 }, - { 0x53, 0x00 }, - { 0x54, 0x01 }, - { 0x55, 0x01 }, /* crop window height */ - { 0x56, 0xf0 }, - { 0x57, 0x02 }, /* crop window width */ - { 0x58, 0x90 }, - -///////////////////////////////////////////////// -/////////////////// GAIN //////////////////// -///////////////////////////////////////////////// - { 0x70, 0x70 }, /* 70 //80//global gain */ - { 0x71, 0x20 }, /* pregain gain */ - { 0x72, 0x40 }, /* post gain */ - { 0x5a, 0x84 }, /* 84//analog gain 0 */ - { 0x5b, 0xc9 }, /* c9 */ - { 0x5c, 0xed }, /* ed//not use pga gain highest level */ - { 0x77, 0x40 }, /* R gain 0x74 //awb gain */ - { 0x78, 0x40 }, /* G gain */ - { 0x79, 0x40 }, /* B gain 0x5f */ - - { 0x48, 0x00 }, - { 0xfe, 0x01 }, - { 0x0a, 0x45 }, /* [7]col gain mode */ - - { 0x3e, 0x40 }, - { 0x3f, 0x5c }, - { 0x40, 0x7b }, - { 0x41, 0xbd }, - { 0x42, 0xf6 }, - { 0x43, 0x63 }, - { 0x03, 0x60 }, - { 0x44, 0x03 }, - -///////////////////////////////////////////////// -///////////////// dark sun ////////////////// -///////////////////////////////////////////////// - { 0xfe, 0x01 }, - { 0x45, 0xa4 }, /* 0xf7 */ - { 0x46, 0xf0 }, /* 0xff //f0//sun value th */ - { 0x48, 0x03 }, /* sun mode */ - { 0x4f, 0x60 }, /* sun_clamp */ - { 0xfe, 0x00 }, -}; - -static struct gc0310_reg const gc0310_VGA_30fps[] = { - { 0xfe, 0x00 }, - { 0x0d, 0x01 }, /* height */ - { 0x0e, 0xf2 }, /* 0xf7 //height */ - { 0x0f, 0x02 }, /* width */ - { 0x10, 0x94 }, /* 0xa0 //height */ - - { 0x50, 0x01 }, /* crop enable */ - { 0x51, 0x00 }, - { 0x52, 0x00 }, - { 0x53, 0x00 }, - { 0x54, 0x01 }, - { 0x55, 0x01 }, /* crop window height */ - { 0x56, 0xf0 }, - { 0x57, 0x02 }, /* crop window width */ - { 0x58, 0x90 }, - - { 0xfe, 0x03 }, - { 0x12, 0x90 }, /* 00 //04 //00 //04//00 //LWC[7:0] */ - { 0x13, 0x02 }, /* 05 //05 //LWC[15:8] */ - - { 0xfe, 0x00 }, -}; - -#endif From 1ad997e83110d57af7dca8ccbb490e6c634ba46e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 14 May 2023 19:51:28 +0100 Subject: [PATCH 173/253] media: atomisp: Drop MRFLD_PORT_NUM define The info in the MRFLD_PORT_NUM define is duplicate with the ATOMISP_CAMERA_NR_PORTS and N_MIPI_PORT_ID enum values. Drop the MRFLD_PORT_NUM define and switch to N_MIPI_PORT_ID since the [sensor_]lanes arrays are in enum mipi_port_id order. Link: https://lore.kernel.org/r/20230518153733.195306-2-hdegoede@redhat.com Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp-regs.h | 1 - drivers/staging/media/atomisp/pci/atomisp_v4l2.c | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp-regs.h b/drivers/staging/media/atomisp/pci/atomisp-regs.h index 022997f47121..a7b0196686be 100644 --- a/drivers/staging/media/atomisp/pci/atomisp-regs.h +++ b/drivers/staging/media/atomisp/pci/atomisp-regs.h @@ -112,7 +112,6 @@ /* MRFLD CSI lane configuration related */ #define MRFLD_PORT_CONFIG_NUM 8 -#define MRFLD_PORT_NUM 3 #define MRFLD_PORT1_ENABLE_SHIFT 0 #define MRFLD_PORT2_ENABLE_SHIFT 1 #define MRFLD_PORT3_ENABLE_SHIFT 2 diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index a76b60f8b411..b36dc98f897b 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -701,7 +701,7 @@ int atomisp_csi_lane_config(struct atomisp_device *isp) struct pci_dev *pdev = to_pci_dev(isp->dev); static const struct { u8 code; - u8 lanes[MRFLD_PORT_NUM]; + u8 lanes[N_MIPI_PORT_ID]; } portconfigs[] = { /* Tangier/Merrifield available lane configurations */ { 0x00, { 4, 1, 0 } }, /* 00000 */ @@ -725,7 +725,7 @@ int atomisp_csi_lane_config(struct atomisp_device *isp) }; unsigned int i, j; - u8 sensor_lanes[MRFLD_PORT_NUM] = { 0 }; + u8 sensor_lanes[N_MIPI_PORT_ID] = { }; u32 csi_control; int nportconfigs; u32 port_config_mask; @@ -782,12 +782,12 @@ int atomisp_csi_lane_config(struct atomisp_device *isp) } for (i = 0; i < nportconfigs; i++) { - for (j = 0; j < MRFLD_PORT_NUM; j++) + for (j = 0; j < N_MIPI_PORT_ID; j++) if (sensor_lanes[j] && sensor_lanes[j] != portconfigs[i].lanes[j]) break; - if (j == MRFLD_PORT_NUM) + if (j == N_MIPI_PORT_ID) break; /* Found matching setting */ } From 9af6100f4ff55bc3295803c58f535363e3693b38 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 14 May 2023 19:59:13 +0100 Subject: [PATCH 174/253] media: atomisp: Remove unused fields from struct atomisp_input_subdev Remove unused fields from struct atomisp_input_subdev: 1. frame_size is never used at all 2. sensor_index is always 0, just directly pass 0 in the single user. Link: https://lore.kernel.org/r/20230518153733.195306-3-hdegoede@redhat.com Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_internal.h | 3 --- drivers/staging/media/atomisp/pci/atomisp_ioctl.c | 2 +- drivers/staging/media/atomisp/pci/atomisp_v4l2.c | 7 ------- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_internal.h b/drivers/staging/media/atomisp/pci/atomisp_internal.h index feaf4037a389..ee0dd5eb4711 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_internal.h +++ b/drivers/staging/media/atomisp/pci/atomisp_internal.h @@ -126,15 +126,12 @@ struct atomisp_input_subdev { enum atomisp_camera_port port; struct v4l2_subdev *camera; struct v4l2_subdev *motor; - struct v4l2_frmsizeenum frame_size; /* * To show this resource is used by * which stream, in ISP multiple stream mode */ struct atomisp_sub_device *asd; - - int sensor_index; }; enum atomisp_dfs_mode { diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 900e4c79cd78..2cde1af77a2d 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -673,7 +673,7 @@ static int atomisp_s_input(struct file *file, void *fh, unsigned int input) /* select operating sensor */ ret = v4l2_subdev_call(isp->inputs[input].camera, video, s_routing, - 0, isp->inputs[input].sensor_index, 0); + 0, 0, 0); if (ret && (ret != -ENOIOCTLCMD)) { dev_err(isp->dev, "Failed to select sensor\n"); return ret; diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index b36dc98f897b..e78c738b3008 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -866,13 +866,6 @@ static int atomisp_subdev_probe(struct atomisp_device *isp) isp->inputs[isp->input_cnt].type = subdevs->type; isp->inputs[isp->input_cnt].port = subdevs->port; isp->inputs[isp->input_cnt].camera = subdevs->subdev; - isp->inputs[isp->input_cnt].sensor_index = 0; - /* - * initialize the subdev frame size, then next we can - * judge whether frame_size store effective value via - * pixel_format. - */ - isp->inputs[isp->input_cnt].frame_size.pixel_format = 0; isp->input_cnt++; break; case CAMERA_MOTOR: From 45b4ab382a9ef7ff8dc62f6625601879ba8af4c0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 15 May 2023 19:08:05 +0100 Subject: [PATCH 175/253] media: atomisp: Remove atomisp_video_init() parametrization Now that we only have a single /dev/video# node it is no longer necessary for atomisp_video_init() to be parametrized. Remove its parameters and while at it also change the name from the single /dev/video# node from "ATOMISP ISP PREVIEW output" to "ATOMISP video output". Link: https://lore.kernel.org/r/20230518153733.195306-4-hdegoede@redhat.com Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_fops.c | 2 +- .../media/atomisp/pci/atomisp_subdev.c | 2 +- .../media/atomisp/pci/atomisp_subdev.h | 2 -- .../staging/media/atomisp/pci/atomisp_v4l2.c | 24 +++++-------------- .../staging/media/atomisp/pci/atomisp_v4l2.h | 3 +-- 5 files changed, 9 insertions(+), 24 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index fb42c2710795..36e441dce7d5 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -537,7 +537,7 @@ static int atomisp_open(struct file *file) atomisp_subdev_init_struct(asd); /* Ensure that a mode is set */ - v4l2_ctrl_s_ctrl(asd->run_mode, pipe->default_run_mode); + v4l2_ctrl_s_ctrl(asd->run_mode, ATOMISP_RUN_MODE_PREVIEW); pipe->users++; mutex_unlock(&isp->mutex); diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c index 8b99805bcc77..c2ae77cd77a7 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c @@ -898,7 +898,7 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd) if (ret) return ret; - ret = atomisp_video_init(&asd->video_out, "PREVIEW", ATOMISP_RUN_MODE_PREVIEW); + ret = atomisp_video_init(&asd->video_out); if (ret < 0) return ret; diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.h b/drivers/staging/media/atomisp/pci/atomisp_subdev.h index dc6970b48633..cd82554d5f65 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.h +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.h @@ -67,8 +67,6 @@ struct atomisp_video_pipe { /* Filled through atomisp_get_css_frame_info() on queue setup */ struct ia_css_frame_info frame_info; - /* Store here the initial run mode */ - unsigned int default_run_mode; /* Set from streamoff to disallow queuing further buffers in CSS */ bool stopping; diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index e78c738b3008..b2b5a61e06ba 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -333,34 +333,22 @@ const struct atomisp_dfs_config dfs_config_cht_soc = { .dfs_table_size = ARRAY_SIZE(dfs_rules_cht_soc), }; -int atomisp_video_init(struct atomisp_video_pipe *video, const char *name, - unsigned int run_mode) +int atomisp_video_init(struct atomisp_video_pipe *video) { int ret; - const char *direction; - - switch (video->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - direction = "output"; - video->pad.flags = MEDIA_PAD_FL_SINK; - video->vdev.fops = &atomisp_fops; - video->vdev.ioctl_ops = &atomisp_ioctl_ops; - video->vdev.lock = &video->isp->mutex; - break; - default: - return -EINVAL; - } + video->pad.flags = MEDIA_PAD_FL_SINK; ret = media_entity_pads_init(&video->vdev.entity, 1, &video->pad); if (ret < 0) return ret; /* Initialize the video device. */ - snprintf(video->vdev.name, sizeof(video->vdev.name), - "ATOMISP ISP %s %s", name, direction); + strscpy(video->vdev.name, "ATOMISP video output", sizeof(video->vdev.name)); + video->vdev.fops = &atomisp_fops; + video->vdev.ioctl_ops = &atomisp_ioctl_ops; + video->vdev.lock = &video->isp->mutex; video->vdev.release = video_device_release_empty; video_set_drvdata(&video->vdev, video->isp); - video->default_run_mode = run_mode; return 0; } diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.h b/drivers/staging/media/atomisp/pci/atomisp_v4l2.h index ccf1c0ac17b2..c8ee3ad83320 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.h +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.h @@ -26,8 +26,7 @@ struct v4l2_device; struct atomisp_device; struct firmware; -int atomisp_video_init(struct atomisp_video_pipe *video, const char *name, - unsigned int run_mode); +int atomisp_video_init(struct atomisp_video_pipe *video); void atomisp_video_unregister(struct atomisp_video_pipe *video); const struct firmware *atomisp_load_firmware(struct atomisp_device *isp); int atomisp_csi_lane_config(struct atomisp_device *isp); From 64be20708a4b51661ae6d2dd4cc0d7bec4116d12 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 16 May 2023 21:36:14 +0100 Subject: [PATCH 176/253] media: atomisp: Rename __get_mipi_port() to atomisp_port_to_mipi_port() Rename __get_mipi_port() to atomisp_port_to_mipi_port(), this is not a private (not static) function so its name should be properly prefixed. While at is also cleanup the weird handling of ATOMISP_CAMERA_PORT_TERTIARY this seems to be a left over from when the driver also supported CSI receivers with only 2 ports, but those are not supported by the current code base, so this can be cleaned up now. Link: https://lore.kernel.org/r/20230518153733.195306-5-hdegoede@redhat.com Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 10 ++++------ drivers/staging/media/atomisp/pci/atomisp_cmd.h | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 9c44ffba2828..f4a0341d1f8d 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -3893,8 +3893,8 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f) return 0; } -enum mipi_port_id __get_mipi_port(struct atomisp_device *isp, - enum atomisp_camera_port port) +enum mipi_port_id atomisp_port_to_mipi_port(struct atomisp_device *isp, + enum atomisp_camera_port port) { switch (port) { case ATOMISP_CAMERA_PORT_PRIMARY: @@ -3902,9 +3902,7 @@ enum mipi_port_id __get_mipi_port(struct atomisp_device *isp, case ATOMISP_CAMERA_PORT_SECONDARY: return MIPI_PORT1_ID; case ATOMISP_CAMERA_PORT_TERTIARY: - if (MIPI_PORT1_ID + 1 != N_MIPI_PORT_ID) - return MIPI_PORT1_ID + 1; - fallthrough; + return MIPI_PORT2_ID; default: dev_err(isp->dev, "unsupported port: %d\n", port); return MIPI_PORT0_ID; @@ -3980,7 +3978,7 @@ static inline int atomisp_set_sensor_mipi_to_isp( return -EINVAL; input_format = fc->atomisp_in_fmt; atomisp_css_input_configure_port(asd, - __get_mipi_port(asd->isp, mipi_info->port), + atomisp_port_to_mipi_port(asd->isp, mipi_info->port), mipi_info->num_lanes, 0xffff4, mipi_freq, input_format, diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.h b/drivers/staging/media/atomisp/pci/atomisp_cmd.h index 783fb1e6f4f9..5270c370e463 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.h +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.h @@ -285,8 +285,8 @@ void atomisp_buf_done(struct atomisp_sub_device *asd, int error, /* Events. Only one event has to be exported for now. */ void atomisp_eof_event(struct atomisp_sub_device *asd, uint8_t exp_id); -enum mipi_port_id __get_mipi_port(struct atomisp_device *isp, - enum atomisp_camera_port port); +enum mipi_port_id atomisp_port_to_mipi_port(struct atomisp_device *isp, + enum atomisp_camera_port port); void atomisp_apply_css_parameters( struct atomisp_sub_device *asd, From 5b9ca47a258871739d60476afafd77519bcc59ee Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 14 May 2023 20:37:00 +0100 Subject: [PATCH 177/253] media: atomisp: Store number of sensor lanes per port in struct atomisp_device Store number of sensor lanes per port in struct atomisp_device. This is a preparation patch for adding v4l2-async sensor probing support. With async probing the inputs will get registered later, but we can already fill the sensor_lanes array when parsing the fwnodes. Link: https://lore.kernel.org/r/20230518153733.195306-6-hdegoede@redhat.com Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../atomisp/include/linux/atomisp_platform.h | 1 + .../media/atomisp/pci/atomisp_gmin_platform.c | 2 + .../media/atomisp/pci/atomisp_internal.h | 5 ++ .../staging/media/atomisp/pci/atomisp_v4l2.c | 56 ++++--------------- 4 files changed, 20 insertions(+), 44 deletions(-) diff --git a/drivers/staging/media/atomisp/include/linux/atomisp_platform.h b/drivers/staging/media/atomisp/include/linux/atomisp_platform.h index e8e965f73fc8..487ef5846c24 100644 --- a/drivers/staging/media/atomisp/include/linux/atomisp_platform.h +++ b/drivers/staging/media/atomisp/include/linux/atomisp_platform.h @@ -125,6 +125,7 @@ struct intel_v4l2_subdev_id { struct intel_v4l2_subdev_table { enum intel_v4l2_subdev_type type; enum atomisp_camera_port port; + unsigned int lanes; struct v4l2_subdev *subdev; }; diff --git a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c index c718a74ea70a..6512e3c17af0 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c +++ b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c @@ -189,6 +189,7 @@ int atomisp_register_i2c_module(struct v4l2_subdev *subdev, pdata.subdevs[i].type = type; pdata.subdevs[i].port = gs->csi_port; + pdata.subdevs[i].lanes = gs->csi_lanes; pdata.subdevs[i].subdev = subdev; return 0; } @@ -1150,6 +1151,7 @@ int atomisp_register_sensor_no_gmin(struct v4l2_subdev *subdev, u32 lanes, pdata.subdevs[i].type = RAW_CAMERA; pdata.subdevs[i].port = port; + pdata.subdevs[i].lanes = lanes; pdata.subdevs[i].subdev = subdev; return 0; } diff --git a/drivers/staging/media/atomisp/pci/atomisp_internal.h b/drivers/staging/media/atomisp/pci/atomisp_internal.h index ee0dd5eb4711..b8d643c9df8f 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_internal.h +++ b/drivers/staging/media/atomisp/pci/atomisp_internal.h @@ -189,6 +189,11 @@ struct atomisp_device { * structures and css API calls. */ struct mutex mutex; + /* + * Number of lanes used by each sensor per port. + * Note this is indexed by mipi_port_id not atomisp_camera_port. + */ + int sensor_lanes[N_MIPI_PORT_ID]; unsigned int input_cnt; struct atomisp_input_subdev inputs[ATOM_ISP_MAX_INPUTS]; struct v4l2_subdev *flash; diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index b2b5a61e06ba..4a30fff129cc 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -713,7 +713,6 @@ int atomisp_csi_lane_config(struct atomisp_device *isp) }; unsigned int i, j; - u8 sensor_lanes[N_MIPI_PORT_ID] = { }; u32 csi_control; int nportconfigs; u32 port_config_mask; @@ -741,38 +740,10 @@ int atomisp_csi_lane_config(struct atomisp_device *isp) nportconfigs = ARRAY_SIZE(portconfigs); } - for (i = 0; i < isp->input_cnt; i++) { - struct camera_mipi_info *mipi_info; - - if (isp->inputs[i].type != RAW_CAMERA) - continue; - - mipi_info = atomisp_to_sensor_mipi_info(isp->inputs[i].camera); - if (!mipi_info) - continue; - - switch (mipi_info->port) { - case ATOMISP_CAMERA_PORT_PRIMARY: - sensor_lanes[0] = mipi_info->num_lanes; - break; - case ATOMISP_CAMERA_PORT_SECONDARY: - sensor_lanes[1] = mipi_info->num_lanes; - break; - case ATOMISP_CAMERA_PORT_TERTIARY: - sensor_lanes[2] = mipi_info->num_lanes; - break; - default: - dev_err(isp->dev, - "%s: invalid port: %d for the %dth sensor\n", - __func__, mipi_info->port, i); - return -EINVAL; - } - } - for (i = 0; i < nportconfigs; i++) { for (j = 0; j < N_MIPI_PORT_ID; j++) - if (sensor_lanes[j] && - sensor_lanes[j] != portconfigs[i].lanes[j]) + if (isp->sensor_lanes[j] && + isp->sensor_lanes[j] != portconfigs[i].lanes[j]) break; if (j == N_MIPI_PORT_ID) @@ -783,7 +754,7 @@ int atomisp_csi_lane_config(struct atomisp_device *isp) dev_err(isp->dev, "%s: could not find the CSI port setting for %d-%d-%d\n", __func__, - sensor_lanes[0], sensor_lanes[1], sensor_lanes[2]); + isp->sensor_lanes[0], isp->sensor_lanes[1], isp->sensor_lanes[2]); return -EINVAL; } @@ -811,7 +782,7 @@ static int atomisp_subdev_probe(struct atomisp_device *isp) { const struct atomisp_platform_data *pdata; struct intel_v4l2_subdev_table *subdevs; - int ret, raw_index = -1, count; + int ret, mipi_port, raw_index = -1, count; pdata = atomisp_get_platform_data(); if (!pdata) { @@ -851,10 +822,18 @@ static int atomisp_subdev_probe(struct atomisp_device *isp) break; } + if (subdevs->port >= ATOMISP_CAMERA_NR_PORTS) { + dev_err(isp->dev, "port %d not supported\n", subdevs->port); + break; + } + isp->inputs[isp->input_cnt].type = subdevs->type; isp->inputs[isp->input_cnt].port = subdevs->port; isp->inputs[isp->input_cnt].camera = subdevs->subdev; isp->input_cnt++; + + mipi_port = atomisp_port_to_mipi_port(isp, subdevs->port); + isp->sensor_lanes[mipi_port] = subdevs->lanes; break; case CAMERA_MOTOR: if (isp->motor) { @@ -964,15 +943,6 @@ static int atomisp_register_entities(struct atomisp_device *isp) goto subdev_register_failed; } - for (i = 0; i < isp->input_cnt; i++) { - if (isp->inputs[i].port >= ATOMISP_CAMERA_NR_PORTS) { - dev_err(isp->dev, "isp->inputs port %d not supported\n", - isp->inputs[i].port); - ret = -EINVAL; - goto link_failed; - } - } - if (isp->input_cnt < ATOM_ISP_MAX_INPUTS) { dev_dbg(isp->dev, "TPG detected, camera_cnt: %d\n", isp->input_cnt); @@ -985,8 +955,6 @@ static int atomisp_register_entities(struct atomisp_device *isp) return 0; -link_failed: - atomisp_subdev_unregister_entities(&isp->asd); subdev_register_failed: atomisp_tpg_unregister_entities(&isp->tpg); tpg_register_failed: From 96f18f25c1f5f8cee04c1b6895e9404ce1651ebc Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 14 May 2023 21:08:29 +0100 Subject: [PATCH 178/253] media: atomisp: Delay mapping sensors to inputs till atomisp_register_device_nodes() Delay mapping sensors to inputs till atomisp_register_device_nodes() time. There are 2 reasons for this: 1. This guarantees a stable input order independent of the sensor probe order. 2. This is a preparation patch for v4l2-async sensor probing support. Link: https://lore.kernel.org/r/20230518153733.195306-7-hdegoede@redhat.com Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/atomisp_internal.h | 1 + .../staging/media/atomisp/pci/atomisp_v4l2.c | 83 ++++++++++--------- 2 files changed, 45 insertions(+), 39 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_internal.h b/drivers/staging/media/atomisp/pci/atomisp_internal.h index b8d643c9df8f..514c360d4d03 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_internal.h +++ b/drivers/staging/media/atomisp/pci/atomisp_internal.h @@ -194,6 +194,7 @@ struct atomisp_device { * Note this is indexed by mipi_port_id not atomisp_camera_port. */ int sensor_lanes[N_MIPI_PORT_ID]; + struct v4l2_subdev *sensor_subdevs[ATOMISP_CAMERA_NR_PORTS]; unsigned int input_cnt; struct atomisp_input_subdev inputs[ATOM_ISP_MAX_INPUTS]; struct v4l2_subdev *flash; diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index 4a30fff129cc..fce0d99d8532 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -782,7 +782,7 @@ static int atomisp_subdev_probe(struct atomisp_device *isp) { const struct atomisp_platform_data *pdata; struct intel_v4l2_subdev_table *subdevs; - int ret, mipi_port, raw_index = -1, count; + int ret, mipi_port, count; pdata = atomisp_get_platform_data(); if (!pdata) { @@ -814,26 +814,20 @@ static int atomisp_subdev_probe(struct atomisp_device *isp) switch (subdevs->type) { case RAW_CAMERA: - dev_dbg(isp->dev, "raw_index: %d\n", raw_index); - raw_index = isp->input_cnt; - if (isp->input_cnt >= ATOM_ISP_MAX_INPUTS) { - dev_warn(isp->dev, - "too many atomisp inputs, ignored\n"); - break; - } - if (subdevs->port >= ATOMISP_CAMERA_NR_PORTS) { dev_err(isp->dev, "port %d not supported\n", subdevs->port); break; } - isp->inputs[isp->input_cnt].type = subdevs->type; - isp->inputs[isp->input_cnt].port = subdevs->port; - isp->inputs[isp->input_cnt].camera = subdevs->subdev; - isp->input_cnt++; + if (isp->sensor_subdevs[subdevs->port]) { + dev_err(isp->dev, "port %d already has a sensor attached\n", + subdevs->port); + break; + } mipi_port = atomisp_port_to_mipi_port(isp, subdevs->port); isp->sensor_lanes[mipi_port] = subdevs->lanes; + isp->sensor_subdevs[subdevs->port] = subdevs->subdev; break; case CAMERA_MOTOR: if (isp->motor) { @@ -855,21 +849,6 @@ static int atomisp_subdev_probe(struct atomisp_device *isp) } } - /* - * HACK: Currently VCM belongs to primary sensor only, but correct - * approach must be to acquire from platform code which sensor - * owns it. - */ - if (isp->motor && raw_index >= 0) - isp->inputs[raw_index].motor = isp->motor; - - /* Proceed even if no modules detected. For COS mode and no modules. */ - if (!isp->input_cnt) - dev_warn(isp->dev, "no camera attached or fail to detect\n"); - else - dev_info(isp->dev, "detected %d camera sensors\n", - isp->input_cnt); - return atomisp_csi_lane_config(isp); } @@ -943,16 +922,6 @@ static int atomisp_register_entities(struct atomisp_device *isp) goto subdev_register_failed; } - if (isp->input_cnt < ATOM_ISP_MAX_INPUTS) { - dev_dbg(isp->dev, - "TPG detected, camera_cnt: %d\n", isp->input_cnt); - isp->inputs[isp->input_cnt].type = TEST_PATTERN; - isp->inputs[isp->input_cnt].port = -1; - isp->inputs[isp->input_cnt++].camera = &isp->tpg.sd; - } else { - dev_warn(isp->dev, "too many atomisp inputs, TPG ignored.\n"); - } - return 0; subdev_register_failed: @@ -970,7 +939,43 @@ v4l2_device_failed: static int atomisp_register_device_nodes(struct atomisp_device *isp) { - int err; + struct atomisp_input_subdev *input; + int i, err; + + for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) { + if (!isp->sensor_subdevs[i]) + continue; + + input = &isp->inputs[isp->input_cnt]; + + input->type = RAW_CAMERA; + input->port = i; + input->camera = isp->sensor_subdevs[i]; + + /* + * HACK: Currently VCM belongs to primary sensor only, but correct + * approach must be to acquire from platform code which sensor + * owns it. + */ + if (i == ATOMISP_CAMERA_PORT_PRIMARY) + input->motor = isp->motor; + + isp->input_cnt++; + } + + if (!isp->input_cnt) + dev_warn(isp->dev, "no camera attached or fail to detect\n"); + else + dev_info(isp->dev, "detected %d camera sensors\n", isp->input_cnt); + + if (isp->input_cnt < ATOM_ISP_MAX_INPUTS) { + dev_dbg(isp->dev, "TPG detected, camera_cnt: %d\n", isp->input_cnt); + isp->inputs[isp->input_cnt].type = TEST_PATTERN; + isp->inputs[isp->input_cnt].port = -1; + isp->inputs[isp->input_cnt++].camera = &isp->tpg.sd; + } else { + dev_warn(isp->dev, "too many atomisp inputs, TPG ignored.\n"); + } isp->asd.video_out.vdev.v4l2_dev = &isp->v4l2_dev; isp->asd.video_out.vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; From d374e4559127e68c63f07af02153df37c42989bd Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 15 May 2023 14:40:11 +0100 Subject: [PATCH 179/253] media: atomisp: Move pad linking to atomisp_register_device_nodes() atomisp_register_device_nodes() already iterates over the ports/sensors in a loop and that loop already does not include the TPG input. So we can simply setup the CSI2-port <-> ISP and sensor <-> CSI2-port mediactl-pad links there instead of repeating the loop in atomisp_create_pads_links(), which atomisp_register_device_nodes() used to call later on. Link: https://lore.kernel.org/r/20230518153733.195306-8-hdegoede@redhat.com Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/atomisp_subdev.c | 35 ------------------- .../media/atomisp/pci/atomisp_subdev.h | 1 - .../staging/media/atomisp/pci/atomisp_v4l2.c | 16 ++++++++- 3 files changed, 15 insertions(+), 37 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c index c2ae77cd77a7..7985a0319a39 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c @@ -933,41 +933,6 @@ static int isp_subdev_init_entities(struct atomisp_sub_device *asd) return asd->ctrl_handler.error; } -int atomisp_create_pads_links(struct atomisp_device *isp) -{ - int i, ret; - - for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) { - ret = media_create_pad_link(&isp->csi2_port[i].subdev.entity, - CSI2_PAD_SOURCE, &isp->asd.subdev.entity, - ATOMISP_SUBDEV_PAD_SINK, 0); - if (ret < 0) - return ret; - } - - for (i = 0; i < isp->input_cnt; i++) { - /* Don't create links for the test-pattern-generator */ - if (isp->inputs[i].type == TEST_PATTERN) - continue; - - ret = media_create_pad_link(&isp->inputs[i].camera->entity, 0, - &isp->csi2_port[isp->inputs[i]. - port].subdev.entity, - CSI2_PAD_SINK, - MEDIA_LNK_FL_ENABLED | - MEDIA_LNK_FL_IMMUTABLE); - if (ret < 0) - return ret; - } - - ret = media_create_pad_link(&isp->asd.subdev.entity, ATOMISP_SUBDEV_PAD_SOURCE, - &isp->asd.video_out.vdev.entity, 0, 0); - if (ret < 0) - return ret; - - return 0; -} - static void atomisp_subdev_cleanup_entities(struct atomisp_sub_device *asd) { v4l2_ctrl_handler_free(&asd->ctrl_handler); diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.h b/drivers/staging/media/atomisp/pci/atomisp_subdev.h index cd82554d5f65..c9f6561dbcb6 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.h +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.h @@ -366,6 +366,5 @@ int atomisp_subdev_register_subdev(struct atomisp_sub_device *asd, struct v4l2_device *vdev); int atomisp_subdev_init(struct atomisp_device *isp); void atomisp_subdev_cleanup(struct atomisp_device *isp); -int atomisp_create_pads_links(struct atomisp_device *isp); #endif /* __ATOMISP_SUBDEV_H__ */ diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index fce0d99d8532..c95349d315cf 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -943,6 +943,12 @@ static int atomisp_register_device_nodes(struct atomisp_device *isp) int i, err; for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) { + err = media_create_pad_link(&isp->csi2_port[i].subdev.entity, + CSI2_PAD_SOURCE, &isp->asd.subdev.entity, + ATOMISP_SUBDEV_PAD_SINK, 0); + if (err) + return err; + if (!isp->sensor_subdevs[i]) continue; @@ -960,6 +966,13 @@ static int atomisp_register_device_nodes(struct atomisp_device *isp) if (i == ATOMISP_CAMERA_PORT_PRIMARY) input->motor = isp->motor; + err = media_create_pad_link(&input->camera->entity, 0, + &isp->csi2_port[i].subdev.entity, + CSI2_PAD_SINK, + MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE); + if (err) + return err; + isp->input_cnt++; } @@ -983,7 +996,8 @@ static int atomisp_register_device_nodes(struct atomisp_device *isp) if (err) return err; - err = atomisp_create_pads_links(isp); + err = media_create_pad_link(&isp->asd.subdev.entity, ATOMISP_SUBDEV_PAD_SOURCE, + &isp->asd.video_out.vdev.entity, 0, 0); if (err) return err; From 4d98580962610e5d41f62e063e759b5bd5f7534a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 16 May 2023 21:29:18 +0100 Subject: [PATCH 180/253] media: atomisp: Allow camera_mipi_info to be NULL camera_mipi_info is an atomisp / atomisp_gmin_platform specific struct, allow mipi_info pointers to be NULL. This is a preparation patch for making atomisp work with standard v4l2 sensor drivers. Link: https://lore.kernel.org/r/20230518153733.195306-9-hdegoede@redhat.com Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 33 ++++++++++--------- .../staging/media/atomisp/pci/atomisp_csi2.c | 6 +--- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index f4a0341d1f8d..5b244d173b9a 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -3919,6 +3919,8 @@ static inline int atomisp_set_sensor_mipi_to_isp( const struct atomisp_in_fmt_conv *fc; int mipi_freq = 0; unsigned int input_format, bayer_order; + enum atomisp_input_format metadata_format = ATOMISP_INPUT_FORMAT_EMBEDDED; + u32 mipi_port, metadata_width = 0, metadata_height = 0; ctrl.id = V4L2_CID_LINK_FREQ; if (v4l2_g_ctrl @@ -3946,7 +3948,7 @@ static inline int atomisp_set_sensor_mipi_to_isp( /* Compatibility for sensors which provide no media bus code * in s_mbus_framefmt() nor support pad formats. */ - if (mipi_info->input_format != -1) { + if (mipi_info && mipi_info->input_format != -1) { bayer_order = mipi_info->raw_bayer_order; /* Input stream config is still needs configured */ @@ -3956,6 +3958,9 @@ static inline int atomisp_set_sensor_mipi_to_isp( if (!fc) return -EINVAL; input_format = fc->atomisp_in_fmt; + metadata_format = mipi_info->metadata_format; + metadata_width = mipi_info->metadata_width; + metadata_height = mipi_info->metadata_height; } else { struct v4l2_mbus_framefmt *sink; @@ -3972,18 +3977,17 @@ static inline int atomisp_set_sensor_mipi_to_isp( atomisp_css_input_set_format(asd, stream_id, input_format); atomisp_css_input_set_bayer_order(asd, stream_id, bayer_order); - fc = atomisp_find_in_fmt_conv_by_atomisp_in_fmt( - mipi_info->metadata_format); + fc = atomisp_find_in_fmt_conv_by_atomisp_in_fmt(metadata_format); if (!fc) return -EINVAL; + input_format = fc->atomisp_in_fmt; - atomisp_css_input_configure_port(asd, - atomisp_port_to_mipi_port(asd->isp, mipi_info->port), - mipi_info->num_lanes, + mipi_port = atomisp_port_to_mipi_port(isp, isp->inputs[asd->input_curr].port); + atomisp_css_input_configure_port(asd, mipi_port, + isp->sensor_lanes[mipi_port], 0xffff4, mipi_freq, input_format, - mipi_info->metadata_width, - mipi_info->metadata_height); + metadata_width, metadata_height); return 0; } @@ -4071,7 +4075,7 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, int (*configure_pp_input)(struct atomisp_sub_device *asd, unsigned int width, unsigned int height) = configure_pp_input_nop; - const struct atomisp_in_fmt_conv *fc; + const struct atomisp_in_fmt_conv *fc = NULL; int ret, i; if (!asd) { @@ -4093,15 +4097,14 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, if (isp->inputs[asd->input_curr].type != TEST_PATTERN) { mipi_info = atomisp_to_sensor_mipi_info( isp->inputs[asd->input_curr].camera); - if (!mipi_info) { - dev_err(isp->dev, "mipi_info is NULL\n"); - return -EINVAL; - } + if (atomisp_set_sensor_mipi_to_isp(asd, ATOMISP_INPUT_STREAM_GENERAL, mipi_info)) return -EINVAL; - fc = atomisp_find_in_fmt_conv_by_atomisp_in_fmt( - mipi_info->input_format); + + if (mipi_info) + fc = atomisp_find_in_fmt_conv_by_atomisp_in_fmt(mipi_info->input_format); + if (!fc) fc = atomisp_find_in_fmt_conv( atomisp_subdev_get_ffmt(&asd->subdev, diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2.c b/drivers/staging/media/atomisp/pci/atomisp_csi2.c index b00bc0b7aaad..0045c4d3a7f6 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_csi2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2.c @@ -322,15 +322,11 @@ static void atomisp_csi2_configure_isp2401(struct atomisp_sub_device *asd) struct v4l2_control ctrl; struct atomisp_device *isp = asd->isp; - struct camera_mipi_info *mipi_info; int mipi_freq = 0; enum atomisp_camera_port port; - int n; - mipi_info = atomisp_to_sensor_mipi_info( - isp->inputs[asd->input_curr].camera); - port = mipi_info->port; + port = isp->inputs[asd->input_curr].port; ctrl.id = V4L2_CID_LINK_FREQ; if (v4l2_g_ctrl From 625ac9af384481e8644e0653a4aa472aa95f0395 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 24 May 2023 16:16:43 +0100 Subject: [PATCH 181/253] media: atomisp: Switch i2c drivers back to use .probe() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After commit b8a1a4cd5a98 ("i2c: Provide a temporary .probe_new() call-back type"), all drivers being converted to .probe_new() and then commit 03c835f498b5 ("i2c: Switch .probe() to not take an id parameter") convert back to (the new) .probe() to be able to eventually drop .probe_new() from struct i2c_driver. Link: https://lore.kernel.org/r/20230524151646.486847-3-u.kleine-koenig@pengutronix.de Signed-off-by: Uwe Kleine-König Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/i2c/atomisp-gc0310.c | 2 +- drivers/staging/media/atomisp/i2c/atomisp-gc2235.c | 2 +- drivers/staging/media/atomisp/i2c/atomisp-lm3554.c | 2 +- drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c | 2 +- drivers/staging/media/atomisp/i2c/atomisp-ov2680.c | 2 +- drivers/staging/media/atomisp/i2c/atomisp-ov2722.c | 2 +- drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c index 77a2bd1fe749..1829ba419e3e 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c @@ -705,7 +705,7 @@ static struct i2c_driver gc0310_driver = { .pm = pm_sleep_ptr(&gc0310_pm_ops), .acpi_match_table = gc0310_acpi_match, }, - .probe_new = gc0310_probe, + .probe = gc0310_probe, .remove = gc0310_remove, }; module_i2c_driver(gc0310_driver); diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c index cb4c79b483ca..9fa390fbc5f3 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c @@ -864,7 +864,7 @@ static struct i2c_driver gc2235_driver = { .name = "gc2235", .acpi_match_table = gc2235_acpi_match, }, - .probe_new = gc2235_probe, + .probe = gc2235_probe, .remove = gc2235_remove, }; module_i2c_driver(gc2235_driver); diff --git a/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c b/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c index c4ce4cd445d7..cf5d9317b11a 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-lm3554.c @@ -945,7 +945,7 @@ static struct i2c_driver lm3554_driver = { .pm = &lm3554_pm_ops, .acpi_match_table = lm3554_acpi_match, }, - .probe_new = lm3554_probe, + .probe = lm3554_probe, .remove = lm3554_remove, }; module_i2c_driver(lm3554_driver); diff --git a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c index 0e5a981dd331..1c6643c442ef 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c @@ -1600,7 +1600,7 @@ static struct i2c_driver mt9m114_driver = { .name = "mt9m114", .acpi_match_table = mt9m114_acpi_match, }, - .probe_new = mt9m114_probe, + .probe = mt9m114_probe, .remove = mt9m114_remove, }; module_i2c_driver(mt9m114_driver); diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index c079368019e8..cdb3097b3259 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -719,7 +719,7 @@ static struct i2c_driver ov2680_driver = { .pm = pm_sleep_ptr(&ov2680_pm_ops), .acpi_match_table = ov2680_acpi_match, }, - .probe_new = ov2680_probe, + .probe = ov2680_probe, .remove = ov2680_remove, }; module_i2c_driver(ov2680_driver); diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c index 5d2e6e2e72f0..6a72691ed5b7 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c @@ -1019,7 +1019,7 @@ static struct i2c_driver ov2722_driver = { .name = "ov2722", .acpi_match_table = ov2722_acpi_match, }, - .probe_new = ov2722_probe, + .probe = ov2722_probe, .remove = ov2722_remove, }; module_i2c_driver(ov2722_driver); diff --git a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c index da8c3b1d3bcd..c94fe8e861a5 100644 --- a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c +++ b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c @@ -1794,7 +1794,7 @@ static struct i2c_driver ov5693_driver = { .name = "ov5693", .acpi_match_table = ov5693_acpi_match, }, - .probe_new = ov5693_probe, + .probe = ov5693_probe, .remove = ov5693_remove, }; module_i2c_driver(ov5693_driver); From 66c1dfad00120d15abb1bca4e97b1dcf82002019 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 24 May 2023 13:11:43 +0100 Subject: [PATCH 182/253] media: atomisp: initialize settings to 0 Fix a compiler warning: drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c:1525:13: warning: 'settings' may be used uninitialized [-Wmaybe-uninitialized] The 'settings' variable is actually always initialized, but the compiler isn't quite able to figure that out. Just initialize it to 0 to avoid this warning. Link: https://lore.kernel.org/r/20230524121150.435736-2-hverkuil-cisco@xs4all.nl Signed-off-by: Hans Verkuil Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c index 6512e3c17af0..10b7871017d5 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c +++ b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c @@ -1524,7 +1524,7 @@ static int v4l2_acpi_handle_gpio_res(struct acpi_resource *ares, void *_data) const char *name; bool active_low; unsigned int i; - u32 settings; + u32 settings = 0; u8 pin; if (!acpi_gpio_get_io_resource(ares, &agpio)) From 5e131b80605a391bb61c23e1f5950a343b4d8a58 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 24 May 2023 13:11:50 +0100 Subject: [PATCH 183/253] media: atomisp: move up sanity checks The sanity checks were done too late, so move them up. This fixes this smatch warning: drivers/staging/media/atomisp/pci/sh_css_firmware.c:247 sh_css_load_firmware() warn: variable dereferenced before check 'fw_data' (see line 237) Link: https://lore.kernel.org/r/20230524121150.435736-9-hverkuil-cisco@xs4all.nl Signed-off-by: Hans Verkuil Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/sh_css_firmware.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/sh_css_firmware.c b/drivers/staging/media/atomisp/pci/sh_css_firmware.c index 49ee88fe151d..197ab2085e8d 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_firmware.c +++ b/drivers/staging/media/atomisp/pci/sh_css_firmware.c @@ -233,8 +233,16 @@ sh_css_load_firmware(struct device *dev, const char *fw_data, struct sh_css_fw_bi_file_h *file_header; int ret; + /* some sanity checks */ + if (!fw_data || fw_size < sizeof(struct sh_css_fw_bi_file_h)) + return -EINVAL; + firmware_header = (struct firmware_header *)fw_data; file_header = &firmware_header->file_header; + + if (file_header->h_size != sizeof(struct sh_css_fw_bi_file_h)) + return -EINVAL; + binaries = &firmware_header->binary_header; strscpy(FW_rel_ver_name, file_header->version, min(sizeof(FW_rel_ver_name), sizeof(file_header->version))); @@ -251,13 +259,6 @@ sh_css_load_firmware(struct device *dev, const char *fw_data, IA_CSS_LOG("successfully load firmware version %s", release_version); } - /* some sanity checks */ - if (!fw_data || fw_size < sizeof(struct sh_css_fw_bi_file_h)) - return -EINVAL; - - if (file_header->h_size != sizeof(struct sh_css_fw_bi_file_h)) - return -EINVAL; - sh_css_num_binaries = file_header->binary_nr; /* Only allocate memory for ISP blob info */ if (sh_css_num_binaries > NUM_OF_SPS) { From 8d28ec7e9145ef6308ab3438d73308ec6ea14360 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 25 May 2023 20:00:56 +0100 Subject: [PATCH 184/253] media: atomisp: Add support for v4l2-async sensor registration Add support for using v4l2-async sensor registration. This has been tested with both the gc0310 and the ov2680 sensor drivers. Drivers must add the ACPI HIDs they match on to the supported_sensors[] array in the same commit as that they are converted to v4l2_async_register_subdev_sensor(). Sensor drivers also must check they have a fwnode graph endpoint and return -EPROBE_DEFER from probe() if there is no endpoint yet. This guarantees that the GPIO mappings are in place before the driver tries to get GPIOs. For now it also is still possible to use the old atomisp_gmin_platform based sensor drivers. This is mainly intended for testing while moving other sensor drivers over to runtime-pm + v4l2-async. Link: https://lore.kernel.org/r/20230525190100.130010-2-hdegoede@redhat.com Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/Makefile | 1 + .../staging/media/atomisp/pci/atomisp_csi2.c | 4 + .../staging/media/atomisp/pci/atomisp_csi2.h | 89 +- .../media/atomisp/pci/atomisp_csi2_bridge.c | 810 ++++++++++++++++++ .../media/atomisp/pci/atomisp_internal.h | 2 + .../staging/media/atomisp/pci/atomisp_v4l2.c | 38 +- .../staging/media/atomisp/pci/atomisp_v4l2.h | 1 + 7 files changed, 923 insertions(+), 22 deletions(-) create mode 100644 drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c diff --git a/drivers/staging/media/atomisp/Makefile b/drivers/staging/media/atomisp/Makefile index 532e12ed72e6..38b370124109 100644 --- a/drivers/staging/media/atomisp/Makefile +++ b/drivers/staging/media/atomisp/Makefile @@ -16,6 +16,7 @@ atomisp-objs += \ pci/atomisp_cmd.o \ pci/atomisp_compat_css20.o \ pci/atomisp_csi2.o \ + pci/atomisp_csi2_bridge.o \ pci/atomisp_drvfs.o \ pci/atomisp_fops.o \ pci/atomisp_ioctl.o \ diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2.c b/drivers/staging/media/atomisp/pci/atomisp_csi2.c index 0045c4d3a7f6..abf55a86f795 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_csi2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2.c @@ -371,6 +371,10 @@ int atomisp_mipi_csi2_init(struct atomisp_device *isp) unsigned int i; int ret; + ret = atomisp_csi2_bridge_init(isp); + if (ret < 0) + return ret; + for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) { csi2_port = &isp->csi2_port[i]; csi2_port->isp = isp; diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2.h b/drivers/staging/media/atomisp/pci/atomisp_csi2.h index b245b2f5ce99..b389ccda5e98 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_csi2.h +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2.h @@ -18,17 +18,102 @@ #ifndef __ATOMISP_CSI2_H__ #define __ATOMISP_CSI2_H__ +#include +#include + #include #include +#include "../../include/linux/atomisp.h" + #define CSI2_PAD_SINK 0 #define CSI2_PAD_SOURCE 1 #define CSI2_PADS_NUM 2 -struct atomisp_device; +#define CSI2_MAX_LANES 4 + +#define CSI2_MAX_ACPI_GPIOS 2u + +struct acpi_device; struct v4l2_device; + +struct atomisp_device; struct atomisp_sub_device; +struct atomisp_csi2_acpi_gpio_map { + struct acpi_gpio_params params[CSI2_MAX_ACPI_GPIOS]; + struct acpi_gpio_mapping mapping[CSI2_MAX_ACPI_GPIOS + 1]; +}; + +struct atomisp_csi2_acpi_gpio_parsing_data { + struct acpi_device *adev; + struct atomisp_csi2_acpi_gpio_map *map; + u32 settings[CSI2_MAX_ACPI_GPIOS]; + unsigned int settings_count; + unsigned int res_count; + unsigned int map_count; +}; + +enum atomisp_csi2_sensor_swnodes { + SWNODE_SENSOR, + SWNODE_SENSOR_PORT, + SWNODE_SENSOR_ENDPOINT, + SWNODE_CSI2_PORT, + SWNODE_CSI2_ENDPOINT, + SWNODE_COUNT +}; + +struct atomisp_csi2_property_names { + char rotation[9]; + char bus_type[9]; + char data_lanes[11]; + char remote_endpoint[16]; +}; + +struct atomisp_csi2_node_names { + char port[7]; + char endpoint[11]; + char remote_port[7]; +}; + +struct atomisp_csi2_sensor_config { + const char *hid; + int lanes; +}; + +struct atomisp_csi2_sensor { + /* Append port in "-%u" format as suffix of HID */ + char name[ACPI_ID_LEN + 4]; + struct acpi_device *adev; + int port; + int lanes; + + /* SWNODE_COUNT + 1 for terminating NULL */ + const struct software_node *group[SWNODE_COUNT + 1]; + struct software_node swnodes[SWNODE_COUNT]; + struct atomisp_csi2_node_names node_names; + struct atomisp_csi2_property_names prop_names; + /* "rotation" + terminating entry */ + struct property_entry dev_properties[2]; + /* "bus-type", "data-lanes", "remote-endpoint" + terminating entry */ + struct property_entry ep_properties[4]; + /* "data-lanes", "remote-endpoint" + terminating entry */ + struct property_entry csi2_properties[3]; + struct software_node_ref_args local_ref[1]; + struct software_node_ref_args remote_ref[1]; + struct software_node_ref_args vcm_ref[1]; + /* GPIO mappings storage */ + struct atomisp_csi2_acpi_gpio_map gpio_map; +}; + +struct atomisp_csi2_bridge { + struct software_node csi2_node; + char csi2_node_name[14]; + u32 data_lanes[CSI2_MAX_LANES]; + unsigned int n_sensors; + struct atomisp_csi2_sensor sensors[ATOMISP_CAMERA_NR_PORTS]; +}; + struct atomisp_mipi_csi2_device { struct v4l2_subdev subdev; struct media_pad pads[CSI2_PADS_NUM]; @@ -48,6 +133,8 @@ void atomisp_mipi_csi2_unregister_entities( struct atomisp_mipi_csi2_device *csi2); int atomisp_mipi_csi2_register_entities(struct atomisp_mipi_csi2_device *csi2, struct v4l2_device *vdev); +int atomisp_csi2_bridge_init(struct atomisp_device *isp); +int atomisp_csi2_bridge_parse_firmware(struct atomisp_device *isp); void atomisp_csi2_configure(struct atomisp_sub_device *asd); diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c new file mode 100644 index 000000000000..e07562d6a63e --- /dev/null +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c @@ -0,0 +1,810 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Code to build software firmware node graph for atomisp2 connected sensors + * from ACPI tables. + * + * Copyright (C) 2023 Hans de Goede + * + * Based on drivers/media/pci/intel/ipu3/cio2-bridge.c written by: + * Dan Scally + */ + +#include +#include +#include +#include +#include + +#include "atomisp_cmd.h" +#include "atomisp_csi2.h" +#include "atomisp_internal.h" + +#define NODE_SENSOR(_HID, _PROPS) \ + ((const struct software_node) { \ + .name = _HID, \ + .properties = _PROPS, \ + }) + +#define NODE_PORT(_PORT, _SENSOR_NODE) \ + ((const struct software_node) { \ + .name = _PORT, \ + .parent = _SENSOR_NODE, \ + }) + +#define NODE_ENDPOINT(_EP, _PORT, _PROPS) \ + ((const struct software_node) { \ + .name = _EP, \ + .parent = _PORT, \ + .properties = _PROPS, \ + }) + +/* + * 79234640-9e10-4fea-a5c1-b5aa8b19756f + * This _DSM GUID returns information about the GPIO lines mapped to a sensor. + * Function number 1 returns a count of the GPIO lines that are mapped. + * Subsequent functions return 32 bit ints encoding information about the GPIO. + */ +static const guid_t intel_sensor_gpio_info_guid = + GUID_INIT(0x79234640, 0x9e10, 0x4fea, + 0xa5, 0xc1, 0xb5, 0xaa, 0x8b, 0x19, 0x75, 0x6f); + +#define INTEL_GPIO_DSM_TYPE_SHIFT 0 +#define INTEL_GPIO_DSM_TYPE_MASK GENMASK(7, 0) +#define INTEL_GPIO_DSM_PIN_SHIFT 8 +#define INTEL_GPIO_DSM_PIN_MASK GENMASK(15, 8) +#define INTEL_GPIO_DSM_SENSOR_ON_VAL_SHIFT 24 +#define INTEL_GPIO_DSM_SENSOR_ON_VAL_MASK GENMASK(31, 24) + +#define INTEL_GPIO_DSM_TYPE(x) \ + (((x) & INTEL_GPIO_DSM_TYPE_MASK) >> INTEL_GPIO_DSM_TYPE_SHIFT) +#define INTEL_GPIO_DSM_PIN(x) \ + (((x) & INTEL_GPIO_DSM_PIN_MASK) >> INTEL_GPIO_DSM_PIN_SHIFT) +#define INTEL_GPIO_DSM_SENSOR_ON_VAL(x) \ + (((x) & INTEL_GPIO_DSM_SENSOR_ON_VAL_MASK) >> INTEL_GPIO_DSM_SENSOR_ON_VAL_SHIFT) + +/* + * 822ace8f-2814-4174-a56b-5f029fe079ee + * This _DSM GUID returns a string from the sensor device, which acts as a + * module identifier. + */ +static const guid_t intel_sensor_module_guid = + GUID_INIT(0x822ace8f, 0x2814, 0x4174, + 0xa5, 0x6b, 0x5f, 0x02, 0x9f, 0xe0, 0x79, 0xee); + +/* + * dc2f6c4f-045b-4f1d-97b9-882a6860a4be + * This _DSM GUID returns a package with n*2 strings, with each set of 2 strings + * forming a key, value pair for settings like e.g. "CsiLanes" = "1". + */ +static const guid_t atomisp_dsm_guid = + GUID_INIT(0xdc2f6c4f, 0x045b, 0x4f1d, + 0x97, 0xb9, 0x88, 0x2a, 0x68, 0x60, 0xa4, 0xbe); + +/* + * Extend this array with ACPI Hardware IDs of sensors known to be working + * plus the number of links expected by their drivers. + * + * Do not add an entry for a sensor that is not actually supported, + * or which have not yet been converted to work without atomisp_gmin + * power-management and with v4l2-async probing. + */ +static const struct atomisp_csi2_sensor_config supported_sensors[] = { +}; + +/* + * gmin_cfg parsing code. This is a cleaned up version of the gmin_cfg parsing + * code from atomisp_gmin_platform.c. + * Once all sensors are moved to v4l2-async probing atomisp_gmin_platform.c can + * be removed and the duplication of this code goes away. + */ +struct gmin_cfg_var { + const char *acpi_dev_name; + const char *key; + const char *val; +}; + +static struct gmin_cfg_var lenovo_ideapad_miix_310_vars[] = { + /* _DSM contains the wrong CsiPort! */ + { "OVTI2680:01", "CsiPort", "0" }, + {} +}; + +static const struct dmi_system_id gmin_cfg_dmi_overrides[] = { + { + /* Lenovo Ideapad Miix 310 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "MIIX 310-10"), + }, + .driver_data = lenovo_ideapad_miix_310_vars, + }, + {} +}; + +static char *gmin_cfg_get_dsm(struct acpi_device *adev, const char *key) +{ + union acpi_object *obj, *key_el, *val_el; + char *val = NULL; + int i; + + obj = acpi_evaluate_dsm_typed(adev->handle, &atomisp_dsm_guid, 0, 0, + NULL, ACPI_TYPE_PACKAGE); + if (!obj) + return NULL; + + for (i = 0; i < obj->package.count - 1; i += 2) { + key_el = &obj->package.elements[i + 0]; + val_el = &obj->package.elements[i + 1]; + + if (key_el->type != ACPI_TYPE_STRING || val_el->type != ACPI_TYPE_STRING) + break; + + if (!strcmp(key_el->string.pointer, key)) { + val = kstrdup(val_el->string.pointer, GFP_KERNEL); + if (!val) + break; + + acpi_handle_info(adev->handle, "Using DSM entry %s=%s\n", key, val); + break; + } + } + + ACPI_FREE(obj); + return val; +} + +static char *gmin_cfg_get_dmi_override(struct acpi_device *adev, const char *key) +{ + const struct dmi_system_id *id; + struct gmin_cfg_var *gv; + + id = dmi_first_match(gmin_cfg_dmi_overrides); + if (!id) + return NULL; + + for (gv = id->driver_data; gv->acpi_dev_name; gv++) { + if (strcmp(gv->acpi_dev_name, acpi_dev_name(adev))) + continue; + + if (strcmp(key, gv->key)) + continue; + + acpi_handle_info(adev->handle, "Using DMI entry %s=%s\n", key, gv->val); + return kstrdup(gv->val, GFP_KERNEL); + } + + return NULL; +} + +static char *gmin_cfg_get(struct acpi_device *adev, const char *key) +{ + char *val; + + val = gmin_cfg_get_dmi_override(adev, key); + if (val) + return val; + + return gmin_cfg_get_dsm(adev, key); +} + +static int gmin_cfg_get_int(struct acpi_device *adev, const char *key, int default_val) +{ + char *str_val; + long int_val; + int ret; + + str_val = gmin_cfg_get(adev, key); + if (!str_val) + goto out_use_default; + + ret = kstrtoul(str_val, 0, &int_val); + kfree(str_val); + if (ret) + goto out_use_default; + + return int_val; + +out_use_default: + acpi_handle_info(adev->handle, "Using default %s=%d\n", key, default_val); + return default_val; +} + +static int atomisp_csi2_get_pmc_clk_nr_from_acpi_pr0(struct acpi_device *adev) +{ + /* ACPI_PATH_SEGMENT_LENGTH is guaranteed to be big enough for name + 0 term. */ + char name[ACPI_PATH_SEGMENT_LENGTH]; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_buffer b_name = { sizeof(name), name }; + union acpi_object *package, *element; + int i, ret = -ENOENT; + acpi_handle rhandle; + acpi_status status; + u8 clock_num; + + status = acpi_evaluate_object_typed(adev->handle, "_PR0", NULL, &buffer, ACPI_TYPE_PACKAGE); + if (ACPI_FAILURE(status)) + return -ENOENT; + + package = buffer.pointer; + for (i = 0; i < package->package.count; i++) { + element = &package->package.elements[i]; + + if (element->type != ACPI_TYPE_LOCAL_REFERENCE) + continue; + + rhandle = element->reference.handle; + if (!rhandle) + continue; + + acpi_get_name(rhandle, ACPI_SINGLE_NAME, &b_name); + + if (str_has_prefix(name, "CLK") && !kstrtou8(&name[3], 10, &clock_num) && + clock_num <= 4) { + ret = clock_num; + break; + } + } + + ACPI_FREE(buffer.pointer); + return ret; +} + +static int atomisp_csi2_get_port(struct acpi_device *adev) +{ + int clock_num, port; + + /* + * Get PMC-clock number from ACPI _PR0 method and compare this to + * the CsiPort 1 PMC-clock used in the CHT/BYT reference designs. + */ + clock_num = atomisp_csi2_get_pmc_clk_nr_from_acpi_pr0(adev); + if (IS_ISP2401) + port = clock_num == 4 ? 1 : 0; + else + port = clock_num == 0 ? 1 : 0; + + /* Intel DSM or DMI quirk overrides PR0 derived default */ + return gmin_cfg_get_int(adev, "CsiPort", port); +} + +/* Note this always returns 1 to continue looping so that res_count is accurate */ +static int atomisp_csi2_handle_acpi_gpio_res(struct acpi_resource *ares, void *_data) +{ + struct atomisp_csi2_acpi_gpio_parsing_data *data = _data; + struct acpi_resource_gpio *agpio; + const char *name; + bool active_low; + unsigned int i; + u32 settings = 0; + u16 pin; + + if (!acpi_gpio_get_io_resource(ares, &agpio)) + return 1; /* Not a GPIO, continue the loop */ + + data->res_count++; + + pin = agpio->pin_table[0]; + for (i = 0; i < data->settings_count; i++) { + if (INTEL_GPIO_DSM_PIN(data->settings[i]) == pin) { + settings = data->settings[i]; + break; + } + } + + if (i == data->settings_count) { + acpi_handle_warn(data->adev->handle, + "Could not find DSM GPIO settings for pin %u\n", pin); + return 1; + } + + switch (INTEL_GPIO_DSM_TYPE(settings)) { + case 0: + name = "reset-gpios"; + break; + case 1: + name = "powerdown-gpios"; + break; + default: + acpi_handle_warn(data->adev->handle, "Unknown GPIO type 0x%02lx for pin %u\n", + INTEL_GPIO_DSM_TYPE(settings), pin); + return 1; + } + + /* + * Both reset and power-down need to be logical false when the sensor + * is on (sensor should not be in reset and not be powered-down). So + * when the sensor-on-value (which is the physical pin value) is high, + * then the signal is active-low. + */ + active_low = INTEL_GPIO_DSM_SENSOR_ON_VAL(settings); + + i = data->map_count; + if (i == CSI2_MAX_ACPI_GPIOS) + return 1; + + /* res_count is already incremented */ + data->map->params[i].crs_entry_index = data->res_count - 1; + data->map->params[i].active_low = active_low; + data->map->mapping[i].name = name; + data->map->mapping[i].data = &data->map->params[i]; + data->map->mapping[i].size = 1; + data->map_count++; + + acpi_handle_info(data->adev->handle, "%s crs %d %s pin %u active-%s\n", name, + data->res_count - 1, agpio->resource_source.string_ptr, + pin, active_low ? "low" : "high"); + + return 1; +} + +/* + * Helper function to create an ACPI GPIO lookup table for sensor reset and + * powerdown signals on Intel Bay Trail (BYT) and Cherry Trail (CHT) devices, + * including setting the correct polarity for the GPIO. + * + * This uses the "79234640-9e10-4fea-a5c1-b5aa8b19756f" DSM method directly + * on the sensor device's ACPI node. This is different from later Intel + * hardware which has a separate INT3472 acpi_device with this info. + * + * This function must be called before creating the sw-noded describing + * the fwnode graph endpoint. And sensor drivers used on these devices + * must return -EPROBE_DEFER when there is no endpoint description yet. + * Together this guarantees that the GPIO lookups are in place before + * the sensor driver tries to get GPIOs with gpiod_get(). + * + * Note this code uses the same DSM GUID as the int3472_gpio_guid in + * the INT3472 discrete.c code and there is some overlap, but there are + * enough differences that it is difficult to share the code. + */ +static int atomisp_csi2_add_gpio_mappings(struct atomisp_csi2_sensor *sensor, + struct acpi_device *adev) +{ + struct atomisp_csi2_acpi_gpio_parsing_data data = { }; + LIST_HEAD(resource_list); + union acpi_object *obj; + unsigned int i, j; + int ret; + + obj = acpi_evaluate_dsm_typed(adev->handle, &intel_sensor_module_guid, + 0x00, 1, NULL, ACPI_TYPE_STRING); + if (obj) { + acpi_handle_info(adev->handle, "Sensor module id: '%s'\n", obj->string.pointer); + ACPI_FREE(obj); + } + + /* + * First get the GPIO-settings count and then get count GPIO-settings + * values. Note the order of these may differ from the order in which + * the GPIOs are listed on the ACPI resources! So we first store them all + * and then enumerate the ACPI resources and match them up by pin number. + */ + obj = acpi_evaluate_dsm_typed(adev->handle, + &intel_sensor_gpio_info_guid, 0x00, 1, + NULL, ACPI_TYPE_INTEGER); + if (!obj) { + acpi_handle_err(adev->handle, "No _DSM entry for GPIO pin count\n"); + return -EIO; + } + + data.settings_count = obj->integer.value; + ACPI_FREE(obj); + + if (data.settings_count > CSI2_MAX_ACPI_GPIOS) { + acpi_handle_err(adev->handle, "Too many GPIOs %u > %u\n", data.settings_count, CSI2_MAX_ACPI_GPIOS); + return -EOVERFLOW; + } + + for (i = 0; i < data.settings_count; i++) { + /* + * i + 2 because the index of this _DSM function is 1-based + * and the first function is just a count. + */ + obj = acpi_evaluate_dsm_typed(adev->handle, + &intel_sensor_gpio_info_guid, + 0x00, i + 2, + NULL, ACPI_TYPE_INTEGER); + if (!obj) { + acpi_handle_err(adev->handle, "No _DSM entry for pin %u\n", i); + return -EIO; + } + + data.settings[i] = obj->integer.value; + ACPI_FREE(obj); + } + + /* Since we match up by pin-number the pin-numbers must be unique */ + for (i = 0; i < data.settings_count; i++) { + for (j = i + 1; j < data.settings_count; j++) { + if (INTEL_GPIO_DSM_PIN(data.settings[i]) != + INTEL_GPIO_DSM_PIN(data.settings[j])) + continue; + + acpi_handle_err(adev->handle, "Duplicate pin number %lu\n", + INTEL_GPIO_DSM_PIN(data.settings[i])); + return -EIO; + } + } + + /* Now parse the ACPI resources and build the lookup table */ + data.adev = adev; + data.map = &sensor->gpio_map; + ret = acpi_dev_get_resources(adev, &resource_list, + atomisp_csi2_handle_acpi_gpio_res, &data); + if (ret < 0) + return ret; + + acpi_dev_free_resource_list(&resource_list); + + if (data.map_count != data.settings_count || + data.res_count != data.settings_count) + acpi_handle_warn(adev->handle, "ACPI GPIO resources vs DSM GPIO-info count mismatch (dsm: %d res: %d map %d\n", + data.settings_count, data.res_count, data.map_count); + + ret = acpi_dev_add_driver_gpios(adev, data.map->mapping); + if (ret) + acpi_handle_err(adev->handle, "Error adding driver GPIOs: %d\n", ret); + + return ret; +} + +static const struct atomisp_csi2_property_names prop_names = { + .rotation = "rotation", + .bus_type = "bus-type", + .data_lanes = "data-lanes", + .remote_endpoint = "remote-endpoint", +}; + +static void atomisp_csi2_create_fwnode_properties(struct atomisp_csi2_sensor *sensor, + struct atomisp_csi2_bridge *bridge, + const struct atomisp_csi2_sensor_config *cfg) +{ + sensor->prop_names = prop_names; + + sensor->local_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_CSI2_ENDPOINT]); + sensor->remote_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_SENSOR_ENDPOINT]); + + sensor->dev_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.rotation, 0); + + sensor->ep_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.bus_type, + V4L2_FWNODE_BUS_TYPE_CSI2_DPHY); + sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes, + bridge->data_lanes, + sensor->lanes); + sensor->ep_properties[2] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint, + sensor->local_ref); + + sensor->csi2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes, + bridge->data_lanes, + sensor->lanes); + sensor->csi2_properties[1] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint, + sensor->remote_ref); +} + +static void atomisp_csi2_init_swnode_names(struct atomisp_csi2_sensor *sensor) +{ + snprintf(sensor->node_names.remote_port, + sizeof(sensor->node_names.remote_port), + SWNODE_GRAPH_PORT_NAME_FMT, sensor->port); + snprintf(sensor->node_names.port, + sizeof(sensor->node_names.port), + SWNODE_GRAPH_PORT_NAME_FMT, 0); /* Always port 0 */ + snprintf(sensor->node_names.endpoint, + sizeof(sensor->node_names.endpoint), + SWNODE_GRAPH_ENDPOINT_NAME_FMT, 0); /* And endpoint 0 */ +} + +static void atomisp_csi2_init_swnode_group(struct atomisp_csi2_sensor *sensor) +{ + struct software_node *nodes = sensor->swnodes; + + sensor->group[SWNODE_SENSOR] = &nodes[SWNODE_SENSOR]; + sensor->group[SWNODE_SENSOR_PORT] = &nodes[SWNODE_SENSOR_PORT]; + sensor->group[SWNODE_SENSOR_ENDPOINT] = &nodes[SWNODE_SENSOR_ENDPOINT]; + sensor->group[SWNODE_CSI2_PORT] = &nodes[SWNODE_CSI2_PORT]; + sensor->group[SWNODE_CSI2_ENDPOINT] = &nodes[SWNODE_CSI2_ENDPOINT]; +} + +static void atomisp_csi2_create_connection_swnodes(struct atomisp_csi2_bridge *bridge, + struct atomisp_csi2_sensor *sensor) +{ + struct software_node *nodes = sensor->swnodes; + + atomisp_csi2_init_swnode_names(sensor); + + nodes[SWNODE_SENSOR] = NODE_SENSOR(sensor->name, + sensor->dev_properties); + nodes[SWNODE_SENSOR_PORT] = NODE_PORT(sensor->node_names.port, + &nodes[SWNODE_SENSOR]); + nodes[SWNODE_SENSOR_ENDPOINT] = NODE_ENDPOINT(sensor->node_names.endpoint, + &nodes[SWNODE_SENSOR_PORT], + sensor->ep_properties); + nodes[SWNODE_CSI2_PORT] = NODE_PORT(sensor->node_names.remote_port, + &bridge->csi2_node); + nodes[SWNODE_CSI2_ENDPOINT] = NODE_ENDPOINT(sensor->node_names.endpoint, + &nodes[SWNODE_CSI2_PORT], + sensor->csi2_properties); + + atomisp_csi2_init_swnode_group(sensor); +} + +static void atomisp_csi2_unregister_sensors(struct atomisp_csi2_bridge *bridge) +{ + struct atomisp_csi2_sensor *sensor; + unsigned int i; + + for (i = 0; i < bridge->n_sensors; i++) { + sensor = &bridge->sensors[i]; + software_node_unregister_node_group(sensor->group); + acpi_dev_remove_driver_gpios(sensor->adev); + acpi_dev_put(sensor->adev); + } +} + +static int atomisp_csi2_connect_sensor(const struct atomisp_csi2_sensor_config *cfg, + struct atomisp_csi2_bridge *bridge, + struct atomisp_device *isp) +{ + struct fwnode_handle *fwnode, *primary; + struct atomisp_csi2_sensor *sensor; + struct acpi_device *adev; + int ret; + + for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) { + if (!adev->status.enabled) + continue; + + if (bridge->n_sensors >= ATOMISP_CAMERA_NR_PORTS) { + dev_err(isp->dev, "Exceeded available CSI2 ports\n"); + ret = -EOVERFLOW; + goto err_put_adev; + } + + sensor = &bridge->sensors[bridge->n_sensors]; + + sensor->port = atomisp_csi2_get_port(adev); + if (sensor->port >= ATOMISP_CAMERA_NR_PORTS) { + acpi_handle_err(adev->handle, "Invalid port: %d\n", sensor->port); + ret = -EINVAL; + goto err_put_adev; + } + + sensor->lanes = gmin_cfg_get_int(adev, "CsiLanes", cfg->lanes); + if (sensor->lanes > CSI2_MAX_LANES) { + acpi_handle_err(adev->handle, "Invalid number of lanes: %d\n", sensor->lanes); + ret = -EINVAL; + goto err_put_adev; + } + + ret = atomisp_csi2_add_gpio_mappings(sensor, adev); + if (ret) + goto err_put_adev; + + snprintf(sensor->name, sizeof(sensor->name), "%s-%u", + cfg->hid, sensor->port); + + atomisp_csi2_create_fwnode_properties(sensor, bridge, cfg); + atomisp_csi2_create_connection_swnodes(bridge, sensor); + + ret = software_node_register_node_group(sensor->group); + if (ret) + goto err_remove_mappings; + + fwnode = software_node_fwnode(&sensor->swnodes[SWNODE_SENSOR]); + if (!fwnode) { + ret = -ENODEV; + goto err_free_swnodes; + } + + sensor->adev = acpi_dev_get(adev); + + primary = acpi_fwnode_handle(adev); + primary->secondary = fwnode; + + bridge->n_sensors++; + } + + return 0; + +err_free_swnodes: + software_node_unregister_node_group(sensor->group); +err_remove_mappings: + acpi_dev_remove_driver_gpios(adev); +err_put_adev: + acpi_dev_put(adev); + return ret; +} + +static int atomisp_csi2_connect_sensors(struct atomisp_csi2_bridge *bridge, + struct atomisp_device *isp) +{ + unsigned int i; + int ret; + + for (i = 0; i < ARRAY_SIZE(supported_sensors); i++) { + const struct atomisp_csi2_sensor_config *cfg = &supported_sensors[i]; + + ret = atomisp_csi2_connect_sensor(cfg, bridge, isp); + if (ret) + goto err_unregister_sensors; + } + + return 0; + +err_unregister_sensors: + atomisp_csi2_unregister_sensors(bridge); + return ret; +} + +int atomisp_csi2_bridge_init(struct atomisp_device *isp) +{ + struct atomisp_csi2_bridge *bridge; + struct device *dev = isp->dev; + struct fwnode_handle *fwnode; + int i, ret; + + /* + * This function is intended to run only once and then leave + * the created nodes attached even after a rmmod, therefore: + * 1. The bridge memory is leaked deliberately on success + * 2. If a secondary fwnode is already set exit early. + */ + fwnode = dev_fwnode(dev); + if (fwnode && fwnode->secondary) + return 0; + + bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); + if (!bridge) + return -ENOMEM; + + strscpy(bridge->csi2_node_name, "atomisp-csi2", sizeof(bridge->csi2_node_name)); + bridge->csi2_node.name = bridge->csi2_node_name; + + ret = software_node_register(&bridge->csi2_node); + if (ret < 0) { + dev_err(dev, "Failed to register the CSI2 HID node\n"); + goto err_free_bridge; + } + + /* + * Map the lane arrangement, which is fixed for the ISP2 (meaning we + * only need one, rather than one per sensor). We include it as a + * member of the bridge struct rather than a global variable so + * that it survives if the module is unloaded along with the rest of + * the struct. + */ + for (i = 0; i < CSI2_MAX_LANES; i++) + bridge->data_lanes[i] = i + 1; + + ret = atomisp_csi2_connect_sensors(bridge, isp); + if (ret || bridge->n_sensors == 0) + goto err_unregister_csi2; + + fwnode = software_node_fwnode(&bridge->csi2_node); + if (!fwnode) { + dev_err(dev, "Error getting fwnode from csi2 software_node\n"); + ret = -ENODEV; + goto err_unregister_sensors; + } + + set_secondary_fwnode(dev, fwnode); + + return 0; + +err_unregister_sensors: + atomisp_csi2_unregister_sensors(bridge); +err_unregister_csi2: + software_node_unregister(&bridge->csi2_node); +err_free_bridge: + kfree(bridge); + + return ret; +} + +/******* V4L2 sub-device asynchronous registration callbacks***********/ + +struct sensor_async_subdev { + struct v4l2_async_subdev asd; + int port; +}; + +#define to_sensor_asd(a) container_of(a, struct sensor_async_subdev, asd) +#define notifier_to_atomisp(n) container_of(n, struct atomisp_device, notifier) + +/* .bound() notifier callback when a match is found */ +static int atomisp_notifier_bound(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd, + struct v4l2_async_subdev *asd) +{ + struct atomisp_device *isp = notifier_to_atomisp(notifier); + struct sensor_async_subdev *s_asd = to_sensor_asd(asd); + + if (s_asd->port >= ATOMISP_CAMERA_NR_PORTS) { + dev_err(isp->dev, "port %d not supported\n", s_asd->port); + return -EINVAL; + } + + if (isp->sensor_subdevs[s_asd->port]) { + dev_err(isp->dev, "port %d already has a sensor attached\n", s_asd->port); + return -EBUSY; + } + + isp->sensor_subdevs[s_asd->port] = sd; + return 0; +} + +/* The .unbind callback */ +static void atomisp_notifier_unbind(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd, + struct v4l2_async_subdev *asd) +{ + struct atomisp_device *isp = notifier_to_atomisp(notifier); + struct sensor_async_subdev *s_asd = to_sensor_asd(asd); + + isp->sensor_subdevs[s_asd->port] = NULL; +} + +/* .complete() is called after all subdevices have been located */ +static int atomisp_notifier_complete(struct v4l2_async_notifier *notifier) +{ + struct atomisp_device *isp = notifier_to_atomisp(notifier); + + return atomisp_register_device_nodes(isp); +} + +static const struct v4l2_async_notifier_operations atomisp_async_ops = { + .bound = atomisp_notifier_bound, + .unbind = atomisp_notifier_unbind, + .complete = atomisp_notifier_complete, +}; + +int atomisp_csi2_bridge_parse_firmware(struct atomisp_device *isp) +{ + int i, mipi_port, ret; + + v4l2_async_nf_init(&isp->notifier); + isp->notifier.ops = &atomisp_async_ops; + + for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) { + struct v4l2_fwnode_endpoint vep = { + .bus_type = V4L2_MBUS_CSI2_DPHY, + }; + struct sensor_async_subdev *s_asd; + struct fwnode_handle *ep; + + ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(isp->dev), i, 0, + FWNODE_GRAPH_ENDPOINT_NEXT); + if (!ep) + continue; + + ret = v4l2_fwnode_endpoint_parse(ep, &vep); + if (ret) + goto err_parse; + + if (vep.base.port >= ATOMISP_CAMERA_NR_PORTS) { + dev_err(isp->dev, "port %d not supported\n", vep.base.port); + ret = -EINVAL; + goto err_parse; + } + + mipi_port = atomisp_port_to_mipi_port(isp, vep.base.port); + isp->sensor_lanes[mipi_port] = vep.bus.mipi_csi2.num_data_lanes; + + s_asd = v4l2_async_nf_add_fwnode_remote(&isp->notifier, ep, + struct sensor_async_subdev); + if (IS_ERR(s_asd)) { + ret = PTR_ERR(s_asd); + goto err_parse; + } + + s_asd->port = vep.base.port; + + fwnode_handle_put(ep); + continue; + +err_parse: + fwnode_handle_put(ep); + return ret; + } + + return 0; +} diff --git a/drivers/staging/media/atomisp/pci/atomisp_internal.h b/drivers/staging/media/atomisp/pci/atomisp_internal.h index 514c360d4d03..e59c0f1e7f53 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_internal.h +++ b/drivers/staging/media/atomisp/pci/atomisp_internal.h @@ -27,6 +27,7 @@ #include #include +#include #include /* ISP2400*/ @@ -173,6 +174,7 @@ struct atomisp_device { struct v4l2_device v4l2_dev; struct media_device media_dev; struct atomisp_sub_device asd; + struct v4l2_async_notifier notifier; struct atomisp_platform_data *pdata; void *mmu_l1_base; void __iomem *base; diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index c95349d315cf..a2ce9bbf10df 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -782,7 +783,11 @@ static int atomisp_subdev_probe(struct atomisp_device *isp) { const struct atomisp_platform_data *pdata; struct intel_v4l2_subdev_table *subdevs; - int ret, mipi_port, count; + int ret, mipi_port; + + ret = atomisp_csi2_bridge_parse_firmware(isp); + if (ret) + return ret; pdata = atomisp_get_platform_data(); if (!pdata) { @@ -790,23 +795,12 @@ static int atomisp_subdev_probe(struct atomisp_device *isp) return 0; } - /* FIXME: should return -EPROBE_DEFER if not all subdevs were probed */ - for (count = 0; count < SUBDEV_WAIT_TIMEOUT_MAX_COUNT; count++) { - int camera_count = 0; - - for (subdevs = pdata->subdevs; subdevs->type; ++subdevs) { - if (subdevs->type == RAW_CAMERA) - camera_count++; - } - if (camera_count) - break; - msleep(SUBDEV_WAIT_TIMEOUT); - } - /* Wait more time to give more time for subdev init code to finish */ - msleep(5 * SUBDEV_WAIT_TIMEOUT); - - /* FIXME: should, instead, use I2C probe */ - + /* + * TODO: this is left here for now to allow testing atomisp-sensor + * drivers which are still using the atomisp_gmin_platform infra before + * converting them to standard v4l2 sensor drivers using runtime-pm + + * ACPI for pm and v4l2_async_register_subdev_sensor() registration. + */ for (subdevs = pdata->subdevs; subdevs->type; ++subdevs) { ret = v4l2_device_register_subdev(&isp->v4l2_dev, subdevs->subdev); if (ret) @@ -937,7 +931,7 @@ v4l2_device_failed: return ret; } -static int atomisp_register_device_nodes(struct atomisp_device *isp) +int atomisp_register_device_nodes(struct atomisp_device *isp) { struct atomisp_input_subdev *input; int i, err; @@ -1429,9 +1423,11 @@ static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i isp->firmware = NULL; isp->css_env.isp_css_fw.data = NULL; - err = atomisp_register_device_nodes(isp); - if (err) + err = v4l2_async_nf_register(&isp->v4l2_dev, &isp->notifier); + if (err) { + dev_err(isp->dev, "failed to register async notifier : %d\n", err); goto css_init_fail; + } atomisp_drvfs_init(isp); diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.h b/drivers/staging/media/atomisp/pci/atomisp_v4l2.h index c8ee3ad83320..fad9573374b3 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.h +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.h @@ -30,5 +30,6 @@ int atomisp_video_init(struct atomisp_video_pipe *video); void atomisp_video_unregister(struct atomisp_video_pipe *video); const struct firmware *atomisp_load_firmware(struct atomisp_device *isp); int atomisp_csi_lane_config(struct atomisp_device *isp); +int atomisp_register_device_nodes(struct atomisp_device *isp); #endif /* __ATOMISP_V4L2_H__ */ From 947550f8c08ec68db637dbb27f80dbb922536a82 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 25 May 2023 20:00:57 +0100 Subject: [PATCH 185/253] media: atomisp: ov2680: Turn into standard v4l2 sensor driver Turn the atomisp-ov2680 driver into a standard v4l2 sensor driver: 1. Stop filling camera_mipi_info 2. Stop calling v4l2_get_acpi_sensor_info() this will be done by atomisp_csi2_bridge_parse_firmware() now 3. Switch to v4l2 async device registration After this change this driver no longer depends on atomisp_gmin_platform and all atomisp-isms are gone. While at it, also add missing mutex_destroy() to ov2680_remove(). Link: https://lore.kernel.org/r/20230525190100.130010-3-hdegoede@redhat.com Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-ov2680.c | 38 ++++++++----------- drivers/staging/media/atomisp/i2c/ov2680.h | 3 +- .../media/atomisp/pci/atomisp_csi2_bridge.c | 2 + 3 files changed, 18 insertions(+), 25 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index cdb3097b3259..6d49a12ea5a3 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -28,17 +28,8 @@ #include #include -#include "../include/linux/atomisp_gmin_platform.h" - #include "ov2680.h" -static enum atomisp_bayer_order ov2680_bayer_order_mapping[] = { - atomisp_bayer_order_bggr, - atomisp_bayer_order_grbg, - atomisp_bayer_order_gbrg, - atomisp_bayer_order_rggb, -}; - static int ov2680_write_reg_array(struct i2c_client *client, const struct ov2680_reg *reglist) { @@ -62,7 +53,6 @@ static void ov2680_set_bayer_order(struct ov2680_device *sensor, struct v4l2_mbu MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10, }; - struct camera_mipi_info *ov2680_info; int hv_flip = 0; if (sensor->ctrls.vflip->val) @@ -72,11 +62,6 @@ static void ov2680_set_bayer_order(struct ov2680_device *sensor, struct v4l2_mbu hv_flip += 2; fmt->code = ov2680_hv_flip_bayer_order[hv_flip]; - - /* TODO atomisp specific custom API, should be removed */ - ov2680_info = v4l2_get_subdev_hostdata(&sensor->sd); - if (ov2680_info) - ov2680_info->raw_bayer_order = ov2680_bayer_order_mapping[hv_flip]; } static int ov2680_set_vflip(struct ov2680_device *sensor, s32 val) @@ -609,10 +594,11 @@ static void ov2680_remove(struct i2c_client *client) dev_dbg(&client->dev, "ov2680_remove...\n"); - atomisp_unregister_subdev(sd); - v4l2_device_unregister_subdev(sd); + v4l2_async_unregister_subdev(&sensor->sd); media_entity_cleanup(&sensor->sd.entity); v4l2_ctrl_handler_free(&sensor->ctrls.handler); + mutex_destroy(&sensor->input_lock); + fwnode_handle_put(sensor->ep_fwnode); pm_runtime_disable(&client->dev); } @@ -631,13 +617,19 @@ static int ov2680_probe(struct i2c_client *client) sensor->client = client; v4l2_i2c_subdev_init(&sensor->sd, client, &ov2680_ops); - ret = v4l2_get_acpi_sensor_info(dev, NULL); - if (ret) - return ret; + /* + * Sometimes the fwnode graph is initialized by the bridge driver. + * Bridge drivers doing this may also add GPIO mappings, wait for this. + */ + sensor->ep_fwnode = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL); + if (!sensor->ep_fwnode) + return dev_err_probe(dev, -EPROBE_DEFER, "waiting for fwnode graph endpoint\n"); sensor->powerdown = devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH); - if (IS_ERR(sensor->powerdown)) + if (IS_ERR(sensor->powerdown)) { + fwnode_handle_put(sensor->ep_fwnode); return dev_err_probe(dev, PTR_ERR(sensor->powerdown), "getting powerdown GPIO\n"); + } pm_runtime_set_suspended(dev); pm_runtime_enable(dev); @@ -653,6 +645,7 @@ static int ov2680_probe(struct i2c_client *client) sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; sensor->pad.flags = MEDIA_PAD_FL_SOURCE; sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + sensor->sd.fwnode = sensor->ep_fwnode; ret = ov2680_init_controls(sensor); if (ret) { @@ -668,8 +661,7 @@ static int ov2680_probe(struct i2c_client *client) ov2680_fill_format(sensor, &sensor->mode.fmt, OV2680_NATIVE_WIDTH, OV2680_NATIVE_HEIGHT); - ret = atomisp_register_sensor_no_gmin(&sensor->sd, 1, ATOMISP_INPUT_FORMAT_RAW_10, - atomisp_bayer_order_bggr); + ret = v4l2_async_register_subdev_sensor(&sensor->sd); if (ret) { ov2680_remove(client); return ret; diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index baf49eb0659e..a3eeb0c2de5c 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -30,8 +30,6 @@ #include #include -#include "../include/linux/atomisp_platform.h" - #define OV2680_NATIVE_WIDTH 1616 #define OV2680_NATIVE_HEIGHT 1216 @@ -114,6 +112,7 @@ struct ov2680_device { struct mutex input_lock; struct i2c_client *client; struct gpio_desc *powerdown; + struct fwnode_handle *ep_fwnode; bool is_streaming; struct ov2680_mode { diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c index e07562d6a63e..d1789f171228 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c @@ -89,6 +89,8 @@ static const guid_t atomisp_dsm_guid = * power-management and with v4l2-async probing. */ static const struct atomisp_csi2_sensor_config supported_sensors[] = { + /* Omnivision OV2680 */ + { "OVTI2680", 1 }, }; /* From 1aace3da2847a003a3dcadada2820dbb9b4291ec Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 25 May 2023 20:00:58 +0100 Subject: [PATCH 186/253] media: atomisp: gc0310: Turn into standard v4l2 sensor driver Switch the atomisp-gc0310 driver to v4l2 async device registration. After this change this driver no longer depends on atomisp_gmin_platform and all atomisp-isms are gone. Link: https://lore.kernel.org/r/20230525190100.130010-4-hdegoede@redhat.com Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-gc0310.c | 29 ++++++++++++------- .../media/atomisp/pci/atomisp_csi2_bridge.c | 2 ++ 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c index 1829ba419e3e..9a11793f34f7 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc0310.c @@ -29,8 +29,6 @@ #include #include -#include "../include/linux/atomisp_gmin_platform.h" - #define GC0310_NATIVE_WIDTH 656 #define GC0310_NATIVE_HEIGHT 496 @@ -85,6 +83,7 @@ struct gc0310_device { struct mutex input_lock; bool is_streaming; + struct fwnode_handle *ep_fwnode; struct gpio_desc *reset; struct gpio_desc *powerdown; @@ -596,11 +595,11 @@ static void gc0310_remove(struct i2c_client *client) dev_dbg(&client->dev, "gc0310_remove...\n"); - atomisp_unregister_subdev(sd); - v4l2_device_unregister_subdev(sd); + v4l2_async_unregister_subdev(sd); media_entity_cleanup(&dev->sd.entity); v4l2_ctrl_handler_free(&dev->ctrls.handler); mutex_destroy(&dev->input_lock); + fwnode_handle_put(dev->ep_fwnode); pm_runtime_disable(&client->dev); } @@ -613,19 +612,27 @@ static int gc0310_probe(struct i2c_client *client) if (!dev) return -ENOMEM; - ret = v4l2_get_acpi_sensor_info(&client->dev, NULL); - if (ret) - return ret; + /* + * Sometimes the fwnode graph is initialized by the bridge driver. + * Bridge drivers doing this may also add GPIO mappings, wait for this. + */ + dev->ep_fwnode = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL); + if (!dev->ep_fwnode) + return dev_err_probe(&client->dev, -EPROBE_DEFER, "waiting for fwnode graph endpoint\n"); dev->reset = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH); - if (IS_ERR(dev->reset)) + if (IS_ERR(dev->reset)) { + fwnode_handle_put(dev->ep_fwnode); return dev_err_probe(&client->dev, PTR_ERR(dev->reset), "getting reset GPIO\n"); + } dev->powerdown = devm_gpiod_get(&client->dev, "powerdown", GPIOD_OUT_HIGH); - if (IS_ERR(dev->powerdown)) + if (IS_ERR(dev->powerdown)) { + fwnode_handle_put(dev->ep_fwnode); return dev_err_probe(&client->dev, PTR_ERR(dev->powerdown), "getting powerdown GPIO\n"); + } mutex_init(&dev->input_lock); v4l2_i2c_subdev_init(&dev->sd, client, &gc0310_ops); @@ -645,6 +652,7 @@ static int gc0310_probe(struct i2c_client *client) dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; dev->pad.flags = MEDIA_PAD_FL_SOURCE; dev->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + dev->sd.fwnode = dev->ep_fwnode; ret = gc0310_init_controls(dev); if (ret) { @@ -658,8 +666,7 @@ static int gc0310_probe(struct i2c_client *client) return ret; } - ret = atomisp_register_sensor_no_gmin(&dev->sd, 1, ATOMISP_INPUT_FORMAT_RAW_8, - atomisp_bayer_order_grbg); + ret = v4l2_async_register_subdev_sensor(&dev->sd); if (ret) { gc0310_remove(client); return ret; diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c index d1789f171228..b55a7ff9844e 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c @@ -89,6 +89,8 @@ static const guid_t atomisp_dsm_guid = * power-management and with v4l2-async probing. */ static const struct atomisp_csi2_sensor_config supported_sensors[] = { + /* GalaxyCore GC0310 */ + { "INT0310", 1 }, /* Omnivision OV2680 */ { "OVTI2680", 1 }, }; From d80be6a10cd3855004dc0ba3716fb1c76471dea1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 25 May 2023 20:00:59 +0100 Subject: [PATCH 187/253] media: atomisp: Drop v4l2_get_acpi_sensor_info() function Drop v4l2_get_acpi_sensor_info() the 2 sensor drivers which were using this have both been converted to v4l2-async probing, relying on the atomisp_csi2_bridge.c code to add the GPIO mappings instead. Link: https://lore.kernel.org/r/20230525190100.130010-5-hdegoede@redhat.com Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/atomisp_gmin_platform.c | 240 ------------------ 1 file changed, 240 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c index 10b7871017d5..bc2dd96176d0 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c +++ b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c @@ -1460,243 +1460,3 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0f38, isp_pm_cap_fixup); MODULE_DESCRIPTION("Ancillary routines for binding ACPI devices"); MODULE_LICENSE("GPL"); - -/* - * The below helper functions don't really belong here and should eventually be - * moved to some place under drivers/media/v4l2-core. - */ -#include - -/* - * 79234640-9e10-4fea-a5c1-b5aa8b19756f - * This _DSM GUID returns information about the GPIO lines mapped to a sensor. - * Function number 1 returns a count of the GPIO lines that are mapped. - * Subsequent functions return 32 bit ints encoding information about the GPIO. - */ -static const guid_t intel_sensor_gpio_info_guid = - GUID_INIT(0x79234640, 0x9e10, 0x4fea, - 0xa5, 0xc1, 0xb5, 0xaa, 0x8b, 0x19, 0x75, 0x6f); - -/* - * 822ace8f-2814-4174-a56b-5f029fe079ee - * This _DSM GUID returns a string from the sensor device, which acts as a - * module identifier. - */ -static const guid_t intel_sensor_module_guid = - GUID_INIT(0x822ace8f, 0x2814, 0x4174, - 0xa5, 0x6b, 0x5f, 0x02, 0x9f, 0xe0, 0x79, 0xee); - -#define INTEL_DSM_TYPE_SHIFT 0 -#define INTEL_DSM_TYPE_MASK GENMASK(7, 0) -#define INTEL_DSM_PIN_SHIFT 8 -#define INTEL_DSM_PIN_MASK GENMASK(15, 8) -#define INTEL_DSM_SENSOR_ON_VAL_SHIFT 24 -#define INTEL_DSM_SENSOR_ON_VAL_MASK GENMASK(31, 24) - -#define INTEL_DSM_TYPE(x) \ - (((x) & INTEL_DSM_TYPE_MASK) >> INTEL_DSM_TYPE_SHIFT) -#define INTEL_DSM_PIN(x) \ - (((x) & INTEL_DSM_PIN_MASK) >> INTEL_DSM_PIN_SHIFT) -#define INTEL_DSM_SENSOR_ON_VAL(x) \ - (((x) & INTEL_DSM_SENSOR_ON_VAL_MASK) >> INTEL_DSM_SENSOR_ON_VAL_SHIFT) - -#define V4L2_SENSOR_MAX_ACPI_GPIOS 2u - -struct v4l2_acpi_gpio_map { - struct acpi_gpio_params params[V4L2_SENSOR_MAX_ACPI_GPIOS]; - struct acpi_gpio_mapping mapping[V4L2_SENSOR_MAX_ACPI_GPIOS + 1]; -}; - -struct v4l2_acpi_gpio_parsing_data { - struct device *dev; - u32 settings[V4L2_SENSOR_MAX_ACPI_GPIOS]; - unsigned int settings_count; - unsigned int res_count; - unsigned int map_count; - struct v4l2_acpi_gpio_map *map; -}; - -/* Note this always returns 1 to continue looping so that res_count is accurate */ -static int v4l2_acpi_handle_gpio_res(struct acpi_resource *ares, void *_data) -{ - struct v4l2_acpi_gpio_parsing_data *data = _data; - struct acpi_resource_gpio *agpio; - const char *name; - bool active_low; - unsigned int i; - u32 settings = 0; - u8 pin; - - if (!acpi_gpio_get_io_resource(ares, &agpio)) - return 1; /* Not a GPIO, continue the loop */ - - data->res_count++; - - pin = agpio->pin_table[0]; - for (i = 0; i < data->settings_count; i++) { - if (INTEL_DSM_PIN(data->settings[i]) == pin) { - settings = data->settings[i]; - break; - } - } - - if (i == data->settings_count) { - dev_warn(data->dev, "Could not find DSM GPIO settings for pin %d\n", pin); - return 1; - } - - switch (INTEL_DSM_TYPE(settings)) { - case 0: - name = "reset-gpios"; - break; - case 1: - name = "powerdown-gpios"; - break; - default: - dev_warn(data->dev, "Unknown GPIO type 0x%02lx for pin %d\n", - INTEL_DSM_TYPE(settings), pin); - return 1; - } - - /* - * Both reset and power-down need to be logical false when the sensor - * is on (sensor should not be in reset and not be powered-down). So - * when the sensor-on-value (which is the physical pin value) is high, - * then the signal is active-low. - */ - active_low = INTEL_DSM_SENSOR_ON_VAL(settings) ? true : false; - - i = data->map_count; - if (i == V4L2_SENSOR_MAX_ACPI_GPIOS) - return 1; - - /* res_count is already incremented */ - data->map->params[i].crs_entry_index = data->res_count - 1; - data->map->params[i].active_low = active_low; - data->map->mapping[i].name = name; - data->map->mapping[i].data = &data->map->params[i]; - data->map->mapping[i].size = 1; - data->map_count++; - - dev_info(data->dev, "%s crs %d %s pin %d active-%s\n", name, - data->res_count - 1, agpio->resource_source.string_ptr, - pin, active_low ? "low" : "high"); - - return 1; -} - -/* - * Helper function to create an ACPI GPIO lookup table for sensor reset and - * powerdown signals on Intel Bay Trail (BYT) and Cherry Trail (CHT) devices, - * including setting the correct polarity for the GPIO. - * - * This uses the "79234640-9e10-4fea-a5c1-b5aa8b19756f" DSM method directly - * on the sensor device's ACPI node. This is different from later Intel - * hardware which has a separate INT3472 with this info. Since there is - * no separate firmware-node to which we can bind to register the GPIO lookups - * this unfortunately means that all sensor drivers which may be used on - * BYT or CHT hw need to call this function. This also means that this function - * may only fail when it is actually called on BYT/CHT hw. In all other cases - * it must always succeed. - * - * Note this code uses the same DSM GUID as the INT3472 discrete.c code - * and there is some overlap, but there are enough differences that it is - * difficult to share the code. - */ -int v4l2_get_acpi_sensor_info(struct device *dev, char **module_id_str) -{ - struct acpi_device *adev = ACPI_COMPANION(dev); - struct v4l2_acpi_gpio_parsing_data data = { }; - LIST_HEAD(resource_list); - union acpi_object *obj; - unsigned int i, j; - int ret; - - if (module_id_str) - *module_id_str = NULL; - - if (!adev) - return 0; - - obj = acpi_evaluate_dsm_typed(adev->handle, &intel_sensor_module_guid, - 0x00, 0x01, NULL, ACPI_TYPE_STRING); - if (obj) { - dev_info(dev, "Sensor module id: '%s'\n", obj->string.pointer); - if (module_id_str) - *module_id_str = kstrdup(obj->string.pointer, GFP_KERNEL); - - ACPI_FREE(obj); - } - - if (!soc_intel_is_byt() && !soc_intel_is_cht()) - return 0; - - /* - * First get the GPIO-settings count and then get count GPIO-settings - * values. Note the order of these may differ from the order in which - * the GPIOs are listed on the ACPI resources! So we first store them all - * and then enumerate the ACPI resources and match them up by pin number. - */ - obj = acpi_evaluate_dsm_typed(adev->handle, - &intel_sensor_gpio_info_guid, 0x00, 1, - NULL, ACPI_TYPE_INTEGER); - if (!obj) - return dev_err_probe(dev, -EIO, "No _DSM entry for GPIO pin count\n"); - - data.settings_count = obj->integer.value; - ACPI_FREE(obj); - - if (data.settings_count > V4L2_SENSOR_MAX_ACPI_GPIOS) - return dev_err_probe(dev, -EIO, "Too many GPIOs %u > %u\n", - data.settings_count, V4L2_SENSOR_MAX_ACPI_GPIOS); - - for (i = 0; i < data.settings_count; i++) { - /* - * i + 2 because the index of this _DSM function is 1-based - * and the first function is just a count. - */ - obj = acpi_evaluate_dsm_typed(adev->handle, - &intel_sensor_gpio_info_guid, - 0x00, i + 2, - NULL, ACPI_TYPE_INTEGER); - if (!obj) - return dev_err_probe(dev, -EIO, "No _DSM entry for GPIO pin %u\n", i); - - data.settings[i] = obj->integer.value; - ACPI_FREE(obj); - } - - /* Since we match up by pin-number the pin-numbers must be unique */ - for (i = 0; i < data.settings_count; i++) { - for (j = i + 1; j < data.settings_count; j++) { - if (INTEL_DSM_PIN(data.settings[i]) != - INTEL_DSM_PIN(data.settings[j])) - continue; - - return dev_err_probe(dev, -EIO, "Duplicate pin number %lu\n", - INTEL_DSM_PIN(data.settings[i])); - } - } - - /* Use devm_kzalloc() for the mappings + params to auto-free them */ - data.map = devm_kzalloc(dev, sizeof(*data.map), GFP_KERNEL); - if (!data.map) - return -ENOMEM; - - /* Now parse the ACPI resources and build the lookup table */ - data.dev = dev; - ret = acpi_dev_get_resources(adev, &resource_list, - v4l2_acpi_handle_gpio_res, &data); - if (ret < 0) - return ret; - - acpi_dev_free_resource_list(&resource_list); - - if (data.map_count != data.settings_count || - data.res_count != data.settings_count) - dev_warn(dev, "ACPI GPIO resources vs DSM GPIO-info count mismatch (dsm: %d res: %d map %d\n", - data.settings_count, data.res_count, data.map_count); - - return devm_acpi_dev_add_driver_gpios(dev, data.map->mapping); -} -EXPORT_SYMBOL_GPL(v4l2_get_acpi_sensor_info); From 1657f2934daf89e8d9fa4b2697008909eb22c73e Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 26 May 2023 12:53:23 +0100 Subject: [PATCH 188/253] media: atomisp: gmin_platform: fix out_len in gmin_get_config_dsm_var() Ideally, strlen(cur->string.pointer) and strlen(out) would be the same. But this code is using strscpy() to avoid a potential buffer overflow. So in the same way we should take the strlen() of the smaller string to avoid a buffer overflow in the caller, gmin_get_var_int(). Link: https://lore.kernel.org/r/26124bcd-8132-4483-9d67-225c87d424e8@kili.mountain Fixes: 387041cda44e ("media: atomisp: improve sensor detection code to use _DSM table") Signed-off-by: Dan Carpenter Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c index bc2dd96176d0..93bfb3fadcf7 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c +++ b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c @@ -1359,7 +1359,7 @@ static int gmin_get_config_dsm_var(struct device *dev, dev_info(dev, "found _DSM entry for '%s': %s\n", var, cur->string.pointer); strscpy(out, cur->string.pointer, *out_len); - *out_len = strlen(cur->string.pointer); + *out_len = strlen(out); ACPI_FREE(obj); return 0; From fadac6afccf7d8a4efa1e0ca89958f6716685333 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 27 May 2023 16:38:12 +0100 Subject: [PATCH 189/253] media: atomisp: Fix buffer overrun in gmin_get_var_int() Not all functions used in gmin_get_var_int() update len to the actual length of the returned string. So len may still have its initial value of the length of val[] when "val[len] = 0;" is run to ensure 0 termination. If this happens we end up writing one beyond the bounds of val[], fix this. Note this is a quick fix for this since the entirety of atomisp_gmin_platform.c will be removed once all atomisp sensor drivers have been moved over to runtime-pm + v4l2-async device registration. Closes: https://lore.kernel.org/linux-media/26f37e19-c240-4d77-831d-ef3f1a4dd51d@kili.mountain/ Reported-by: Dan Carpenter Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c index 93bfb3fadcf7..139ad7ad1dcf 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c +++ b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c @@ -1429,8 +1429,8 @@ static int gmin_get_config_var(struct device *maindev, int gmin_get_var_int(struct device *dev, bool is_gmin, const char *var, int def) { - char val[CFG_VAR_NAME_MAX]; - size_t len = sizeof(val); + char val[CFG_VAR_NAME_MAX + 1]; + size_t len = CFG_VAR_NAME_MAX; long result; int ret; From 36f48c705242bd21a295992c3b0bd2ebbcdef1df Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:21 +0100 Subject: [PATCH 190/253] media: atomisp: Update TODO A lot of work has been done on the atomisp driver lately. Rewrite the TODO file to drop all the already fixed items: * Moved to videobuf2 + fixed mmap support * Whole bunch of v4l2 API fixes making more apps work * v4l2-async sensor probing support * pm-runtime support (for some sensor drivers at least) * buffer MM code was cleaned up / replaced when moving the videobuf2 And add a new TODO list (retaining some of the old items) split into items which absolutely must be fixed before the driver can be moved out of staging: 1. Conflicting hw-ids with regular sensor drivers 2. Private userspace API stuff As well as a list of items which also definitely needs to be fixed but which could also be fixed after moving the driver out of staging. Link: https://lore.kernel.org/r/20230529103741.11904-2-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/TODO | 240 +++++++---------------------- 1 file changed, 55 insertions(+), 185 deletions(-) diff --git a/drivers/staging/media/atomisp/TODO b/drivers/staging/media/atomisp/TODO index 43b842043f29..12fe1f21b169 100644 --- a/drivers/staging/media/atomisp/TODO +++ b/drivers/staging/media/atomisp/TODO @@ -1,213 +1,83 @@ -For both Cherrytrail (CHT) and Baytrail (BHT) the driver -requires the "candrpv_0415_20150521_0458" firmware version. -It should be noticed that the firmware file is different, -depending on the ISP model, so they're stored with different -names: +Required firmware +================= -- for BHT: /lib/firmware/shisp_2400b0_v21.bin +The atomisp driver requires the following firmware: - Warning: The driver was not tested yet for BHT. +- for BYT: /lib/firmware/shisp_2400b0_v21.bin + + With a version of "irci_stable_candrpv_0415_20150423_1753" to check + the version run: "strings shisp_2400b0_v21.bin | head -n1", sha256sum: + + 3847b95fb9f1f8352c595ba7394d55b33176751372baae17f89aa483ec02a21b shisp_2400b0_v21.bin + + The shisp_2400b0_v21.bin file with this version can be found on + the Android factory images of various X86 Android tablets such as + e.g. the Chuwi Hi8 Pro. - for CHT: /lib/firmware/shisp_2401a0_v21.bin + With a version of "irci_stable_candrpv_0415_20150521_0458", sha256sum: + + e89359f4e4934c410c83d525e283f34c5fcce9cb5caa75ad8a32d66d3842d95c shisp_2401a0_v21.bin + + This can be found here: https://github.com/intel-aero/meta-intel-aero-base/blob/master/recipes-kernel/linux/linux-yocto/shisp_2401a0_v21.bin -NOTE: -===== - -This driver currently doesn't work with most V4L2 applications, -as there are still some issues with regards to implementing -certain APIs at the standard way. - -Also, currently only USERPTR streaming mode is working. - -In order to test, it is needed to know what's the sensor's -resolution. This can be checked with: - -$ v4l2-ctl --get-fmt-video - Format Video Capture: - Width/Height : 1600/1200 - ... - -It is known to work with: - -- v4l2grab at contrib/test directory at https://git.linuxtv.org/v4l-utils.git/ - - The resolution should not be bigger than the max resolution - supported by the sensor, or it will fail. So, if the sensor - reports: - - The driver can be tested with: - - v4l2grab -f YUYV -x 1600 -y 1200 -d /dev/video2 -u - -- NVT at https://github.com/intel/nvt - - $ ./v4l2n -o testimage_@.raw \ - --device /dev/video2 \ - --input 0 \ - --exposure=30000,30000,30000,30000 \ - --parm type=1,capturemode=CI_MODE_PREVIEW \ - --fmt type=1,width=1600,height=1200,pixelformat=YUYV \ - --reqbufs count=2,memory=USERPTR \ - --parameters=wb_config.r=32768,wb_config.gr=21043,wb_config.gb=21043,wb_config.b=30863 \ - --capture=20 - - As the output is in raw format, images need to be converted with: - - $ for i in $(seq 0 19); do - name="testimage_$(printf "%03i" $i)" - ./raw2pnm -x$WIDTH -y$HEIGHT -f$FORMAT $name.raw $name.pnm - rm $name.raw - done TODO ==== -1. Fix support for MMAP streaming mode. This is required for most - V4L2 applications; +1. Items which MUST be fixed before the driver can be moved out of staging: -2. Implement and/or fix V4L2 ioctls in order to allow a normal app to - use it; +* The atomisp ov2680 and ov5693 sensor drivers bind to the same hw-ids as + the standard ov2680 and ov5693 drivers under drivers/media/i2c, which + conflicts. Drop the atomisp private ov2680 and ov5693 drivers: + * Make atomisp code use v4l2 selections to deal with the extra padding + it wants to receive from sensors instead of relying on the ov2680 code + sending e.g. 1616x1216 for a 1600x1200 mode + * Port various ov2680 improvements from atomisp_ov2680.c to regular ov2680.c + and switch to regular ov2680 driver + * Make atomisp work with the regular ov5693 driver and drop atomisp_ov5693 -3. Ensure that the driver will pass v4l2-compliance tests; +* Fix atomisp causing the whole machine to hang in its probe() error-exit + path taken in the firmware missing case -4. Get manufacturer's authorization to redistribute the binaries for - the firmware files; +* Remove/disable private IOCTLs -5. remove VIDEO_ATOMISP_ISP2401, making the driver to auto-detect the - register address differences between ISP2400 and ISP2401; +* Remove/disable custom v4l2-ctrls -6. Cleanup the driver code, removing the abstraction layers inside it; +* Remove custom sysfs files created by atomisp_drvfs.c -7. The atomisp doesn't rely at the usual i2c stuff to discover the - sensors. Instead, it calls a function from atomisp_gmin_platform.c. - There are some hacks added there for it to wait for sensors to be - probed (with a timeout of 2 seconds or so). This should be converted - to the usual way, using V4L2 async subdev framework to wait for - cameras to be probed; +* Remove abuse of priv field in various v4l2 userspace API structs -8. Switch to standard V4L2 sub-device API for sensor and lens. In - particular, the user space API needs to support V4L2 controls as - defined in the V4L2 spec and references to atomisp must be removed from - these drivers. +* Without a 3A library the capture behaviour is not very good. To take a good + picture, the exposure/gain needs to be tuned using v4l2-ctl on the sensor + subdev. To fix this, support for the atomisp needs to be added to libcamera. -9. Use LED flash API for flash LED drivers such as LM3554 (which already - has a LED class driver). - -10. Migrate the sensor drivers out of staging or re-using existing - drivers; - -11. Switch the driver to use pm_runtime stuff. Right now, it probes the - existing PMIC code and sensors call it directly. - -12. There's a problem on sensor drivers: when trying to set a video - format, the atomisp main driver calls the sensor drivers with the - sensor turned off. This causes them to fail. - - This was fixed at atomisp-ov2880, which has a hack inside it - to turn it on when VIDIOC_S_FMT is called, but this has to be - cheked on other drivers as well. - - The right fix seems to power on the sensor when a video device is - opened (or at the first VIDIOC_ ioctl - except for VIDIOC_QUERYCAP), - powering it down at close() syscall. - - Such kind of control would need to be done inside the atomisp driver, - not at the sensors code. - -13. There are several issues related to memory management, that can - cause crashes and/or memory leaks. The atomisp splits the memory - management on three separate regions: - - - dynamic pool; - - reserved pool; - - generic pool - - The code implementing it is at: - - drivers/staging/media/atomisp/pci/hmm/ - - It also has a separate code for managing DMA buffers at: - - drivers/staging/media/atomisp/pci/mmu/ - - The code there is really dirty, ugly and probably wrong. I fixed - one bug there already, but the best would be to just trash it and use - something else. Maybe the code from the newer intel driver could - serve as a model: - - drivers/staging/media/ipu3/ipu3-mmu.c - - But converting it to use something like that is painful and may - cause some breakages. - -14. The file structure needs to get tidied up to resemble a normal Linux - driver. - -15. Lots of the midlayer glue. Unused code and abstraction needs removing. - -16. The AtomISP driver includes some special IOCTLS (ATOMISP_IOC_XXXX_XXXX) - and controls that require some cleanup. Some of those code may have - been removed during the cleanups. They could be needed in order to - properly support 3A algorithms. - - Such IOCTL interface needs more documentation. The better would - be to use something close to the interface used by the IPU3 IMGU driver. - -17. The ISP code has some dependencies of the exact FW version. - The version defined in pci/sh_css_firmware.c: - - BYT (isp2400): "irci_stable_candrpv_0415_20150521_0458" - - CHT (isp2401): "irci_ecr - master_20150911_0724" - - Those versions don't seem to be available anymore. On the tests we've - done so far, this version also seems to work for CHT: - - "irci_stable_candrpv_0415_20150521_0458" - - Which can be obtainable from Yocto Atom ISP respository. - - but this was not thoroughly tested. - - At some point we may need to round up a few driver versions and see if - there are any specific things that can be done to fold in support for - multiple firmware versions. + This MUST be done before moving the driver out of staging so that we can + still make changes to e.g. the mediactl topology if necessary for + libcamera integration. Since this would be a userspace API break, this + means that at least proof-of-concept libcamera integration needs to be + ready before moving the driver out of staging. -18. Switch from videobuf1 to videobuf2. Videobuf1 is being removed! +2. Items which SHOULD also be fixed eventually: -19. Correct Coding Style. Please refrain sending coding style patches - for this driver until the other work is done, as there will be a lot - of code churn until this driver becomes functional again. +* Remove VIDEO_ATOMISP_ISP2401, making the driver to auto-detect the + register address differences between ISP2400 and ISP2401 -20. Remove the logic which sets up pipelines inside it, moving it to - libcamera and implement MC support. +* The driver is intended to drive the PCI exposed versions of the device. + It will not detect those devices enumerated via ACPI as a field of the + i915 GPU driver (only a problem on BYT). + There are some patches adding i915 GPU support floating at the Yocto's + Aero repository (so far, untested upstream). -Limitations -=========== +* Ensure that the driver will pass v4l2-compliance tests -1. To test the patches, you also need the ISP firmware +* Fix not all v4l2 apps working, e.g. cheese does not work - for BYT: /lib/firmware/shisp_2400b0_v21.bin - for CHT: /lib/firmware/shisp_2401a0_v21.bin +* Get manufacturer's authorization to redistribute the binaries for + the firmware files - The firmware files will usually be found in /etc/firmware on an Android - device but can also be extracted from the upgrade kit if you've managed - to lose them somehow. - -2. Without a 3A library the capture behaviour is not very good. To take a good - picture, you need tune ISP parameters by IOCTL functions or use a 3A library - such as libxcam. - -3. The driver is intended to drive the PCI exposed versions of the device. - It will not detect those devices enumerated via ACPI as a field of the - i915 GPU driver. - - There are some patches adding i915 GPU support floating at the Yocto's - Aero repository (so far, untested upstream). - -4. The driver supports only v2 of the IPU/Camera. It will not work with the - versions of the hardware in other SoCs. +* The atomisp code still has a lot of cruft which needs cleaning up From 19cdcf676355a93a139113d3008112c895915cfc Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:22 +0100 Subject: [PATCH 191/253] media: atomisp: ov2680: s/ov2680_device/ov2680_dev/ s/ov2680_device/ov2680_dev/ ov2680_dev is used by the generic drivers/media/i2c/ov2680.c driver. Bring the atomisp ov2680 code inline to make it easier to port changes between the two, with the end goal of getting rid of the atomisp specific version. Link: https://lore.kernel.org/r/20230529103741.11904-3-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-ov2680.c | 38 +++++++++---------- drivers/staging/media/atomisp/i2c/ov2680.h | 8 ++-- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index 6d49a12ea5a3..2e9a4792a7b2 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -45,7 +45,7 @@ static int ov2680_write_reg_array(struct i2c_client *client, return 0; } -static void ov2680_set_bayer_order(struct ov2680_device *sensor, struct v4l2_mbus_framefmt *fmt) +static void ov2680_set_bayer_order(struct ov2680_dev *sensor, struct v4l2_mbus_framefmt *fmt) { static const int ov2680_hv_flip_bayer_order[] = { MEDIA_BUS_FMT_SBGGR10_1X10, @@ -64,7 +64,7 @@ static void ov2680_set_bayer_order(struct ov2680_device *sensor, struct v4l2_mbu fmt->code = ov2680_hv_flip_bayer_order[hv_flip]; } -static int ov2680_set_vflip(struct ov2680_device *sensor, s32 val) +static int ov2680_set_vflip(struct ov2680_dev *sensor, s32 val) { int ret; @@ -79,7 +79,7 @@ static int ov2680_set_vflip(struct ov2680_device *sensor, s32 val) return 0; } -static int ov2680_set_hflip(struct ov2680_device *sensor, s32 val) +static int ov2680_set_hflip(struct ov2680_dev *sensor, s32 val) { int ret; @@ -94,17 +94,17 @@ static int ov2680_set_hflip(struct ov2680_device *sensor, s32 val) return 0; } -static int ov2680_exposure_set(struct ov2680_device *sensor, u32 exp) +static int ov2680_exposure_set(struct ov2680_dev *sensor, u32 exp) { return ov_write_reg24(sensor->client, OV2680_REG_EXPOSURE_PK_HIGH, exp << 4); } -static int ov2680_gain_set(struct ov2680_device *sensor, u32 gain) +static int ov2680_gain_set(struct ov2680_dev *sensor, u32 gain) { return ov_write_reg16(sensor->client, OV2680_REG_GAIN_PK, gain); } -static int ov2680_test_pattern_set(struct ov2680_device *sensor, int value) +static int ov2680_test_pattern_set(struct ov2680_dev *sensor, int value) { int ret; @@ -125,7 +125,7 @@ static int ov2680_test_pattern_set(struct ov2680_device *sensor, int value) static int ov2680_s_ctrl(struct v4l2_ctrl *ctrl) { struct v4l2_subdev *sd = ctrl_to_sd(ctrl); - struct ov2680_device *sensor = to_ov2680_sensor(sd); + struct ov2680_dev *sensor = to_ov2680_sensor(sd); int ret; /* Only apply changes to the controls if the device is powered up */ @@ -174,7 +174,7 @@ static int ov2680_init_registers(struct v4l2_subdev *sd) } static struct v4l2_mbus_framefmt * -__ov2680_get_pad_format(struct ov2680_device *sensor, +__ov2680_get_pad_format(struct ov2680_dev *sensor, struct v4l2_subdev_state *state, unsigned int pad, enum v4l2_subdev_format_whence which) { @@ -184,7 +184,7 @@ __ov2680_get_pad_format(struct ov2680_device *sensor, return &sensor->mode.fmt; } -static void ov2680_fill_format(struct ov2680_device *sensor, +static void ov2680_fill_format(struct ov2680_dev *sensor, struct v4l2_mbus_framefmt *fmt, unsigned int width, unsigned int height) { @@ -195,7 +195,7 @@ static void ov2680_fill_format(struct ov2680_device *sensor, ov2680_set_bayer_order(sensor, fmt); } -static void ov2680_calc_mode(struct ov2680_device *sensor, int width, int height) +static void ov2680_calc_mode(struct ov2680_dev *sensor, int width, int height) { int orig_width = width; int orig_height = height; @@ -221,7 +221,7 @@ static void ov2680_calc_mode(struct ov2680_device *sensor, int width, int height sensor->mode.vts = OV2680_LINES_PER_FRAME; } -static int ov2680_set_mode(struct ov2680_device *sensor) +static int ov2680_set_mode(struct ov2680_dev *sensor) { struct i2c_client *client = sensor->client; u8 pll_div, unknown, inc, fmt1, fmt2; @@ -322,7 +322,7 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *format) { - struct ov2680_device *sensor = to_ov2680_sensor(sd); + struct ov2680_dev *sensor = to_ov2680_sensor(sd); struct v4l2_mbus_framefmt *fmt; unsigned int width, height; @@ -347,7 +347,7 @@ static int ov2680_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *format) { - struct ov2680_device *sensor = to_ov2680_sensor(sd); + struct ov2680_dev *sensor = to_ov2680_sensor(sd); struct v4l2_mbus_framefmt *fmt; fmt = __ov2680_get_pad_format(sensor, sd_state, format->pad, format->which); @@ -390,7 +390,7 @@ static int ov2680_detect(struct i2c_client *client) static int ov2680_s_stream(struct v4l2_subdev *sd, int enable) { - struct ov2680_device *sensor = to_ov2680_sensor(sd); + struct ov2680_dev *sensor = to_ov2680_sensor(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; @@ -548,7 +548,7 @@ static const struct v4l2_subdev_ops ov2680_ops = { .sensor = &ov2680_sensor_ops, }; -static int ov2680_init_controls(struct ov2680_device *sensor) +static int ov2680_init_controls(struct ov2680_dev *sensor) { static const char * const test_pattern_menu[] = { "Disabled", @@ -590,7 +590,7 @@ static int ov2680_init_controls(struct ov2680_device *sensor) static void ov2680_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct ov2680_device *sensor = to_ov2680_sensor(sd); + struct ov2680_dev *sensor = to_ov2680_sensor(sd); dev_dbg(&client->dev, "ov2680_remove...\n"); @@ -605,7 +605,7 @@ static void ov2680_remove(struct i2c_client *client) static int ov2680_probe(struct i2c_client *client) { struct device *dev = &client->dev; - struct ov2680_device *sensor; + struct ov2680_dev *sensor; int ret; sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL); @@ -673,7 +673,7 @@ static int ov2680_probe(struct i2c_client *client) static int ov2680_suspend(struct device *dev) { struct v4l2_subdev *sd = dev_get_drvdata(dev); - struct ov2680_device *sensor = to_ov2680_sensor(sd); + struct ov2680_dev *sensor = to_ov2680_sensor(sd); gpiod_set_value_cansleep(sensor->powerdown, 1); return 0; @@ -682,7 +682,7 @@ static int ov2680_suspend(struct device *dev) static int ov2680_resume(struct device *dev) { struct v4l2_subdev *sd = dev_get_drvdata(dev); - struct ov2680_device *sensor = to_ov2680_sensor(sd); + struct ov2680_dev *sensor = to_ov2680_sensor(sd); /* according to DS, at least 5ms is needed after DOVDD (enabled by ACPI) */ usleep_range(5000, 6000); diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index a3eeb0c2de5c..077ca6ee08b6 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -106,7 +106,7 @@ /* * ov2680 device structure. */ -struct ov2680_device { +struct ov2680_dev { struct v4l2_subdev sd; struct media_pad pad; struct mutex input_lock; @@ -151,12 +151,12 @@ struct ov2680_reg { u32 val; /* @set value for read/mod/write, @mask */ }; -#define to_ov2680_sensor(x) container_of(x, struct ov2680_device, sd) +#define to_ov2680_sensor(x) container_of(x, struct ov2680_dev, sd) static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl) { - struct ov2680_device *sensor = - container_of(ctrl->handler, struct ov2680_device, ctrls.handler); + struct ov2680_dev *sensor = + container_of(ctrl->handler, struct ov2680_dev, ctrls.handler); return &sensor->sd; } From b0e880e4a85b87b68a76391cdfd1046f024386ef Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:23 +0100 Subject: [PATCH 192/253] media: atomisp: ov2680: s/input_lock/lock/ s/input_lock/lock/ lock is used by the generic drivers/media/i2c/ov2680.c driver. Bring the atomisp ov2680 code inline to make it easier to port changes between the two, with the end goal of getting rid of the atomisp specific version. Link: https://lore.kernel.org/r/20230529103741.11904-4-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/i2c/atomisp-ov2680.c | 16 ++++++++-------- drivers/staging/media/atomisp/i2c/ov2680.h | 3 ++- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index 2e9a4792a7b2..cf3f9649928a 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -337,9 +337,9 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd, if (format->which == V4L2_SUBDEV_FORMAT_TRY) return 0; - mutex_lock(&sensor->input_lock); + mutex_lock(&sensor->lock); ov2680_calc_mode(sensor, fmt->width, fmt->height); - mutex_unlock(&sensor->input_lock); + mutex_unlock(&sensor->lock); return 0; } @@ -394,7 +394,7 @@ static int ov2680_s_stream(struct v4l2_subdev *sd, int enable) struct i2c_client *client = v4l2_get_subdevdata(sd); int ret = 0; - mutex_lock(&sensor->input_lock); + mutex_lock(&sensor->lock); if (sensor->is_streaming == enable) { dev_warn(&client->dev, "stream already %s\n", enable ? "started" : "stopped"); @@ -427,14 +427,14 @@ static int ov2680_s_stream(struct v4l2_subdev *sd, int enable) v4l2_ctrl_activate(sensor->ctrls.vflip, !enable); v4l2_ctrl_activate(sensor->ctrls.hflip, !enable); - mutex_unlock(&sensor->input_lock); + mutex_unlock(&sensor->lock); return 0; error_power_down: pm_runtime_put(sensor->sd.dev); sensor->is_streaming = false; error_unlock: - mutex_unlock(&sensor->input_lock); + mutex_unlock(&sensor->lock); return ret; } @@ -564,7 +564,7 @@ static int ov2680_init_controls(struct ov2680_dev *sensor) v4l2_ctrl_handler_init(hdl, 4); - hdl->lock = &sensor->input_lock; + hdl->lock = &sensor->lock; ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP, 0, 1, 1, 0); ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP, 0, 1, 1, 0); @@ -597,7 +597,7 @@ static void ov2680_remove(struct i2c_client *client) v4l2_async_unregister_subdev(&sensor->sd); media_entity_cleanup(&sensor->sd.entity); v4l2_ctrl_handler_free(&sensor->ctrls.handler); - mutex_destroy(&sensor->input_lock); + mutex_destroy(&sensor->lock); fwnode_handle_put(sensor->ep_fwnode); pm_runtime_disable(&client->dev); } @@ -612,7 +612,7 @@ static int ov2680_probe(struct i2c_client *client) if (!sensor) return -ENOMEM; - mutex_init(&sensor->input_lock); + mutex_init(&sensor->lock); sensor->client = client; v4l2_i2c_subdev_init(&sensor->sd, client, &ov2680_ops); diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index 077ca6ee08b6..4bcdd9fd0ce7 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -109,7 +109,8 @@ struct ov2680_dev { struct v4l2_subdev sd; struct media_pad pad; - struct mutex input_lock; + /* Protect against concurrent changes to controls */ + struct mutex lock; struct i2c_client *client; struct gpio_desc *powerdown; struct fwnode_handle *ep_fwnode; From c1ee1db3c936c09141020007a11da24660c5393f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:24 +0100 Subject: [PATCH 193/253] media: atomisp: ov2680: Add missing ov2680_calc_mode() call to probe() Call ov2680_calc_mode() from probe() instead of relying on userspace to make at least one s_fmt call to fill the mode parameters. Link: https://lore.kernel.org/r/20230529103741.11904-5-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/i2c/atomisp-ov2680.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index cf3f9649928a..b1585b4d2c4d 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -195,8 +195,10 @@ static void ov2680_fill_format(struct ov2680_dev *sensor, ov2680_set_bayer_order(sensor, fmt); } -static void ov2680_calc_mode(struct ov2680_dev *sensor, int width, int height) +static void ov2680_calc_mode(struct ov2680_dev *sensor) { + int width = sensor->mode.fmt.width; + int height = sensor->mode.fmt.height; int orig_width = width; int orig_height = height; @@ -338,7 +340,7 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd, return 0; mutex_lock(&sensor->lock); - ov2680_calc_mode(sensor, fmt->width, fmt->height); + ov2680_calc_mode(sensor); mutex_unlock(&sensor->lock); return 0; } @@ -660,6 +662,7 @@ static int ov2680_probe(struct i2c_client *client) } ov2680_fill_format(sensor, &sensor->mode.fmt, OV2680_NATIVE_WIDTH, OV2680_NATIVE_HEIGHT); + ov2680_calc_mode(sensor); ret = v4l2_async_register_subdev_sensor(&sensor->sd); if (ret) { From b1b2d3992623290833f7f4ddea1986c7f123f3ad Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:25 +0100 Subject: [PATCH 194/253] media: atomisp: ov2680: Add init_cfg pad-op Having an init_cfg to initialize the passed in subdev-state is important to make which == V4L2_SUBDEV_FORMAT_TRY ops work when userspace is talking to a /dev/v4l2-subdev# node. Copy the ov2680_init_cfg() from the standard drivers/media/i2c/ov2680.c driver. This is esp. relevant once support for cropping is added where the v4l2_subdev_state.pads[pad].try_crop rectangle needs to be set correctly for set_fmt which == V4L2_SUBDEV_FORMAT_TRY calls to work. Link: https://lore.kernel.org/r/20230529103741.11904-6-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/i2c/atomisp-ov2680.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index b1585b4d2c4d..b1cb6135bbc3 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -357,6 +357,21 @@ static int ov2680_get_fmt(struct v4l2_subdev *sd, return 0; } +static int ov2680_init_cfg(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state) +{ + struct v4l2_subdev_format fmt = { + .which = sd_state ? V4L2_SUBDEV_FORMAT_TRY + : V4L2_SUBDEV_FORMAT_ACTIVE, + .format = { + .width = 800, + .height = 600, + }, + }; + + return ov2680_set_fmt(sd, sd_state, &fmt); +} + static int ov2680_detect(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; @@ -537,6 +552,7 @@ static const struct v4l2_subdev_sensor_ops ov2680_sensor_ops = { }; static const struct v4l2_subdev_pad_ops ov2680_pad_ops = { + .init_cfg = ov2680_init_cfg, .enum_mbus_code = ov2680_enum_mbus_code, .enum_frame_size = ov2680_enum_frame_size, .enum_frame_interval = ov2680_enum_frame_interval, From a5cc2f0dc51964c200dc6cfcdf8a77aa711b7c0c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:26 +0100 Subject: [PATCH 195/253] media: atomisp: ov2680: Implement selection support Implement selection support. Modelled after ov5693 selection support, but allow setting sizes smaller than crop-size through set_fmt since that was already allowed. Link: https://lore.kernel.org/r/20230529103741.11904-7-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-ov2680.c | 127 ++++++++++++++++-- drivers/staging/media/atomisp/i2c/ov2680.h | 9 ++ 2 files changed, 128 insertions(+), 8 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index b1cb6135bbc3..18b604a8b932 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -30,6 +30,13 @@ #include "ov2680.h" +static const struct v4l2_rect ov2680_default_crop = { + .left = OV2680_ACTIVE_START_LEFT, + .top = OV2680_ACTIVE_START_TOP, + .width = OV2680_ACTIVE_WIDTH, + .height = OV2680_ACTIVE_HEIGHT, +}; + static int ov2680_write_reg_array(struct i2c_client *client, const struct ov2680_reg *reglist) { @@ -174,8 +181,7 @@ static int ov2680_init_registers(struct v4l2_subdev *sd) } static struct v4l2_mbus_framefmt * -__ov2680_get_pad_format(struct ov2680_dev *sensor, - struct v4l2_subdev_state *state, +__ov2680_get_pad_format(struct ov2680_dev *sensor, struct v4l2_subdev_state *state, unsigned int pad, enum v4l2_subdev_format_whence which) { if (which == V4L2_SUBDEV_FORMAT_TRY) @@ -184,6 +190,16 @@ __ov2680_get_pad_format(struct ov2680_dev *sensor, return &sensor->mode.fmt; } +static struct v4l2_rect * +__ov2680_get_pad_crop(struct ov2680_dev *sensor, struct v4l2_subdev_state *state, + unsigned int pad, enum v4l2_subdev_format_whence which) +{ + if (which == V4L2_SUBDEV_FORMAT_TRY) + return v4l2_subdev_get_try_crop(&sensor->sd, state, pad); + + return &sensor->mode.crop; +} + static void ov2680_fill_format(struct ov2680_dev *sensor, struct v4l2_mbus_framefmt *fmt, unsigned int width, unsigned int height) @@ -202,8 +218,8 @@ static void ov2680_calc_mode(struct ov2680_dev *sensor) int orig_width = width; int orig_height = height; - if (width <= (OV2680_NATIVE_WIDTH / 2) && - height <= (OV2680_NATIVE_HEIGHT / 2)) { + if (width <= (sensor->mode.crop.width / 2) && + height <= (sensor->mode.crop.height / 2)) { sensor->mode.binning = true; width *= 2; height *= 2; @@ -211,8 +227,10 @@ static void ov2680_calc_mode(struct ov2680_dev *sensor) sensor->mode.binning = false; } - sensor->mode.h_start = ((OV2680_NATIVE_WIDTH - width) / 2) & ~1; - sensor->mode.v_start = ((OV2680_NATIVE_HEIGHT - height) / 2) & ~1; + sensor->mode.h_start = + (sensor->mode.crop.left + (sensor->mode.crop.width - width) / 2) & ~1; + sensor->mode.v_start = + (sensor->mode.crop.top + (sensor->mode.crop.height - height) / 2) & ~1; sensor->mode.h_end = min(sensor->mode.h_start + width + OV2680_END_MARGIN - 1, OV2680_NATIVE_WIDTH - 1); sensor->mode.v_end = min(sensor->mode.v_start + height + OV2680_END_MARGIN - 1, @@ -326,10 +344,16 @@ static int ov2680_set_fmt(struct v4l2_subdev *sd, { struct ov2680_dev *sensor = to_ov2680_sensor(sd); struct v4l2_mbus_framefmt *fmt; + const struct v4l2_rect *crop; unsigned int width, height; - width = min_t(unsigned int, ALIGN(format->format.width, 2), OV2680_NATIVE_WIDTH); - height = min_t(unsigned int, ALIGN(format->format.height, 2), OV2680_NATIVE_HEIGHT); + crop = __ov2680_get_pad_crop(sensor, sd_state, format->pad, format->which); + + /* Limit set_fmt max size to crop width / height */ + width = clamp_t(unsigned int, ALIGN(format->format.width, 2), + OV2680_MIN_CROP_WIDTH, crop->width); + height = clamp_t(unsigned int, ALIGN(format->format.height, 2), + OV2680_MIN_CROP_HEIGHT, crop->height); fmt = __ov2680_get_pad_format(sensor, sd_state, format->pad, format->which); ov2680_fill_format(sensor, fmt, width, height); @@ -357,6 +381,88 @@ static int ov2680_get_fmt(struct v4l2_subdev *sd, return 0; } +static int ov2680_get_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_selection *sel) +{ + struct ov2680_dev *sensor = to_ov2680_sensor(sd); + + switch (sel->target) { + case V4L2_SEL_TGT_CROP: + mutex_lock(&sensor->lock); + sel->r = *__ov2680_get_pad_crop(sensor, state, sel->pad, sel->which); + mutex_unlock(&sensor->lock); + break; + case V4L2_SEL_TGT_NATIVE_SIZE: + case V4L2_SEL_TGT_CROP_BOUNDS: + sel->r.top = 0; + sel->r.left = 0; + sel->r.width = OV2680_NATIVE_WIDTH; + sel->r.height = OV2680_NATIVE_HEIGHT; + break; + case V4L2_SEL_TGT_CROP_DEFAULT: + sel->r.top = OV2680_ACTIVE_START_TOP; + sel->r.left = OV2680_ACTIVE_START_LEFT; + sel->r.width = OV2680_ACTIVE_WIDTH; + sel->r.height = OV2680_ACTIVE_HEIGHT; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int ov2680_set_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_selection *sel) +{ + struct ov2680_dev *sensor = to_ov2680_sensor(sd); + struct v4l2_mbus_framefmt *format; + struct v4l2_rect *__crop; + struct v4l2_rect rect; + + if (sel->target != V4L2_SEL_TGT_CROP) + return -EINVAL; + + /* + * Clamp the boundaries of the crop rectangle to the size of the sensor + * pixel array. Align to multiples of 2 to ensure Bayer pattern isn't + * disrupted. + */ + rect.left = clamp(ALIGN(sel->r.left, 2), OV2680_NATIVE_START_LEFT, + OV2680_NATIVE_WIDTH); + rect.top = clamp(ALIGN(sel->r.top, 2), OV2680_NATIVE_START_TOP, + OV2680_NATIVE_HEIGHT); + rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2), + OV2680_MIN_CROP_WIDTH, OV2680_NATIVE_WIDTH); + rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2), + OV2680_MIN_CROP_HEIGHT, OV2680_NATIVE_HEIGHT); + + /* Make sure the crop rectangle isn't outside the bounds of the array */ + rect.width = min_t(unsigned int, rect.width, + OV2680_NATIVE_WIDTH - rect.left); + rect.height = min_t(unsigned int, rect.height, + OV2680_NATIVE_HEIGHT - rect.top); + + __crop = __ov2680_get_pad_crop(sensor, state, sel->pad, sel->which); + + if (rect.width != __crop->width || rect.height != __crop->height) { + /* + * Reset the output image size if the crop rectangle size has + * been modified. + */ + format = __ov2680_get_pad_format(sensor, state, sel->pad, sel->which); + format->width = rect.width; + format->height = rect.height; + } + + *__crop = rect; + sel->r = rect; + + return 0; +} + static int ov2680_init_cfg(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state) { @@ -369,6 +475,8 @@ static int ov2680_init_cfg(struct v4l2_subdev *sd, }, }; + sd_state->pads[0].try_crop = ov2680_default_crop; + return ov2680_set_fmt(sd, sd_state, &fmt); } @@ -558,6 +666,8 @@ static const struct v4l2_subdev_pad_ops ov2680_pad_ops = { .enum_frame_interval = ov2680_enum_frame_interval, .get_fmt = ov2680_get_fmt, .set_fmt = ov2680_set_fmt, + .get_selection = ov2680_get_selection, + .set_selection = ov2680_set_selection, }; static const struct v4l2_subdev_ops ov2680_ops = { @@ -677,6 +787,7 @@ static int ov2680_probe(struct i2c_client *client) return ret; } + sensor->mode.crop = ov2680_default_crop; ov2680_fill_format(sensor, &sensor->mode.fmt, OV2680_NATIVE_WIDTH, OV2680_NATIVE_HEIGHT); ov2680_calc_mode(sensor); diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index 4bcdd9fd0ce7..fd9c7485f8c1 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -32,6 +32,14 @@ #define OV2680_NATIVE_WIDTH 1616 #define OV2680_NATIVE_HEIGHT 1216 +#define OV2680_NATIVE_START_LEFT 0 +#define OV2680_NATIVE_START_TOP 0 +#define OV2680_ACTIVE_WIDTH 1600 +#define OV2680_ACTIVE_HEIGHT 1200 +#define OV2680_ACTIVE_START_LEFT 8 +#define OV2680_ACTIVE_START_TOP 8 +#define OV2680_MIN_CROP_WIDTH 2 +#define OV2680_MIN_CROP_HEIGHT 2 /* 1704 * 1294 * 30fps = 66MHz pixel clock */ #define OV2680_PIXELS_PER_LINE 1704 @@ -117,6 +125,7 @@ struct ov2680_dev { bool is_streaming; struct ov2680_mode { + struct v4l2_rect crop; struct v4l2_mbus_framefmt fmt; bool binning; u16 h_start; From 503bf3090a19b6c7ba620b9c224a9409a41d3c91 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:27 +0100 Subject: [PATCH 196/253] media: atomisp: Remove a bunch of sensor related custom IOCTLs Remove a bunch of sensor related custom IOCTLs because: 1. They are custom IOCTLs and all custom IOCTLs should be removed 2. Userspace should directly talk to the sensor v4l2-subdev, rather then relying on ioctl-s on the output /dev/video# node to pass through ioctl-s to the senor 3. Some of these rely on the atomisp specific camera_mipi_info struct which is going away as we are switching to using standard v4l2 sensor drivers 4. In the case of ATOMISP_IOC_S_EXPOSURE_WINDOW this was using the v4l2-subdev set_selection API in an undocumented atomisp custom way Link: https://lore.kernel.org/r/20230529103741.11904-8-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/ov5693/atomisp-ov5693.c | 40 --- .../media/atomisp/include/linux/atomisp.h | 120 --------- .../staging/media/atomisp/pci/atomisp_cmd.c | 240 ------------------ .../staging/media/atomisp/pci/atomisp_cmd.h | 10 - .../atomisp/pci/atomisp_compat_ioctl32.h | 55 ---- .../staging/media/atomisp/pci/atomisp_ioctl.c | 39 --- 6 files changed, 504 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c index c94fe8e861a5..460a4e34c55b 100644 --- a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c +++ b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c @@ -726,51 +726,11 @@ static void *ov5693_otp_read(struct v4l2_subdev *sd) return buf; } -static int ov5693_g_priv_int_data(struct v4l2_subdev *sd, - struct v4l2_private_int_data *priv) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov5693_device *dev = to_ov5693_sensor(sd); - u8 __user *to = priv->data; - u32 read_size = priv->size; - int ret; - - /* No need to copy data if size is 0 */ - if (!read_size) - goto out; - - if (IS_ERR(dev->otp_data)) { - dev_err(&client->dev, "OTP data not available"); - return PTR_ERR(dev->otp_data); - } - - /* Correct read_size value only if bigger than maximum */ - if (read_size > OV5693_OTP_DATA_SIZE) - read_size = OV5693_OTP_DATA_SIZE; - - ret = copy_to_user(to, dev->otp_data, read_size); - if (ret) { - dev_err(&client->dev, "%s: failed to copy OTP data to user\n", - __func__); - return -EFAULT; - } - - pr_debug("%s read_size:%d\n", __func__, read_size); - -out: - /* Return correct size */ - priv->size = dev->otp_size; - - return 0; -} - static long ov5693_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { switch (cmd) { case ATOMISP_IOC_S_EXPOSURE: return ov5693_s_exposure(sd, arg); - case ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA: - return ov5693_g_priv_int_data(sd, arg); default: return -EINVAL; } diff --git a/drivers/staging/media/atomisp/include/linux/atomisp.h b/drivers/staging/media/atomisp/include/linux/atomisp.h index bada4c9911fd..14b1757e6674 100644 --- a/drivers/staging/media/atomisp/include/linux/atomisp.h +++ b/drivers/staging/media/atomisp/include/linux/atomisp.h @@ -149,12 +149,6 @@ enum atomisp_calibration_type { calibration_type3 }; -struct atomisp_calibration_group { - unsigned int size; - unsigned int type; - unsigned short *calb_grp_values; -}; - struct atomisp_gc_config { __u16 gain_k1; __u16 gain_k2; @@ -265,26 +259,6 @@ enum atomisp_metadata_type { ATOMISP_METADATA_TYPE_NUM, }; -struct atomisp_metadata_with_type { - /* to specify which type of metadata to get */ - enum atomisp_metadata_type type; - void __user *data; - u32 width; - u32 height; - u32 stride; /* in bytes */ - u32 exp_id; /* exposure ID */ - u32 *effective_width; /* mipi packets valid data size */ -}; - -struct atomisp_metadata { - void __user *data; - u32 width; - u32 height; - u32 stride; /* in bytes */ - u32 exp_id; /* exposure ID */ - u32 *effective_width; /* mipi packets valid data size */ -}; - struct atomisp_ext_isp_ctrl { u32 id; u32 data; @@ -298,14 +272,6 @@ struct atomisp_3a_statistics { u32 isp_config_id; /* isp config ID */ }; -struct atomisp_ae_window { - int x_left; - int x_right; - int y_top; - int y_bottom; - int weight; -}; - /* White Balance (Gain Adjust) */ struct atomisp_wb_config { unsigned int integer_bits; @@ -754,53 +720,6 @@ struct atomisp_s_runmode { __u32 mode; }; -struct atomisp_update_exposure { - unsigned int gain; - unsigned int digi_gain; - unsigned int update_gain; - unsigned int update_digi_gain; -}; - -/* - * V4L2 private internal data interface. - * ----------------------------------------------------------------------------- - * struct v4l2_private_int_data - request private data stored in video device - * internal memory. - * @size: sanity check to ensure userspace's buffer fits whole private data. - * If not, kernel will make partial copy (or nothing if @size == 0). - * @size is always corrected for the minimum necessary if IOCTL returns - * no error. - * @data: pointer to userspace buffer. - */ -struct v4l2_private_int_data { - __u32 size; - void __user *data; - __u32 reserved[2]; -}; - -enum atomisp_sensor_ae_bracketing_mode { - SENSOR_AE_BRACKETING_MODE_OFF = 0, - SENSOR_AE_BRACKETING_MODE_SINGLE, /* back to SW standby after bracketing */ - SENSOR_AE_BRACKETING_MODE_SINGLE_TO_STREAMING, /* back to normal streaming after bracketing */ - SENSOR_AE_BRACKETING_MODE_LOOP, /* continue AE bracketing in loop mode */ -}; - -struct atomisp_sensor_ae_bracketing_info { - unsigned int modes; /* bit mask to indicate supported modes */ - unsigned int lut_depth; -}; - -struct atomisp_sensor_ae_bracketing_lut_entry { - __u16 coarse_integration_time; - __u16 analog_gain; - __u16 digital_gain; -}; - -struct atomisp_sensor_ae_bracketing_lut { - struct atomisp_sensor_ae_bracketing_lut_entry *lut; - unsigned int lut_size; -}; - /*Private IOCTLs for ISP */ #define ATOMISP_IOC_G_XNR \ _IOR('v', BASE_VIDIOC_PRIVATE + 0, int) @@ -905,20 +824,12 @@ struct atomisp_sensor_ae_bracketing_lut { #define ATOMISP_IOC_S_EXPOSURE \ _IOW('v', BASE_VIDIOC_PRIVATE + 21, struct atomisp_exposure) -/* sensor calibration registers group */ -#define ATOMISP_IOC_G_SENSOR_CALIBRATION_GROUP \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 22, struct atomisp_calibration_group) - /* white balance Correction */ #define ATOMISP_IOC_G_3A_CONFIG \ _IOR('v', BASE_VIDIOC_PRIVATE + 23, struct atomisp_3a_config) #define ATOMISP_IOC_S_3A_CONFIG \ _IOW('v', BASE_VIDIOC_PRIVATE + 23, struct atomisp_3a_config) -/* sensor OTP memory read */ -#define ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 26, struct v4l2_private_int_data) - /* LCS (shading) table write */ #define ATOMISP_IOC_S_ISP_SHD_TAB \ _IOWR('v', BASE_VIDIOC_PRIVATE + 27, struct atomisp_shading_table) @@ -930,19 +841,9 @@ struct atomisp_sensor_ae_bracketing_lut { #define ATOMISP_IOC_S_ISP_GAMMA_CORRECTION \ _IOW('v', BASE_VIDIOC_PRIVATE + 28, struct atomisp_gc_config) -/* motor internal memory read */ -#define ATOMISP_IOC_G_MOTOR_PRIV_INT_DATA \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 29, struct v4l2_private_int_data) - #define ATOMISP_IOC_S_PARAMETERS \ _IOW('v', BASE_VIDIOC_PRIVATE + 32, struct atomisp_parameters) -#define ATOMISP_IOC_G_METADATA \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 34, struct atomisp_metadata) - -#define ATOMISP_IOC_G_METADATA_BY_TYPE \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 34, struct atomisp_metadata_with_type) - #define ATOMISP_IOC_EXT_ISP_CTRL \ _IOWR('v', BASE_VIDIOC_PRIVATE + 35, struct atomisp_ext_isp_ctrl) @@ -961,27 +862,9 @@ struct atomisp_sensor_ae_bracketing_lut { #define ATOMISP_IOC_S_FORMATS_CONFIG \ _IOW('v', BASE_VIDIOC_PRIVATE + 39, struct atomisp_formats_config) -#define ATOMISP_IOC_S_EXPOSURE_WINDOW \ - _IOW('v', BASE_VIDIOC_PRIVATE + 40, struct atomisp_ae_window) - #define ATOMISP_IOC_INJECT_A_FAKE_EVENT \ _IOW('v', BASE_VIDIOC_PRIVATE + 42, int) -#define ATOMISP_IOC_G_SENSOR_AE_BRACKETING_INFO \ - _IOR('v', BASE_VIDIOC_PRIVATE + 43, struct atomisp_sensor_ae_bracketing_info) - -#define ATOMISP_IOC_S_SENSOR_AE_BRACKETING_MODE \ - _IOW('v', BASE_VIDIOC_PRIVATE + 43, unsigned int) - -#define ATOMISP_IOC_G_SENSOR_AE_BRACKETING_MODE \ - _IOR('v', BASE_VIDIOC_PRIVATE + 43, unsigned int) - -#define ATOMISP_IOC_S_SENSOR_AE_BRACKETING_LUT \ - _IOW('v', BASE_VIDIOC_PRIVATE + 43, struct atomisp_sensor_ae_bracketing_lut) - -#define ATOMISP_IOC_G_INVALID_FRAME_NUM \ - _IOR('v', BASE_VIDIOC_PRIVATE + 44, unsigned int) - #define ATOMISP_IOC_S_ARRAY_RESOLUTION \ _IOW('v', BASE_VIDIOC_PRIVATE + 45, struct atomisp_resolution) @@ -995,9 +878,6 @@ struct atomisp_sensor_ae_bracketing_lut { #define ATOMISP_IOC_S_SENSOR_RUNMODE \ _IOW('v', BASE_VIDIOC_PRIVATE + 48, struct atomisp_s_runmode) -#define ATOMISP_IOC_G_UPDATE_EXPOSURE \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 49, struct atomisp_update_exposure) - /* * Reserved ioctls. We have customer implementing it internally. * We can't use both numbers to not cause ABI conflict. diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 5b244d173b9a..748cb78d1ee8 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -1851,161 +1851,6 @@ int atomisp_3a_stat(struct atomisp_sub_device *asd, int flag, return 0; } -int atomisp_get_metadata(struct atomisp_sub_device *asd, int flag, - struct atomisp_metadata *md) -{ - struct atomisp_device *isp = asd->isp; - struct ia_css_stream_info *stream_info; - struct camera_mipi_info *mipi_info; - struct atomisp_metadata_buf *md_buf; - enum atomisp_metadata_type md_type = ATOMISP_MAIN_METADATA; - int ret, i; - - if (flag != 0) - return -EINVAL; - - stream_info = &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]. - stream_info; - - /* We always return the resolution and stride even if there is - * no valid metadata. This allows the caller to get the information - * needed to allocate user-space buffers. */ - md->width = stream_info->metadata_info.resolution.width; - md->height = stream_info->metadata_info.resolution.height; - md->stride = stream_info->metadata_info.stride; - - /* sanity check to avoid writing into unallocated memory. - * This does not return an error because it is a valid way - * for applications to detect that metadata is not enabled. */ - if (md->width == 0 || md->height == 0 || !md->data) - return 0; - - /* This is done in the atomisp_buf_done() */ - if (list_empty(&asd->metadata_ready[md_type])) { - dev_warn(isp->dev, "Metadata queue is empty now!\n"); - return -EAGAIN; - } - - mipi_info = atomisp_to_sensor_mipi_info( - isp->inputs[asd->input_curr].camera); - if (!mipi_info) - return -EINVAL; - - if (mipi_info->metadata_effective_width) { - for (i = 0; i < md->height; i++) - md->effective_width[i] = - mipi_info->metadata_effective_width[i]; - } - - md_buf = list_entry(asd->metadata_ready[md_type].next, - struct atomisp_metadata_buf, list); - md->exp_id = md_buf->metadata->exp_id; - if (md_buf->md_vptr) { - ret = copy_to_user(md->data, - md_buf->md_vptr, - stream_info->metadata_info.size); - } else { - hmm_load(md_buf->metadata->address, - asd->params.metadata_user[md_type], - stream_info->metadata_info.size); - - ret = copy_to_user(md->data, - asd->params.metadata_user[md_type], - stream_info->metadata_info.size); - } - if (ret) { - dev_err(isp->dev, "copy to user failed: copied %d bytes\n", - ret); - return -EFAULT; - } - - list_del_init(&md_buf->list); - list_add_tail(&md_buf->list, &asd->metadata[md_type]); - - dev_dbg(isp->dev, "%s: HAL de-queued metadata type %d with exp_id %d\n", - __func__, md_type, md->exp_id); - return 0; -} - -int atomisp_get_metadata_by_type(struct atomisp_sub_device *asd, int flag, - struct atomisp_metadata_with_type *md) -{ - struct atomisp_device *isp = asd->isp; - struct ia_css_stream_info *stream_info; - struct camera_mipi_info *mipi_info; - struct atomisp_metadata_buf *md_buf; - enum atomisp_metadata_type md_type; - int ret, i; - - if (flag != 0) - return -EINVAL; - - stream_info = &asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL]. - stream_info; - - /* We always return the resolution and stride even if there is - * no valid metadata. This allows the caller to get the information - * needed to allocate user-space buffers. */ - md->width = stream_info->metadata_info.resolution.width; - md->height = stream_info->metadata_info.resolution.height; - md->stride = stream_info->metadata_info.stride; - - /* sanity check to avoid writing into unallocated memory. - * This does not return an error because it is a valid way - * for applications to detect that metadata is not enabled. */ - if (md->width == 0 || md->height == 0 || !md->data) - return 0; - - md_type = md->type; - if (md_type < 0 || md_type >= ATOMISP_METADATA_TYPE_NUM) - return -EINVAL; - - /* This is done in the atomisp_buf_done() */ - if (list_empty(&asd->metadata_ready[md_type])) { - dev_warn(isp->dev, "Metadata queue is empty now!\n"); - return -EAGAIN; - } - - mipi_info = atomisp_to_sensor_mipi_info( - isp->inputs[asd->input_curr].camera); - if (!mipi_info) - return -EINVAL; - - if (mipi_info->metadata_effective_width) { - for (i = 0; i < md->height; i++) - md->effective_width[i] = - mipi_info->metadata_effective_width[i]; - } - - md_buf = list_entry(asd->metadata_ready[md_type].next, - struct atomisp_metadata_buf, list); - md->exp_id = md_buf->metadata->exp_id; - if (md_buf->md_vptr) { - ret = copy_to_user(md->data, - md_buf->md_vptr, - stream_info->metadata_info.size); - } else { - hmm_load(md_buf->metadata->address, - asd->params.metadata_user[md_type], - stream_info->metadata_info.size); - - ret = copy_to_user(md->data, - asd->params.metadata_user[md_type], - stream_info->metadata_info.size); - } - if (ret) { - dev_err(isp->dev, "copy to user failed: copied %d bytes\n", - ret); - return -EFAULT; - } else { - list_del_init(&md_buf->list); - list_add_tail(&md_buf->list, &asd->metadata[md_type]); - } - dev_dbg(isp->dev, "%s: HAL de-queued metadata type %d with exp_id %d\n", - __func__, md_type, md->exp_id); - return 0; -} - /* * Function to calculate real zoom region for every pipe */ @@ -4665,30 +4510,6 @@ out: return ret; } -/* - * set auto exposure metering window to camera sensor - */ -int atomisp_s_ae_window(struct atomisp_sub_device *asd, - struct atomisp_ae_window *arg) -{ - struct atomisp_device *isp = asd->isp; - /* Coverity CID 298071 - initialzize struct */ - struct v4l2_subdev_selection sel = { 0 }; - - sel.r.left = arg->x_left; - sel.r.top = arg->y_top; - sel.r.width = arg->x_right - arg->x_left + 1; - sel.r.height = arg->y_bottom - arg->y_top + 1; - - if (v4l2_subdev_call(isp->inputs[asd->input_curr].camera, - pad, set_selection, NULL, &sel)) { - dev_err(isp->dev, "failed to call sensor set_selection.\n"); - return -EINVAL; - } - - return 0; -} - int atomisp_flash_enable(struct atomisp_sub_device *asd, int num_frames) { struct atomisp_device *isp = asd->isp; @@ -4868,64 +4689,3 @@ int atomisp_inject_a_fake_event(struct atomisp_sub_device *asd, int *event) return 0; } - -static int atomisp_get_pipe_id(struct atomisp_video_pipe *pipe) -{ - struct atomisp_sub_device *asd = pipe->asd; - - if (!asd) { - dev_err(pipe->isp->dev, "%s(): asd is NULL, device is %s\n", - __func__, pipe->vdev.name); - return -EINVAL; - } - - if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_SCALER) { - return IA_CSS_PIPE_ID_VIDEO; - } else if (asd->vfpp->val == ATOMISP_VFPP_DISABLE_LOWLAT) { - return IA_CSS_PIPE_ID_CAPTURE; - } else if (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { - return IA_CSS_PIPE_ID_VIDEO; - } else if (asd->run_mode->val == ATOMISP_RUN_MODE_PREVIEW) { - return IA_CSS_PIPE_ID_PREVIEW; - } else if (asd->run_mode->val == ATOMISP_RUN_MODE_STILL_CAPTURE) { - if (asd->copy_mode) - return IA_CSS_PIPE_ID_COPY; - else - return IA_CSS_PIPE_ID_CAPTURE; - } - - /* fail through */ - dev_warn(asd->isp->dev, "%s failed to find proper pipe\n", - __func__); - return IA_CSS_PIPE_ID_CAPTURE; -} - -int atomisp_get_invalid_frame_num(struct video_device *vdev, - int *invalid_frame_num) -{ - struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); - struct atomisp_sub_device *asd = pipe->asd; - enum ia_css_pipe_id pipe_id; - struct ia_css_pipe_info p_info; - int ret; - - pipe_id = atomisp_get_pipe_id(pipe); - if (!asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL].pipes[pipe_id]) { - dev_warn(asd->isp->dev, - "%s pipe %d has not been created yet, do SET_FMT first!\n", - __func__, pipe_id); - return -EINVAL; - } - - ret = ia_css_pipe_get_info( - asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL] - .pipes[pipe_id], &p_info); - if (!ret) { - *invalid_frame_num = p_info.num_invalid_frames; - return 0; - } else { - dev_warn(asd->isp->dev, "%s get pipe infor failed %d\n", - __func__, ret); - return -EINVAL; - } -} diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.h b/drivers/staging/media/atomisp/pci/atomisp_cmd.h index 5270c370e463..ff2178c96fb8 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.h +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.h @@ -159,13 +159,6 @@ int atomisp_set_dis_vector(struct atomisp_sub_device *asd, int atomisp_3a_stat(struct atomisp_sub_device *asd, int flag, struct atomisp_3a_statistics *config); -/* Function to get metadata from isp */ -int atomisp_get_metadata(struct atomisp_sub_device *asd, int flag, - struct atomisp_metadata *config); - -int atomisp_get_metadata_by_type(struct atomisp_sub_device *asd, int flag, - struct atomisp_metadata_with_type *config); - int atomisp_set_parameters(struct video_device *vdev, struct atomisp_parameters *arg); @@ -267,9 +260,6 @@ int atomisp_set_shading_table(struct atomisp_sub_device *asd, void atomisp_free_internal_buffers(struct atomisp_sub_device *asd); -int atomisp_s_ae_window(struct atomisp_sub_device *asd, - struct atomisp_ae_window *arg); - int atomisp_flash_enable(struct atomisp_sub_device *asd, int num_frames); diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_ioctl32.h b/drivers/staging/media/atomisp/pci/atomisp_compat_ioctl32.h index 33821b51d90e..762520ed87a5 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_ioctl32.h +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_ioctl32.h @@ -67,26 +67,6 @@ struct atomisp_3a_statistics32 { u32 isp_config_id; }; -struct atomisp_metadata_with_type32 { - /* to specify which type of metadata to get */ - enum atomisp_metadata_type type; - compat_uptr_t data; - u32 width; - u32 height; - u32 stride; /* in bytes */ - u32 exp_id; /* exposure ID */ - compat_uptr_t effective_width; -}; - -struct atomisp_metadata32 { - compat_uptr_t data; - u32 width; - u32 height; - u32 stride; - u32 exp_id; - compat_uptr_t effective_width; -}; - struct atomisp_morph_table32 { unsigned int enabled; unsigned int height; @@ -134,18 +114,6 @@ struct atomisp_overlay32 { unsigned int overlay_start_y; }; -struct atomisp_calibration_group32 { - unsigned int size; - unsigned int type; - compat_uptr_t calb_grp_values; -}; - -struct v4l2_private_int_data32 { - __u32 size; - compat_uptr_t data; - __u32 reserved[2]; -}; - struct atomisp_shading_table32 { __u32 enable; __u32 sensor_width; @@ -249,11 +217,6 @@ struct atomisp_dvs_6axis_config32 { compat_uptr_t ycoords_uv; }; -struct atomisp_sensor_ae_bracketing_lut32 { - compat_uptr_t lut; - unsigned int lut_size; -}; - #define ATOMISP_IOC_G_HISTOGRAM32 \ _IOWR('v', BASE_VIDIOC_PRIVATE + 3, struct atomisp_histogram32) #define ATOMISP_IOC_S_HISTOGRAM32 \ @@ -283,28 +246,10 @@ struct atomisp_sensor_ae_bracketing_lut32 { #define ATOMISP_IOC_S_ISP_OVERLAY32 \ _IOW('v', BASE_VIDIOC_PRIVATE + 18, struct atomisp_overlay32) -#define ATOMISP_IOC_G_SENSOR_CALIBRATION_GROUP32 \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 22, struct atomisp_calibration_group32) - -#define ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA32 \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 26, struct v4l2_private_int_data32) - #define ATOMISP_IOC_S_ISP_SHD_TAB32 \ _IOWR('v', BASE_VIDIOC_PRIVATE + 27, struct atomisp_shading_table32) -#define ATOMISP_IOC_G_MOTOR_PRIV_INT_DATA32 \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 29, struct v4l2_private_int_data32) - #define ATOMISP_IOC_S_PARAMETERS32 \ _IOW('v', BASE_VIDIOC_PRIVATE + 32, struct atomisp_parameters32) -#define ATOMISP_IOC_G_METADATA32 \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 34, struct atomisp_metadata32) - -#define ATOMISP_IOC_G_METADATA_BY_TYPE32 \ - _IOWR('v', BASE_VIDIOC_PRIVATE + 34, struct atomisp_metadata_with_type32) - -#define ATOMISP_IOC_S_SENSOR_AE_BRACKETING_LUT32 \ - _IOW('v', BASE_VIDIOC_PRIVATE + 43, struct atomisp_sensor_ae_bracketing_lut32) - #endif /* __ATOMISP_COMPAT_IOCTL32_H__ */ diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 2cde1af77a2d..bc8ceeb1c315 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -1763,14 +1763,8 @@ static long atomisp_vidioc_default(struct file *file, void *fh, struct video_device *vdev = video_devdata(file); struct atomisp_device *isp = video_get_drvdata(vdev); struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; - struct v4l2_subdev *motor; int err; - if (!IS_ISP2401) - motor = isp->inputs[asd->input_curr].motor; - else - motor = isp->motor; - switch (cmd) { case ATOMISP_IOC_S_SENSOR_RUNMODE: if (IS_ISP2401) @@ -1921,31 +1915,10 @@ static long atomisp_vidioc_default(struct file *file, void *fh, err = atomisp_fixed_pattern_table(asd, arg); break; - case ATOMISP_IOC_G_MOTOR_PRIV_INT_DATA: - if (motor) - err = v4l2_subdev_call(motor, core, ioctl, cmd, arg); - else - err = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, - core, ioctl, cmd, arg); - break; - case ATOMISP_IOC_S_EXPOSURE: - case ATOMISP_IOC_G_SENSOR_CALIBRATION_GROUP: - case ATOMISP_IOC_G_SENSOR_PRIV_INT_DATA: - case ATOMISP_IOC_G_SENSOR_AE_BRACKETING_INFO: - case ATOMISP_IOC_S_SENSOR_AE_BRACKETING_MODE: - case ATOMISP_IOC_G_SENSOR_AE_BRACKETING_MODE: - case ATOMISP_IOC_S_SENSOR_AE_BRACKETING_LUT: err = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, core, ioctl, cmd, arg); break; - case ATOMISP_IOC_G_UPDATE_EXPOSURE: - if (IS_ISP2401) - err = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, - core, ioctl, cmd, arg); - else - err = -EINVAL; - break; case ATOMISP_IOC_S_ISP_SHD_TAB: err = atomisp_set_shading_table(asd, arg); @@ -1963,12 +1936,6 @@ static long atomisp_vidioc_default(struct file *file, void *fh, err = atomisp_set_parameters(vdev, arg); break; - case ATOMISP_IOC_G_METADATA: - err = atomisp_get_metadata(asd, 0, arg); - break; - case ATOMISP_IOC_G_METADATA_BY_TYPE: - err = atomisp_get_metadata_by_type(asd, 0, arg); - break; case ATOMISP_IOC_EXT_ISP_CTRL: err = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, core, ioctl, cmd, arg); @@ -1989,15 +1956,9 @@ static long atomisp_vidioc_default(struct file *file, void *fh, case ATOMISP_IOC_S_FORMATS_CONFIG: err = atomisp_formats(asd, 1, arg); break; - case ATOMISP_IOC_S_EXPOSURE_WINDOW: - err = atomisp_s_ae_window(asd, arg); - break; case ATOMISP_IOC_INJECT_A_FAKE_EVENT: err = atomisp_inject_a_fake_event(asd, arg); break; - case ATOMISP_IOC_G_INVALID_FRAME_NUM: - err = atomisp_get_invalid_frame_num(vdev, arg); - break; case ATOMISP_IOC_S_ARRAY_RESOLUTION: err = atomisp_set_array_res(asd, arg); break; From af330c965fdd6bb86b8aaf804334f03623d6d2cd Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:28 +0100 Subject: [PATCH 197/253] media: atomisp: Remove redundant atomisp_subdev_set_selection() calls from atomisp_set_fmt() atomisp_subdev_set_selection(sink-pad, V4L2_SEL_TGT_CROP, rect) ignores the passed in rect, using the width and height from the last atomisp_subdev_set_ffmt(ATOMISP_SUBDEV_PAD_SINK, ffmt) call instead. The atomisp_subdev_set_ffmt() call done by atomisp_set_fmt_to_snr() already propagates the sink ffmt changes to V4L2_SEL_TGT_CROP (this is what allows atomisp_set_fmt() to get the isp_sink_crop in the first place). Remove the redundant atomisp_subdev_set_selection(sink-pad, ...) calls. Note the removed aspect ratio correction in the last else block is is already done by atomisp_subdev_set_selection() itself when setting V4L2_SEL_TGT_COMPOSE on the source-pad. Link: https://lore.kernel.org/r/20230529103741.11904-9-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 748cb78d1ee8..36618d2eba72 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -4327,12 +4327,6 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) isp_sink_crop.width = f->fmt.pix.width; isp_sink_crop.height = f->fmt.pix.height; - atomisp_subdev_set_selection(&asd->subdev, fh.state, - V4L2_SUBDEV_FORMAT_ACTIVE, - ATOMISP_SUBDEV_PAD_SINK, - V4L2_SEL_TGT_CROP, - V4L2_SEL_FLAG_KEEP_CONFIG, - &isp_sink_crop); atomisp_subdev_set_selection(&asd->subdev, fh.state, V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SOURCE, V4L2_SEL_TGT_COMPOSE, @@ -4358,38 +4352,11 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) V4L2_SEL_TGT_COMPOSE, 0, &main_compose); } else { - struct v4l2_rect sink_crop = {0}; struct v4l2_rect main_compose = {0}; main_compose.width = f->fmt.pix.width; main_compose.height = f->fmt.pix.height; - /* WORKAROUND: this override is universally enabled in - * GMIN to work around a CTS failures (GMINL-539) - * which appears to be related by a hardware - * performance limitation. It's unclear why this - * particular code triggers the issue. */ - if (isp_sink_crop.width * main_compose.height > - isp_sink_crop.height * main_compose.width) { - sink_crop.height = isp_sink_crop.height; - sink_crop.width = - DIV_NEAREST_STEP(sink_crop.height * f->fmt.pix.width, - f->fmt.pix.height, - ATOM_ISP_STEP_WIDTH); - } else { - sink_crop.width = isp_sink_crop.width; - sink_crop.height = - DIV_NEAREST_STEP(sink_crop.width * f->fmt.pix.height, - f->fmt.pix.width, - ATOM_ISP_STEP_HEIGHT); - } - atomisp_subdev_set_selection(&asd->subdev, fh.state, - V4L2_SUBDEV_FORMAT_ACTIVE, - ATOMISP_SUBDEV_PAD_SINK, - V4L2_SEL_TGT_CROP, - V4L2_SEL_FLAG_KEEP_CONFIG, - &sink_crop); - atomisp_subdev_set_selection(&asd->subdev, fh.state, V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SOURCE, From 7caa6570da6a21973340edf4075f31a59f08187a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:29 +0100 Subject: [PATCH 198/253] media: atomisp: Simplify atomisp_subdev_set_selection() calls in atomisp_set_fmt() With the atomisp_subdev_set_selection(sink-pad, V4L2_SEL_TGT_CROP, rect) calls dropped. The first and last compount code blocks of the 3 code blocks in the if (...) {} else if (...) {} else {} code setting the source-pad V4L2_SEL_TGT_COMPOSE selection are the same. The both set V4L2_SEL_TGT_COMPOSE to a rectangle with the same dimensions as f->fmt.pix.height. Remove the else {} block at the end, drop the second if and prepend the first if condition with "!second-if-condition ||" to remove the code duplication. Link: https://lore.kernel.org/r/20230529103741.11904-10-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 36618d2eba72..2a1cb3049019 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -4319,7 +4319,8 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) /* Try to enable YUV downscaling if ISP input is 10 % (either * width or height) bigger than the desired result. */ - if (isp_sink_crop.width * 9 / 10 < f->fmt.pix.width || + if (!IS_MOFD || + isp_sink_crop.width * 9 / 10 < f->fmt.pix.width || isp_sink_crop.height * 9 / 10 < f->fmt.pix.height || (atomisp_subdev_format_conversion(asd) && (asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO || @@ -4331,7 +4332,7 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SOURCE, V4L2_SEL_TGT_COMPOSE, 0, &isp_sink_crop); - } else if (IS_MOFD) { + } else { struct v4l2_rect main_compose = {0}; main_compose.width = isp_sink_crop.width; @@ -4346,17 +4347,6 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) f->fmt.pix.height); } - atomisp_subdev_set_selection(&asd->subdev, fh.state, - V4L2_SUBDEV_FORMAT_ACTIVE, - ATOMISP_SUBDEV_PAD_SOURCE, - V4L2_SEL_TGT_COMPOSE, 0, - &main_compose); - } else { - struct v4l2_rect main_compose = {0}; - - main_compose.width = f->fmt.pix.width; - main_compose.height = f->fmt.pix.height; - atomisp_subdev_set_selection(&asd->subdev, fh.state, V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SOURCE, From 566f6de6aa283be619e870fae175404b447cdee1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:30 +0100 Subject: [PATCH 199/253] media: atomisp: Add target validation to atomisp_subdev_set_selection() As the 2 comments in the function already say both the sink and the source pads only support setting the selection for 1 target: /* Only crop target supported on sink pad. */ /* Only compose target is supported on source pads. */ Validate that the passed in target actually matches these expectations. Link: https://lore.kernel.org/r/20230529103741.11904-11-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_subdev.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c index 7985a0319a39..04e257ede7d4 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c @@ -360,6 +360,10 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, unsigned int padding_w = pad_w; unsigned int padding_h = pad_h; + if ((pad == ATOMISP_SUBDEV_PAD_SINK && target != V4L2_SEL_TGT_CROP) || + (pad == ATOMISP_SUBDEV_PAD_SOURCE && target != V4L2_SEL_TGT_COMPOSE)) + return -EINVAL; + isp_get_fmt_rect(sd, sd_state, which, ffmt, crop, comp); dev_dbg(isp->dev, From e79fae3d15095542db18c4cb2adfbd9e8fda91a4 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:31 +0100 Subject: [PATCH 200/253] media: atomisp: Remove bogus fh use from atomisp_set_fmt*() atomisp_set_fmt*() use a local v4l2_subdev_fh declared on the stack, specifically they use fh.state which is never initialized so when passing fh.state to atomisp_subdev_set_ffmt() / to atomisp_subdev_set_selection() these functions are passing random stack contents as a pointer. The reason this works is because when the which parameter is V4L2_SUBDEV_FORMAT_ACTIVE the passed in state is not used. Remove the bogus fh usage and just pass NULL as state. Link: https://lore.kernel.org/r/20230529103741.11904-12-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 2a1cb3049019..87184ddf94c5 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -3908,7 +3908,6 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, const struct atomisp_format_bridge *format; struct v4l2_rect *isp_sink_crop; enum ia_css_pipe_id pipe_id; - struct v4l2_subdev_fh fh; int (*configure_output)(struct atomisp_sub_device *asd, unsigned int width, unsigned int height, unsigned int min_width, @@ -3929,8 +3928,6 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, return -EINVAL; } - v4l2_fh_init(&fh.vfh, vdev); - isp_sink_crop = atomisp_subdev_get_rect( &asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SINK, V4L2_SEL_TGT_CROP); @@ -4138,7 +4135,6 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p struct atomisp_device *isp; struct atomisp_input_stream_info *stream_info = (struct atomisp_input_stream_info *)ffmt->reserved; - struct v4l2_subdev_fh fh; int ret; if (!asd) { @@ -4149,8 +4145,6 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p isp = asd->isp; - v4l2_fh_init(&fh.vfh, vdev); - format = atomisp_get_format_bridge(f->pixelformat); if (!format) return -EINVAL; @@ -4210,7 +4204,7 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p asd->params.video_dis_en = false; } - atomisp_subdev_set_ffmt(&asd->subdev, fh.state, + atomisp_subdev_set_ffmt(&asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SINK, ffmt); @@ -4232,7 +4226,6 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) .which = V4L2_SUBDEV_FORMAT_ACTIVE, }; struct v4l2_rect isp_sink_crop; - struct v4l2_subdev_fh fh; int ret; ret = atomisp_pipe_check(pipe, true); @@ -4243,8 +4236,6 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) "setting resolution %ux%u bytesperline %u\n", f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.bytesperline); - v4l2_fh_init(&fh.vfh, vdev); - format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat); if (!format_bridge) return -EINVAL; @@ -4288,7 +4279,7 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) snr_format_bridge->mbus_code; isp_source_fmt.code = format_bridge->mbus_code; - atomisp_subdev_set_ffmt(&asd->subdev, fh.state, + atomisp_subdev_set_ffmt(&asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SOURCE, &isp_source_fmt); @@ -4328,7 +4319,7 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) isp_sink_crop.width = f->fmt.pix.width; isp_sink_crop.height = f->fmt.pix.height; - atomisp_subdev_set_selection(&asd->subdev, fh.state, + atomisp_subdev_set_selection(&asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SOURCE, V4L2_SEL_TGT_COMPOSE, 0, &isp_sink_crop); @@ -4347,7 +4338,7 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) f->fmt.pix.height); } - atomisp_subdev_set_selection(&asd->subdev, fh.state, + atomisp_subdev_set_selection(&asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SOURCE, V4L2_SEL_TGT_COMPOSE, 0, From 9f221053342ab943c4bac8d5cf10ca256793a878 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:32 +0100 Subject: [PATCH 201/253] media: atomisp: Add input helper variable for isp->asd->inputs[asd->input_curr] Passing 'isp->asd->inputs[asd->input_curr].foo' as argument to various function calls is rather long. Add a local input helper variable for this, so that the function calls will fit on one line. Link: https://lore.kernel.org/r/20230529103741.11904-13-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 33 +++++++++---------- .../staging/media/atomisp/pci/atomisp_ioctl.c | 4 +-- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 87184ddf94c5..243a789fef6a 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -3662,6 +3662,7 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f) { struct atomisp_device *isp = video_get_drvdata(vdev); struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; + struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; struct v4l2_subdev_pad_config pad_cfg; struct v4l2_subdev_state pad_state = { .pads = &pad_cfg, @@ -3678,7 +3679,7 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f) return -EINVAL; } - if (!isp->inputs[asd->input_curr].camera) + if (!input->camera) return -EINVAL; fmt = atomisp_get_format_bridge(f->pixelformat); @@ -3700,8 +3701,7 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f) dev_dbg(isp->dev, "try_mbus_fmt: asking for %ux%u\n", format.format.width, format.format.height); - ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, - pad, set_fmt, &pad_state, &format); + ret = v4l2_subdev_call(input->camera, pad, set_fmt, &pad_state, &format); if (ret) return ret; @@ -3761,6 +3761,7 @@ static inline int atomisp_set_sensor_mipi_to_isp( { struct v4l2_control ctrl; struct atomisp_device *isp = asd->isp; + struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; const struct atomisp_in_fmt_conv *fc; int mipi_freq = 0; unsigned int input_format, bayer_order; @@ -3768,8 +3769,7 @@ static inline int atomisp_set_sensor_mipi_to_isp( u32 mipi_port, metadata_width = 0, metadata_height = 0; ctrl.id = V4L2_CID_LINK_FREQ; - if (v4l2_g_ctrl - (isp->inputs[asd->input_curr].camera->ctrl_handler, &ctrl) == 0) + if (v4l2_g_ctrl(input->camera->ctrl_handler, &ctrl) == 0) mipi_freq = ctrl.value; if (asd->stream_env[stream_id].isys_configs == 1) { @@ -3827,7 +3827,7 @@ static inline int atomisp_set_sensor_mipi_to_isp( return -EINVAL; input_format = fc->atomisp_in_fmt; - mipi_port = atomisp_port_to_mipi_port(isp, isp->inputs[asd->input_curr].port); + mipi_port = atomisp_port_to_mipi_port(isp, input->port); atomisp_css_input_configure_port(asd, mipi_port, isp->sensor_lanes[mipi_port], 0xffff4, mipi_freq, @@ -3905,6 +3905,7 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, struct camera_mipi_info *mipi_info; struct atomisp_device *isp = video_get_drvdata(vdev); struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; + struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; const struct atomisp_format_bridge *format; struct v4l2_rect *isp_sink_crop; enum ia_css_pipe_id pipe_id; @@ -3936,9 +3937,8 @@ static int atomisp_set_fmt_to_isp(struct video_device *vdev, if (!format) return -EINVAL; - if (isp->inputs[asd->input_curr].type != TEST_PATTERN) { - mipi_info = atomisp_to_sensor_mipi_info( - isp->inputs[asd->input_curr].camera); + if (input->type != TEST_PATTERN) { + mipi_info = atomisp_to_sensor_mipi_info(input->camera); if (atomisp_set_sensor_mipi_to_isp(asd, ATOMISP_INPUT_STREAM_GENERAL, mipi_info)) @@ -4122,6 +4122,8 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p { struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); struct atomisp_sub_device *asd = pipe->asd; + struct atomisp_device *isp = asd->isp; + struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; const struct atomisp_format_bridge *format; struct v4l2_subdev_pad_config pad_cfg; struct v4l2_subdev_state pad_state = { @@ -4132,7 +4134,6 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p }; struct v4l2_mbus_framefmt *ffmt = &vformat.format; struct v4l2_mbus_framefmt *req_ffmt; - struct atomisp_device *isp; struct atomisp_input_stream_info *stream_info = (struct atomisp_input_stream_info *)ffmt->reserved; int ret; @@ -4143,8 +4144,6 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p return -EINVAL; } - isp = asd->isp; - format = atomisp_get_format_bridge(f->pixelformat); if (!format) return -EINVAL; @@ -4164,8 +4163,7 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p /* Disable dvs if resolution can't be supported by sensor */ if (asd->params.video_dis_en && asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { vformat.which = V4L2_SUBDEV_FORMAT_TRY; - ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, - pad, set_fmt, &pad_state, &vformat); + ret = v4l2_subdev_call(input->camera, pad, set_fmt, &pad_state, &vformat); if (ret) return ret; @@ -4183,8 +4181,7 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p } } vformat.which = V4L2_SUBDEV_FORMAT_ACTIVE; - ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, pad, - set_fmt, NULL, &vformat); + ret = v4l2_subdev_call(input->camera, pad, set_fmt, NULL, &vformat); if (ret) return ret; @@ -4216,6 +4213,7 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) struct atomisp_device *isp = video_get_drvdata(vdev); struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); struct atomisp_sub_device *asd = pipe->asd; + struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; const struct atomisp_format_bridge *format_bridge; const struct atomisp_format_bridge *snr_format_bridge; struct ia_css_frame_info output_info; @@ -4259,8 +4257,7 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) vformat.format.height += padding_h; vformat.format.width += padding_w; - ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, pad, - set_fmt, NULL, &vformat); + ret = v4l2_subdev_call(input->camera, pad, set_fmt, NULL, &vformat); if (ret) return ret; diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index bc8ceeb1c315..384d3bf2b61e 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -703,14 +703,14 @@ static int atomisp_enum_framesizes(struct file *file, void *priv, struct video_device *vdev = video_devdata(file); struct atomisp_device *isp = video_get_drvdata(vdev); struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; + struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; struct v4l2_subdev_frame_size_enum fse = { .index = fsize->index, .which = V4L2_SUBDEV_FORMAT_ACTIVE, }; int ret; - ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, - pad, enum_frame_size, NULL, &fse); + ret = v4l2_subdev_call(input->camera, pad, enum_frame_size, NULL, &fse); if (ret) return ret; From eec8787bfb5558999ac97ac3363acc7fc8c4fdf8 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:33 +0100 Subject: [PATCH 202/253] media: atomisp: Add ia_css_frame_pad_width() helper function Factor the code to go from width to a properly aligned pitch out of ia_css_frame_info_set_width(). This is a preparation patch to fix try_fmt() calls returning a bogus bytesperline value. Link: https://lore.kernel.org/r/20230529103741.11904-14-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- .../runtime/frame/interface/ia_css_frame.h | 2 + .../atomisp/pci/runtime/frame/src/frame.c | 49 ++++++++++++------- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h b/drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h index 700070c58eda..90c17884968b 100644 --- a/drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h +++ b/drivers/staging/media/atomisp/pci/runtime/frame/interface/ia_css_frame.h @@ -138,4 +138,6 @@ bool ia_css_frame_is_same_type( int ia_css_dma_configure_from_info(struct dma_port_config *config, const struct ia_css_frame_info *info); +unsigned int ia_css_frame_pad_width(unsigned int width, enum ia_css_frame_format format); + #endif /* __IA_CSS_FRAME_H__ */ diff --git a/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c b/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c index 1e374ae848e3..2d7fddb114f6 100644 --- a/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c +++ b/drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c @@ -269,6 +269,34 @@ int ia_css_frame_init_planes(struct ia_css_frame *frame) return 0; } +unsigned int ia_css_frame_pad_width(unsigned int width, enum ia_css_frame_format format) +{ + switch (format) { + /* + * Frames with a U and V plane of 8 bits per pixel need to have + * all planes aligned, this means double the alignment for the + * Y plane if the horizontal decimation is 2. + */ + case IA_CSS_FRAME_FORMAT_YUV420: + case IA_CSS_FRAME_FORMAT_YV12: + case IA_CSS_FRAME_FORMAT_NV12: + case IA_CSS_FRAME_FORMAT_NV21: + case IA_CSS_FRAME_FORMAT_BINARY_8: + case IA_CSS_FRAME_FORMAT_YUV_LINE: + return CEIL_MUL(width, 2 * HIVE_ISP_DDR_WORD_BYTES); + + case IA_CSS_FRAME_FORMAT_NV12_TILEY: + return CEIL_MUL(width, NV12_TILEY_TILE_WIDTH); + + case IA_CSS_FRAME_FORMAT_RAW: + case IA_CSS_FRAME_FORMAT_RAW_PACKED: + return CEIL_MUL(width, 2 * ISP_VEC_NELEMS); + + default: + return CEIL_MUL(width, HIVE_ISP_DDR_WORD_BYTES); + } +} + void ia_css_frame_info_set_width(struct ia_css_frame_info *info, unsigned int width, unsigned int min_padded_width) @@ -285,25 +313,8 @@ void ia_css_frame_info_set_width(struct ia_css_frame_info *info, align = max(min_padded_width, width); info->res.width = width; - /* frames with a U and V plane of 8 bits per pixel need to have - all planes aligned, this means double the alignment for the - Y plane if the horizontal decimation is 2. */ - if (info->format == IA_CSS_FRAME_FORMAT_YUV420 || - info->format == IA_CSS_FRAME_FORMAT_YV12 || - info->format == IA_CSS_FRAME_FORMAT_NV12 || - info->format == IA_CSS_FRAME_FORMAT_NV21 || - info->format == IA_CSS_FRAME_FORMAT_BINARY_8 || - info->format == IA_CSS_FRAME_FORMAT_YUV_LINE) - info->padded_width = - CEIL_MUL(align, 2 * HIVE_ISP_DDR_WORD_BYTES); - else if (info->format == IA_CSS_FRAME_FORMAT_NV12_TILEY) - info->padded_width = CEIL_MUL(align, NV12_TILEY_TILE_WIDTH); - else if (info->format == IA_CSS_FRAME_FORMAT_RAW || - info->format == IA_CSS_FRAME_FORMAT_RAW_PACKED) - info->padded_width = CEIL_MUL(align, 2 * ISP_VEC_NELEMS); - else { - info->padded_width = CEIL_MUL(align, HIVE_ISP_DDR_WORD_BYTES); - } + info->padded_width = ia_css_frame_pad_width(align, info->format); + IA_CSS_LEAVE_PRIVATE(""); } From 929eee2fb07aee951c493cfdd87cb19719606d91 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:34 +0100 Subject: [PATCH 203/253] media: atomisp: Refactor atomisp_try_fmt() / atomisp_set_fmt() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are a number of bugs in atomisp_try_fmt_cap() and atomisp_set_fmt(): 1. atomisp_try_fmt_cap() uses atomisp_adjust_fmt() which adds the sensor padding to the width passed to atomisp_adjust_fmt() to calculate bytesperline. This is buggy for 2 reasons: a) The width passed to atomisp_adjust_fmt() already contains   the sensor padding. b) The fmt returned by atomisp_try_fmt_cap() is the fmt outputted by the ISP and the sensor padding applies to the input side of the ISP not the output side. The output side of the ISP has its own padding / pitch requirements which have nothing to do with the sensor. Both these issues are fixed in this refactor by switching to ia_css_frame_pad_width() to calculate the padding. 2. atomisp_set_fmt() takes the passed in bytesperline value without doing any validation on it and then passes this unchecked value to the configure_output() callback. If bytesperline converted to pixels is > 1920 ia_css_binary_find() will fail to find a valid binary for the preview pipeline triggering a dump_stack_lvl() call inside ia_css_binary_find() and causing atomisp_set_fmt() to fail. This is fixed by making atomisp_set_fmt() call atomisp_try_fmt() first which we override the userspace specified bytesperline with the correct value. Besides this bug there is also a bunch of weirdness and a lot of duplication in the code: 1. atomisp_try_fmt_cap() adds the sensor padding itself but then it gets substracted again in atomisp_adjust_fmt() not doing the addition + substraction in the same place makes the code hard to follow (weirdness). 2. atomisp_set_fmt() starts with basically an atomisp_try_fmt() call, except that the only atomisp_try_fmt() caller: atomisp_try_fmt_cap() adds the sensor padding itself rather than letting atomisp_try_fmt() do this (duplication). 3. Both atomisp_try_fmt_cap() and atomisp_set_fmt() contain code to lookup the bridge-format matching the requested pixelformat and both will fallback to YUV420 if this is not set (duplication). 4. Both atomisp_try_fmt_cap() and atomisp_set_fmt() contain code to fill in the passed in v4l2_pix_format struct (duplication). Cleanup all of this (and fix the bugs mentioned above) by: 1. Adding a new atomisp_fill_pix_format() helper which properly uses ia_css_frame_pad_width() to calculate bytesperline. 2. Move all sensor padding handling to atomisp_try_fmt() and make atomisp_try_fmt() fill the passed in v4l2_pix_format struct. 3. This reduces atomisp_try_fmt_cap() to just a small wrapper around atomisp_try_fmt(). 4. Replace the DIY try_fmt code at the beginning of atomisp_set_fmt() with atomisp_try_fmt(), this will also override/fix the bytersperline passed by userspace. 5. Replace the DIY v4l2_pix_format filling at the end of atomisp_set_fmt() with atomisp_fill_pix_format(). Link: https://lore.kernel.org/r/20230529103741.11904-15-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 170 ++++++++---------- .../staging/media/atomisp/pci/atomisp_cmd.h | 4 +- .../staging/media/atomisp/pci/atomisp_ioctl.c | 67 +------ 3 files changed, 78 insertions(+), 163 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 243a789fef6a..e17d057f8867 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -3657,11 +3657,46 @@ static void __atomisp_init_stream_info(u16 stream_index, } } -/* This function looks up the closest available resolution. */ -int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f) +static void atomisp_fill_pix_format(struct v4l2_pix_format *f, + u32 width, u32 height, + const struct atomisp_format_bridge *br_fmt) { - struct atomisp_device *isp = video_get_drvdata(vdev); - struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; + u32 bytes; + + f->width = width; + f->height = height; + f->pixelformat = br_fmt->pixelformat; + + /* Adding padding to width for bytesperline calculation */ + width = ia_css_frame_pad_width(width, br_fmt->sh_fmt); + bytes = BITS_TO_BYTES(br_fmt->depth * width); + + if (br_fmt->planar) + f->bytesperline = width; + else + f->bytesperline = bytes; + + f->sizeimage = PAGE_ALIGN(height * bytes); + + if (f->field == V4L2_FIELD_ANY) + f->field = V4L2_FIELD_NONE; + + /* + * FIXME: do we need to set this up differently, depending on the + * sensor or the pipeline? + */ + f->colorspace = V4L2_COLORSPACE_REC709; + f->ycbcr_enc = V4L2_YCBCR_ENC_709; + f->xfer_func = V4L2_XFER_FUNC_709; +} + +/* This function looks up the closest available resolution. */ +int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f, + const struct atomisp_format_bridge **fmt_ret, + const struct atomisp_format_bridge **snr_fmt_ret) +{ + const struct atomisp_format_bridge *fmt, *snr_fmt; + struct atomisp_sub_device *asd = &isp->asd; struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; struct v4l2_subdev_pad_config pad_cfg; struct v4l2_subdev_state pad_state = { @@ -3670,33 +3705,29 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f) struct v4l2_subdev_format format = { .which = V4L2_SUBDEV_FORMAT_TRY, }; - const struct atomisp_format_bridge *fmt; int ret; - if (!asd) { - dev_err(isp->dev, "%s(): asd is NULL, device is %s\n", - __func__, vdev->name); - return -EINVAL; - } - if (!input->camera) return -EINVAL; fmt = atomisp_get_format_bridge(f->pixelformat); - if (!fmt) { - dev_err(isp->dev, "unsupported pixelformat!\n"); - fmt = atomisp_output_fmts; + /* Currently, raw formats are broken!!! */ + if (!fmt || fmt->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) { + f->pixelformat = V4L2_PIX_FMT_YUV420; + + fmt = atomisp_get_format_bridge(f->pixelformat); + if (!fmt) + return -EINVAL; } - if (f->width <= 0 || f->height <= 0) - return -EINVAL; - - format.format.code = fmt->mbus_code; - format.format.width = f->width; - format.format.height = f->height; - - __atomisp_init_stream_info(ATOMISP_INPUT_STREAM_GENERAL, - (struct atomisp_input_stream_info *)format.format.reserved); + /* + * atomisp_set_fmt() will set the sensor resolution to the requested + * resolution + padding. Add padding here and remove it again after + * the set_fmt call, like atomisp_set_fmt_to_snr() does. + */ + v4l2_fill_mbus_format(&format.format, f, fmt->mbus_code); + format.format.width += pad_w; + format.format.height += pad_h; dev_dbg(isp->dev, "try_mbus_fmt: asking for %ux%u\n", format.format.width, format.format.height); @@ -3708,16 +3739,15 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f) dev_dbg(isp->dev, "try_mbus_fmt: got %ux%u\n", format.format.width, format.format.height); - fmt = atomisp_get_format_bridge_from_mbus(format.format.code); - if (!fmt) { + snr_fmt = atomisp_get_format_bridge_from_mbus(format.format.code); + if (!snr_fmt) { dev_err(isp->dev, "unknown sensor format 0x%8.8x\n", format.format.code); return -EINVAL; } - f->pixelformat = fmt->pixelformat; - f->width = format.format.width; - f->height = format.format.height; + f->width = format.format.width - pad_w; + f->height = format.format.height - pad_h; /* * If the format is jpeg or custom RAW, then the width and height will @@ -3727,7 +3757,7 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f) */ if (f->pixelformat == V4L2_PIX_FMT_JPEG || f->pixelformat == V4L2_PIX_FMT_CUSTOM_M10MO_RAW) - return 0; + goto out_fill_pix_format; /* app vs isp */ f->width = rounddown(clamp_t(u32, f->width, ATOM_ISP_MIN_WIDTH, @@ -3735,6 +3765,15 @@ int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f) f->height = rounddown(clamp_t(u32, f->height, ATOM_ISP_MIN_HEIGHT, ATOM_ISP_MAX_HEIGHT), ATOM_ISP_STEP_HEIGHT); +out_fill_pix_format: + atomisp_fill_pix_format(f, f->width, f->height, fmt); + + if (fmt_ret) + *fmt_ret = fmt; + + if (snr_fmt_ret) + *snr_fmt_ret = snr_fmt; + return 0; } @@ -3900,7 +3939,7 @@ static int css_input_resolution_changed(struct atomisp_sub_device *asd, static int atomisp_set_fmt_to_isp(struct video_device *vdev, struct ia_css_frame_info *output_info, - struct v4l2_pix_format *pix) + const struct v4l2_pix_format *pix) { struct camera_mipi_info *mipi_info; struct atomisp_device *isp = video_get_drvdata(vdev); @@ -4213,16 +4252,12 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) struct atomisp_device *isp = video_get_drvdata(vdev); struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); struct atomisp_sub_device *asd = pipe->asd; - struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; const struct atomisp_format_bridge *format_bridge; const struct atomisp_format_bridge *snr_format_bridge; struct ia_css_frame_info output_info; unsigned int dvs_env_w = 0, dvs_env_h = 0; unsigned int padding_w = pad_w, padding_h = pad_h; struct v4l2_mbus_framefmt isp_source_fmt = {0}; - struct v4l2_subdev_format vformat = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - }; struct v4l2_rect isp_sink_crop; int ret; @@ -4234,41 +4269,13 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) "setting resolution %ux%u bytesperline %u\n", f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.bytesperline); - format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat); - if (!format_bridge) - return -EINVAL; - - /* Currently, raw formats are broken!!! */ - - if (format_bridge->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) { - f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; - - format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat); - if (!format_bridge) - return -EINVAL; - } - pipe->sh_fmt = format_bridge->sh_fmt; - pipe->pix.pixelformat = f->fmt.pix.pixelformat; - /* Ensure that the resolution is equal or below the maximum supported */ - - vformat.which = V4L2_SUBDEV_FORMAT_ACTIVE; - v4l2_fill_mbus_format(&vformat.format, &f->fmt.pix, format_bridge->mbus_code); - vformat.format.height += padding_h; - vformat.format.width += padding_w; - - ret = v4l2_subdev_call(input->camera, pad, set_fmt, NULL, &vformat); + ret = atomisp_try_fmt(isp, &f->fmt.pix, &format_bridge, &snr_format_bridge); if (ret) return ret; - f->fmt.pix.width = vformat.format.width - padding_w; - f->fmt.pix.height = vformat.format.height - padding_h; - - snr_format_bridge = atomisp_get_format_bridge_from_mbus(vformat.format.code); - if (!snr_format_bridge) { - dev_warn(isp->dev, "Can't find bridge format\n"); - return -EINVAL; - } + pipe->sh_fmt = format_bridge->sh_fmt; + pipe->pix.pixelformat = format_bridge->pixelformat; atomisp_subdev_get_ffmt(&asd->subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, @@ -4348,42 +4355,11 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) return -EINVAL; } - pipe->pix.width = f->fmt.pix.width; - pipe->pix.height = f->fmt.pix.height; - pipe->pix.pixelformat = f->fmt.pix.pixelformat; - /* - * FIXME: do we need to setup this differently, depending on the - * sensor or the pipeline? - */ - pipe->pix.colorspace = V4L2_COLORSPACE_REC709; - pipe->pix.ycbcr_enc = V4L2_YCBCR_ENC_709; - pipe->pix.xfer_func = V4L2_XFER_FUNC_709; - - if (format_bridge->planar) { - pipe->pix.bytesperline = output_info.padded_width; - pipe->pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * - DIV_ROUND_UP(format_bridge->depth * - output_info.padded_width, 8)); - } else { - pipe->pix.bytesperline = - DIV_ROUND_UP(format_bridge->depth * - output_info.padded_width, 8); - pipe->pix.sizeimage = - PAGE_ALIGN(f->fmt.pix.height * pipe->pix.bytesperline); - } - dev_dbg(isp->dev, "%s: image size: %d, %d bytes per line\n", - __func__, pipe->pix.sizeimage, pipe->pix.bytesperline); - - if (f->fmt.pix.field == V4L2_FIELD_ANY) - f->fmt.pix.field = V4L2_FIELD_NONE; - pipe->pix.field = f->fmt.pix.field; + atomisp_fill_pix_format(&pipe->pix, f->fmt.pix.width, f->fmt.pix.height, format_bridge); f->fmt.pix = pipe->pix; f->fmt.pix.priv = PAGE_ALIGN(pipe->pix.width * pipe->pix.height * 2); - /* Report the needed sizes */ - f->fmt.pix.sizeimage = pipe->pix.sizeimage; - f->fmt.pix.bytesperline = pipe->pix.bytesperline; dev_dbg(isp->dev, "%s: %dx%d, image size: %d, %d bytes per line\n", __func__, diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.h b/drivers/staging/media/atomisp/pci/atomisp_cmd.h index ff2178c96fb8..c9a587b34e70 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.h +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.h @@ -251,7 +251,9 @@ int atomisp_compare_grid(struct atomisp_sub_device *asd, struct atomisp_grid_info *atomgrid); /* This function looks up the closest available resolution. */ -int atomisp_try_fmt(struct video_device *vdev, struct v4l2_pix_format *f); +int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f, + const struct atomisp_format_bridge **fmt_ret, + const struct atomisp_format_bridge **snr_fmt_ret); int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f); diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 384d3bf2b61e..446297fef861 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -806,77 +806,14 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh, return -EINVAL; } -static int atomisp_adjust_fmt(struct v4l2_format *f) -{ - const struct atomisp_format_bridge *format_bridge; - u32 padded_width; - - format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat); - /* Currently, raw formats are broken!!! */ - if (!format_bridge || format_bridge->sh_fmt == IA_CSS_FRAME_FORMAT_RAW) { - f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; - - format_bridge = atomisp_get_format_bridge(f->fmt.pix.pixelformat); - if (!format_bridge) - return -EINVAL; - } - - padded_width = f->fmt.pix.width + pad_w; - - if (format_bridge->planar) { - f->fmt.pix.bytesperline = padded_width; - f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * - DIV_ROUND_UP(format_bridge->depth * - padded_width, 8)); - } else { - f->fmt.pix.bytesperline = DIV_ROUND_UP(format_bridge->depth * - padded_width, 8); - f->fmt.pix.sizeimage = PAGE_ALIGN(f->fmt.pix.height * f->fmt.pix.bytesperline); - } - - if (f->fmt.pix.field == V4L2_FIELD_ANY) - f->fmt.pix.field = V4L2_FIELD_NONE; - - /* - * FIXME: do we need to setup this differently, depending on the - * sensor or the pipeline? - */ - f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; - f->fmt.pix.ycbcr_enc = V4L2_YCBCR_ENC_709; - f->fmt.pix.xfer_func = V4L2_XFER_FUNC_709; - - f->fmt.pix.width -= pad_w; - f->fmt.pix.height -= pad_h; - - return 0; -} - /* This function looks up the closest available resolution. */ static int atomisp_try_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) { struct video_device *vdev = video_devdata(file); - u32 pixfmt = f->fmt.pix.pixelformat; - int ret; + struct atomisp_device *isp = video_get_drvdata(vdev); - /* - * atomisp_try_fmt() gived results with padding included, note - * (this gets removed again by the atomisp_adjust_fmt() call below. - */ - f->fmt.pix.width += pad_w; - f->fmt.pix.height += pad_h; - - ret = atomisp_try_fmt(vdev, &f->fmt.pix); - if (ret) - return ret; - - /* - * atomisp_try_fmt() replaces pixelformat with the sensors native - * format, restore the actual format requested by userspace. - */ - f->fmt.pix.pixelformat = pixfmt; - - return atomisp_adjust_fmt(f); + return atomisp_try_fmt(isp, &f->fmt.pix, NULL, NULL); } static int atomisp_g_fmt_cap(struct file *file, void *fh, From 04eca831605390071be83b87774e4987639e6331 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:35 +0100 Subject: [PATCH 204/253] media: atomisp: Add support for sensors which implement selection API / cropping Sensor drivers which implement set_selection V4L2_SEL_TGT_CROP expect v4l2_subdev_state.pads[pad].try_crop to have valid contents when calling set_fmt with which == V4L2_SUBDEV_FORMAT_TRY since the crop-rectangle may influence the available image size. Just passing an uninitalized struct v4l2_subdev_pad_config from the stack to set_fmt with which == V4L2_SUBDEV_FORMAT_TRY will result in wrong results with such drivers. Store a per sensor v4l2_subdev_pad_config and add a new atomisp_init_sensor_crop() function to initialize this before registering /dev/* nodes with userspace. Sensor drivers which implement the selection API will allow the atomisp to properly deal with the extra padding the ISP wants on a per sensor basis instead of hardcoding this. atomisp_init_sensor_crop() stores the native and active rects of the sensor in preparation for using these for this. Link: https://lore.kernel.org/r/20230529103741.11904-16-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 6 +- .../media/atomisp/pci/atomisp_internal.h | 7 +++ .../staging/media/atomisp/pci/atomisp_v4l2.c | 55 +++++++++++++++++++ 3 files changed, 64 insertions(+), 4 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index e17d057f8867..4564b9ad7223 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -3698,9 +3698,8 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f, const struct atomisp_format_bridge *fmt, *snr_fmt; struct atomisp_sub_device *asd = &isp->asd; struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; - struct v4l2_subdev_pad_config pad_cfg; struct v4l2_subdev_state pad_state = { - .pads = &pad_cfg, + .pads = &input->pad_cfg, }; struct v4l2_subdev_format format = { .which = V4L2_SUBDEV_FORMAT_TRY, @@ -4164,9 +4163,8 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p struct atomisp_device *isp = asd->isp; struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; const struct atomisp_format_bridge *format; - struct v4l2_subdev_pad_config pad_cfg; struct v4l2_subdev_state pad_state = { - .pads = &pad_cfg, + .pads = &input->pad_cfg, }; struct v4l2_subdev_format vformat = { .which = V4L2_SUBDEV_FORMAT_TRY, diff --git a/drivers/staging/media/atomisp/pci/atomisp_internal.h b/drivers/staging/media/atomisp/pci/atomisp_internal.h index e59c0f1e7f53..14d21c6e227d 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_internal.h +++ b/drivers/staging/media/atomisp/pci/atomisp_internal.h @@ -125,7 +125,14 @@ struct atomisp_input_subdev { unsigned int type; enum atomisp_camera_port port; + bool crop_support; struct v4l2_subdev *camera; + /* Sensor rects for sensors which support crop */ + struct v4l2_rect native_rect; + struct v4l2_rect active_rect; + /* Sensor pad_cfg for which == V4L2_SUBDEV_FORMAT_TRY calls */ + struct v4l2_subdev_pad_config pad_cfg; + struct v4l2_subdev *motor; /* diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index a2ce9bbf10df..506f04ca92b1 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -931,6 +931,59 @@ v4l2_device_failed: return ret; } +static void atomisp_init_sensor(struct atomisp_input_subdev *input) +{ + struct v4l2_subdev_state sd_state = { + .pads = &input->pad_cfg, + }; + struct v4l2_subdev_selection sel = { }; + int err; + + sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; + sel.target = V4L2_SEL_TGT_NATIVE_SIZE; + err = v4l2_subdev_call(input->camera, pad, get_selection, NULL, &sel); + if (err) + return; + + input->native_rect = sel.r; + + sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; + sel.target = V4L2_SEL_TGT_CROP_DEFAULT; + err = v4l2_subdev_call(input->camera, pad, get_selection, NULL, &sel); + if (err) + return; + + input->active_rect = sel.r; + + /* + * The ISP also wants the non-active pixels at the border of the sensor + * for padding, set the crop rect to cover the entire sensor instead + * of only the default active area. + * + * Do this for both try and active formats since the try_crop rect in + * pad_cfg may influence (clamp) future try_fmt calls with which == try. + */ + sel.which = V4L2_SUBDEV_FORMAT_TRY; + sel.target = V4L2_SEL_TGT_CROP; + sel.r = input->native_rect; + err = v4l2_subdev_call(input->camera, pad, set_selection, &sd_state, &sel); + if (err) + return; + + sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; + sel.target = V4L2_SEL_TGT_CROP; + sel.r = input->native_rect; + err = v4l2_subdev_call(input->camera, pad, set_selection, NULL, &sel); + if (err) + return; + + dev_info(input->camera->dev, "Supports crop native %dx%d active %dx%d\n", + input->native_rect.width, input->native_rect.height, + input->active_rect.width, input->active_rect.height); + + input->crop_support = true; +} + int atomisp_register_device_nodes(struct atomisp_device *isp) { struct atomisp_input_subdev *input; @@ -952,6 +1005,8 @@ int atomisp_register_device_nodes(struct atomisp_device *isp) input->port = i; input->camera = isp->sensor_subdevs[i]; + atomisp_init_sensor(input); + /* * HACK: Currently VCM belongs to primary sensor only, but correct * approach must be to acquire from platform code which sensor From a08183b8460e4800c186b754026b6fd937370871 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:36 +0100 Subject: [PATCH 205/253] media: atomisp: Pass MEDIA_BUS_FMT_* code when calling enum_frame_size pad-op A sensor driver's enum_frame_size pad-op may return -EINVAL when v4l2_subdev_frame_size_enum.code is not set to a supported MEDIA_BUS_FMT_* code. Make atomisp_init_sensor() get the sensor's MEDIA_BUS_FMT_* code and pass this when calling the enum_frame_size pad-op. Link: https://lore.kernel.org/r/20230529103741.11904-17-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_internal.h | 1 + drivers/staging/media/atomisp/pci/atomisp_ioctl.c | 1 + drivers/staging/media/atomisp/pci/atomisp_v4l2.c | 6 ++++++ 3 files changed, 8 insertions(+) diff --git a/drivers/staging/media/atomisp/pci/atomisp_internal.h b/drivers/staging/media/atomisp/pci/atomisp_internal.h index 14d21c6e227d..9fded17a2c71 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_internal.h +++ b/drivers/staging/media/atomisp/pci/atomisp_internal.h @@ -125,6 +125,7 @@ struct atomisp_input_subdev { unsigned int type; enum atomisp_camera_port port; + u32 code; /* MEDIA_BUS_FMT_* */ bool crop_support; struct v4l2_subdev *camera; /* Sensor rects for sensors which support crop */ diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 446297fef861..c5465b28a65d 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -707,6 +707,7 @@ static int atomisp_enum_framesizes(struct file *file, void *priv, struct v4l2_subdev_frame_size_enum fse = { .index = fsize->index, .which = V4L2_SUBDEV_FORMAT_ACTIVE, + .code = input->code, }; int ret; diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index 506f04ca92b1..3a2e15605919 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -933,12 +933,18 @@ v4l2_device_failed: static void atomisp_init_sensor(struct atomisp_input_subdev *input) { + struct v4l2_subdev_mbus_code_enum mbus_code_enum = { }; struct v4l2_subdev_state sd_state = { .pads = &input->pad_cfg, }; struct v4l2_subdev_selection sel = { }; int err; + mbus_code_enum.which = V4L2_SUBDEV_FORMAT_ACTIVE; + err = v4l2_subdev_call(input->camera, pad, enum_mbus_code, NULL, &mbus_code_enum); + if (!err) + input->code = mbus_code_enum.code; + sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; sel.target = V4L2_SEL_TGT_NATIVE_SIZE; err = v4l2_subdev_call(input->camera, pad, get_selection, NULL, &sel); From 62866c23c78d2c5db85bf82d61d8801aa9e93176 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:37 +0100 Subject: [PATCH 206/253] media: atomisp: Make atomisp_init_sensor() check if the sensor supports binning Make atomisp_init_sensor() check if the sensor supports binning. This is a preparation patch for using the selection / crop support to determine the padding values to use with a specific sensor. Link: https://lore.kernel.org/r/20230529103741.11904-18-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/atomisp_internal.h | 1 + .../staging/media/atomisp/pci/atomisp_v4l2.c | 30 +++++++++++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_internal.h b/drivers/staging/media/atomisp/pci/atomisp_internal.h index 9fded17a2c71..f7b4bee9574b 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_internal.h +++ b/drivers/staging/media/atomisp/pci/atomisp_internal.h @@ -126,6 +126,7 @@ struct atomisp_input_subdev { unsigned int type; enum atomisp_camera_port port; u32 code; /* MEDIA_BUS_FMT_* */ + bool binning_support; bool crop_support; struct v4l2_subdev *camera; /* Sensor rects for sensors which support crop */ diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index 3a2e15605919..c43b916a006e 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -934,11 +934,12 @@ v4l2_device_failed: static void atomisp_init_sensor(struct atomisp_input_subdev *input) { struct v4l2_subdev_mbus_code_enum mbus_code_enum = { }; + struct v4l2_subdev_frame_size_enum fse = { }; struct v4l2_subdev_state sd_state = { .pads = &input->pad_cfg, }; struct v4l2_subdev_selection sel = { }; - int err; + int i, err; mbus_code_enum.which = V4L2_SUBDEV_FORMAT_ACTIVE; err = v4l2_subdev_call(input->camera, pad, enum_mbus_code, NULL, &mbus_code_enum); @@ -961,6 +962,28 @@ static void atomisp_init_sensor(struct atomisp_input_subdev *input) input->active_rect = sel.r; + /* + * Check for a framesize with half active_rect width and height, + * if found assume the sensor supports binning. + * Do this before changing the crop-rect since that may influence + * enum_frame_size results. + */ + for (i = 0; ; i++) { + fse.index = i; + fse.code = input->code; + fse.which = V4L2_SUBDEV_FORMAT_ACTIVE; + + err = v4l2_subdev_call(input->camera, pad, enum_frame_size, NULL, &fse); + if (err) + break; + + if (fse.min_width <= (input->active_rect.width / 2) && + fse.min_height <= (input->active_rect.height / 2)) { + input->binning_support = true; + break; + } + } + /* * The ISP also wants the non-active pixels at the border of the sensor * for padding, set the crop rect to cover the entire sensor instead @@ -983,9 +1006,10 @@ static void atomisp_init_sensor(struct atomisp_input_subdev *input) if (err) return; - dev_info(input->camera->dev, "Supports crop native %dx%d active %dx%d\n", + dev_info(input->camera->dev, "Supports crop native %dx%d active %dx%d binning %d\n", input->native_rect.width, input->native_rect.height, - input->active_rect.width, input->active_rect.height); + input->active_rect.width, input->active_rect.height, + input->binning_support); input->crop_support = true; } From 3e399cf20f69b7f810bcdf98c8df6b1c2af88465 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:38 +0100 Subject: [PATCH 207/253] media: atomisp: Use selection API info to determine sensor padding Using the selection / crop info to determine the padding values to use with a specific resolution on specific sensor. This allows e.g. automatically halving the padding when using the max binned resolution and also ensures the right amount of padding is used on models with 2 sensors with different padding requirements. Link: https://lore.kernel.org/r/20230529103741.11904-19-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 57 ++++++++++++++----- .../media/atomisp/pci/atomisp_subdev.c | 14 +---- .../media/atomisp/pci/atomisp_subdev.h | 3 + 3 files changed, 48 insertions(+), 26 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 4564b9ad7223..eba4d3ceaa31 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -3690,6 +3690,33 @@ static void atomisp_fill_pix_format(struct v4l2_pix_format *f, f->xfer_func = V4L2_XFER_FUNC_709; } +/* Get sensor padding values for the non padded width x height resolution */ +static void atomisp_get_padding(struct atomisp_device *isp, + u32 width, u32 height, + u32 *padding_w, u32 *padding_h) +{ + struct atomisp_input_subdev *input = &isp->inputs[isp->asd.input_curr]; + struct v4l2_rect native_rect = input->native_rect; + + if (!input->crop_support) { + *padding_w = pad_w; + *padding_h = pad_h; + return; + } + + width = min(width, input->active_rect.width); + height = min(height, input->active_rect.height); + + if (input->binning_support && width <= (input->active_rect.width / 2) && + height <= (input->active_rect.height / 2)) { + native_rect.width /= 2; + native_rect.height /= 2; + } + + *padding_w = min_t(u32, (native_rect.width - width) & ~1, pad_w); + *padding_h = min_t(u32, (native_rect.height - height) & ~1, pad_h); +} + /* This function looks up the closest available resolution. */ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f, const struct atomisp_format_bridge **fmt_ret, @@ -3704,6 +3731,7 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f, struct v4l2_subdev_format format = { .which = V4L2_SUBDEV_FORMAT_TRY, }; + u32 padding_w, padding_h; int ret; if (!input->camera) @@ -3724,9 +3752,10 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f, * resolution + padding. Add padding here and remove it again after * the set_fmt call, like atomisp_set_fmt_to_snr() does. */ + atomisp_get_padding(isp, f->width, f->height, &padding_w, &padding_h); v4l2_fill_mbus_format(&format.format, f, fmt->mbus_code); - format.format.width += pad_w; - format.format.height += pad_h; + format.format.width += padding_w; + format.format.height += padding_h; dev_dbg(isp->dev, "try_mbus_fmt: asking for %ux%u\n", format.format.width, format.format.height); @@ -3745,8 +3774,8 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f, return -EINVAL; } - f->width = format.format.width - pad_w; - f->height = format.format.height - pad_h; + f->width = format.format.width - padding_w; + f->height = format.format.height - padding_h; /* * If the format is jpeg or custom RAW, then the width and height will @@ -4155,7 +4184,6 @@ static void atomisp_check_copy_mode(struct atomisp_sub_device *asd, } static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_pix_format *f, - unsigned int padding_w, unsigned int padding_h, unsigned int dvs_env_w, unsigned int dvs_env_h) { struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); @@ -4186,11 +4214,11 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p return -EINVAL; v4l2_fill_mbus_format(ffmt, f, format->mbus_code); - ffmt->height += padding_h + dvs_env_h; - ffmt->width += padding_w + dvs_env_w; + ffmt->height += asd->sink_pad_padding_h + dvs_env_h; + ffmt->width += asd->sink_pad_padding_w + dvs_env_w; dev_dbg(isp->dev, "s_mbus_fmt: ask %ux%u (padding %ux%u, dvs %ux%u)\n", - ffmt->width, ffmt->height, padding_w, padding_h, + ffmt->width, ffmt->height, asd->sink_pad_padding_w, asd->sink_pad_padding_h, dvs_env_w, dvs_env_h); __atomisp_init_stream_info(ATOMISP_INPUT_STREAM_GENERAL, stream_info); @@ -4254,7 +4282,6 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) const struct atomisp_format_bridge *snr_format_bridge; struct ia_css_frame_info output_info; unsigned int dvs_env_w = 0, dvs_env_h = 0; - unsigned int padding_w = pad_w, padding_h = pad_h; struct v4l2_mbus_framefmt isp_source_fmt = {0}; struct v4l2_rect isp_sink_crop; int ret; @@ -4285,16 +4312,18 @@ int atomisp_set_fmt(struct video_device *vdev, struct v4l2_format *f) V4L2_SUBDEV_FORMAT_ACTIVE, ATOMISP_SUBDEV_PAD_SOURCE, &isp_source_fmt); - if (!atomisp_subdev_format_conversion(asd)) { - padding_w = 0; - padding_h = 0; + if (atomisp_subdev_format_conversion(asd)) { + atomisp_get_padding(isp, f->fmt.pix.width, f->fmt.pix.height, + &asd->sink_pad_padding_w, &asd->sink_pad_padding_h); + } else { + asd->sink_pad_padding_w = 0; + asd->sink_pad_padding_h = 0; } atomisp_get_dis_envelop(asd, f->fmt.pix.width, f->fmt.pix.height, &dvs_env_w, &dvs_env_h); - ret = atomisp_set_fmt_to_snr(vdev, &f->fmt.pix, - padding_w, padding_h, dvs_env_w, dvs_env_h); + ret = atomisp_set_fmt_to_snr(vdev, &f->fmt.pix, dvs_env_w, dvs_env_h); if (ret) { dev_warn(isp->dev, "Set format to sensor failed with %d\n", ret); diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.c b/drivers/staging/media/atomisp/pci/atomisp_subdev.c index 04e257ede7d4..45073e401bac 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.c +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.c @@ -357,8 +357,6 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *ffmt[ATOMISP_SUBDEV_PADS_NUM]; struct v4l2_rect *crop[ATOMISP_SUBDEV_PADS_NUM], *comp[ATOMISP_SUBDEV_PADS_NUM]; - unsigned int padding_w = pad_w; - unsigned int padding_h = pad_h; if ((pad == ATOMISP_SUBDEV_PAD_SINK && target != V4L2_SEL_TGT_CROP) || (pad == ATOMISP_SUBDEV_PAD_SOURCE && target != V4L2_SEL_TGT_COMPOSE)) @@ -384,18 +382,10 @@ int atomisp_subdev_set_selection(struct v4l2_subdev *sd, crop[pad]->width = ffmt[pad]->width; crop[pad]->height = ffmt[pad]->height; - /* Workaround for BYT 1080p perfectshot since the maxinum resolution of - * front camera ov2722 is 1932x1092 and cannot use pad_w > 12*/ - if (!strncmp(isp->inputs[isp_sd->input_curr].camera->name, - "ov2722", 6) && crop[pad]->height == 1092) { - padding_w = 12; - padding_h = 12; - } - if (atomisp_subdev_format_conversion(isp_sd) && crop[pad]->width && crop[pad]->height) { - crop[pad]->width -= padding_w; - crop[pad]->height -= padding_h; + crop[pad]->width -= isp_sd->sink_pad_padding_w; + crop[pad]->height -= isp_sd->sink_pad_padding_h; } if (isp_sd->params.video_dis_en && diff --git a/drivers/staging/media/atomisp/pci/atomisp_subdev.h b/drivers/staging/media/atomisp/pci/atomisp_subdev.h index c9f6561dbcb6..9a04511b9efd 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_subdev.h +++ b/drivers/staging/media/atomisp/pci/atomisp_subdev.h @@ -239,6 +239,9 @@ struct atomisp_sub_device { struct v4l2_subdev subdev; struct media_pad pads[ATOMISP_SUBDEV_PADS_NUM]; struct atomisp_pad_format fmt[ATOMISP_SUBDEV_PADS_NUM]; + /* Padding for currently set sink-pad fmt */ + u32 sink_pad_padding_w; + u32 sink_pad_padding_h; unsigned int output; struct atomisp_video_pipe video_out; From 1e28b9e048b5edd29c7bf9c8ce6d9d5dcda6f36b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:39 +0100 Subject: [PATCH 208/253] media: atomisp: Set crop before setting fmt Some drivers which implement selections/crop only allow setting the format with and height to either the crop rectangle width and height or to half the crop rectangle width and height (binning). An example of such a driver is the standard v4l2 ov5693 driver. First set the crop rectangle to match the requested format when trying or setting the sensor format, to match these drivers expectations. Link: https://lore.kernel.org/r/20230529103741.11904-20-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index eba4d3ceaa31..76307f793dc8 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -3717,6 +3717,47 @@ static void atomisp_get_padding(struct atomisp_device *isp, *padding_h = min_t(u32, (native_rect.height - height) & ~1, pad_h); } +static int atomisp_set_crop(struct atomisp_device *isp, + const struct v4l2_mbus_framefmt *format, + int which) +{ + struct atomisp_input_subdev *input = &isp->inputs[isp->asd.input_curr]; + struct v4l2_subdev_state pad_state = { + .pads = &input->pad_cfg, + }; + struct v4l2_subdev_selection sel = { + .which = which, + .target = V4L2_SEL_TGT_CROP, + .r.width = format->width, + .r.height = format->height, + }; + int ret; + + if (!input->crop_support) + return 0; + + /* Cropping is done before binning, when binning double the crop rect */ + if (input->binning_support && sel.r.width <= (input->active_rect.width / 2) && + sel.r.height <= (input->active_rect.height / 2)) { + sel.r.width *= 2; + sel.r.height *= 2; + } + + /* Clamp to avoid top/left calculations overflowing */ + sel.r.width = min(sel.r.width, input->native_rect.width); + sel.r.height = min(sel.r.height, input->native_rect.height); + + sel.r.left = ((input->native_rect.width - sel.r.width) / 2) & ~1; + sel.r.top = ((input->native_rect.height - sel.r.height) / 2) & ~1; + + ret = v4l2_subdev_call(input->camera, pad, set_selection, &pad_state, &sel); + if (ret) + dev_err(isp->dev, "Error setting crop to %ux%u @%ux%u: %d\n", + sel.r.width, sel.r.height, sel.r.left, sel.r.top, ret); + + return ret; +} + /* This function looks up the closest available resolution. */ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f, const struct atomisp_format_bridge **fmt_ret, @@ -3760,6 +3801,10 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f, dev_dbg(isp->dev, "try_mbus_fmt: asking for %ux%u\n", format.format.width, format.format.height); + ret = atomisp_set_crop(isp, &format.format, V4L2_SUBDEV_FORMAT_TRY); + if (ret) + return ret; + ret = v4l2_subdev_call(input->camera, pad, set_fmt, &pad_state, &format); if (ret) return ret; @@ -4227,6 +4272,10 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p /* Disable dvs if resolution can't be supported by sensor */ if (asd->params.video_dis_en && asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { + ret = atomisp_set_crop(isp, &vformat.format, V4L2_SUBDEV_FORMAT_TRY); + if (ret) + return ret; + vformat.which = V4L2_SUBDEV_FORMAT_TRY; ret = v4l2_subdev_call(input->camera, pad, set_fmt, &pad_state, &vformat); if (ret) @@ -4245,6 +4294,11 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p asd->params.video_dis_en = false; } } + + ret = atomisp_set_crop(isp, &vformat.format, V4L2_SUBDEV_FORMAT_ACTIVE); + if (ret) + return ret; + vformat.which = V4L2_SUBDEV_FORMAT_ACTIVE; ret = v4l2_subdev_call(input->camera, pad, set_fmt, NULL, &vformat); if (ret) From e980fb04e779730b799a4ba712db901a7b08e8f9 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:40 +0100 Subject: [PATCH 209/253] media: atomisp: Add enum_framesizes function for sensors with selection / crop support Some sensor drivers with crop support (e.g. the ov5693 driver) only return the current crop rectangle + 1/2 (binning) of the current crop rectangle when calling their enum_frame_sizes op. This causes 2 issues: 1. Atomisp sets to the crop area to include the padding, where as the enum_framesizes ioctl should return values without padding. 2. With cropping a lot more standard resolutions are possible then just these 2 and many apps limit the list given to the end user to the list returned by enum_framesizes. Add an alternative enum_framesizes function for sensors which support cropping to fix both issues. Link: https://lore.kernel.org/r/20230529103741.11904-21-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/TODO | 3 - .../staging/media/atomisp/pci/atomisp_ioctl.c | 69 +++++++++++++++++++ 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/drivers/staging/media/atomisp/TODO b/drivers/staging/media/atomisp/TODO index 12fe1f21b169..b7a09eb20d0d 100644 --- a/drivers/staging/media/atomisp/TODO +++ b/drivers/staging/media/atomisp/TODO @@ -32,9 +32,6 @@ TODO * The atomisp ov2680 and ov5693 sensor drivers bind to the same hw-ids as the standard ov2680 and ov5693 drivers under drivers/media/i2c, which conflicts. Drop the atomisp private ov2680 and ov5693 drivers: - * Make atomisp code use v4l2 selections to deal with the extra padding - it wants to receive from sensors instead of relying on the ov2680 code - sending e.g. 1616x1216 for a 1600x1200 mode * Port various ov2680 improvements from atomisp_ov2680.c to regular ov2680.c and switch to regular ov2680 driver * Make atomisp work with the regular ov5693 driver and drop atomisp_ov5693 diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index c5465b28a65d..279493af6e0d 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -697,6 +697,72 @@ static int atomisp_s_input(struct file *file, void *fh, unsigned int input) return 0; } +/* + * With crop any framesize <= sensor-size can be made, give + * userspace a list of sizes to choice from. + */ +static int atomisp_enum_framesizes_crop_inner(struct atomisp_device *isp, + struct v4l2_frmsizeenum *fsize, + struct v4l2_rect *active, + int *valid_sizes) +{ + static const struct v4l2_frmsize_discrete frame_sizes[] = { + { 1600, 1200 }, + { 1600, 1080 }, + { 1600, 900 }, + { 1440, 1080 }, + { 1280, 960 }, + { 1280, 720 }, + { 800, 600 }, + { 640, 480 }, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(frame_sizes); i++) { + if (frame_sizes[i].width > active->width || + frame_sizes[i].height > active->height) + continue; + + /* + * Skip sizes where width and height are less then 2/3th of the + * sensor size to avoid sizes with a too small field of view. + */ + if (frame_sizes[i].width < (active->width * 2 / 3) && + frame_sizes[i].height < (active->height * 2 / 3)) + continue; + + if (*valid_sizes == fsize->index) { + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete = frame_sizes[i]; + return 0; + } + + (*valid_sizes)++; + } + + return -EINVAL; +} + +static int atomisp_enum_framesizes_crop(struct atomisp_device *isp, + struct v4l2_frmsizeenum *fsize) +{ + struct atomisp_input_subdev *input = &isp->inputs[isp->asd.input_curr]; + struct v4l2_rect active = input->active_rect; + int ret, valid_sizes = 0; + + ret = atomisp_enum_framesizes_crop_inner(isp, fsize, &active, &valid_sizes); + if (ret == 0) + return 0; + + if (!input->binning_support) + return -EINVAL; + + active.width /= 2; + active.height /= 2; + + return atomisp_enum_framesizes_crop_inner(isp, fsize, &active, &valid_sizes); +} + static int atomisp_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize) { @@ -711,6 +777,9 @@ static int atomisp_enum_framesizes(struct file *file, void *priv, }; int ret; + if (input->crop_support) + return atomisp_enum_framesizes_crop(isp, fsize); + ret = v4l2_subdev_call(input->camera, pad, enum_frame_size, NULL, &fse); if (ret) return ret; From 0af9078315c1a737675f041996c02582610b7cfd Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 29 May 2023 11:37:41 +0100 Subject: [PATCH 210/253] media: atomisp: csi2-bridge: Set PMC clk-rate for sensors to 19.2 MHz The ACPI code takes care of enabling/disabling the PMC clk(s) for the sensors as necessary based on the runtime-pm state of the sensor. But the GMIN code this replaces also set the clk-rate of the PMC clk to 19.2 MHz. At least on BYT devices the PMC clks may come up running at 25 MHz instead of the expected 19.2 MHz. Ensure the sensor clk also runs at the expected 19.2 MHz for sensors using v4l2-async probing by explicitly setting it to 19.2 MHz when enumerating sensors in atomisp_csi2_bridge.c. Link: https://lore.kernel.org/r/20230529103741.11904-22-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/pci/atomisp_csi2_bridge.c | 68 ++++++++++++++++--- 1 file changed, 60 insertions(+), 8 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c index b55a7ff9844e..28d8779bbbc4 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c @@ -10,6 +10,7 @@ */ #include +#include #include #include #include @@ -38,6 +39,8 @@ .properties = _PROPS, \ }) +#define PMC_CLK_RATE_19_2MHZ 19200000 + /* * 79234640-9e10-4fea-a5c1-b5aa8b19756f * This _DSM GUID returns information about the GPIO lines mapped to a sensor. @@ -250,24 +253,61 @@ static int atomisp_csi2_get_pmc_clk_nr_from_acpi_pr0(struct acpi_device *adev) } ACPI_FREE(buffer.pointer); + + if (ret < 0) + acpi_handle_warn(adev->handle, "Could not find PMC clk in _PR0\n"); + return ret; } -static int atomisp_csi2_get_port(struct acpi_device *adev) +static int atomisp_csi2_set_pmc_clk_freq(struct acpi_device *adev, int clock_num) { - int clock_num, port; + struct clk *clk; + char name[14]; + int ret; + + if (clock_num < 0) + return 0; + + snprintf(name, sizeof(name), "pmc_plt_clk_%d", clock_num); + + clk = clk_get(NULL, name); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + acpi_handle_err(adev->handle, "Error getting clk %s:%d\n", name, ret); + return ret; + } /* - * Get PMC-clock number from ACPI _PR0 method and compare this to - * the CsiPort 1 PMC-clock used in the CHT/BYT reference designs. + * The firmware might enable the clock at boot, to change + * the rate we must ensure the clock is disabled. + */ + ret = clk_prepare_enable(clk); + if (!ret) + clk_disable_unprepare(clk); + if (!ret) + ret = clk_set_rate(clk, PMC_CLK_RATE_19_2MHZ); + if (ret) + acpi_handle_err(adev->handle, "Error setting clk-rate for %s:%d\n", name, ret); + + clk_put(clk); + return ret; +} + +static int atomisp_csi2_get_port(struct acpi_device *adev, int clock_num) +{ + int port; + + /* + * Compare clock-number to the PMC-clock used for CsiPort 1 + * in the CHT/BYT reference designs. */ - clock_num = atomisp_csi2_get_pmc_clk_nr_from_acpi_pr0(adev); if (IS_ISP2401) port = clock_num == 4 ? 1 : 0; else port = clock_num == 0 ? 1 : 0; - /* Intel DSM or DMI quirk overrides PR0 derived default */ + /* Intel DSM or DMI quirk overrides _PR0 CLK derived default */ return gmin_cfg_get_int(adev, "CsiPort", port); } @@ -551,7 +591,7 @@ static int atomisp_csi2_connect_sensor(const struct atomisp_csi2_sensor_config * struct fwnode_handle *fwnode, *primary; struct atomisp_csi2_sensor *sensor; struct acpi_device *adev; - int ret; + int ret, clock_num; for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) { if (!adev->status.enabled) @@ -565,7 +605,19 @@ static int atomisp_csi2_connect_sensor(const struct atomisp_csi2_sensor_config * sensor = &bridge->sensors[bridge->n_sensors]; - sensor->port = atomisp_csi2_get_port(adev); + /* + * ACPI takes care of turning the PMC clock on and off, but on BYT + * the clock defaults to 25 MHz instead of the expected 19.2 MHz. + * Get the PMC-clock number from ACPI _PR0 method and set it to 19.2 MHz. + * The PMC-clock number is also used to determine the default CSI port. + */ + clock_num = atomisp_csi2_get_pmc_clk_nr_from_acpi_pr0(adev); + + ret = atomisp_csi2_set_pmc_clk_freq(adev, clock_num); + if (ret) + goto err_put_adev; + + sensor->port = atomisp_csi2_get_port(adev, clock_num); if (sensor->port >= ATOMISP_CAMERA_NR_PORTS) { acpi_handle_err(adev->handle, "Invalid port: %d\n", sensor->port); ret = -EINVAL; From 72f0ba79a063ec2b21d5874e41c6d82193100515 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 1 Jun 2023 15:58:56 +0100 Subject: [PATCH 211/253] media: atomisp: Take minimum padding requirement on BYT/ISP2400 into account The main binary for the pipeline on BYT/ISP2400 has its ia_css_binary_info.pipeline.left_cropping and .top_cropping fields set to 12. So a minimum padding of 12 is required. And for certain bayer-orders additional width / height padding is necessary so that the ISP crop rectangle for the raw sensor data can be used to change the bayer-order to the fixed bayer-order supported by the debayer block. Without the minmum required padding ia_css_ifmtr_configure() will fail inside ifmtr_input_start_line() and/or ifmtr_start_column() because it cannot set the ISP crop rectangle for the raw sensor data. Fix this by making atomisp_get_padding() take the minimum padding requirements into account on BYT/ISP2400 (CHT/ISP2401 does not seem to need this). Link: https://lore.kernel.org/r/20230601145858.59652-2-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 33 +++++++++++++++++++ .../media/atomisp/pci/atomisp_common.h | 4 +++ 2 files changed, 37 insertions(+) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 76307f793dc8..5c984edfb3fc 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -3697,6 +3697,10 @@ static void atomisp_get_padding(struct atomisp_device *isp, { struct atomisp_input_subdev *input = &isp->inputs[isp->asd.input_curr]; struct v4l2_rect native_rect = input->native_rect; + const struct atomisp_in_fmt_conv *fc = NULL; + u32 min_pad_w = ISP2400_MIN_PAD_W; + u32 min_pad_h = ISP2400_MIN_PAD_H; + struct v4l2_mbus_framefmt *sink; if (!input->crop_support) { *padding_w = pad_w; @@ -3715,6 +3719,35 @@ static void atomisp_get_padding(struct atomisp_device *isp, *padding_w = min_t(u32, (native_rect.width - width) & ~1, pad_w); *padding_h = min_t(u32, (native_rect.height - height) & ~1, pad_h); + + /* The below minimum padding requirements are for BYT / ISP2400 only */ + if (IS_ISP2401) + return; + + sink = atomisp_subdev_get_ffmt(&isp->asd.subdev, NULL, V4L2_SUBDEV_FORMAT_ACTIVE, + ATOMISP_SUBDEV_PAD_SINK); + if (sink) + fc = atomisp_find_in_fmt_conv(sink->code); + if (!fc) { + dev_warn(isp->dev, "%s: Could not get sensor format\n", __func__); + goto apply_min_padding; + } + + /* + * The ISP only supports GRBG for other bayer-orders additional padding + * is used so that the raw sensor data can be cropped to fix the order. + */ + if (fc->bayer_order == IA_CSS_BAYER_ORDER_RGGB || + fc->bayer_order == IA_CSS_BAYER_ORDER_GBRG) + min_pad_w += 2; + + if (fc->bayer_order == IA_CSS_BAYER_ORDER_BGGR || + fc->bayer_order == IA_CSS_BAYER_ORDER_GBRG) + min_pad_h += 2; + +apply_min_padding: + *padding_w = max_t(u32, *padding_w, min_pad_w); + *padding_h = max_t(u32, *padding_h, min_pad_h); } static int atomisp_set_crop(struct atomisp_device *isp, diff --git a/drivers/staging/media/atomisp/pci/atomisp_common.h b/drivers/staging/media/atomisp/pci/atomisp_common.h index 07c38e487a66..9d23a6ccfc33 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_common.h +++ b/drivers/staging/media/atomisp/pci/atomisp_common.h @@ -37,6 +37,10 @@ extern int mipicsi_flag; extern int pad_w; extern int pad_h; +/* Minimum padding requirements for ISP2400 (BYT) */ +#define ISP2400_MIN_PAD_W 12 +#define ISP2400_MIN_PAD_H 12 + #define CSS_DTRACE_VERBOSITY_LEVEL 5 /* Controls trace verbosity */ #define CSS_DTRACE_VERBOSITY_TIMEOUT 9 /* Verbosity on ISP timeout */ #define MRFLD_MAX_ZOOM_FACTOR 1024 From 0f417dc1b7330aae06f155ea505899fa74b2eabe Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 1 Jun 2023 15:58:57 +0100 Subject: [PATCH 212/253] media: atomisp: Make atomisp_enum_framesizes_crop() check resolution fits with padding Now that atomisp_get_padding() takes minimum padding requirements on BYT/ISP2400 into account, it is possible for a resolution which fits in the active area of the sensor to not fit in the native area once padding is added. For example on the ov2680 which has a native resolution of 1616x1216 the max active resolution of 1600x1200 leaves 16x16 for padding which meets the worst-case minimum padding requirement of 14x14 on BYT. But after binning we are left with an native area of 808x608 and an active area of 800x600. This leaves 8x8 for padding which is not enough. So on BYT 800x600 is not a valid resolution (it could be made by lots of cropping without binning but then the remaining field of view is no good). Modify atomisp_enum_framesizes_crop() to check the resolution + padding fits in the native rectangle, removing 800x600 from the list of valid modes on BYT. Link: https://lore.kernel.org/r/20230601145858.59652-3-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- .../staging/media/atomisp/pci/atomisp_cmd.c | 5 ++--- .../staging/media/atomisp/pci/atomisp_cmd.h | 4 ++++ .../staging/media/atomisp/pci/atomisp_ioctl.c | 18 +++++++++++++----- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 5c984edfb3fc..68550cd49a83 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -3691,9 +3691,8 @@ static void atomisp_fill_pix_format(struct v4l2_pix_format *f, } /* Get sensor padding values for the non padded width x height resolution */ -static void atomisp_get_padding(struct atomisp_device *isp, - u32 width, u32 height, - u32 *padding_w, u32 *padding_h) +void atomisp_get_padding(struct atomisp_device *isp, u32 width, u32 height, + u32 *padding_w, u32 *padding_h) { struct atomisp_input_subdev *input = &isp->inputs[isp->asd.input_curr]; struct v4l2_rect native_rect = input->native_rect; diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.h b/drivers/staging/media/atomisp/pci/atomisp_cmd.h index c9a587b34e70..8305161d2062 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.h +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.h @@ -250,6 +250,10 @@ int atomisp_makeup_css_parameters(struct atomisp_sub_device *asd, int atomisp_compare_grid(struct atomisp_sub_device *asd, struct atomisp_grid_info *atomgrid); +/* Get sensor padding values for the non padded width x height resolution */ +void atomisp_get_padding(struct atomisp_device *isp, u32 width, u32 height, + u32 *padding_w, u32 *padding_h); + /* This function looks up the closest available resolution. */ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f, const struct atomisp_format_bridge **fmt_ret, diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 279493af6e0d..d2174156573a 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -703,7 +703,8 @@ static int atomisp_s_input(struct file *file, void *fh, unsigned int input) */ static int atomisp_enum_framesizes_crop_inner(struct atomisp_device *isp, struct v4l2_frmsizeenum *fsize, - struct v4l2_rect *active, + const struct v4l2_rect *active, + const struct v4l2_rect *native, int *valid_sizes) { static const struct v4l2_frmsize_discrete frame_sizes[] = { @@ -716,11 +717,15 @@ static int atomisp_enum_framesizes_crop_inner(struct atomisp_device *isp, { 800, 600 }, { 640, 480 }, }; + u32 padding_w, padding_h; int i; for (i = 0; i < ARRAY_SIZE(frame_sizes); i++) { - if (frame_sizes[i].width > active->width || - frame_sizes[i].height > active->height) + atomisp_get_padding(isp, frame_sizes[i].width, frame_sizes[i].height, + &padding_w, &padding_h); + + if ((frame_sizes[i].width + padding_w) > native->width || + (frame_sizes[i].height + padding_h) > native->height) continue; /* @@ -748,9 +753,10 @@ static int atomisp_enum_framesizes_crop(struct atomisp_device *isp, { struct atomisp_input_subdev *input = &isp->inputs[isp->asd.input_curr]; struct v4l2_rect active = input->active_rect; + struct v4l2_rect native = input->native_rect; int ret, valid_sizes = 0; - ret = atomisp_enum_framesizes_crop_inner(isp, fsize, &active, &valid_sizes); + ret = atomisp_enum_framesizes_crop_inner(isp, fsize, &active, &native, &valid_sizes); if (ret == 0) return 0; @@ -759,8 +765,10 @@ static int atomisp_enum_framesizes_crop(struct atomisp_device *isp, active.width /= 2; active.height /= 2; + native.width /= 2; + native.height /= 2; - return atomisp_enum_framesizes_crop_inner(isp, fsize, &active, &valid_sizes); + return atomisp_enum_framesizes_crop_inner(isp, fsize, &active, &native, &valid_sizes); } static int atomisp_enum_framesizes(struct file *file, void *priv, From 930d333a00e1c7ac6caa83b70402367069f6c377 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 1 Jun 2023 15:58:58 +0100 Subject: [PATCH 213/253] media: atomisp: Fix binning check in atomisp_set_crop() The fmt / size passed to atomisp_set_crop() includes padding, so the binning check should be against 1/2 of the native rect. of the sensor, rather then 1/2 of the active rect. This fixes binning not being used when using e.g. 800x600 on a 1600x1200 sensor leading to a very small field of view. Link: https://lore.kernel.org/r/20230601145858.59652-4-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 68550cd49a83..e27f9dc8e7aa 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -3769,8 +3769,8 @@ static int atomisp_set_crop(struct atomisp_device *isp, return 0; /* Cropping is done before binning, when binning double the crop rect */ - if (input->binning_support && sel.r.width <= (input->active_rect.width / 2) && - sel.r.height <= (input->active_rect.height / 2)) { + if (input->binning_support && sel.r.width <= (input->native_rect.width / 2) && + sel.r.height <= (input->native_rect.height / 2)) { sel.r.width *= 2; sel.r.height *= 2; } From ef0feca22e866a8544847232fe32d5fdc11f0fbd Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 4 Jun 2023 17:14:02 +0100 Subject: [PATCH 214/253] media: atomisp: Stop resetting selected input to 0 between /dev/video# opens No other V4L2 driver resets the selected input (front cam or back cam selected in case of the atomisp). Stop resetting selected input to 0 between /dev/video# opens. This allows e.g. using v4l2-ctl -i to switch the input before starting another app, which is useful since most apps don't support selecting the input. Note more in general the whole resetting of a bunch of internal state from the open fop needs to be removed there to allow multiple opens of /dev/video# for full v4l2 API compliance. Link: https://lore.kernel.org/r/20230604161406.69369-2-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_fops.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_fops.c b/drivers/staging/media/atomisp/pci/atomisp_fops.c index 36e441dce7d5..54466d2f323a 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_fops.c +++ b/drivers/staging/media/atomisp/pci/atomisp_fops.c @@ -474,9 +474,6 @@ static void atomisp_subdev_init_struct(struct atomisp_sub_device *asd) /* s3a grid not enabled for any pipe */ asd->params.s3a_enabled_pipe = IA_CSS_PIPE_ID_NUM; - /* Add for channel */ - asd->input_curr = 0; - asd->copy_mode = false; asd->stream_prepared = false; From 7d45a432251a30ed0252655177e708229b163291 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 4 Jun 2023 17:14:03 +0100 Subject: [PATCH 215/253] media: atomisp: ov2680: Stop using half pixelclock for binned modes Stop using half pixelclock for binned modes this fixes: 1. The exposure being twice as high for binned mods (due to the half clk) 2. The framerate being 15 fps instead of 30 fps The original code with fixed per mode register lists did use half pixel clk, but this should be combined with using half for the VTS value too. Using half VTS fixes the framerate issue, but this has the undesired side-effect of change the exposure ctrl range (half the range, double the amount of exposure per step). Link: https://lore.kernel.org/r/20230604161406.69369-3-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/i2c/atomisp-ov2680.c | 8 +------- drivers/staging/media/atomisp/i2c/ov2680.h | 1 + 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index 18b604a8b932..10b27a45b885 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -244,27 +244,21 @@ static void ov2680_calc_mode(struct ov2680_dev *sensor) static int ov2680_set_mode(struct ov2680_dev *sensor) { struct i2c_client *client = sensor->client; - u8 pll_div, unknown, inc, fmt1, fmt2; + u8 unknown, inc, fmt1, fmt2; int ret; if (sensor->mode.binning) { - pll_div = 1; unknown = 0x23; inc = 0x31; fmt1 = 0xc2; fmt2 = 0x01; } else { - pll_div = 0; unknown = 0x21; inc = 0x11; fmt1 = 0xc0; fmt2 = 0x00; } - ret = ov_write_reg8(client, 0x3086, pll_div); - if (ret) - return ret; - ret = ov_write_reg8(client, 0x370a, unknown); if (ret) return ret; diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index fd9c7485f8c1..b6c0ef591c69 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -181,6 +181,7 @@ static struct ov2680_reg const ov2680_global_setting[] = { {0x3082, 0x45}, {0x3084, 0x09}, {0x3085, 0x04}, + {0x3086, 0x00}, {0x3503, 0x03}, {0x350b, 0x36}, {0x3600, 0xb4}, From 61ae5ec4c8b8ffbe160ce1acaa860eb9599c46a7 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 4 Jun 2023 17:14:04 +0100 Subject: [PATCH 216/253] media: atomisp: ov2680: Remove unnecessary registers from ov2680_global_setting[] Many of the values in ov2680_global_setting[] match the default/reset register value for the ov2680 sensor (verified with both datasheet and actual hw) so they are no-ops. And there are also a couple of others which are later overwritten by ctrls or by ov2680_set_mode(). Remove all the unnecessary entries and add annotations to the remaining entries documenting what they change (in so far as things are documented in the datasheet). This also removes the double writing of OV2680_REG_SOFT_RESET in ov2680_init_registers() (one direct write, one in ov2680_global_setting[]) instead add a short sleep after the first write to give the sensor time to reset. Link: https://lore.kernel.org/r/20230604161406.69369-4-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- .../media/atomisp/i2c/atomisp-ov2680.c | 4 + drivers/staging/media/atomisp/i2c/ov2680.h | 117 ++++++++---------- 2 files changed, 59 insertions(+), 62 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index 10b27a45b885..85e01358fa19 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -175,6 +175,10 @@ static int ov2680_init_registers(struct v4l2_subdev *sd) int ret; ret = ov_write_reg8(client, OV2680_SW_RESET, 0x01); + + /* Wait for sensor reset */ + usleep_range(1000, 2000); + ret |= ov2680_write_reg_array(client, ov2680_global_setting); return ret; diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index b6c0ef591c69..6a71de55600b 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -172,82 +172,75 @@ static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl) } static struct ov2680_reg const ov2680_global_setting[] = { - {0x0103, 0x01}, - {0x3002, 0x00}, + /* MIPI PHY, 0x10 -> 0x1c enable bp_c_hs_en_lat and bp_d_hs_en_lat */ {0x3016, 0x1c}, - {0x3018, 0x44}, - {0x3020, 0x00}, - {0x3080, 0x02}, + + /* PLL MULT bits 0-7, datasheet default 0x37 for 24MHz extclk, use 0x45 for 19.2 Mhz extclk */ {0x3082, 0x45}, - {0x3084, 0x09}, - {0x3085, 0x04}, - {0x3086, 0x00}, + + /* R MANUAL set exposure (0x01) and gain (0x02) to manual (hw does not do auto) */ {0x3503, 0x03}, - {0x350b, 0x36}, - {0x3600, 0xb4}, - {0x3603, 0x39}, - {0x3604, 0x24}, - {0x3605, 0x00}, - {0x3620, 0x26}, - {0x3621, 0x37}, - {0x3622, 0x04}, - {0x3628, 0x00}, - {0x3705, 0x3c}, - {0x370c, 0x50}, - {0x370d, 0xc0}, - {0x3718, 0x88}, - {0x3720, 0x00}, - {0x3721, 0x00}, - {0x3722, 0x00}, - {0x3723, 0x00}, - {0x3738, 0x00}, - {0x3717, 0x58}, - {0x3781, 0x80}, - {0x3789, 0x60}, - {0x3800, 0x00}, - {0x3819, 0x04}, + + /* Analog control register tweaks */ + {0x3603, 0x39}, /* Reset value 0x99 */ + {0x3604, 0x24}, /* Reset value 0x74 */ + {0x3621, 0x37}, /* Reset value 0x44 */ + + /* Sensor control register tweaks */ + {0x3701, 0x64}, /* Reset value 0x61 */ + {0x3705, 0x3c}, /* Reset value 0x21 */ + {0x370c, 0x50}, /* Reset value 0x10 */ + {0x370d, 0xc0}, /* Reset value 0x00 */ + {0x3718, 0x88}, /* Reset value 0x80 */ + + /* PSRAM tweaks */ + {0x3781, 0x80}, /* Reset value 0x00 */ + {0x3784, 0x0c}, /* Reset value 0x00, based on OV2680_R1A_AM10.ovt */ + {0x3789, 0x60}, /* Reset value 0x50 */ + + /* BLC CTRL00 0x01 -> 0x81 set avg_weight to 8 */ {0x4000, 0x81}, - {0x4001, 0x40}, + + /* Set black level compensation range to 0 - 3 (default 0 - 11) */ {0x4008, 0x00}, {0x4009, 0x03}, + + /* VFIFO R2 0x00 -> 0x02 set Frame reset enable */ {0x4602, 0x02}, + + /* MIPI ctrl CLK PREPARE MIN change from 0x26 (38) -> 0x36 (54) */ {0x481f, 0x36}, + + /* MIPI ctrl CLK LPX P MIN change from 0x32 (50) -> 0x36 (54) */ {0x4825, 0x36}, - {0x4837, 0x18}, + + /* R ISP CTRL2 0x20 -> 0x30, set sof_sel bit */ {0x5002, 0x30}, - {0x5004, 0x04},//manual awb 1x - {0x5005, 0x00}, - {0x5006, 0x04}, - {0x5007, 0x00}, - {0x5008, 0x04}, - {0x5009, 0x00}, - {0x5080, 0x00}, - {0x5081, 0x41}, - {0x5708, 0x01}, /* add for full size flip off and mirror off 2014/09/11 */ - {0x3701, 0x64}, //add on 14/05/13 - {0x3784, 0x0c}, //based OV2680_R1A_AM10.ovt add on 14/06/13 - {0x5780, 0x3e}, //based OV2680_R1A_AM10.ovt,Adjust DPC setting (57xx) on 14/06/13 - {0x5781, 0x0f}, - {0x5782, 0x04}, - {0x5783, 0x02}, - {0x5784, 0x01}, - {0x5785, 0x01}, - {0x5786, 0x00}, - {0x5787, 0x04}, + + /* + * Window CONTROL 0x00 -> 0x01, enable manual window control, + * this is necessary for full size flip and mirror support. + */ + {0x5708, 0x01}, + + /* + * DPC CTRL0 0x14 -> 0x3e, set enable_tail, enable_3x3_cluster + * and enable_general_tail bits based OV2680_R1A_AM10.ovt. + */ + {0x5780, 0x3e}, + + /* DPC MORE CONNECTION CASE THRE 0x0c (12) -> 0x02 (2) */ {0x5788, 0x02}, - {0x5789, 0x00}, - {0x578a, 0x01}, - {0x578b, 0x02}, - {0x578c, 0x03}, - {0x578d, 0x03}, + + /* DPC GAIN LIST1 0x0f (15) -> 0x08 (8) */ {0x578e, 0x08}, + + /* DPC GAIN LIST2 0x3f (63) -> 0x0c (12) */ {0x578f, 0x0c}, - {0x5790, 0x08}, - {0x5791, 0x04}, + + /* DPC THRE RATIO 0x04 (4) -> 0x00 (0) */ {0x5792, 0x00}, - {0x5793, 0x00}, - {0x5794, 0x03}, //based OV2680_R1A_AM10.ovt,Adjust DPC setting (57xx) on 14/06/13 - {0x0100, 0x00}, //stream off + {} }; From dbacd5c5e1ff4220c239f4522de3450996cea62f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 4 Jun 2023 17:14:05 +0100 Subject: [PATCH 217/253] media: atomisp: ov2680: Rename unknown/0x370a to sensor_ctrl_0a The data sheets say the registers at offset 0x3700 - 0x373f are "sensor control" registers rename the unknown variable in ov2680_set_mode() to sensor_ctrl_0a and add a OV2680_REG_SENSOR_CTRL_0A define. Link: https://lore.kernel.org/r/20230604161406.69369-5-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/i2c/atomisp-ov2680.c | 8 ++++---- drivers/staging/media/atomisp/i2c/ov2680.h | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index 85e01358fa19..4cc2839937af 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -248,22 +248,22 @@ static void ov2680_calc_mode(struct ov2680_dev *sensor) static int ov2680_set_mode(struct ov2680_dev *sensor) { struct i2c_client *client = sensor->client; - u8 unknown, inc, fmt1, fmt2; + u8 sensor_ctrl_0a, inc, fmt1, fmt2; int ret; if (sensor->mode.binning) { - unknown = 0x23; + sensor_ctrl_0a = 0x23; inc = 0x31; fmt1 = 0xc2; fmt2 = 0x01; } else { - unknown = 0x21; + sensor_ctrl_0a = 0x21; inc = 0x11; fmt1 = 0xc0; fmt2 = 0x00; } - ret = ov_write_reg8(client, 0x370a, unknown); + ret = ov_write_reg8(client, OV2680_REG_SENSOR_CTRL_0A, sensor_ctrl_0a); if (ret) return ret; diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index 6a71de55600b..d032af245674 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -72,6 +72,8 @@ #define OV2680_REG_EXPOSURE_PK_HIGH 0x3500 #define OV2680_REG_GAIN_PK 0x350a +#define OV2680_REG_SENSOR_CTRL_0A 0x370a + #define OV2680_HORIZONTAL_START_H 0x3800 /* Bit[11:8] */ #define OV2680_HORIZONTAL_START_L 0x3801 /* Bit[7:0] */ #define OV2680_VERTICAL_START_H 0x3802 /* Bit[11:8] */ From 4f7d1334114f056b4b5bc102bd22d078a7154923 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 4 Jun 2023 17:14:06 +0100 Subject: [PATCH 218/253] media: atomisp: Add testing instructions to TODO file Testing the atomisp can be a bit tricky. The BYT/CHT CPUs are not very powerful so some apps like camorama cannot run at full FPS. Add instructions for how to test with gstreamer which does runs at full FPS without issues. Link: https://lore.kernel.org/r/20230604161406.69369-6-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/TODO | 33 ++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/staging/media/atomisp/TODO b/drivers/staging/media/atomisp/TODO index b7a09eb20d0d..ecf8ba67b7af 100644 --- a/drivers/staging/media/atomisp/TODO +++ b/drivers/staging/media/atomisp/TODO @@ -78,3 +78,36 @@ TODO the firmware files * The atomisp code still has a lot of cruft which needs cleaning up + + +Testing +======= + +Since libcamera support is not available yet, the easiest way to test for +now is using v4l2-ctl to select the input and gstreamer for streaming. + +To select the input run: + +v4l2-ctl -i + +Where is 0 (front cam) or 1 (back cam). + +The simplest gstreamer pipeline for testing running the sensor +at its max resolution is: + +gst-launch-1.0 v4l2src ! videoconvert ! xvimagesink sync=false + +To select e.g 640x480 as resolution use: + +gst-launch-1.0 v4l2src ! video/x-raw,format=YV12,width=640,height=480 ! \ + videoconvert ! xvimagesink sync=false + +And to show fps use: + +gst-launch-1.0 v4l2src ! video/x-raw,format=YV12,width=640,height=480 ! \ + videoconvert ! fpsdisplaysink video-sink=xvimagesink sync=false + +Often the image will be over / under exposed. This can be fixed by using +v4l2-ctl on the sensor subdev to tweak the exposure ctrl; or by using a GUI +app for v4l2-controls which also supports subdev such as the Fedora patched +gtk-v4l tool. From f7c487366b3a82ced30923e591aaab0cdf1e4199 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 6 Jun 2023 14:31:36 +0100 Subject: [PATCH 219/253] media: atomisp: csi2-bridge: Add support for setting "clock-" and "link-frequencies" props Some standard v4l2 sensor drivers from drivers/media/i2c expect a "clock-frequency" property on the device indicating the frequency of the extclk for the sensor. Example of such drivers are the ov2680 and ov5693 drivers. The standard ov5693 sensor also expects a "link-frequencies" property. Add support for setting both properties. Note the "clock-frequency" prop is added before the "rotation" prop while the "link-frequencies" are added at the end to match the ipu3 cio2-bridge code from which this is derived. Link: https://lore.kernel.org/r/20230606133136.23619-1-hdegoede@redhat.com Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/atomisp/pci/atomisp_csi2.h | 13 +++++++++---- .../staging/media/atomisp/pci/atomisp_csi2_bridge.c | 12 ++++++++++-- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2.h b/drivers/staging/media/atomisp/pci/atomisp_csi2.h index b389ccda5e98..16ddb3ab2963 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_csi2.h +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2.h @@ -31,6 +31,7 @@ #define CSI2_PADS_NUM 2 #define CSI2_MAX_LANES 4 +#define CSI2_MAX_LINK_FREQS 3 #define CSI2_MAX_ACPI_GPIOS 2u @@ -64,10 +65,12 @@ enum atomisp_csi2_sensor_swnodes { }; struct atomisp_csi2_property_names { + char clock_frequency[16]; char rotation[9]; char bus_type[9]; char data_lanes[11]; char remote_endpoint[16]; + char link_frequencies[17]; }; struct atomisp_csi2_node_names { @@ -79,6 +82,8 @@ struct atomisp_csi2_node_names { struct atomisp_csi2_sensor_config { const char *hid; int lanes; + int nr_link_freqs; + u64 link_freqs[CSI2_MAX_LINK_FREQS]; }; struct atomisp_csi2_sensor { @@ -93,10 +98,10 @@ struct atomisp_csi2_sensor { struct software_node swnodes[SWNODE_COUNT]; struct atomisp_csi2_node_names node_names; struct atomisp_csi2_property_names prop_names; - /* "rotation" + terminating entry */ - struct property_entry dev_properties[2]; - /* "bus-type", "data-lanes", "remote-endpoint" + terminating entry */ - struct property_entry ep_properties[4]; + /* "clock-frequency", "rotation" + terminating entry */ + struct property_entry dev_properties[3]; + /* "bus-type", "data-lanes", "remote-endpoint" + "link-freq" + terminating entry */ + struct property_entry ep_properties[5]; /* "data-lanes", "remote-endpoint" + terminating entry */ struct property_entry csi2_properties[3]; struct software_node_ref_args local_ref[1]; diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c index 28d8779bbbc4..0d12ba78d9c1 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2_bridge.c @@ -85,7 +85,7 @@ static const guid_t atomisp_dsm_guid = /* * Extend this array with ACPI Hardware IDs of sensors known to be working - * plus the number of links expected by their drivers. + * plus the default number of links + link-frequencies. * * Do not add an entry for a sensor that is not actually supported, * or which have not yet been converted to work without atomisp_gmin @@ -492,10 +492,12 @@ static int atomisp_csi2_add_gpio_mappings(struct atomisp_csi2_sensor *sensor, } static const struct atomisp_csi2_property_names prop_names = { + .clock_frequency = "clock-frequency", .rotation = "rotation", .bus_type = "bus-type", .data_lanes = "data-lanes", .remote_endpoint = "remote-endpoint", + .link_frequencies = "link-frequencies", }; static void atomisp_csi2_create_fwnode_properties(struct atomisp_csi2_sensor *sensor, @@ -507,7 +509,9 @@ static void atomisp_csi2_create_fwnode_properties(struct atomisp_csi2_sensor *se sensor->local_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_CSI2_ENDPOINT]); sensor->remote_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_SENSOR_ENDPOINT]); - sensor->dev_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.rotation, 0); + sensor->dev_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.clock_frequency, + PMC_CLK_RATE_19_2MHZ); + sensor->dev_properties[1] = PROPERTY_ENTRY_U32(sensor->prop_names.rotation, 0); sensor->ep_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.bus_type, V4L2_FWNODE_BUS_TYPE_CSI2_DPHY); @@ -516,6 +520,10 @@ static void atomisp_csi2_create_fwnode_properties(struct atomisp_csi2_sensor *se sensor->lanes); sensor->ep_properties[2] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint, sensor->local_ref); + if (cfg->nr_link_freqs > 0) + sensor->ep_properties[3] = + PROPERTY_ENTRY_U64_ARRAY_LEN(sensor->prop_names.link_frequencies, + cfg->link_freqs, cfg->nr_link_freqs); sensor->csi2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes, bridge->data_lanes, From 254f3337ce2575bf94f1fb40cc40fdbc70371116 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 24 May 2023 13:11:44 +0100 Subject: [PATCH 220/253] media: rockchip: rga: fix clock cleanup Fix this smatch warning: drivers/media/platform/rockchip/rga/rga.c:734 rga_enable_clocks() warn: 'rga->sclk' from clk_prepare_enable() not released on lines: 734. The reason is that aclk should be disabled/unprepared before sclk, instead of the other way around. Signed-off-by: Hans Verkuil Cc: Jacob Chen Cc: Ezequiel Garcia Reviewed-by: Michael Tretter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/rockchip/rga/rga.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c index e4b8ce9ab3c6..f1c532a5802a 100644 --- a/drivers/media/platform/rockchip/rga/rga.c +++ b/drivers/media/platform/rockchip/rga/rga.c @@ -723,10 +723,10 @@ static int rga_enable_clocks(struct rockchip_rga *rga) return 0; -err_disable_sclk: - clk_disable_unprepare(rga->sclk); err_disable_aclk: clk_disable_unprepare(rga->aclk); +err_disable_sclk: + clk_disable_unprepare(rga->sclk); return ret; } From 7cc471112edd5292a05698dd3f7b9543844a26a1 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 24 May 2023 13:11:45 +0100 Subject: [PATCH 221/253] media: usb: as102: drop as102_dev NULL check Fixes this smatch warning: drivers/media/usb/as102/as102_usb_drv.c:306 as102_usb_release() warn: can 'as102_dev' even be NULL? And indeed, as102_dev can never be NULL, so just drop the NULL check. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/as102/as102_usb_drv.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/media/usb/as102/as102_usb_drv.c b/drivers/media/usb/as102/as102_usb_drv.c index 50419e8ae56c..6b380144d6c2 100644 --- a/drivers/media/usb/as102/as102_usb_drv.c +++ b/drivers/media/usb/as102/as102_usb_drv.c @@ -303,10 +303,8 @@ static void as102_usb_release(struct kref *kref) struct as102_dev_t *as102_dev; as102_dev = container_of(kref, struct as102_dev_t, kref); - if (as102_dev != NULL) { - usb_put_dev(as102_dev->bus_adap.usb_dev); - kfree(as102_dev); - } + usb_put_dev(as102_dev->bus_adap.usb_dev); + kfree(as102_dev); } static void as102_usb_disconnect(struct usb_interface *intf) From 99f9cd2e25cc4cd1a193c8e4c9ea4877abf6bddd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 24 May 2023 13:11:46 +0100 Subject: [PATCH 222/253] media: platform: renesas-ceu: drop buf NULL check Since start_streaming is only called if there are at least two buffers queued, the ceudev->capture list will never be empty, so the check whether there are no buffers can be dropped. Note that the '!buf' check was wrong in any case, if we wanted to check for an empty list it should have used list_empty(). This fixes this smatch warning: drivers/media/platform/renesas/renesas-ceu.c:705 ceu_start_streaming() warn: can 'buf' even be NULL? Signed-off-by: Hans Verkuil Reviewed-by: Jacopo Mondi Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/renesas/renesas-ceu.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/media/platform/renesas/renesas-ceu.c b/drivers/media/platform/renesas/renesas-ceu.c index 56b9c59cfda8..5c9e27f8c94b 100644 --- a/drivers/media/platform/renesas/renesas-ceu.c +++ b/drivers/media/platform/renesas/renesas-ceu.c @@ -702,12 +702,6 @@ static int ceu_start_streaming(struct vb2_queue *vq, unsigned int count) /* Grab the first available buffer and trigger the first capture. */ buf = list_first_entry(&ceudev->capture, struct ceu_buffer, queue); - if (!buf) { - spin_unlock_irqrestore(&ceudev->lock, irqflags); - dev_dbg(ceudev->dev, - "No buffer available for capture.\n"); - goto error_stop_sensor; - } list_del(&buf->queue); ceudev->active = &buf->vb; @@ -722,9 +716,6 @@ static int ceu_start_streaming(struct vb2_queue *vq, unsigned int count) return 0; -error_stop_sensor: - v4l2_subdev_call(v4l2_sd, video, s_stream, 0); - error_return_bufs: spin_lock_irqsave(&ceudev->lock, irqflags); list_for_each_entry(buf, &ceudev->capture, queue) From 3df55cd773e8603b623425cc97b05e542854ad27 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 24 May 2023 13:11:47 +0100 Subject: [PATCH 223/253] media: platform: mediatek: vpu: fix NULL ptr dereference If pdev is NULL, then it is still dereferenced. This fixes this smatch warning: drivers/media/platform/mediatek/vpu/mtk_vpu.c:570 vpu_load_firmware() warn: address of NULL pointer 'pdev' Signed-off-by: Hans Verkuil Cc: Yunfei Dong Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/mediatek/vpu/mtk_vpu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/mediatek/vpu/mtk_vpu.c b/drivers/media/platform/mediatek/vpu/mtk_vpu.c index 5e2bc286f168..1a95958a1f90 100644 --- a/drivers/media/platform/mediatek/vpu/mtk_vpu.c +++ b/drivers/media/platform/mediatek/vpu/mtk_vpu.c @@ -562,15 +562,17 @@ static int load_requested_vpu(struct mtk_vpu *vpu, int vpu_load_firmware(struct platform_device *pdev) { struct mtk_vpu *vpu; - struct device *dev = &pdev->dev; + struct device *dev; struct vpu_run *run; int ret; if (!pdev) { - dev_err(dev, "VPU platform device is invalid\n"); + pr_err("VPU platform device is invalid\n"); return -EINVAL; } + dev = &pdev->dev; + vpu = platform_get_drvdata(pdev); run = &vpu->run; From 2192fa95276b0561a579fa4cd19de3f16d47d171 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 24 May 2023 13:11:48 +0100 Subject: [PATCH 224/253] media: mediatek: vpu: add missing clk_unprepare If vpu_clock_enable() fails, then call clk_unprepare(). This fixes this smatch warning: drivers/media/platform/mediatek/vpu/mtk_vpu.c:1031 mtk_vpu_resume() warn: 'vpu->clk' from clk_prepare() not released on lines: 1020. Signed-off-by: Hans Verkuil Cc: Yunfei Dong Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/mediatek/vpu/mtk_vpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/mediatek/vpu/mtk_vpu.c b/drivers/media/platform/mediatek/vpu/mtk_vpu.c index 1a95958a1f90..4c8f5296d120 100644 --- a/drivers/media/platform/mediatek/vpu/mtk_vpu.c +++ b/drivers/media/platform/mediatek/vpu/mtk_vpu.c @@ -1018,6 +1018,7 @@ static int mtk_vpu_resume(struct device *dev) clk_prepare(vpu->clk); ret = vpu_clock_enable(vpu); if (ret) { + clk_unprepare(vpu->clk); dev_err(dev, "failed to enable vpu clock\n"); return ret; } From 2104793233c2b803107fa39baa9fa149648adce7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 24 May 2023 13:11:49 +0100 Subject: [PATCH 225/253] media: pci: tw686x: no need to check 'next' If 'done' is not NULL, then next can never be NULL, so just drop the 'next' check. This fixes this smatch warning: drivers/media/pci/tw686x/tw686x-audio.c:62 tw686x_audio_irq() warn: can 'next' even be NULL? Signed-off-by: Hans Verkuil Cc: Ezequiel Garcia Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/tw686x/tw686x-audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/tw686x/tw686x-audio.c b/drivers/media/pci/tw686x/tw686x-audio.c index 74cba1368cfa..1ae3845b6743 100644 --- a/drivers/media/pci/tw686x/tw686x-audio.c +++ b/drivers/media/pci/tw686x/tw686x-audio.c @@ -59,7 +59,7 @@ void tw686x_audio_irq(struct tw686x_dev *dev, unsigned long requests, } spin_unlock_irqrestore(&ac->lock, flags); - if (!done || !next) + if (!done) continue; /* * Checking for a non-nil dma_desc[pb]->virt buffer is From 9de30f579980b498606a9c2440b73ae3b670771b Mon Sep 17 00:00:00 2001 From: Daniel Almeida Date: Mon, 6 Mar 2023 16:18:50 +0000 Subject: [PATCH 226/253] media: Add AV1 uAPI This patch adds the AOMedia Video 1 (AV1) kernel uAPI. This design is based on currently available AV1 API implementations and aims to support the development of AV1 stateless video codecs on Linux. Signed-off-by: Daniel Almeida Co-developed-by: Nicolas Dufresne Signed-off-by: Nicolas Dufresne Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../userspace-api/media/v4l/biblio.rst | 9 + .../media/v4l/ext-ctrls-codec-stateless.rst | 1209 ++++++++++++++++- .../media/v4l/pixfmt-compressed.rst | 16 + .../media/v4l/vidioc-g-ext-ctrls.rst | 16 + .../media/v4l/vidioc-queryctrl.rst | 24 + .../media/videodev2.h.rst.exceptions | 4 + drivers/media/v4l2-core/v4l2-ctrls-core.c | 258 ++++ drivers/media/v4l2-core/v4l2-ctrls-defs.c | 61 + drivers/media/v4l2-core/v4l2-ioctl.c | 1 + include/media/v4l2-ctrls.h | 8 + include/uapi/linux/v4l2-controls.h | 721 ++++++++++ include/uapi/linux/videodev2.h | 10 + 12 files changed, 2335 insertions(+), 2 deletions(-) diff --git a/Documentation/userspace-api/media/v4l/biblio.rst b/Documentation/userspace-api/media/v4l/biblio.rst index 9cd18c153d19..72aef1759b60 100644 --- a/Documentation/userspace-api/media/v4l/biblio.rst +++ b/Documentation/userspace-api/media/v4l/biblio.rst @@ -427,3 +427,12 @@ VP9 :title: VP9 Bitstream & Decoding Process Specification :author: Adrian Grange (Google), Peter de Rivaz (Argon Design), Jonathan Hunt (Argon Design) + +.. _av1: + +AV1 +=== + +:title: AV1 Bitstream & Decoding Process Specification + +:author: Peter de Rivaz, Argon Design Ltd, Jack Haughton, Argon Design Ltd diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst index 677bf0fbcc5a..81e60f4002c8 100644 --- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst +++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec-stateless.rst @@ -1890,11 +1890,11 @@ params syntax' of the :ref:`vp9` specification for more details. * - __u8 - ``tree_probs[7]`` - Specifies the probability values to be used when decoding a Segment-ID. - See '5.15. Segmentation map' section of :ref:`vp9` for more details. + See '5.15 Segmentation map' section of :ref:`vp9` for more details. * - __u8 - ``pred_probs[3]`` - Specifies the probability values to be used when decoding a - Predicted-Segment-ID. See '6.4.14. Get segment id syntax' + Predicted-Segment-ID. See '6.4.14 Get segment id syntax' section of :ref:`vp9` for more details. * - __u8 - ``flags`` @@ -2957,3 +2957,1208 @@ This structure contains all loop filter related parameters. See sections * - ``V4L2_HEVC_DECODE_PARAM_FLAG_NO_OUTPUT_OF_PRIOR`` - 0x00000004 - + +.. _v4l2-codec-stateless-av1: + +``V4L2_CID_STATELESS_AV1_SEQUENCE (struct)`` + Represents an AV1 Sequence OBU (Open Bitstream Unit). See section 5.5 + "Sequence header OBU syntax" in :ref:`av1` for more details. + +.. c:type:: v4l2_ctrl_av1_sequence + +.. cssclass:: longtable + +.. tabularcolumns:: |p{5.8cm}|p{4.8cm}|p{6.6cm}| + +.. flat-table:: struct v4l2_ctrl_av1_sequence + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u32 + - ``flags`` + - See :ref:`AV1 Sequence Flags `. + * - __u8 + - ``seq_profile`` + - Specifies the features that can be used in the coded video sequence. + * - __u8 + - ``order_hint_bits`` + - Specifies the number of bits used for the order_hint field at each frame. + * - __u8 + - ``bit_depth`` + - the bit depth to use for the sequence as described in section 5.5.2 + "Color config syntax" in :ref:`av1` for more details. + * - __u8 + - ``reserved`` + - Applications and drivers must set this to zero. + * - __u16 + - ``max_frame_width_minus_1`` + - specifies the maximum frame width minus 1 for the frames represented by + this sequence header. + +.. _av1_sequence_flags: + +``AV1 Sequence Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_SEQUENCE_FLAG_STILL_PICTURE`` + - 0x00000001 + - If set, specifies that the coded video sequence contains only one coded + frame. If not set, specifies that the coded video sequence contains one + or more coded frames. + * - ``V4L2_AV1_SEQUENCE_FLAG_USE_128X128_SUPERBLOCK`` + - 0x00000002 + - If set, indicates that superblocks contain 128x128 luma samples. + When equal to 0, it indicates that superblocks contain 64x64 luma + samples. The number of contained chroma samples depends on + subsampling_x and subsampling_y. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_FILTER_INTRA`` + - 0x00000004 + - If set, specifies that the use_filter_intra syntax element may be + present. If not set, specifies that the use_filter_intra syntax element + will not be present. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTRA_EDGE_FILTER`` + - 0x00000008 + - Specifies whether the intra edge filtering process should be enabled. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTERINTRA_COMPOUND`` + - 0x00000010 + - If set, specifies that the mode info for inter blocks may contain the + syntax element interintra. If not set, specifies that the syntax element + interintra will not be present. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_MASKED_COMPOUND`` + - 0x00000020 + - If set, specifies that the mode info for inter blocks may contain the + syntax element compound_type. If not set, specifies that the syntax + element compound_type will not be present. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_WARPED_MOTION`` + - 0x00000040 + - If set, indicates that the allow_warped_motion syntax element may be + present. If not set, indicates that the allow_warped_motion syntax + element will not be present. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_DUAL_FILTER`` + - 0x00000080 + - If set, indicates that the inter prediction filter type may be specified + independently in the horizontal and vertical directions. If the flag is + equal to 0, only one filter type may be specified, which is then used in + both directions. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_ORDER_HINT`` + - 0x00000100 + - If set, indicates that tools based on the values of order hints may be + used. If not set, indicates that tools based on order hints are + disabled. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_JNT_COMP`` + - 0x00000200 + - If set, indicates that the distance weights process may be used for + inter prediction. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_REF_FRAME_MVS`` + - 0x00000400 + - If set, indicates that the use_ref_frame_mvs syntax element may be + present. If not set, indicates that the use_ref_frame_mvs syntax element + will not be present. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_SUPERRES`` + - 0x00000800 + - If set, specifies that the use_superres syntax element will be present + in the uncompressed header. If not set, specifies that the use_superres + syntax element will not be present (instead use_superres will be set to + 0 in the uncompressed header without being read). + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_CDEF`` + - 0x00001000 + - If set, specifies that cdef filtering may be enabled. If not set, + specifies that cdef filtering is disabled. + * - ``V4L2_AV1_SEQUENCE_FLAG_ENABLE_RESTORATION`` + - 0x00002000 + - If set, specifies that loop restoration filtering may be enabled. If not + set, specifies that loop restoration filtering is disabled. + * - ``V4L2_AV1_SEQUENCE_FLAG_MONO_CHROME`` + - 0x00004000 + - If set, indicates that the video does not contain U and V color planes. + If not set, indicates that the video contains Y, U, and V color planes. + * - ``V4L2_AV1_SEQUENCE_FLAG_COLOR_RANGE`` + - 0x00008000 + - If set, signals full swing representation, i.e. "Full Range + Quantization". If not set, signals studio swing representation, i.e. + "Limited Range Quantization". + * - ``V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_X`` + - 0x00010000 + - Specify the chroma subsampling format. + * - ``V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_Y`` + - 0x00020000 + - Specify the chroma subsampling format. + * - ``V4L2_AV1_SEQUENCE_FLAG_FILM_GRAIN_PARAMS_PRESENT`` + - 0x00040000 + - Specifies whether film grain parameters are present in the coded video + sequence. + * - ``V4L2_AV1_SEQUENCE_FLAG_SEPARATE_UV_DELTA_Q`` + - 0x00080000 + - If set, indicates that the U and V planes may have separate delta + quantizer values. If not set, indicates that the U and V planes will share + the same delta quantizer value. + +``V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY (struct)`` + Represents a single AV1 tile inside an AV1 Tile Group. Note that MiRowStart, + MiRowEnd, MiColStart and MiColEnd can be retrieved from struct + v4l2_av1_tile_info in struct v4l2_ctrl_av1_frame using tile_row and + tile_col. See section 6.10.1 "General tile group OBU semantics" in + :ref:`av1` for more details. + +.. c:type:: v4l2_ctrl_av1_tile_group_entry + +.. cssclass:: longtable + +.. tabularcolumns:: |p{5.8cm}|p{4.8cm}|p{6.6cm}| + +.. flat-table:: struct v4l2_ctrl_av1_tile_group_entry + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u32 + - ``tile_offset`` + - Offset from the OBU data, i.e. where the coded tile data actually starts. + * - __u32 + - ``tile_size`` + - Specifies the size in bytes of the coded tile. Equivalent to "TileSize" + in :ref:`av1`. + * - __u32 + - ``tile_row`` + - Specifies the row of the current tile. Equivalent to "TileRow" in + :ref:`av1`. + * - __u32 + - ``tile_col`` + - Specifies the column of the current tile. Equivalent to "TileColumn" in + :ref:`av1`. + +.. c:type:: v4l2_av1_warp_model + + AV1 Warp Model as described in section 3 "Symbols and abbreviated terms" of + :ref:`av1`. + +.. raw:: latex + + \scriptsize + +.. tabularcolumns:: |p{7.4cm}|p{0.3cm}|p{9.6cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_WARP_MODEL_IDENTITY`` + - 0 + - Warp model is just an identity transform. + * - ``V4L2_AV1_WARP_MODEL_TRANSLATION`` + - 1 + - Warp model is a pure translation. + * - ``V4L2_AV1_WARP_MODEL_ROTZOOM`` + - 2 + - Warp model is a rotation + symmetric zoom + translation. + * - ``V4L2_AV1_WARP_MODEL_AFFINE`` + - 3 + - Warp model is a general affine transform. + +.. c:type:: v4l2_av1_reference_frame + +AV1 Reference Frames as described in section 6.10.24 "Ref frames semantics" +of :ref:`av1`. + +.. raw:: latex + + \scriptsize + +.. tabularcolumns:: |p{7.4cm}|p{0.3cm}|p{9.6cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_REF_INTRA_FRAME`` + - 0 + - Intra Frame Reference. + * - ``V4L2_AV1_REF_LAST_FRAME`` + - 1 + - Last Frame Reference. + * - ``V4L2_AV1_REF_LAST2_FRAME`` + - 2 + - Last2 Frame Reference. + * - ``V4L2_AV1_REF_LAST3_FRAME`` + - 3 + - Last3 Frame Reference. + * - ``V4L2_AV1_REF_GOLDEN_FRAME`` + - 4 + - Golden Frame Reference. + * - ``V4L2_AV1_REF_BWDREF_FRAME`` + - 5 + - BWD Frame Reference. + * - ``V4L2_AV1_REF_ALTREF2_FRAME`` + - 6 + - ALTREF2 Frame Reference. + * - ``V4L2_AV1_REF_ALTREF_FRAME`` + - 7 + - ALTREF Frame Reference. + +.. c:type:: v4l2_av1_global_motion + +AV1 Global Motion parameters as described in section 6.8.17 +"Global motion params semantics" of :ref:`av1`. + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{5.8cm}|p{10.0cm}| + +.. flat-table:: struct v4l2_av1_global_motion + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``flags[V4L2_AV1_TOTAL_REFS_PER_FRAME]`` + - A bitfield containing the flags per reference frame. See + :ref:`AV1 Global Motion Flags ` for more + details. + * - enum :c:type:`v4l2_av1_warp_model` + - ``type[V4L2_AV1_TOTAL_REFS_PER_FRAME]`` + - The type of global motion transform used. + * - __s32 + - ``params[V4L2_AV1_TOTAL_REFS_PER_FRAME][6]`` + - This field has the same meaning as "gm_params" in :ref:`av1`. + * - __u8 + - ``invalid`` + - Bitfield indicating whether the global motion params are invalid for a + given reference frame. See section 7.11.3.6 Setup shear process and the + variable "warpValid". Use V4L2_AV1_GLOBAL_MOTION_IS_INVALID(ref) to + create a suitable mask. + * - __u8 + - ``reserved[3]`` + - Applications and drivers must set this to zero. + +.. _av1_global_motion_flags: + +``AV1 Global Motion Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_GLOBAL_MOTION_FLAG_IS_GLOBAL`` + - 0x00000001 + - Specifies whether global motion parameters are present for a particular + reference frame. + * - ``V4L2_AV1_GLOBAL_MOTION_FLAG_IS_ROT_ZOOM`` + - 0x00000002 + - Specifies whether a particular reference frame uses rotation and zoom + global motion. + * - ``V4L2_AV1_GLOBAL_MOTION_FLAG_IS_TRANSLATION`` + - 0x00000004 + - Specifies whether a particular reference frame uses translation global + motion + +.. c:type:: v4l2_av1_frame_restoration_type + +AV1 Frame Restoration Type. + +.. raw:: latex + + \scriptsize + +.. tabularcolumns:: |p{7.4cm}|p{0.3cm}|p{9.6cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_FRAME_RESTORE_NONE`` + - 0 + - No filtering is applied. + * - ``V4L2_AV1_FRAME_RESTORE_WIENER`` + - 1 + - Wiener filter process is invoked. + * - ``V4L2_AV1_FRAME_RESTORE_SGRPROJ`` + - 2 + - Self guided filter process is invoked. + * - ``V4L2_AV1_FRAME_RESTORE_SWITCHABLE`` + - 3 + - Restoration filter is swichtable. + +.. c:type:: v4l2_av1_loop_restoration + +AV1 Loop Restauration as described in section 6.10.15 "Loop restoration params +semantics" of :ref:`av1`. + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{5.8cm}|p{10.0cm}| + +.. flat-table:: struct v4l2_av1_loop_restoration + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``flags`` + - See :ref:`AV1 Loop Restoration Flags `. + * - __u8 + - ``lr_unit_shift`` + - Specifies if the luma restoration size should be halved. + * - __u8 + - ``lr_uv_shift`` + - Specifies if the chroma size should be half the luma size. + * - __u8 + - ``reserved`` + - Applications and drivers must set this to zero. + * - :c:type:`v4l2_av1_frame_restoration_type` + - ``frame_restoration_type[V4L2_AV1_NUM_PLANES_MAX]`` + - Specifies the type of restoration used for each plane. + * - __u8 + - ``loop_restoration_size[V4L2_AV1_MAX_NUM_PLANES]`` + - Specifies the size of loop restoration units in units of samples in the + current plane. + +.. _av1_loop_restoration_flags: + +``AV1 Loop Restoration Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_LOOP_RESTORATION_FLAG_USES_LR`` + - 0x00000001 + - Retains the same meaning as UsesLr in :ref:`av1`. + * - ``V4L2_AV1_LOOP_RESTORATION_FLAG_USES_CHROMA_LR`` + - 0x00000002 + - Retains the same meaning as UsesChromaLr in :ref:`av1`. + +.. c:type:: v4l2_av1_cdef + +AV1 CDEF params semantics as described in section 6.10.14 "CDEF params +semantics" of :ref:`av1`. + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{5.8cm}|p{10.0cm}| + +.. flat-table:: struct v4l2_av1_cdef + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``damping_minus_3`` + - Controls the amount of damping in the deringing filter. + * - __u8 + - ``bits`` + - Specifies the number of bits needed to specify which CDEF filter to + apply. + * - __u8 + - ``y_pri_strength[V4L2_AV1_CDEF_MAX]`` + - Specifies the strength of the primary filter. + * - __u8 + - ``y_sec_strength[V4L2_AV1_CDEF_MAX]`` + - Specifies the strength of the secondary filter. + * - __u8 + - ``uv_pri_strength[V4L2_AV1_CDEF_MAX]`` + - Specifies the strength of the primary filter. + * - __u8 + - ``uv_secondary_strength[V4L2_AV1_CDEF_MAX]`` + - Specifies the strength of the secondary filter. + +.. c:type:: v4l2_av1_segment_feature + +AV1 segment features as described in section 3 "Symbols and abbreviated terms" +of :ref:`av1`. + +.. raw:: latex + + \scriptsize + +.. tabularcolumns:: |p{7.4cm}|p{0.3cm}|p{9.6cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_SEG_LVL_ALT_Q`` + - 0 + - Index for quantizer segment feature. + * - ``V4L2_AV1_SEG_LVL_ALT_LF_Y_V`` + - 1 + - Index for vertical luma loop filter segment feature. + * - ``V4L2_AV1_SEG_LVL_REF_FRAME`` + - 5 + - Index for reference frame segment feature. + * - ``V4L2_AV1_SEG_LVL_REF_SKIP`` + - 6 + - Index for skip segment feature. + * - ``V4L2_AV1_SEG_LVL_REF_GLOBALMV`` + - 7 + - Index for global mv feature. + * - ``V4L2_AV1_SEG_LVL_MAX`` + - 8 + - Number of segment features. + +.. c:type:: v4l2_av1_segmentation + +AV1 Segmentation params as defined in section 6.8.13 "Segmentation params +semantics" of :ref:`av1`. + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{5.8cm}|p{10.0cm}| + +.. flat-table:: struct v4l2_av1_segmentation + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``flags`` + - See :ref:`AV1 Segmentation Flags ` + * - __u8 + - ``last_active_seg_id`` + - Indicates the highest numbered segment id that has some + enabled feature. This is used when decoding the segment id to only decode + choices corresponding to used segments. + * - __u8 + - ``feature_enabled[V4L2_AV1_MAX_SEGMENTS]`` + - Bitmask defining which features are enabled in each segment. Use + V4L2_AV1_SEGMENT_FEATURE_ENABLED to build a suitable mask. + * - __u16 + - `feature_data[V4L2_AV1_MAX_SEGMENTS][V4L2_AV1_SEG_LVL_MAX]`` + - Data attached to each feature. Data entry is only valid if the feature + is enabled. + +.. _av1_segmentation_flags: + +``AV1 Segmentation Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_SEGMENTATION_FLAG_ENABLED`` + - 0x00000001 + - If set, indicates that this frame makes use of the segmentation tool. If + not set, indicates that the frame does not use segmentation. + * - ``V4L2_AV1_SEGMENTATION_FLAG_UPDATE_MAP`` + - 0x00000002 + - If set, indicates that the segmentation map are updated during the + decoding of this frame. If not set, indicates that the segmentation map + from the previous frame is used. + * - ``V4L2_AV1_SEGMENTATION_FLAG_TEMPORAL_UPDATE`` + - 0x00000004 + - If set, indicates that the updates to the segmentation map are coded + relative to the existing segmentation map. If not set, indicates that + the new segmentation map is coded without reference to the existing + segmentation map. + * - ``V4L2_AV1_SEGMENTATION_FLAG_UPDATE_DATA`` + - 0x00000008 + - If set, indicates that the updates to the segmentation map are coded + relative to the existing segmentation map. If not set, indicates that + the new segmentation map is coded without reference to the existing + segmentation map. + * - ``V4L2_AV1_SEGMENTATION_FLAG_SEG_ID_PRE_SKIP`` + - 0x00000010 + - If set, indicates that the segment id will be read before the skip + syntax element. If not set, indicates that the skip syntax element will + be read first. + +.. c:type:: v4l2_av1_loop_filter + +AV1 Loop filter params as defined in section 6.8.10 "Loop filter semantics" of +:ref:`av1`. + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{5.8cm}|p{10.0cm}| + +.. flat-table:: struct v4l2_av1_global_motion + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``flags`` + - See + :ref:`AV1 Loop Filter flags ` for more details. + * - __u8 + - ``level[4]`` + - An array containing loop filter strength values. Different loop + filter strength values from the array are used depending on the image + plane being filtered, and the edge direction (vertical or horizontal) + being filtered. + * - __u8 + - ``sharpness`` + - indicates the sharpness level. The loop_filter_level and + loop_filter_sharpness together determine when a block edge is filtered, + and by how much the filtering can change the sample values. The loop + filter process is described in section 7.14 of :ref:`av1`. + * - __u8 + - ``ref_deltas[V4L2_AV1_TOTAL_REFS_PER_FRAME]`` + - contains the adjustment needed for the filter level based on the + chosen reference frame. If this syntax element is not present, it + maintains its previous value. + * - __u8 + - ``mode_deltas[2]`` + - contains the adjustment needed for the filter level based on + the chosen mode. If this syntax element is not present, it maintains its + previous value. + * - __u8 + - ``delta_lf_res`` + - specifies the left shift which should be applied to decoded loop filter + delta values. + +.. _av1_loop_filter_flags: + +``AV1 Loop Filter Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_LOOP_FILTER_FLAG_DELTA_ENABLED`` + - 0x00000001 + - If set, means that the filter level depends on the mode and reference + frame used to predict a block. If not set, means that the filter level + does not depend on the mode and reference frame. + * - ``V4L2_AV1_LOOP_FILTER_FLAG_DELTA_UPDATE`` + - 0x00000002 + - If set, means that additional syntax elements are present that specify + which mode and reference frame deltas are to be updated. If not set, + means that these syntax elements are not present. + * - ``V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_PRESENT`` + - 0x00000004 + - Specifies whether loop filter delta values are present + * - ``V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_MULTI`` + - 0x00000008 + - A value equal to 1 specifies that separate loop filter + deltas are sent for horizontal luma edges, vertical luma edges, + the U edges, and the V edges. A value of delta_lf_multi equal to 0 + specifies that the same loop filter delta is used for all edges. + +.. c:type:: v4l2_av1_quantization + +AV1 Quantization params as defined in section 6.8.11 "Quantization params +semantics" of :ref:`av1`. + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{5.8cm}|p{10.0cm}| + +.. flat-table:: struct v4l2_av1_quantization + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``flags`` + - See + :ref:`AV1 Loop Filter flags ` for more details. + * - __u8 + - ``base_q_idx`` + - Indicates the base frame qindex. This is used for Y AC coefficients and + as the base value for the other quantizers. + * - __u8 + - ``delta_q_y_dc`` + - Indicates the Y DC quantizer relative to base_q_idx. + * - __u8 + - ``delta_q_u_dc`` + - Indicates the U DC quantizer relative to base_q_idx. + * - __u8 + - ``delta_q_u_ac`` + - Indicates the U AC quantizer relative to base_q_idx. + * - __u8 + - ``delta_q_v_dc`` + - Indicates the V DC quantizer relative to base_q_idx. + * - __u8 + - ``delta_q_v_ac`` + - Indicates the V AC quantizer relative to base_q_idx. + * - __u8 + - ``qm_y`` + - Specifies the level in the quantizer matrix that should be used for + luma plane decoding. + * - __u8 + - ``qm_u`` + - Specifies the level in the quantizer matrix that should be used for + chroma U plane decoding. + * - __u8 + - ``qm_v`` + - Specifies the level in the quantizer matrix that should be used for + chroma V plane decoding. + * - __u8 + - ``delta_q_res`` + - Specifies the left shift which should be applied to decoded quantizer + index delta values. + +.. _av1_quantization_flags: + +``AV1 Quantization Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_QUANTIZATION_FLAG_DIFF_UV_DELTA`` + - 0x00000001 + - If set, indicates that the U and V delta quantizer values are coded + separately. If not set, indicates that the U and V delta quantizer + values share a common value. + * - ``V4L2_AV1_QUANTIZATION_FLAG_USING_QMATRIX`` + - 0x00000002 + - If set, specifies that the quantizer matrix will be used to compute + quantizers. + * - ``V4L2_AV1_QUANTIZATION_FLAG_DELTA_Q_PRESENT`` + - 0x00000004 + - Specifies whether quantizer index delta values are present. + +.. c:type:: v4l2_av1_tile_info + +AV1 Tile info as defined in section 6.8.14 "Tile info semantics" of ref:`av1`. + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{5.8cm}|p{10.0cm}| + +.. flat-table:: struct v4l2_av1_tile_info + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``flags`` + - See + :ref:`AV1 Tile Info flags ` for more details. + * - __u8 + - ``context_update_tile_id`` + - Specifies which tile to use for the CDF update. + * - __u8 + - ``tile_cols`` + - Specifies the number of tiles across the frame. + * - __u8 + - ``tile_rows`` + - Specifies the number of tiles down the frame. + * - __u32 + - ``mi_col_starts[V4L2_AV1_MAX_TILE_COLS + 1]`` + - An array specifying the start column (in units of 4x4 luma + samples) for each tile across the image. + * - __u32 + - ``mi_row_starts[V4L2_AV1_MAX_TILE_ROWS + 1]`` + - An array specifying the start row (in units of 4x4 luma + samples) for each tile across the image. + * - __u32 + - ``width_in_sbs_minus_1[V4L2_AV1_MAX_TILE_COLS]`` + - Specifies the width of a tile minus 1 in units of superblocks. + * - __u32 + - ``height_in_sbs_minus_1[V4L2_AV1_MAX_TILE_ROWS]`` + - Specifies the height of a tile minus 1 in units of superblocks. + * - __u8 + - ``tile_size_bytes`` + - Specifies the number of bytes needed to code each tile size. + * - __u8 + - ``reserved[3]`` + - Applications and drivers must set this to zero. + +.. _av1_tile_info_flags: + +``AV1 Tile Info Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_TILE_INFO_FLAG_UNIFORM_TILE_SPACING`` + - 0x00000001 + - If set, means that the tiles are uniformly spaced across the frame. (In + other words, all tiles are the same size except for the ones at the + right and bottom edge which can be smaller). If not set means that the + tile sizes are coded. + +.. c:type:: v4l2_av1_frame_type + +AV1 Frame Type + +.. raw:: latex + + \scriptsize + +.. tabularcolumns:: |p{7.4cm}|p{0.3cm}|p{9.6cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_KEY_FRAME`` + - 0 + - Key frame. + * - ``V4L2_AV1_INTER_FRAME`` + - 1 + - Inter frame. + * - ``V4L2_AV1_INTRA_ONLY_FRAME`` + - 2 + - Intra-only frame. + * - ``V4L2_AV1_SWITCH_FRAME`` + - 3 + - Switch frame. + +.. c:type:: v4l2_av1_interpolation_filter + +AV1 Interpolation Filter + +.. raw:: latex + + \scriptsize + +.. tabularcolumns:: |p{7.4cm}|p{0.3cm}|p{9.6cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_INTERPOLATION_FILTER_EIGHTTAP`` + - 0 + - Eight tap filter. + * - ``V4L2_AV1_INTERPOLATION_FILTER_EIGHTTAP_SMOOTH`` + - 1 + - Eight tap smooth filter. + * - ``V4L2_AV1_INTERPOLATION_FILTER_EIGHTTAP_SHARP`` + - 2 + - Eight tap sharp filter. + * - ``V4L2_AV1_INTERPOLATION_FILTER_BILINEAR`` + - 3 + - Bilinear filter. + * - ``V4L2_AV1_INTERPOLATION_FILTER_SWITCHABLE`` + - 4 + - Filter selection is signaled at the block level. + +.. c:type:: v4l2_av1_tx_mode + +AV1 Tx mode as described in section 6.8.21 "TX mode semantics" of :ref:`av1`. + +.. raw:: latex + + \scriptsize + +.. tabularcolumns:: |p{7.4cm}|p{0.3cm}|p{9.6cm}| + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_TX_MODE_ONLY_4X4`` + - 0 + - The inverse transform will use only 4x4 transforms. + * - ``V4L2_AV1_TX_MODE_LARGEST`` + - 1 + - The inverse transform will use the largest transform size that fits + inside the block. + * - ``V4L2_AV1_TX_MODE_SELECT`` + - 2 + - The choice of transform size is specified explicitly for each block. + +``V4L2_CID_STATELESS_AV1_FRAME (struct)`` + Represents a Frame Header OBU. See 6.8 "Frame Header OBU semantics" of + :ref:`av1` for more details. + +.. c:type:: v4l2_ctrl_av1_frame + +.. cssclass:: longtable + +.. tabularcolumns:: |p{5.8cm}|p{4.8cm}|p{6.6cm}| + +.. flat-table:: struct v4l2_ctrl_av1_frame + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - struct :c:type:`v4l2_av1_tile_info` + - ``tile_info`` + - Tile info + * - struct :c:type:`v4l2_av1_quantization` + - ``quantization`` + - Quantization parameters. + * - struct :c:type:`v4l2_av1_segmentation` + - ``segmentation`` + - Segmentation parameters. + * - __u8 + - ``superres_denom`` + - The denominator for the upscaling ratio. + * - struct :c:type:`v4l2_av1_loop_filter` + - ``loop_filter`` + - Loop filter params + * - struct :c:type:`v4l2_av1_cdef` + - ``cdef`` + - CDEF params + * - __u8 + - ``skip_mode_frame[2]`` + - Specifies the frames to use for compound prediction when skip_mode is + equal to 1. + * - __u8 + - ``primary_ref_frame`` + - Specifies which reference frame contains the CDF values and other state + that should be loaded at the start of the frame. + * - struct :c:type:`v4l2_av1_loop_restoration` + - ``loop_restoration`` + - Loop restoration parameters. + * - struct :c:type:`v4l2_av1_loop_global_motion` + - ``global_motion`` + - Global motion parameters. + * - __u32 + - ``flags`` + - See + :ref:`AV1 Frame flags ` for more details. + * - enum :c:type:`v4l2_av1_frame_type` + - ``frame_type`` + - Specifies the AV1 frame type + * - __u32 + - ``order_hint`` + - Specifies OrderHintBits least significant bits of the expected output + order for this frame. + * - __u32 + - ``upscaled_width`` + - The upscaled width. + * - enum :c:type:`v4l2_av1_interpolation_filter` + - ``interpolation_filter`` + - Specifies the filter selection used for performing inter prediction. + * - enum :c:type:`v4l2_av1_tx_mode` + - ``tx_mode`` + - Specifies how the transform size is determined. + * - __u32 + - ``frame_width_minus_1`` + - Add 1 to get the frame's width. + * - __u32 + - ``frame_height_minus_1`` + - Add 1 to get the frame's height. + * - __u16 + - ``render_width_minus_1`` + - Add 1 to get the render width of the frame in luma samples. + * - __u16 + - ``render_height_minus_1`` + - Add 1 to get the render height of the frame in luma samples. + * - __u32 + - ``current_frame_id`` + - Specifies the frame id number for the current frame. Frame + id numbers are additional information that do not affect the decoding + process, but provide decoders with a way of detecting missing reference + frames so that appropriate action can be taken. + * - __u8 + - ``buffer_removal_time[V4L2_AV1_MAX_OPERATING_POINTS]`` + - Specifies the frame removal time in units of DecCT clock ticks counted + from the removal time of the last random access point for operating point + opNum. + * - __u8 + - ``reserved[4]`` + - Applications and drivers must set this to zero. + * - __u32 + - ``order_hints[V4L2_AV1_TOTAL_REFS_PER_FRAME]`` + - Specifies the expected output order hint for each reference frame. + This field corresponds to the OrderHints variable from the specification + (section 5.9.2 "Uncompressed header syntax"). As such, this is only + used for non-intra frames and ignored otherwise. order_hints[0] is + always ignored. + * - __u64 + - ``reference_frame_ts[V4L2_AV1_TOTAL_REFS_PER_FRAME]`` + - The V4L2 timestamp for each of the reference frames enumerated in + enum :c:type:`v4l2_av1_reference_frame` starting at + ``V4L2_AV1_REF_LAST_FRAME``. This represents the state of reference + slot as described in the spec and updated by userland through the + "Reference frame update process" in section 7.20 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. + * - __s8 + - ``ref_frame_idx[V4L2_AV1_REFS_PER_FRAME]`` + - An index into ``reference_frame_ts`` representing the ordered list of + references used by inter-frame. Matches the bitstream syntax + element of the same name. + * - __u8 + - ``refresh_frame_flags`` + - Contains a bitmask that specifies which reference frame slots will be + updated with the current frame after it is decoded. + +.. _av1_frame_flags: + +``AV1 Frame Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_FRAME_FLAG_SHOW_FRAME`` + - 0x00000001 + - If set, specifies that this frame should be immediately output once + decoded. If not set, specifies that this frame should not be immediately + output; it may be output later if a later uncompressed header uses + show_existing_frame equal to 1. + * - ``V4L2_AV1_FRAME_FLAG_SHOWABLE_FRAME`` + - 0x00000002 + - If set, specifies that the frame may be output using the + show_existing_frame mechanism. If not set, specifies that this frame + will not be output using the show_existing_frame mechanism. + * - ``V4L2_AV1_FRAME_FLAG_ERROR_RESILIENT_MODE`` + - 0x00000004 + - Specifies whether error resilient mode is enabled. + * - ``V4L2_AV1_FRAME_FLAG_DISABLE_CDF_UPDATE`` + - 0x00000008 + - Specifies whether the CDF update in the symbol decoding process should + be disabled. + * - ``V4L2_AV1_FRAME_FLAG_ALLOW_SCREEN_CONTENT_TOOLS`` + - 0x00000010 + - If set, indicates that intra blocks may use palette encoding. If not + set, indicates that palette encoding is never used. + * - ``V4L2_AV1_FRAME_FLAG_FORCE_INTEGER_MV`` + - 0x00000020 + - If set, specifies that motion vectors will always be integers. If not + set, specifies that motion vectors can contain fractional bits. + * - ``V4L2_AV1_FRAME_FLAG_ALLOW_INTRABC`` + - 0x00000040 + - If set, indicates that intra block copy may be used in this frame. If + not set, indicates that intra block copy is not allowed in this frame. + * - ``V4L2_AV1_FRAME_FLAG_USE_SUPERRES`` + - 0x00000080 + - If set, indicates that upscaling is needed. + * - ``V4L2_AV1_FRAME_FLAG_ALLOW_HIGH_PRECISION_MV`` + - 0x00000100 + - If set, specifies that motion vectors are specified to eighth pel + precision. If not set, specifies that motion vectors are specified to + quarter pel precision; + * - ``V4L2_AV1_FRAME_FLAG_IS_MOTION_MODE_SWITCHABLE`` + - 0x00000200 + - If not set, specifies that only the SIMPLE motion mode will be used. + * - ``V4L2_AV1_FRAME_FLAG_USE_REF_FRAME_MVS`` + - 0x00000400 + - If set specifies that motion vector information from a previous frame + can be used when decoding the current frame. If not set, specifies that + this information will not be used. + * - ``V4L2_AV1_FRAME_FLAG_DISABLE_FRAME_END_UPDATE_CDF`` + - 0x00000800 + - If set indicates that the end of frame CDF update is disabled. If not + set, indicates that the end of frame CDF update is enabled + * - ``V4L2_AV1_FRAME_FLAG_ALLOW_WARPED_MOTION`` + - 0x00001000 + - If set, indicates that the syntax element motion_mode may be present, if + not set, indicates that the syntax element motion_mode will not be + present. + * - ``V4L2_AV1_FRAME_FLAG_REFERENCE_SELECT`` + - 0x00002000 + - If set, specifies that the mode info for inter blocks contains the + syntax element comp_mode that indicates whether to use single or + compound reference prediction. If not set, specifies that all inter + blocks will use single prediction. + * - ``V4L2_AV1_FRAME_FLAG_REDUCED_TX_SET`` + - 0x00004000 + - If set, specifies that the frame is restricted to a reduced subset of + the full set of transform types. + * - ``V4L2_AV1_FRAME_FLAG_SKIP_MODE_ALLOWED`` + - 0x00008000 + - This flag retains the same meaning as SkipModeAllowed in :ref:`av1`. + * - ``V4L2_AV1_FRAME_FLAG_SKIP_MODE_PRESENT`` + - 0x00010000 + - If set, specifies that the syntax element skip_mode will be present, if + not set, specifies that skip_mode will not be used for this frame. + * - ``V4L2_AV1_FRAME_FLAG_FRAME_SIZE_OVERRIDE`` + - 0x00020000 + - If set, specifies that the frame size will either be specified as the + size of one of the reference frames, or computed from the + frame_width_minus_1 and frame_height_minus_1 syntax elements. If not + set, specifies that the frame size is equal to the size in the sequence + header. + * - ``V4L2_AV1_FRAME_FLAG_BUFFER_REMOVAL_TIME_PRESENT`` + - 0x00040000 + - If set, specifies that buffer_removal_time is present. If not set, + specifies that buffer_removal_time is not present. + * - ``V4L2_AV1_FRAME_FLAG_FRAME_REFS_SHORT_SIGNALING`` + - 0x00080000 + - If set, indicates that only two reference frames are explicitly + signaled. If not set, indicates that all reference frames are explicitly + signaled. + +``V4L2_CID_STATELESS_AV1_FILM_GRAIN (struct)`` + Represents the optional film grain parameters. See section + 6.8.20 "Film grain params semantics" of :ref:`av1` for more details. + +.. c:type:: v4l2_ctrl_av1_film_grain + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{5.8cm}|p{10.0cm}| + +.. flat-table:: struct v4l2_ctrl_av1_film_grain + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - __u8 + - ``flags`` + - See :ref:`AV1 Film Grain Flags `. + * - __u8 + - ``cr_mult`` + - Represents a multiplier for the cr component used in derivation of the + input index to the cr component scaling function. + * - __u16 + - ``grain_seed`` + - Specifies the starting value for the pseudo-random numbers used during + film grain synthesis. + * - __u8 + - ``film_grain_params_ref_idx`` + - Indicates which reference frame contains the film grain parameters to be + used for this frame. + * - __u8 + - ``num_y_points`` + - Specifies the number of points for the piece-wise linear scaling + function of the luma component. + * - __u8 + - ``point_y_value[V4L2_AV1_MAX_NUM_Y_POINTS]`` + - Represents the x (luma value) coordinate for the i-th point + of the piecewise linear scaling function for luma component. The values + are signaled on the scale of 0..255. In case of 10 bit video, these + values correspond to luma values divided by 4. In case of 12 bit video, + these values correspond to luma values divided by 16. + * - __u8 + - ``point_y_scaling[V4L2_AV1_MAX_NUM_Y_POINTS]`` + - Represents the scaling (output) value for the i-th point + of the piecewise linear scaling function for luma component. + * - __u8 + - ``num_cb_points`` + - Specifies the number of points for the piece-wise linear scaling + function of the cb component. + * - __u8 + - ``point_cb_value[V4L2_AV1_MAX_NUM_CB_POINTS]`` + - Represents the x coordinate for the i-th point of the + piece-wise linear scaling function for cb component. The values are + signaled on the scale of 0..255. + * - __u8 + - ``point_cb_scaling[V4L2_AV1_MAX_NUM_CB_POINTS]`` + - Represents the scaling (output) value for the i-th point of the + piecewise linear scaling function for cb component. + * - __u8 + - ``num_cr_points`` + - Represents the number of points for the piece-wise + linear scaling function of the cr component. + * - __u8 + - ``point_cr_value[V4L2_AV1_MAX_NUM_CR_POINTS]`` + - Represents the x coordinate for the i-th point of the + piece-wise linear scaling function for cr component. The values are + signaled on the scale of 0..255. + * - __u8 + - ``point_cr_scaling[V4L2_AV1_MAX_NUM_CR_POINTS]`` + - Represents the scaling (output) value for the i-th point of the + piecewise linear scaling function for cr component. + * - __u8 + - ``grain_scaling_minus_8`` + - Represents the shift - 8 applied to the values of the chroma component. + The grain_scaling_minus_8 can take values of 0..3 and determines the + range and quantization step of the standard deviation of film grain. + * - __u8 + - ``ar_coeff_lag`` + - Specifies the number of auto-regressive coefficients for luma and + chroma. + * - __u8 + - ``ar_coeffs_y_plus_128[V4L2_AV1_AR_COEFFS_SIZE]`` + - Specifies auto-regressive coefficients used for the Y plane. + * - __u8 + - ``ar_coeffs_cb_plus_128[V4L2_AV1_AR_COEFFS_SIZE]`` + - Specifies auto-regressive coefficients used for the U plane. + * - __u8 + - ``ar_coeffs_cr_plus_128[V4L2_AV1_AR_COEFFS_SIZE]`` + - Specifies auto-regressive coefficients used for the V plane. + * - __u8 + - ``ar_coeff_shift_minus_6`` + - Specifies the range of the auto-regressive coefficients. Values of 0, + 1, 2, and 3 correspond to the ranges for auto-regressive coefficients of + [-2, 2), [-1, 1), [-0.5, 0.5) and [-0.25, 0.25) respectively. + * - __u8 + - ``grain_scale_shift`` + - Specifies how much the Gaussian random numbers should be scaled down + during the grain synthesis process. + * - __u8 + - ``cb_mult`` + - Represents a multiplier for the cb component used in derivation of the + input index to the cb component scaling function. + * - __u8 + - ``cb_luma_mult`` + - Represents a multiplier for the average luma component used in + derivation of the input index to the cb component scaling function.. + * - __u8 + - ``cr_luma_mult`` + - Represents a multiplier for the average luma component used in + derivation of the input index to the cr component scaling function. + * - __u16 + - ``cb_offset`` + - Represents an offset used in derivation of the input index to the + cb component scaling function. + * - __u16 + - ``cr_offset`` + - Represents an offset used in derivation of the input index to the + cr component scaling function. + * - __u8 + - ``reserved[4]`` + - Applications and drivers must set this to zero. + +.. _av1_film_grain_flags: + +``AV1 Film Grain Flags`` + +.. cssclass:: longtable + +.. flat-table:: + :header-rows: 0 + :stub-columns: 0 + :widths: 1 1 2 + + * - ``V4L2_AV1_FILM_GRAIN_FLAG_APPLY_GRAIN`` + - 0x00000001 + - If set, specifies that film grain should be added to this frame. If not + set, specifies that film grain should not be added. + * - ``V4L2_AV1_FILM_GRAIN_FLAG_UPDATE_GRAIN`` + - 0x00000002 + - If set, means that a new set of parameters should be sent. If not set, + specifies that the previous set of parameters should be used. + * - ``V4L2_AV1_FILM_GRAIN_FLAG_CHROMA_SCALING_FROM_LUMA`` + - 0x00000004 + - If set, specifies that the chroma scaling is inferred from the luma + scaling. + * - ``V4L2_AV1_FILM_GRAIN_FLAG_OVERLAP`` + - 0x00000008 + - If set, indicates that the overlap between film grain blocks shall be + applied. If not set, indicates that the overlap between film grain blocks + shall not be applied. + * - ``V4L2_AV1_FILM_GRAIN_FLAG_CLIP_TO_RESTRICTED_RANGE`` + - 0x00000010 + - If set, indicates that clipping to the restricted (studio, i.e. limited) + range shall be applied to the sample values after adding the film grain + (see the semantics for color_range for an explanation of studio swing). + If not set, indicates that clipping to the full range shall be applied + to the sample values after adding the film grain. diff --git a/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst b/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst index 06b78e5589d2..806ed73ac474 100644 --- a/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst +++ b/Documentation/userspace-api/media/v4l/pixfmt-compressed.rst @@ -258,6 +258,22 @@ Compressed Formats RV9 players - the format and decoder did not change, only the encoder did. As a result, it uses the same FourCC. + * .. _V4L2-PIX-FMT-AV1-FRAME: + + - ``V4L2_PIX_FMT_AV1_FRAME`` + - 'AV1F' + - AV1 parsed frame, including the frame header, as extracted from the container. + This format is adapted for stateless video decoders that implement a AV1 + pipeline with the :ref:`stateless_decoder`. Metadata associated with the + frame to decode is required to be passed through the + ``V4L2_CID_STATELESS_AV1_SEQUENCE``, ``V4L2_CID_STATELESS_AV1_FRAME``, + and ``V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY`` controls. + See the :ref:`associated Codec Control IDs `. + Exactly one output and one capture buffer must be provided for use with + this pixel format. The output buffer must contain the appropriate number + of macroblocks to decode a full corresponding frame to the matching + capture buffer. + .. raw:: latex \normalsize diff --git a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst index 6d85ec6a19b4..f9f73530a6be 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst @@ -279,6 +279,22 @@ still cause this situation. - ``p_hevc_decode_params`` - A pointer to a struct :c:type:`v4l2_ctrl_hevc_decode_params`. Valid if this control is of type ``V4L2_CTRL_TYPE_HEVC_DECODE_PARAMS``. + * - struct :c:type:`v4l2_ctrl_av1_sequence` * + - ``p_av1_sequence`` + - A pointer to a struct :c:type:`v4l2_ctrl_av1_sequence`. Valid if this control is + of type ``V4L2_CTRL_TYPE_AV1_SEQUENCE``. + * - struct :c:type:`v4l2_ctrl_av1_tile_group_entry` * + - ``p_av1_tile_group_entry`` + - A pointer to a struct :c:type:`v4l2_ctrl_av1_tile_group_entry`. Valid if this control is + of type ``V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY``. + * - struct :c:type:`v4l2_ctrl_av1_frame` * + - ``p_av1_frame`` + - A pointer to a struct :c:type:`v4l2_ctrl_av1_frame`. Valid if this control is + of type ``V4L2_CTRL_TYPE_AV1_FRAME``. + * - struct :c:type:`v4l2_ctrl_av1_film_grain` * + - ``p_av1_film_grain`` + - A pointer to a struct :c:type:`v4l2_ctrl_av1_film_grain`. Valid if this control is + of type ``V4L2_CTRL_TYPE_AV1_FILM_GRAIN``. * - void * - ``ptr`` - A pointer to a compound type which can be an N-dimensional array diff --git a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst index a20dfa2a933b..4d38acafe8e1 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst @@ -525,6 +525,30 @@ See also the examples in :ref:`control`. - n/a - A struct :c:type:`v4l2_ctrl_vp9_frame`, containing VP9 frame decode parameters for stateless video decoders. + * - ``V4L2_CTRL_TYPE_AV1_SEQUENCE`` + - n/a + - n/a + - n/a + - A struct :c:type:`v4l2_ctrl_av1_sequence`, containing AV1 Sequence OBU + decoding parameters for stateless video decoders. + * - ``V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY`` + - n/a + - n/a + - n/a + - A struct :c:type:`v4l2_ctrl_av1_tile_group_entry`, containing AV1 Tile Group + OBU decoding parameters for stateless video decoders. + * - ``V4L2_CTRL_TYPE_AV1_FRAME`` + - n/a + - n/a + - n/a + - A struct :c:type:`v4l2_ctrl_av1_frame`, containing AV1 Frame/Frame + Header OBU decoding parameters for stateless video decoders. + * - ``V4L2_CTRL_TYPE_AV1_FILM_GRAIN`` + - n/a + - n/a + - n/a + - A struct :c:type:`v4l2_ctrl_av1_film_grain`, containing AV1 Film Grain + parameters for stateless video decoders. .. raw:: latex diff --git a/Documentation/userspace-api/media/videodev2.h.rst.exceptions b/Documentation/userspace-api/media/videodev2.h.rst.exceptions index 2a589d34b80e..3e58aac4ef0b 100644 --- a/Documentation/userspace-api/media/videodev2.h.rst.exceptions +++ b/Documentation/userspace-api/media/videodev2.h.rst.exceptions @@ -161,6 +161,10 @@ replace symbol V4L2_CTRL_TYPE_HEVC_PPS :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_HEVC_DECODE_PARAMS :c:type:`v4l2_ctrl_type` +replace symbol V4L2_CTRL_TYPE_AV1_SEQUENCE :c:type:`v4l2_ctrl_type` +replace symbol V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY :c:type:`v4l2_ctrl_type` +replace symbol V4L2_CTRL_TYPE_AV1_FRAME :c:type:`v4l2_ctrl_type` +replace symbol V4L2_CTRL_TYPE_AV1_FILM_GRAIN :c:type:`v4l2_ctrl_type` # V4L2 capability defines replace define V4L2_CAP_VIDEO_CAPTURE device-capabilities diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c index 29169170880a..9fd37e94db17 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-core.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c @@ -350,6 +350,19 @@ void v4l2_ctrl_type_op_log(const struct v4l2_ctrl *ctrl) case V4L2_CTRL_TYPE_HEVC_DECODE_PARAMS: pr_cont("HEVC_DECODE_PARAMS"); break; + case V4L2_CTRL_TYPE_AV1_SEQUENCE: + pr_cont("AV1_SEQUENCE"); + break; + case V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY: + pr_cont("AV1_TILE_GROUP_ENTRY"); + break; + case V4L2_CTRL_TYPE_AV1_FRAME: + pr_cont("AV1_FRAME"); + break; + case V4L2_CTRL_TYPE_AV1_FILM_GRAIN: + pr_cont("AV1_FILM_GRAIN"); + break; + default: pr_cont("unknown type %d", ctrl->type); break; @@ -547,6 +560,231 @@ validate_vp9_frame(struct v4l2_ctrl_vp9_frame *frame) return 0; } +static int validate_av1_quantization(struct v4l2_av1_quantization *q) +{ + if (q->flags > GENMASK(2, 0)) + return -EINVAL; + + if (q->delta_q_y_dc < -64 || q->delta_q_y_dc > 63 || + q->delta_q_u_dc < -64 || q->delta_q_u_dc > 63 || + q->delta_q_v_dc < -64 || q->delta_q_v_dc > 63 || + q->delta_q_u_ac < -64 || q->delta_q_u_ac > 63 || + q->delta_q_v_ac < -64 || q->delta_q_v_ac > 63 || + q->delta_q_res > GENMASK(1, 0)) + return -EINVAL; + + if (q->qm_y > GENMASK(3, 0) || + q->qm_u > GENMASK(3, 0) || + q->qm_v > GENMASK(3, 0)) + return -EINVAL; + + return 0; +} + +static int validate_av1_segmentation(struct v4l2_av1_segmentation *s) +{ + u32 i; + u32 j; + + if (s->flags > GENMASK(4, 0)) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(s->feature_data); i++) { + static const int segmentation_feature_signed[] = { 1, 1, 1, 1, 1, 0, 0, 0 }; + static const int segmentation_feature_max[] = { 255, 63, 63, 63, 63, 7, 0, 0}; + + for (j = 0; j < ARRAY_SIZE(s->feature_data[j]); j++) { + s32 limit = segmentation_feature_max[j]; + + if (segmentation_feature_signed[j]) { + if (s->feature_data[i][j] < -limit || + s->feature_data[i][j] > limit) + return -EINVAL; + } else { + if (s->feature_data[i][j] < 0 || s->feature_data[i][j] > limit) + return -EINVAL; + } + } + } + + return 0; +} + +static int validate_av1_loop_filter(struct v4l2_av1_loop_filter *lf) +{ + u32 i; + + if (lf->flags > GENMASK(3, 0)) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(lf->level); i++) { + if (lf->level[i] > GENMASK(5, 0)) + return -EINVAL; + } + + if (lf->sharpness > GENMASK(2, 0)) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(lf->ref_deltas); i++) { + if (lf->ref_deltas[i] < -64 || lf->ref_deltas[i] > 63) + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(lf->mode_deltas); i++) { + if (lf->mode_deltas[i] < -64 || lf->mode_deltas[i] > 63) + return -EINVAL; + } + + return 0; +} + +static int validate_av1_cdef(struct v4l2_av1_cdef *cdef) +{ + u32 i; + + if (cdef->damping_minus_3 > GENMASK(1, 0) || + cdef->bits > GENMASK(1, 0)) + return -EINVAL; + + for (i = 0; i < 1 << cdef->bits; i++) { + if (cdef->y_pri_strength[i] > GENMASK(3, 0) || + cdef->y_sec_strength[i] > 4 || + cdef->uv_pri_strength[i] > GENMASK(3, 0) || + cdef->uv_sec_strength[i] > 4) + return -EINVAL; + } + + return 0; +} + +static int validate_av1_loop_restauration(struct v4l2_av1_loop_restoration *lr) +{ + if (lr->lr_unit_shift > 3 || lr->lr_uv_shift > 1) + return -EINVAL; + + return 0; +} + +static int validate_av1_film_grain(struct v4l2_ctrl_av1_film_grain *fg) +{ + u32 i; + + if (fg->flags > GENMASK(4, 0)) + return -EINVAL; + + if (fg->film_grain_params_ref_idx > GENMASK(2, 0) || + fg->num_y_points > 14 || + fg->num_cb_points > 10 || + fg->num_cr_points > GENMASK(3, 0) || + fg->grain_scaling_minus_8 > GENMASK(1, 0) || + fg->ar_coeff_lag > GENMASK(1, 0) || + fg->ar_coeff_shift_minus_6 > GENMASK(1, 0) || + fg->grain_scale_shift > GENMASK(1, 0)) + return -EINVAL; + + if (!(fg->flags & V4L2_AV1_FILM_GRAIN_FLAG_APPLY_GRAIN)) + return 0; + + for (i = 1; i < fg->num_y_points; i++) + if (fg->point_y_value[i] <= fg->point_y_value[i - 1]) + return -EINVAL; + + for (i = 1; i < fg->num_cb_points; i++) + if (fg->point_cb_value[i] <= fg->point_cb_value[i - 1]) + return -EINVAL; + + for (i = 1; i < fg->num_cr_points; i++) + if (fg->point_cr_value[i] <= fg->point_cr_value[i - 1]) + return -EINVAL; + + return 0; +} + +static int validate_av1_frame(struct v4l2_ctrl_av1_frame *f) +{ + int ret = 0; + + ret = validate_av1_quantization(&f->quantization); + if (ret) + return ret; + ret = validate_av1_segmentation(&f->segmentation); + if (ret) + return ret; + ret = validate_av1_loop_filter(&f->loop_filter); + if (ret) + return ret; + ret = validate_av1_cdef(&f->cdef); + if (ret) + return ret; + ret = validate_av1_loop_restauration(&f->loop_restoration); + if (ret) + return ret; + + if (f->flags & + ~(V4L2_AV1_FRAME_FLAG_SHOW_FRAME | + V4L2_AV1_FRAME_FLAG_SHOWABLE_FRAME | + V4L2_AV1_FRAME_FLAG_ERROR_RESILIENT_MODE | + V4L2_AV1_FRAME_FLAG_DISABLE_CDF_UPDATE | + V4L2_AV1_FRAME_FLAG_ALLOW_SCREEN_CONTENT_TOOLS | + V4L2_AV1_FRAME_FLAG_FORCE_INTEGER_MV | + V4L2_AV1_FRAME_FLAG_ALLOW_INTRABC | + V4L2_AV1_FRAME_FLAG_USE_SUPERRES | + V4L2_AV1_FRAME_FLAG_ALLOW_HIGH_PRECISION_MV | + V4L2_AV1_FRAME_FLAG_IS_MOTION_MODE_SWITCHABLE | + V4L2_AV1_FRAME_FLAG_USE_REF_FRAME_MVS | + V4L2_AV1_FRAME_FLAG_DISABLE_FRAME_END_UPDATE_CDF | + V4L2_AV1_FRAME_FLAG_ALLOW_WARPED_MOTION | + V4L2_AV1_FRAME_FLAG_REFERENCE_SELECT | + V4L2_AV1_FRAME_FLAG_REDUCED_TX_SET | + V4L2_AV1_FRAME_FLAG_SKIP_MODE_ALLOWED | + V4L2_AV1_FRAME_FLAG_SKIP_MODE_PRESENT | + V4L2_AV1_FRAME_FLAG_FRAME_SIZE_OVERRIDE | + V4L2_AV1_FRAME_FLAG_BUFFER_REMOVAL_TIME_PRESENT | + V4L2_AV1_FRAME_FLAG_FRAME_REFS_SHORT_SIGNALING)) + return -EINVAL; + + if (f->superres_denom > GENMASK(2, 0) + 9) + return -EINVAL; + + return 0; +} + +static int validate_av1_sequence(struct v4l2_ctrl_av1_sequence *s) +{ + if (s->flags & + ~(V4L2_AV1_SEQUENCE_FLAG_STILL_PICTURE | + V4L2_AV1_SEQUENCE_FLAG_USE_128X128_SUPERBLOCK | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_FILTER_INTRA | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTRA_EDGE_FILTER | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTERINTRA_COMPOUND | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_MASKED_COMPOUND | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_WARPED_MOTION | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_DUAL_FILTER | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_ORDER_HINT | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_JNT_COMP | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_REF_FRAME_MVS | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_SUPERRES | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_CDEF | + V4L2_AV1_SEQUENCE_FLAG_ENABLE_RESTORATION | + V4L2_AV1_SEQUENCE_FLAG_MONO_CHROME | + V4L2_AV1_SEQUENCE_FLAG_COLOR_RANGE | + V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_X | + V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_Y | + V4L2_AV1_SEQUENCE_FLAG_FILM_GRAIN_PARAMS_PRESENT | + V4L2_AV1_SEQUENCE_FLAG_SEPARATE_UV_DELTA_Q)) + return -EINVAL; + + if (s->seq_profile == 1 && s->flags & V4L2_AV1_SEQUENCE_FLAG_MONO_CHROME) + return -EINVAL; + + /* reserved */ + if (s->seq_profile > 2) + return -EINVAL; + + /* TODO: PROFILES */ + return 0; +} + /* * Compound controls validation requires setting unused fields/flags to zero * in order to properly detect unchanged controls with v4l2_ctrl_type_op_equal's @@ -911,6 +1149,14 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx, case V4L2_CTRL_TYPE_VP9_FRAME: return validate_vp9_frame(p); + case V4L2_CTRL_TYPE_AV1_FRAME: + return validate_av1_frame(p); + case V4L2_CTRL_TYPE_AV1_SEQUENCE: + return validate_av1_sequence(p); + case V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY: + break; + case V4L2_CTRL_TYPE_AV1_FILM_GRAIN: + return validate_av1_film_grain(p); case V4L2_CTRL_TYPE_AREA: area = p; @@ -1602,6 +1848,18 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, case V4L2_CTRL_TYPE_VP9_FRAME: elem_size = sizeof(struct v4l2_ctrl_vp9_frame); break; + case V4L2_CTRL_TYPE_AV1_SEQUENCE: + elem_size = sizeof(struct v4l2_ctrl_av1_sequence); + break; + case V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY: + elem_size = sizeof(struct v4l2_ctrl_av1_tile_group_entry); + break; + case V4L2_CTRL_TYPE_AV1_FRAME: + elem_size = sizeof(struct v4l2_ctrl_av1_frame); + break; + case V4L2_CTRL_TYPE_AV1_FILM_GRAIN: + elem_size = sizeof(struct v4l2_ctrl_av1_film_grain); + break; case V4L2_CTRL_TYPE_AREA: elem_size = sizeof(struct v4l2_area); break; diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c index 564fedee2c88..8696eb1cdd61 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c @@ -499,6 +499,40 @@ const char * const *v4l2_ctrl_get_menu(u32 id) NULL, }; + static const char * const av1_profile[] = { + "Main", + "High", + "Professional", + NULL, + }; + static const char * const av1_level[] = { + "2.0", + "2.1", + "2.2", + "2.3", + "3.0", + "3.1", + "3.2", + "3.3", + "4.0", + "4.1", + "4.2", + "4.3", + "5.0", + "5.1", + "5.2", + "5.3", + "6.0", + "6.1", + "6.2", + "6.3", + "7.0", + "7.1", + "7.2", + "7.3", + NULL, + }; + static const char * const hevc_profile[] = { "Main", "Main Still Picture", @@ -704,6 +738,10 @@ const char * const *v4l2_ctrl_get_menu(u32 id) return hevc_tier; case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE: return hevc_loop_filter_mode; + case V4L2_CID_MPEG_VIDEO_AV1_PROFILE: + return av1_profile; + case V4L2_CID_MPEG_VIDEO_AV1_LEVEL: + return av1_level; case V4L2_CID_STATELESS_HEVC_DECODE_MODE: return hevc_decode_mode; case V4L2_CID_STATELESS_HEVC_START_CODE: @@ -1004,6 +1042,10 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_MPEG_VIDEO_REF_NUMBER_FOR_PFRAMES: return "Reference Frames for a P-Frame"; case V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR: return "Prepend SPS and PPS to IDR"; + /* AV1 controls */ + case V4L2_CID_MPEG_VIDEO_AV1_PROFILE: return "AV1 Profile"; + case V4L2_CID_MPEG_VIDEO_AV1_LEVEL: return "AV1 Level"; + /* CAMERA controls */ /* Keep the order of the 'case's the same as in v4l2-controls.h! */ case V4L2_CID_CAMERA_CLASS: return "Camera Controls"; @@ -1190,6 +1232,10 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_STATELESS_HEVC_DECODE_MODE: return "HEVC Decode Mode"; case V4L2_CID_STATELESS_HEVC_START_CODE: return "HEVC Start Code"; case V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS: return "HEVC Entry Point Offsets"; + case V4L2_CID_STATELESS_AV1_SEQUENCE: return "AV1 Sequence Parameters"; + case V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY: return "AV1 Tile Group Entry"; + case V4L2_CID_STATELESS_AV1_FRAME: return "AV1 Frame Parameters"; + case V4L2_CID_STATELESS_AV1_FILM_GRAIN: return "AV1 Film Grain"; /* Colorimetry controls */ /* Keep the order of the 'case's the same as in v4l2-controls.h! */ @@ -1365,6 +1411,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD: case V4L2_CID_MPEG_VIDEO_HEVC_TIER: case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE: + case V4L2_CID_MPEG_VIDEO_AV1_PROFILE: + case V4L2_CID_MPEG_VIDEO_AV1_LEVEL: case V4L2_CID_STATELESS_HEVC_DECODE_MODE: case V4L2_CID_STATELESS_HEVC_START_CODE: case V4L2_CID_STATELESS_H264_DECODE_MODE: @@ -1531,6 +1579,19 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_STATELESS_VP9_FRAME: *type = V4L2_CTRL_TYPE_VP9_FRAME; break; + case V4L2_CID_STATELESS_AV1_SEQUENCE: + *type = V4L2_CTRL_TYPE_AV1_SEQUENCE; + break; + case V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY: + *type = V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY; + *flags |= V4L2_CTRL_FLAG_DYNAMIC_ARRAY; + break; + case V4L2_CID_STATELESS_AV1_FRAME: + *type = V4L2_CTRL_TYPE_AV1_FRAME; + break; + case V4L2_CID_STATELESS_AV1_FILM_GRAIN: + *type = V4L2_CTRL_TYPE_AV1_FILM_GRAIN; + break; case V4L2_CID_UNIT_CELL_SIZE: *type = V4L2_CTRL_TYPE_AREA; *flags |= V4L2_CTRL_FLAG_READ_ONLY; diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index a858acea6547..41d7a8e3712a 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1506,6 +1506,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_QC08C: descr = "QCOM Compressed 8-bit Format"; break; case V4L2_PIX_FMT_QC10C: descr = "QCOM Compressed 10-bit Format"; break; case V4L2_PIX_FMT_AJPG: descr = "Aspeed JPEG"; break; + case V4L2_PIX_FMT_AV1_FRAME: descr = "AV1 Frame"; break; default: if (fmt->description[0]) return; diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index 7788eeb3e2bb..59679a42b3e7 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -52,6 +52,10 @@ struct video_device; * @p_hdr10_cll: Pointer to an HDR10 Content Light Level structure. * @p_hdr10_mastering: Pointer to an HDR10 Mastering Display structure. * @p_area: Pointer to an area. + * @p_av1_sequence: Pointer to an AV1 sequence structure. + * @p_av1_tile_group_entry: Pointer to an AV1 tile group entry structure. + * @p_av1_frame: Pointer to an AV1 frame structure. + * @p_av1_film_grain: Pointer to an AV1 film grain structure. * @p: Pointer to a compound value. * @p_const: Pointer to a constant compound value. */ @@ -81,6 +85,10 @@ union v4l2_ctrl_ptr { struct v4l2_ctrl_hdr10_cll_info *p_hdr10_cll; struct v4l2_ctrl_hdr10_mastering_display *p_hdr10_mastering; struct v4l2_area *p_area; + struct v4l2_ctrl_av1_sequence *p_av1_sequence; + struct v4l2_ctrl_av1_tile_group_entry *p_av1_tile_group_entry; + struct v4l2_ctrl_av1_frame *p_av1_frame; + struct v4l2_ctrl_av1_film_grain *p_av1_film_grain; void *p; const void *p_const; }; diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 7bf59a87a1bf..c3604a0a3e30 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -804,6 +804,88 @@ enum v4l2_mpeg_video_frame_skip_mode { #define V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY (V4L2_CID_CODEC_BASE + 653) #define V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE (V4L2_CID_CODEC_BASE + 654) +#define V4L2_CID_MPEG_VIDEO_AV1_PROFILE (V4L2_CID_CODEC_BASE + 655) +/** + * enum v4l2_mpeg_video_av1_profile - AV1 profiles + * + * @V4L2_MPEG_VIDEO_AV1_PROFILE_MAIN: compliant decoders must be able to decode + * streams with seq_profile equal to 0. + * @V4L2_MPEG_VIDEO_AV1_PROFILE_HIGH: compliant decoders must be able to decode + * streams with seq_profile equal less than or equal to 1. + * @V4L2_MPEG_VIDEO_AV1_PROFILE_PROFESSIONAL: compliant decoders must be able to + * decode streams with seq_profile less than or equal to 2. + * + * Conveys the highest profile a decoder can work with. + */ +enum v4l2_mpeg_video_av1_profile { + V4L2_MPEG_VIDEO_AV1_PROFILE_MAIN = 0, + V4L2_MPEG_VIDEO_AV1_PROFILE_HIGH = 1, + V4L2_MPEG_VIDEO_AV1_PROFILE_PROFESSIONAL = 2, +}; + +#define V4L2_CID_MPEG_VIDEO_AV1_LEVEL (V4L2_CID_CODEC_BASE + 656) +/** + * enum v4l2_mpeg_video_av1_level - AV1 levels + * + * @V4L2_MPEG_VIDEO_AV1_LEVEL_2_0: Level 2.0. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_2_1: Level 2.1. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_2_2: Level 2.2. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_2_3: Level 2.3. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_3_0: Level 3.0. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_3_1: Level 3.1. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_3_2: Level 3.2. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_3_3: Level 3.3. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_4_0: Level 4.0. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_4_1: Level 4.1. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_4_2: Level 4.2. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_4_3: Level 4.3. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_5_0: Level 5.0. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_5_1: Level 5.1. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_5_2: Level 5.2. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_5_3: Level 5.3. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_6_0: Level 6.0. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_6_1: Level 6.1. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_6_2: Level 6.2. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_6_3: Level 6.3. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_7_0: Level 7.0. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_7_1: Level 7.1. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_7_2: Level 7.2. + * @V4L2_MPEG_VIDEO_AV1_LEVEL_7_3: Level 7.3. + * + * Conveys the highest level a decoder can work with. + */ +enum v4l2_mpeg_video_av1_level { + V4L2_MPEG_VIDEO_AV1_LEVEL_2_0 = 0, + V4L2_MPEG_VIDEO_AV1_LEVEL_2_1 = 1, + V4L2_MPEG_VIDEO_AV1_LEVEL_2_2 = 2, + V4L2_MPEG_VIDEO_AV1_LEVEL_2_3 = 3, + + V4L2_MPEG_VIDEO_AV1_LEVEL_3_0 = 4, + V4L2_MPEG_VIDEO_AV1_LEVEL_3_1 = 5, + V4L2_MPEG_VIDEO_AV1_LEVEL_3_2 = 6, + V4L2_MPEG_VIDEO_AV1_LEVEL_3_3 = 7, + + V4L2_MPEG_VIDEO_AV1_LEVEL_4_0 = 8, + V4L2_MPEG_VIDEO_AV1_LEVEL_4_1 = 9, + V4L2_MPEG_VIDEO_AV1_LEVEL_4_2 = 10, + V4L2_MPEG_VIDEO_AV1_LEVEL_4_3 = 11, + + V4L2_MPEG_VIDEO_AV1_LEVEL_5_0 = 12, + V4L2_MPEG_VIDEO_AV1_LEVEL_5_1 = 13, + V4L2_MPEG_VIDEO_AV1_LEVEL_5_2 = 14, + V4L2_MPEG_VIDEO_AV1_LEVEL_5_3 = 15, + + V4L2_MPEG_VIDEO_AV1_LEVEL_6_0 = 16, + V4L2_MPEG_VIDEO_AV1_LEVEL_6_1 = 17, + V4L2_MPEG_VIDEO_AV1_LEVEL_6_2 = 18, + V4L2_MPEG_VIDEO_AV1_LEVEL_6_3 = 19, + + V4L2_MPEG_VIDEO_AV1_LEVEL_7_0 = 20, + V4L2_MPEG_VIDEO_AV1_LEVEL_7_1 = 21, + V4L2_MPEG_VIDEO_AV1_LEVEL_7_2 = 22, + V4L2_MPEG_VIDEO_AV1_LEVEL_7_3 = 23 +}; + /* MPEG-class control IDs specific to the CX2341x driver as defined by V4L2 */ #define V4L2_CID_CODEC_CX2341X_BASE (V4L2_CTRL_CLASS_CODEC | 0x1000) #define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE (V4L2_CID_CODEC_CX2341X_BASE+0) @@ -2758,6 +2840,645 @@ struct v4l2_ctrl_vp9_compressed_hdr { struct v4l2_vp9_mv_probs mv; }; +/* Stateless AV1 controls */ + +#define V4L2_AV1_TOTAL_REFS_PER_FRAME 8 +#define V4L2_AV1_CDEF_MAX 8 +#define V4L2_AV1_NUM_PLANES_MAX 3 /* 1 if monochrome, 3 otherwise */ +#define V4L2_AV1_MAX_SEGMENTS 8 +#define V4L2_AV1_MAX_OPERATING_POINTS (1 << 5) /* 5 bits to encode */ +#define V4L2_AV1_REFS_PER_FRAME 7 +#define V4L2_AV1_MAX_NUM_Y_POINTS (1 << 4) /* 4 bits to encode */ +#define V4L2_AV1_MAX_NUM_CB_POINTS (1 << 4) /* 4 bits to encode */ +#define V4L2_AV1_MAX_NUM_CR_POINTS (1 << 4) /* 4 bits to encode */ +#define V4L2_AV1_AR_COEFFS_SIZE 25 /* (2 * 3 * (3 + 1)) + 1 */ +#define V4L2_AV1_MAX_NUM_PLANES 3 +#define V4L2_AV1_MAX_TILE_COLS 64 +#define V4L2_AV1_MAX_TILE_ROWS 64 +#define V4L2_AV1_MAX_TILE_COUNT 512 + +#define V4L2_AV1_SEQUENCE_FLAG_STILL_PICTURE 0x00000001 +#define V4L2_AV1_SEQUENCE_FLAG_USE_128X128_SUPERBLOCK 0x00000002 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_FILTER_INTRA 0x00000004 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTRA_EDGE_FILTER 0x00000008 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTERINTRA_COMPOUND 0x00000010 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_MASKED_COMPOUND 0x00000020 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_WARPED_MOTION 0x00000040 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_DUAL_FILTER 0x00000080 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_ORDER_HINT 0x00000100 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_JNT_COMP 0x00000200 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_REF_FRAME_MVS 0x00000400 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_SUPERRES 0x00000800 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_CDEF 0x00001000 +#define V4L2_AV1_SEQUENCE_FLAG_ENABLE_RESTORATION 0x00002000 +#define V4L2_AV1_SEQUENCE_FLAG_MONO_CHROME 0x00004000 +#define V4L2_AV1_SEQUENCE_FLAG_COLOR_RANGE 0x00008000 +#define V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_X 0x00010000 +#define V4L2_AV1_SEQUENCE_FLAG_SUBSAMPLING_Y 0x00020000 +#define V4L2_AV1_SEQUENCE_FLAG_FILM_GRAIN_PARAMS_PRESENT 0x00040000 +#define V4L2_AV1_SEQUENCE_FLAG_SEPARATE_UV_DELTA_Q 0x00080000 + +#define V4L2_CID_STATELESS_AV1_SEQUENCE (V4L2_CID_CODEC_STATELESS_BASE + 500) +/** + * struct v4l2_ctrl_av1_sequence - AV1 Sequence + * + * Represents an AV1 Sequence OBU. See section 5.5 "Sequence header OBU syntax" + * for more details. + * + * @flags: See V4L2_AV1_SEQUENCE_FLAG_{}. + * @seq_profile: specifies the features that can be used in the coded video + * sequence. + * @order_hint_bits: specifies the number of bits used for the order_hint field + * at each frame. + * @bit_depth: the bitdepth to use for the sequence as described in section + * 5.5.2 "Color config syntax". + * @reserved: padding field. Should be zeroed by applications. + * @max_frame_width_minus_1: specifies the maximum frame width minus 1 for the + * frames represented by this sequence header. + * @max_frame_height_minus_1: specifies the maximum frame height minus 1 for the + * frames represented by this sequence header. + */ +struct v4l2_ctrl_av1_sequence { + __u32 flags; + __u8 seq_profile; + __u8 order_hint_bits; + __u8 bit_depth; + __u8 reserved; + __u16 max_frame_width_minus_1; + __u16 max_frame_height_minus_1; +}; + +#define V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY (V4L2_CID_CODEC_STATELESS_BASE + 501) +/** + * struct v4l2_ctrl_av1_tile_group_entry - AV1 Tile Group entry + * + * Represents a single AV1 tile inside an AV1 Tile Group. Note that MiRowStart, + * MiRowEnd, MiColStart and MiColEnd can be retrieved from struct + * v4l2_av1_tile_info in struct v4l2_ctrl_av1_frame using tile_row and + * tile_col. See section 6.10.1 "General tile group OBU semantics" for more + * details. + * + * @tile_offset: offset from the OBU data, i.e. where the coded tile data + * actually starts. + * @tile_size: specifies the size in bytes of the coded tile. Equivalent to + * "TileSize" in the AV1 Specification. + * @tile_row: specifies the row of the current tile. Equivalent to "TileRow" in + * the AV1 Specification. + * @tile_col: specifies the col of the current tile. Equivalent to "TileCol" in + * the AV1 Specification. + */ +struct v4l2_ctrl_av1_tile_group_entry { + __u32 tile_offset; + __u32 tile_size; + __u32 tile_row; + __u32 tile_col; +}; + +/** + * enum v4l2_av1_warp_model - AV1 Warp Model as described in section 3 + * "Symbols and abbreviated terms" of the AV1 Specification. + * + * @V4L2_AV1_WARP_MODEL_IDENTITY: Warp model is just an identity transform. + * @V4L2_AV1_WARP_MODEL_TRANSLATION: Warp model is a pure translation. + * @V4L2_AV1_WARP_MODEL_ROTZOOM: Warp model is a rotation + symmetric zoom + + * translation. + * @V4L2_AV1_WARP_MODEL_AFFINE: Warp model is a general affine transform. + */ +enum v4l2_av1_warp_model { + V4L2_AV1_WARP_MODEL_IDENTITY = 0, + V4L2_AV1_WARP_MODEL_TRANSLATION = 1, + V4L2_AV1_WARP_MODEL_ROTZOOM = 2, + V4L2_AV1_WARP_MODEL_AFFINE = 3, +}; + +/** + * enum v4l2_av1_reference_frame - AV1 reference frames + * + * @V4L2_AV1_REF_INTRA_FRAME: Intra Frame Reference + * @V4L2_AV1_REF_LAST_FRAME: Last Reference Frame + * @V4L2_AV1_REF_LAST2_FRAME: Last2 Reference Frame + * @V4L2_AV1_REF_LAST3_FRAME: Last3 Reference Frame + * @V4L2_AV1_REF_GOLDEN_FRAME: Golden Reference Frame + * @V4L2_AV1_REF_BWDREF_FRAME: BWD Reference Frame + * @V4L2_AV1_REF_ALTREF2_FRAME: Alternative2 Reference Frame + * @V4L2_AV1_REF_ALTREF_FRAME: Alternative Reference Frame + */ +enum v4l2_av1_reference_frame { + V4L2_AV1_REF_INTRA_FRAME = 0, + V4L2_AV1_REF_LAST_FRAME = 1, + V4L2_AV1_REF_LAST2_FRAME = 2, + V4L2_AV1_REF_LAST3_FRAME = 3, + V4L2_AV1_REF_GOLDEN_FRAME = 4, + V4L2_AV1_REF_BWDREF_FRAME = 5, + V4L2_AV1_REF_ALTREF2_FRAME = 6, + V4L2_AV1_REF_ALTREF_FRAME = 7, +}; + +#define V4L2_AV1_GLOBAL_MOTION_IS_INVALID(ref) (1 << (ref)) + +#define V4L2_AV1_GLOBAL_MOTION_FLAG_IS_GLOBAL 0x1 +#define V4L2_AV1_GLOBAL_MOTION_FLAG_IS_ROT_ZOOM 0x2 +#define V4L2_AV1_GLOBAL_MOTION_FLAG_IS_TRANSLATION 0x4 +/** + * struct v4l2_av1_global_motion - AV1 Global Motion parameters as described in + * section 6.8.17 "Global motion params semantics" of the AV1 specification. + * + * @flags: A bitfield containing the flags per reference frame. See + * V4L2_AV1_GLOBAL_MOTION_FLAG_{} + * @type: The type of global motion transform used. + * @params: this field has the same meaning as "gm_params" in the AV1 + * specification. + * @invalid: bitfield indicating whether the global motion params are invalid + * for a given reference frame. See section 7.11.3.6 Setup shear process and + * the variable "warpValid". Use V4L2_AV1_GLOBAL_MOTION_IS_INVALID(ref) to + * create a suitable mask. + * @reserved: padding field. Should be zeroed by applications. + */ + +struct v4l2_av1_global_motion { + __u8 flags[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + enum v4l2_av1_warp_model type[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + __s32 params[V4L2_AV1_TOTAL_REFS_PER_FRAME][6]; + __u8 invalid; + __u8 reserved[3]; +}; + +/** + * enum v4l2_av1_frame_restoration_type - AV1 Frame Restoration Type + * @V4L2_AV1_FRAME_RESTORE_NONE: no filtering is applied. + * @V4L2_AV1_FRAME_RESTORE_WIENER: Wiener filter process is invoked. + * @V4L2_AV1_FRAME_RESTORE_SGRPROJ: self guided filter process is invoked. + * @V4L2_AV1_FRAME_RESTORE_SWITCHABLE: restoration filter is swichtable. + */ +enum v4l2_av1_frame_restoration_type { + V4L2_AV1_FRAME_RESTORE_NONE = 0, + V4L2_AV1_FRAME_RESTORE_WIENER = 1, + V4L2_AV1_FRAME_RESTORE_SGRPROJ = 2, + V4L2_AV1_FRAME_RESTORE_SWITCHABLE = 3, +}; + +#define V4L2_AV1_LOOP_RESTORATION_FLAG_USES_LR 0x1 +#define V4L2_AV1_LOOP_RESTORATION_FLAG_USES_CHROMA_LR 0x2 + +/** + * struct v4l2_av1_loop_restoration - AV1 Loop Restauration as described in + * section 6.10.15 "Loop restoration params semantics" of the AV1 specification. + * + * @flags: See V4L2_AV1_LOOP_RESTORATION_FLAG_{}. + * @lr_unit_shift: specifies if the luma restoration size should be halved. + * @lr_uv_shift: specifies if the chroma size should be half the luma size. + * @reserved: padding field. Should be zeroed by applications. + * @frame_restoration_type: specifies the type of restoration used for each + * plane. See enum v4l2_av1_frame_restoration_type. + * @loop_restoration_size: specifies the size of loop restoration units in units + * of samples in the current plane. + */ +struct v4l2_av1_loop_restoration { + __u8 flags; + __u8 lr_unit_shift; + __u8 lr_uv_shift; + __u8 reserved; + enum v4l2_av1_frame_restoration_type frame_restoration_type[V4L2_AV1_NUM_PLANES_MAX]; + __u32 loop_restoration_size[V4L2_AV1_MAX_NUM_PLANES]; +}; + +/** + * struct v4l2_av1_cdef - AV1 CDEF params semantics as described in section + * 6.10.14 "CDEF params semantics" of the AV1 specification + * + * @damping_minus_3: controls the amount of damping in the deringing filter. + * @bits: specifies the number of bits needed to specify which CDEF filter to + * apply. + * @y_pri_strength: specifies the strength of the primary filter. + * @y_sec_strength: specifies the strength of the secondary filter. + * @uv_pri_strength: specifies the strength of the primary filter. + * @uv_sec_strength: specifies the strength of the secondary filter. + */ +struct v4l2_av1_cdef { + __u8 damping_minus_3; + __u8 bits; + __u8 y_pri_strength[V4L2_AV1_CDEF_MAX]; + __u8 y_sec_strength[V4L2_AV1_CDEF_MAX]; + __u8 uv_pri_strength[V4L2_AV1_CDEF_MAX]; + __u8 uv_sec_strength[V4L2_AV1_CDEF_MAX]; +}; + +#define V4L2_AV1_SEGMENTATION_FLAG_ENABLED 0x1 +#define V4L2_AV1_SEGMENTATION_FLAG_UPDATE_MAP 0x2 +#define V4L2_AV1_SEGMENTATION_FLAG_TEMPORAL_UPDATE 0x4 +#define V4L2_AV1_SEGMENTATION_FLAG_UPDATE_DATA 0x8 +#define V4L2_AV1_SEGMENTATION_FLAG_SEG_ID_PRE_SKIP 0x10 + +/** + * enum v4l2_av1_segment_feature - AV1 segment features as described in section + * 3 "Symbols and abbreviated terms" of the AV1 specification. + * + * @V4L2_AV1_SEG_LVL_ALT_Q: Index for quantizer segment feature. + * @V4L2_AV1_SEG_LVL_ALT_LF_Y_V: Index for vertical luma loop filter segment + * feature. + * @V4L2_AV1_SEG_LVL_REF_FRAME: Index for reference frame segment feature. + * @V4L2_AV1_SEG_LVL_REF_SKIP: Index for skip segment feature. + * @V4L2_AV1_SEG_LVL_REF_GLOBALMV: Index for global mv feature. + * @V4L2_AV1_SEG_LVL_MAX: Number of segment features. + */ +enum v4l2_av1_segment_feature { + V4L2_AV1_SEG_LVL_ALT_Q = 0, + V4L2_AV1_SEG_LVL_ALT_LF_Y_V = 1, + V4L2_AV1_SEG_LVL_REF_FRAME = 5, + V4L2_AV1_SEG_LVL_REF_SKIP = 6, + V4L2_AV1_SEG_LVL_REF_GLOBALMV = 7, + V4L2_AV1_SEG_LVL_MAX = 8 +}; + +#define V4L2_AV1_SEGMENT_FEATURE_ENABLED(id) (1 << (id)) + +/** + * struct v4l2_av1_segmentation - AV1 Segmentation params as defined in section + * 6.8.13 "Segmentation params semantics" of the AV1 specification. + * + * @flags: see V4L2_AV1_SEGMENTATION_FLAG_{}. + * @last_active_seg_id: indicates the highest numbered segment id that has some + * enabled feature. This is used when decoding the segment id to only decode + * choices corresponding to used segments. + * @feature_enabled: bitmask defining which features are enabled in each + * segment. Use V4L2_AV1_SEGMENT_FEATURE_ENABLED to build a suitable mask. + * @feature_data: data attached to each feature. Data entry is only valid if the + * feature is enabled + */ +struct v4l2_av1_segmentation { + __u8 flags; + __u8 last_active_seg_id; + __u8 feature_enabled[V4L2_AV1_MAX_SEGMENTS]; + __s16 feature_data[V4L2_AV1_MAX_SEGMENTS][V4L2_AV1_SEG_LVL_MAX]; +}; + +#define V4L2_AV1_LOOP_FILTER_FLAG_DELTA_ENABLED 0x1 +#define V4L2_AV1_LOOP_FILTER_FLAG_DELTA_UPDATE 0x2 +#define V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_PRESENT 0x4 +#define V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_MULTI 0x8 + +/** + * struct v4l2_av1_loop_filter - AV1 Loop filter params as defined in section + * 6.8.10 "Loop filter semantics" and 6.8.16 "Loop filter delta parameters + * semantics" of the AV1 specification. + * + * @flags: see V4L2_AV1_LOOP_FILTER_FLAG_{} + * @level: an array containing loop filter strength values. Different loop + * filter strength values from the array are used depending on the image plane + * being filtered, and the edge direction (vertical or horizontal) being + * filtered. + * @sharpness: indicates the sharpness level. The loop_filter_level and + * loop_filter_sharpness together determine when a block edge is filtered, and + * by how much the filtering can change the sample values. The loop filter + * process is described in section 7.14 of the AV1 specification. + * @ref_deltas: contains the adjustment needed for the filter level based on the + * chosen reference frame. If this syntax element is not present, it maintains + * its previous value. + * @mode_deltas: contains the adjustment needed for the filter level based on + * the chosen mode. If this syntax element is not present, it maintains its + * previous value. + * @delta_lf_res: specifies the left shift which should be applied to decoded + * loop filter delta values. + */ +struct v4l2_av1_loop_filter { + __u8 flags; + __u8 level[4]; + __u8 sharpness; + __s8 ref_deltas[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + __s8 mode_deltas[2]; + __u8 delta_lf_res; +}; + +#define V4L2_AV1_QUANTIZATION_FLAG_DIFF_UV_DELTA 0x1 +#define V4L2_AV1_QUANTIZATION_FLAG_USING_QMATRIX 0x2 +#define V4L2_AV1_QUANTIZATION_FLAG_DELTA_Q_PRESENT 0x4 + +/** + * struct v4l2_av1_quantization - AV1 Quantization params as defined in section + * 6.8.11 "Quantization params semantics" of the AV1 specification. + * + * @flags: see V4L2_AV1_QUANTIZATION_FLAG_{} + * @base_q_idx: indicates the base frame qindex. This is used for Y AC + * coefficients and as the base value for the other quantizers. + * @delta_q_y_dc: indicates the Y DC quantizer relative to base_q_idx. + * @delta_q_u_dc: indicates the U DC quantizer relative to base_q_idx. + * @delta_q_u_ac: indicates the U AC quantizer relative to base_q_idx. + * @delta_q_v_dc: indicates the V DC quantizer relative to base_q_idx. + * @delta_q_v_ac: indicates the V AC quantizer relative to base_q_idx. + * @qm_y: specifies the level in the quantizer matrix that should be used for + * luma plane decoding. + * @qm_u: specifies the level in the quantizer matrix that should be used for + * chroma U plane decoding. + * @qm_v: specifies the level in the quantizer matrix that should be used for + * chroma V plane decoding. + * @delta_q_res: specifies the left shift which should be applied to decoded + * quantizer index delta values. + */ +struct v4l2_av1_quantization { + __u8 flags; + __u8 base_q_idx; + __s8 delta_q_y_dc; + __s8 delta_q_u_dc; + __s8 delta_q_u_ac; + __s8 delta_q_v_dc; + __s8 delta_q_v_ac; + __u8 qm_y; + __u8 qm_u; + __u8 qm_v; + __u8 delta_q_res; +}; + +#define V4L2_AV1_TILE_INFO_FLAG_UNIFORM_TILE_SPACING 0x1 + +/** + * struct v4l2_av1_tile_info - AV1 Tile info as defined in section 6.8.14 "Tile + * info semantics" of the AV1 specification. + * + * @flags: see V4L2_AV1_TILE_INFO_FLAG_{} + * @context_update_tile_id: specifies which tile to use for the CDF update. + * @tile_rows: specifies the number of tiles down the frame. + * @tile_cols: specifies the number of tiles across the frame. + * @mi_col_starts: an array specifying the start column (in units of 4x4 luma + * samples) for each tile across the image. + * @mi_row_starts: an array specifying the start row (in units of 4x4 luma + * samples) for each tile down the image. + * @width_in_sbs_minus_1: specifies the width of a tile minus 1 in units of + * superblocks. + * @height_in_sbs_minus_1: specifies the height of a tile minus 1 in units of + * superblocks. + * @tile_size_bytes: specifies the number of bytes needed to code each tile + * size. + * @reserved: padding field. Should be zeroed by applications. + */ +struct v4l2_av1_tile_info { + __u8 flags; + __u8 context_update_tile_id; + __u8 tile_cols; + __u8 tile_rows; + __u32 mi_col_starts[V4L2_AV1_MAX_TILE_COLS + 1]; + __u32 mi_row_starts[V4L2_AV1_MAX_TILE_ROWS + 1]; + __u32 width_in_sbs_minus_1[V4L2_AV1_MAX_TILE_COLS]; + __u32 height_in_sbs_minus_1[V4L2_AV1_MAX_TILE_ROWS]; + __u8 tile_size_bytes; + __u8 reserved[3]; +}; + +/** + * enum v4l2_av1_frame_type - AV1 Frame Type + * + * @V4L2_AV1_KEY_FRAME: Key frame + * @V4L2_AV1_INTER_FRAME: Inter frame + * @V4L2_AV1_INTRA_ONLY_FRAME: Intra-only frame + * @V4L2_AV1_SWITCH_FRAME: Switch frame + */ +enum v4l2_av1_frame_type { + V4L2_AV1_KEY_FRAME = 0, + V4L2_AV1_INTER_FRAME = 1, + V4L2_AV1_INTRA_ONLY_FRAME = 2, + V4L2_AV1_SWITCH_FRAME = 3 +}; + +/** + * enum v4l2_av1_interpolation_filter - AV1 interpolation filter types + * + * @V4L2_AV1_INTERPOLATION_FILTER_EIGHTTAP: eight tap filter + * @V4L2_AV1_INTERPOLATION_FILTER_EIGHTTAP_SMOOTH: eight tap smooth filter + * @V4L2_AV1_INTERPOLATION_FILTER_EIGHTTAP_SHARP: eight tap sharp filter + * @V4L2_AV1_INTERPOLATION_FILTER_BILINEAR: bilinear filter + * @V4L2_AV1_INTERPOLATION_FILTER_SWITCHABLE: filter selection is signaled at + * the block level + * + * See section 6.8.9 "Interpolation filter semantics" of the AV1 specification + * for more details. + */ +enum v4l2_av1_interpolation_filter { + V4L2_AV1_INTERPOLATION_FILTER_EIGHTTAP = 0, + V4L2_AV1_INTERPOLATION_FILTER_EIGHTTAP_SMOOTH = 1, + V4L2_AV1_INTERPOLATION_FILTER_EIGHTTAP_SHARP = 2, + V4L2_AV1_INTERPOLATION_FILTER_BILINEAR = 3, + V4L2_AV1_INTERPOLATION_FILTER_SWITCHABLE = 4, +}; + +/** + * enum v4l2_av1_tx_mode - AV1 Tx mode as described in section 6.8.21 "TX mode + * semantics" of the AV1 specification. + * @V4L2_AV1_TX_MODE_ONLY_4X4: the inverse transform will use only 4x4 + * transforms + * @V4L2_AV1_TX_MODE_LARGEST: the inverse transform will use the largest + * transform size that fits inside the block + * @V4L2_AV1_TX_MODE_SELECT: the choice of transform size is specified + * explicitly for each block. + */ +enum v4l2_av1_tx_mode { + V4L2_AV1_TX_MODE_ONLY_4X4 = 0, + V4L2_AV1_TX_MODE_LARGEST = 1, + V4L2_AV1_TX_MODE_SELECT = 2 +}; + +#define V4L2_AV1_FRAME_FLAG_SHOW_FRAME 0x00000001 +#define V4L2_AV1_FRAME_FLAG_SHOWABLE_FRAME 0x00000002 +#define V4L2_AV1_FRAME_FLAG_ERROR_RESILIENT_MODE 0x00000004 +#define V4L2_AV1_FRAME_FLAG_DISABLE_CDF_UPDATE 0x00000008 +#define V4L2_AV1_FRAME_FLAG_ALLOW_SCREEN_CONTENT_TOOLS 0x00000010 +#define V4L2_AV1_FRAME_FLAG_FORCE_INTEGER_MV 0x00000020 +#define V4L2_AV1_FRAME_FLAG_ALLOW_INTRABC 0x00000040 +#define V4L2_AV1_FRAME_FLAG_USE_SUPERRES 0x00000080 +#define V4L2_AV1_FRAME_FLAG_ALLOW_HIGH_PRECISION_MV 0x00000100 +#define V4L2_AV1_FRAME_FLAG_IS_MOTION_MODE_SWITCHABLE 0x00000200 +#define V4L2_AV1_FRAME_FLAG_USE_REF_FRAME_MVS 0x00000400 +#define V4L2_AV1_FRAME_FLAG_DISABLE_FRAME_END_UPDATE_CDF 0x00000800 +#define V4L2_AV1_FRAME_FLAG_ALLOW_WARPED_MOTION 0x00001000 +#define V4L2_AV1_FRAME_FLAG_REFERENCE_SELECT 0x00002000 +#define V4L2_AV1_FRAME_FLAG_REDUCED_TX_SET 0x00004000 +#define V4L2_AV1_FRAME_FLAG_SKIP_MODE_ALLOWED 0x00008000 +#define V4L2_AV1_FRAME_FLAG_SKIP_MODE_PRESENT 0x00010000 +#define V4L2_AV1_FRAME_FLAG_FRAME_SIZE_OVERRIDE 0x00020000 +#define V4L2_AV1_FRAME_FLAG_BUFFER_REMOVAL_TIME_PRESENT 0x00040000 +#define V4L2_AV1_FRAME_FLAG_FRAME_REFS_SHORT_SIGNALING 0x00080000 + +#define V4L2_CID_STATELESS_AV1_FRAME (V4L2_CID_CODEC_STATELESS_BASE + 502) +/** + * struct v4l2_ctrl_av1_frame - Represents an AV1 Frame Header OBU. + * + * @tile_info: tile info + * @quantization: quantization params + * @segmentation: segmentation params + * @superres_denom: the denominator for the upscaling ratio. + * @loop_filter: loop filter params + * @cdef: cdef params + * @skip_mode_frame: specifies the frames to use for compound prediction when + * skip_mode is equal to 1. + * @primary_ref_frame: specifies which reference frame contains the CDF values + * and other state that should be loaded at the start of the frame. + * @loop_restoration: loop restoration params + * @global_motion: global motion params + * @flags: see V4L2_AV1_FRAME_FLAG_{} + * @frame_type: specifies the AV1 frame type + * @order_hint: specifies OrderHintBits least significant bits of the expected + * output order for this frame. + * @upscaled_width: the upscaled width. + * @interpolation_filter: specifies the filter selection used for performing + * inter prediction. + * @tx_mode: specifies how the transform size is determined. + * @frame_width_minus_1: add 1 to get the frame's width. + * @frame_height_minus_1: add 1 to get the frame's height + * @render_width_minus_1: add 1 to get the render width of the frame in luma + * samples. + * @render_height_minus_1: add 1 to get the render height of the frame in luma + * samples. + * @current_frame_id: specifies the frame id number for the current frame. Frame + * id numbers are additional information that do not affect the decoding + * process, but provide decoders with a way of detecting missing reference + * frames so that appropriate action can be taken. + * @buffer_removal_time: specifies the frame removal time in units of DecCT clock + * ticks counted from the removal time of the last random access point for + * operating point opNum. + * @reserved: padding field. Should be zeroed by applications. + * @order_hints: specifies the expected output order hint for each reference + * frame. This field corresponds to the OrderHints variable from the + * specification (section 5.9.2 "Uncompressed header syntax"). As such, this is + * only used for non-intra frames and ignored otherwise. order_hints[0] is + * always ignored. + * @reference_frame_ts: the V4L2 timestamp of the reference frame slots. + * @ref_frame_idx: used to index into @reference_frame_ts when decoding + * inter-frames. The meaning of this array is the same as in the specification. + * The timestamp refers to the timestamp field in struct v4l2_buffer. Use + * v4l2_timeval_to_ns() to convert the struct timeval to a __u64. + * @refresh_frame_flags: contains a bitmask that specifies which reference frame + * slots will be updated with the current frame after it is decoded. + */ +struct v4l2_ctrl_av1_frame { + struct v4l2_av1_tile_info tile_info; + struct v4l2_av1_quantization quantization; + __u8 superres_denom; + struct v4l2_av1_segmentation segmentation; + struct v4l2_av1_loop_filter loop_filter; + struct v4l2_av1_cdef cdef; + __u8 skip_mode_frame[2]; + __u8 primary_ref_frame; + struct v4l2_av1_loop_restoration loop_restoration; + struct v4l2_av1_global_motion global_motion; + __u32 flags; + enum v4l2_av1_frame_type frame_type; + __u32 order_hint; + __u32 upscaled_width; + enum v4l2_av1_interpolation_filter interpolation_filter; + enum v4l2_av1_tx_mode tx_mode; + __u32 frame_width_minus_1; + __u32 frame_height_minus_1; + __u16 render_width_minus_1; + __u16 render_height_minus_1; + + __u32 current_frame_id; + __u32 buffer_removal_time[V4L2_AV1_MAX_OPERATING_POINTS]; + __u8 reserved[4]; + __u32 order_hints[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + __u64 reference_frame_ts[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + __s8 ref_frame_idx[V4L2_AV1_REFS_PER_FRAME]; + __u8 refresh_frame_flags; +}; + +#define V4L2_AV1_FILM_GRAIN_FLAG_APPLY_GRAIN 0x1 +#define V4L2_AV1_FILM_GRAIN_FLAG_UPDATE_GRAIN 0x2 +#define V4L2_AV1_FILM_GRAIN_FLAG_CHROMA_SCALING_FROM_LUMA 0x4 +#define V4L2_AV1_FILM_GRAIN_FLAG_OVERLAP 0x8 +#define V4L2_AV1_FILM_GRAIN_FLAG_CLIP_TO_RESTRICTED_RANGE 0x10 + +#define V4L2_CID_STATELESS_AV1_FILM_GRAIN (V4L2_CID_CODEC_STATELESS_BASE + 505) +/** + * struct v4l2_ctrl_av1_film_grain - AV1 Film Grain parameters. + * + * Film grain parameters as specified by section 6.8.20 of the AV1 Specification. + * + * @flags: see V4L2_AV1_FILM_GRAIN_{}. + * @cr_mult: represents a multiplier for the cr component used in derivation of + * the input index to the cr component scaling function. + * @grain_seed: specifies the starting value for the pseudo-random numbers used + * during film grain synthesis. + * @film_grain_params_ref_idx: indicates which reference frame contains the + * film grain parameters to be used for this frame. + * @num_y_points: specifies the number of points for the piece-wise linear + * scaling function of the luma component. + * @point_y_value: represents the x (luma value) coordinate for the i-th point + * of the piecewise linear scaling function for luma component. The values are + * signaled on the scale of 0..255. In case of 10 bit video, these values + * correspond to luma values divided by 4. In case of 12 bit video, these values + * correspond to luma values divided by 16. + * @point_y_scaling: represents the scaling (output) value for the i-th point + * of the piecewise linear scaling function for luma component. + * @num_cb_points: specifies the number of points for the piece-wise linear + * scaling function of the cb component. + * @point_cb_value: represents the x coordinate for the i-th point of the + * piece-wise linear scaling function for cb component. The values are signaled + * on the scale of 0..255. + * @point_cb_scaling: represents the scaling (output) value for the i-th point + * of the piecewise linear scaling function for cb component. + * @num_cr_points: specifies represents the number of points for the piece-wise + * linear scaling function of the cr component. + * @point_cr_value: represents the x coordinate for the i-th point of the + * piece-wise linear scaling function for cr component. The values are signaled + * on the scale of 0..255. + * @point_cr_scaling: represents the scaling (output) value for the i-th point + * of the piecewise linear scaling function for cr component. + * @grain_scaling_minus_8: represents the shift – 8 applied to the values of the + * chroma component. The grain_scaling_minus_8 can take values of 0..3 and + * determines the range and quantization step of the standard deviation of film + * grain. + * @ar_coeff_lag: specifies the number of auto-regressive coefficients for luma + * and chroma. + * @ar_coeffs_y_plus_128: specifies auto-regressive coefficients used for the Y + * plane. + * @ar_coeffs_cb_plus_128: specifies auto-regressive coefficients used for the U + * plane. + * @ar_coeffs_cr_plus_128: specifies auto-regressive coefficients used for the V + * plane. + * @ar_coeff_shift_minus_6: specifies the range of the auto-regressive + * coefficients. Values of 0, 1, 2, and 3 correspond to the ranges for + * auto-regressive coefficients of [-2, 2), [-1, 1), [-0.5, 0.5) and [-0.25, + * 0.25) respectively. + * @grain_scale_shift: specifies how much the Gaussian random numbers should be + * scaled down during the grain synthesis process. + * @cb_mult: represents a multiplier for the cb component used in derivation of + * the input index to the cb component scaling function. + * @cb_luma_mult: represents a multiplier for the average luma component used in + * derivation of the input index to the cb component scaling function. + * @cr_luma_mult: represents a multiplier for the average luma component used in + * derivation of the input index to the cr component scaling function. + * @cb_offset: represents an offset used in derivation of the input index to the + * cb component scaling function. + * @cr_offset: represents an offset used in derivation of the input index to the + * cr component scaling function. + * @reserved: padding field. Should be zeroed by applications. + */ +struct v4l2_ctrl_av1_film_grain { + __u8 flags; + __u8 cr_mult; + __u16 grain_seed; + __u8 film_grain_params_ref_idx; + __u8 num_y_points; + __u8 point_y_value[V4L2_AV1_MAX_NUM_Y_POINTS]; + __u8 point_y_scaling[V4L2_AV1_MAX_NUM_Y_POINTS]; + __u8 num_cb_points; + __u8 point_cb_value[V4L2_AV1_MAX_NUM_CB_POINTS]; + __u8 point_cb_scaling[V4L2_AV1_MAX_NUM_CB_POINTS]; + __u8 num_cr_points; + __u8 point_cr_value[V4L2_AV1_MAX_NUM_CR_POINTS]; + __u8 point_cr_scaling[V4L2_AV1_MAX_NUM_CR_POINTS]; + __u8 grain_scaling_minus_8; + __u8 ar_coeff_lag; + __u8 ar_coeffs_y_plus_128[V4L2_AV1_AR_COEFFS_SIZE]; + __u8 ar_coeffs_cb_plus_128[V4L2_AV1_AR_COEFFS_SIZE]; + __u8 ar_coeffs_cr_plus_128[V4L2_AV1_AR_COEFFS_SIZE]; + __u8 ar_coeff_shift_minus_6; + __u8 grain_scale_shift; + __u8 cb_mult; + __u8 cb_luma_mult; + __u8 cr_luma_mult; + __u16 cb_offset; + __u16 cr_offset; + __u8 reserved[4]; +}; + /* MPEG-compression definitions kept for backwards compatibility */ #ifndef __KERNEL__ #define V4L2_CTRL_CLASS_MPEG V4L2_CTRL_CLASS_CODEC diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 5d8bd754c69f..585109d8a643 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -758,6 +758,7 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_FWHT_STATELESS v4l2_fourcc('S', 'F', 'W', 'H') /* Stateless FWHT (vicodec) */ #define V4L2_PIX_FMT_H264_SLICE v4l2_fourcc('S', '2', '6', '4') /* H264 parsed slices */ #define V4L2_PIX_FMT_HEVC_SLICE v4l2_fourcc('S', '2', '6', '5') /* HEVC parsed slices */ +#define V4L2_PIX_FMT_AV1_FRAME v4l2_fourcc('A', 'V', '1', 'F') /* AV1 parsed frame */ #define V4L2_PIX_FMT_SPK v4l2_fourcc('S', 'P', 'K', '0') /* Sorenson Spark */ #define V4L2_PIX_FMT_RV30 v4l2_fourcc('R', 'V', '3', '0') /* RealVideo 8 */ #define V4L2_PIX_FMT_RV40 v4l2_fourcc('R', 'V', '4', '0') /* RealVideo 9 & 10 */ @@ -1828,6 +1829,10 @@ struct v4l2_ext_control { struct v4l2_ctrl_hevc_slice_params __user *p_hevc_slice_params; struct v4l2_ctrl_hevc_scaling_matrix __user *p_hevc_scaling_matrix; struct v4l2_ctrl_hevc_decode_params __user *p_hevc_decode_params; + struct v4l2_ctrl_av1_sequence __user *p_av1_sequence; + struct v4l2_ctrl_av1_tile_group_entry __user *p_av1_tile_group_entry; + struct v4l2_ctrl_av1_frame __user *p_av1_frame; + struct v4l2_ctrl_av1_film_grain __user *p_av1_film_grain; void __user *ptr; }; } __attribute__ ((packed)); @@ -1901,6 +1906,11 @@ enum v4l2_ctrl_type { V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS = 0x0272, V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX = 0x0273, V4L2_CTRL_TYPE_HEVC_DECODE_PARAMS = 0x0274, + + V4L2_CTRL_TYPE_AV1_SEQUENCE = 0x280, + V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY = 0x281, + V4L2_CTRL_TYPE_AV1_FRAME = 0x282, + V4L2_CTRL_TYPE_AV1_FILM_GRAIN = 0x283, }; /* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ From 1fb38c3cfd39ada092a0a1588a119bf297494b9d Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 3 May 2023 09:34:26 +0100 Subject: [PATCH 227/253] media: dt-bindings: media: rockchip-vpu: Add rk3588 vpu compatible Add compatible for rk3588 AV1 vpu decoder. Signed-off-by: Benjamin Gaignard Acked-by: Krzysztof Kozlowski Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/rockchip-vpu.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml index ee622a8ee1cc..772ec3283bc6 100644 --- a/Documentation/devicetree/bindings/media/rockchip-vpu.yaml +++ b/Documentation/devicetree/bindings/media/rockchip-vpu.yaml @@ -24,6 +24,7 @@ properties: - rockchip,rk3399-vpu - rockchip,px30-vpu - rockchip,rk3568-vpu + - rockchip,rk3588-av1-vpu - items: - const: rockchip,rk3188-vpu - const: rockchip,rk3066-vpu From 2ef3372355f63fc1a29310ce9064fb76fe0806ed Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 3 May 2023 09:34:27 +0100 Subject: [PATCH 228/253] media: AV1: Make sure that bit depth in correctly initialize Make sure that bit_depth field of V4L2_CTRL_TYPE_AV1_SEQUENCE is initialized correctly before using it. Signed-off-by: Benjamin Gaignard Reviewed-by: Nicolas Dufresne Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ctrls-core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c index 9fd37e94db17..a662fb60f73f 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-core.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c @@ -111,6 +111,7 @@ static void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx, struct v4l2_ctrl_vp9_frame *p_vp9_frame; struct v4l2_ctrl_fwht_params *p_fwht_params; struct v4l2_ctrl_h264_scaling_matrix *p_h264_scaling_matrix; + struct v4l2_ctrl_av1_sequence *p_av1_sequence; void *p = ptr.p + idx * ctrl->elem_size; if (ctrl->p_def.p_const) @@ -157,6 +158,10 @@ static void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx, p_vp9_frame->flags |= V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING | V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING; break; + case V4L2_CTRL_TYPE_AV1_SEQUENCE: + p_av1_sequence = p; + p_av1_sequence->bit_depth = 8; + break; case V4L2_CTRL_TYPE_FWHT_PARAMS: p_fwht_params = p; p_fwht_params->version = V4L2_FWHT_VERSION; From 86c256be5848b2515702832ce93f748d9ffbebea Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Wed, 3 May 2023 09:34:28 +0100 Subject: [PATCH 229/253] media: v4l2-common: Add support for fractional bpp Fraction bytes-per-pixel exist for some packed format. You will find notably on Rockhip platform that 10bit data is stored fully packed, meaning that there is 1.25 pixels per bytes. This can be represented with the fraction 5/4 and can be used to scale the width into a bytesperline. Signed-off-by: Nicolas Dufresne Signed-off-by: Benjamin Gaignard Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-common.c | 156 +++++++++++++------------- include/media/v4l2-common.h | 2 + 2 files changed, 80 insertions(+), 78 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c index 3c5ab5ecd678..4b3faec14f69 100644 --- a/drivers/media/v4l2-core/v4l2-common.c +++ b/drivers/media/v4l2-core/v4l2-common.c @@ -235,91 +235,91 @@ const struct v4l2_format_info *v4l2_format_info(u32 format) { static const struct v4l2_format_info formats[] = { /* RGB formats */ - { .format = V4L2_PIX_FMT_BGR24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_RGB24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_HSV24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_BGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_XBGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_BGRX32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_RGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_XRGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_RGBX32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_HSV32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_ARGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_RGBA32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_ABGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_BGRA32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_RGB565, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_RGB555, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_BGR666, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_BGR48_12, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_ABGR64_12, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 8, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_BGR24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_RGB24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_HSV24, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_BGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_XBGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_BGRX32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_RGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_XRGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_RGBX32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_HSV32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_ARGB32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_RGBA32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_ABGR32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_BGRA32, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_RGB565, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_RGB555, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_BGR666, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_BGR48_12, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_ABGR64_12, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 8, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, /* YUV packed formats */ - { .format = V4L2_PIX_FMT_YUYV, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_YVYU, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_UYVY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_VYUY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_Y212, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_YUV48_12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YUYV, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YVYU, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_UYVY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_VYUY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_Y212, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YUV48_12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, /* YUV planar formats */ - { .format = V4L2_PIX_FMT_NV12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, - { .format = V4L2_PIX_FMT_NV21, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, - { .format = V4L2_PIX_FMT_NV16, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_NV61, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_NV24, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_NV42, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_P010, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_P012, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_NV12, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_NV21, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_NV16, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_NV61, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_NV24, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_NV42, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_P010, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_P012, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, - { .format = V4L2_PIX_FMT_YUV410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 }, - { .format = V4L2_PIX_FMT_YVU410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 }, - { .format = V4L2_PIX_FMT_YUV411P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_YUV420, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, - { .format = V4L2_PIX_FMT_YVU420, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, - { .format = V4L2_PIX_FMT_YUV422P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_GREY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YUV410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 4, .vdiv = 4 }, + { .format = V4L2_PIX_FMT_YVU410, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 4, .vdiv = 4 }, + { .format = V4L2_PIX_FMT_YUV411P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 4, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YUV420, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_YVU420, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_YUV422P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_GREY, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, /* Tiled YUV formats */ - { .format = V4L2_PIX_FMT_NV12_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, - { .format = V4L2_PIX_FMT_P010_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_NV12_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_P010_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, /* YUV planar formats, non contiguous variant */ - { .format = V4L2_PIX_FMT_YUV420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, - { .format = V4L2_PIX_FMT_YVU420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, - { .format = V4L2_PIX_FMT_YUV422M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_YVU422M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_YUV444M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_YVU444M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YUV420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_YVU420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_YUV422M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YVU422M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YUV444M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_YVU444M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_NV12M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, - { .format = V4L2_PIX_FMT_NV21M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, - { .format = V4L2_PIX_FMT_NV16M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_NV61M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_P012M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_NV12M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_NV21M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_NV16M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_NV61M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_P012M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, /* Bayer RGB formats */ - { .format = V4L2_PIX_FMT_SBGGR8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGBRG8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGRBG8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SRGGB8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SBGGR10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGBRG10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGRBG10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SRGGB10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SBGGR10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGBRG10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGRBG10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SRGGB10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SBGGR10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGBRG10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGRBG10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SRGGB10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SBGGR12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGBRG12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGRBG12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SRGGB12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SBGGR8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGBRG8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGRBG8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SRGGB8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SBGGR10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGBRG10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGRBG10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SRGGB10, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SBGGR10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGBRG10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGRBG10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SRGGB10ALAW8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SBGGR10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGBRG10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGRBG10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SRGGB10DPCM8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SBGGR12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGBRG12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SGRBG12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_SRGGB12, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, }; unsigned int i; @@ -379,7 +379,7 @@ int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, if (info->mem_planes == 1) { plane = &pixfmt->plane_fmt[0]; - plane->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0]; + plane->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0] / info->bpp_div[0]; plane->sizeimage = 0; for (i = 0; i < info->comp_planes; i++) { @@ -393,7 +393,7 @@ int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, plane->sizeimage += info->bpp[i] * DIV_ROUND_UP(aligned_width, hdiv) * - DIV_ROUND_UP(aligned_height, vdiv); + DIV_ROUND_UP(aligned_height, vdiv) / info->bpp_div[i]; } } else { for (i = 0; i < info->comp_planes; i++) { @@ -407,7 +407,7 @@ int v4l2_fill_pixfmt_mp(struct v4l2_pix_format_mplane *pixfmt, plane = &pixfmt->plane_fmt[i]; plane->bytesperline = - info->bpp[i] * DIV_ROUND_UP(aligned_width, hdiv); + info->bpp[i] * DIV_ROUND_UP(aligned_width, hdiv) / info->bpp_div[i]; plane->sizeimage = plane->bytesperline * DIV_ROUND_UP(aligned_height, vdiv); } @@ -433,7 +433,7 @@ int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, u32 pixelformat, pixfmt->width = width; pixfmt->height = height; pixfmt->pixelformat = pixelformat; - pixfmt->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0]; + pixfmt->bytesperline = ALIGN(width, v4l2_format_block_width(info, 0)) * info->bpp[0] / info->bpp_div[0]; pixfmt->sizeimage = 0; for (i = 0; i < info->comp_planes; i++) { @@ -447,7 +447,7 @@ int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, u32 pixelformat, pixfmt->sizeimage += info->bpp[i] * DIV_ROUND_UP(aligned_width, hdiv) * - DIV_ROUND_UP(aligned_height, vdiv); + DIV_ROUND_UP(aligned_height, vdiv) / info->bpp_div[i]; } return 0; } diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 1bdaea248089..d278836fd9cb 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -480,6 +480,7 @@ enum v4l2_pixel_encoding { * @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 + * @bpp_div: Array of per-plane bytes per pixel divisors to support fractional pixel sizes. * @hdiv: Horizontal chroma subsampling factor * @vdiv: Vertical chroma subsampling factor * @block_w: Per-plane macroblock pixel width (optional) @@ -491,6 +492,7 @@ struct v4l2_format_info { u8 mem_planes; u8 comp_planes; u8 bpp[4]; + u8 bpp_div[4]; u8 hdiv; u8 vdiv; u8 block_w[4]; From fc91af075512386facb5f1a84fe85dcf28f68767 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 3 May 2023 09:34:29 +0100 Subject: [PATCH 230/253] media: Add NV15_4L4 pixel format NV15_4L4 is the 10-bits per component 4x4 tiled format. Signed-off-by: Benjamin Gaignard Signed-off-by: Nicolas Dufresne Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/v4l/pixfmt-yuv-planar.rst | 16 ++++++++++++++++ drivers/media/v4l2-core/v4l2-common.c | 2 ++ drivers/media/v4l2-core/v4l2-ioctl.c | 1 + include/uapi/linux/videodev2.h | 1 + 4 files changed, 20 insertions(+) diff --git a/Documentation/userspace-api/media/v4l/pixfmt-yuv-planar.rst b/Documentation/userspace-api/media/v4l/pixfmt-yuv-planar.rst index 72324274f20c..1840224faa41 100644 --- a/Documentation/userspace-api/media/v4l/pixfmt-yuv-planar.rst +++ b/Documentation/userspace-api/media/v4l/pixfmt-yuv-planar.rst @@ -137,6 +137,13 @@ All components are stored with the same number of bits per component. - Cb, Cr - No - Linear + * - V4L2_PIX_FMT_NV15_4L4 + - 'VT15' + - 15 + - 4:2:0 + - Cb, Cr + - Yes + - 4x4 tiles * - V4L2_PIX_FMT_NV16 - 'NV16' - 8 @@ -378,6 +385,15 @@ two non-contiguous planes. Example V4L2_PIX_FMT_NV12MT memory layout of tiles +.. _V4L2-PIX-FMT-NV15-4L4: + +Tiled NV15 +---------- + +Semi-planar 10-bit YUV 4:2:0 formats, using 4x4 tiling. +All components are packed without any padding between each other. +As a side-effect, each group of 4 components are stored over 5 bytes +(YYYY or UVUV = 4 * 10 bits = 40 bits = 5 bytes). .. _V4L2-PIX-FMT-NV16: .. _V4L2-PIX-FMT-NV61: diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c index 4b3faec14f69..bee1535b04d3 100644 --- a/drivers/media/v4l2-core/v4l2-common.c +++ b/drivers/media/v4l2-core/v4l2-common.c @@ -283,6 +283,8 @@ const struct v4l2_format_info *v4l2_format_info(u32 format) /* Tiled YUV formats */ { .format = V4L2_PIX_FMT_NV12_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, + { .format = V4L2_PIX_FMT_NV15_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 5, 10, 0, 0 }, .bpp_div = { 4, 4, 1, 1 }, .hdiv = 2, .vdiv = 2, + .block_w = { 4, 2, 0, 0 }, .block_h = { 1, 1, 0, 0 }}, { .format = V4L2_PIX_FMT_P010_4L4, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, /* YUV planar formats, non contiguous variant */ diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 41d7a8e3712a..01ba27f2ef87 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1356,6 +1356,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_NV12_4L4: descr = "Y/UV 4:2:0 (4x4 Linear)"; break; case V4L2_PIX_FMT_NV12_16L16: descr = "Y/UV 4:2:0 (16x16 Linear)"; break; case V4L2_PIX_FMT_NV12_32L32: descr = "Y/UV 4:2:0 (32x32 Linear)"; break; + case V4L2_PIX_FMT_NV15_4L4: descr = "10-bit Y/UV 4:2:0 (4x4 Linear)"; break; case V4L2_PIX_FMT_P010_4L4: descr = "10-bit Y/UV 4:2:0 (4x4 Linear)"; break; case V4L2_PIX_FMT_NV12M: descr = "Y/UV 4:2:0 (N-C)"; break; case V4L2_PIX_FMT_NV21M: descr = "Y/VU 4:2:0 (N-C)"; break; diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 585109d8a643..3af6a82d0cad 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -672,6 +672,7 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_NV12_4L4 v4l2_fourcc('V', 'T', '1', '2') /* 12 Y/CbCr 4:2:0 4x4 tiles */ #define V4L2_PIX_FMT_NV12_16L16 v4l2_fourcc('H', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 16x16 tiles */ #define V4L2_PIX_FMT_NV12_32L32 v4l2_fourcc('S', 'T', '1', '2') /* 12 Y/CbCr 4:2:0 32x32 tiles */ +#define V4L2_PIX_FMT_NV15_4L4 v4l2_fourcc('V', 'T', '1', '5') /* 15 Y/CbCr 4:2:0 10-bit 4x4 tiles */ #define V4L2_PIX_FMT_P010_4L4 v4l2_fourcc('T', '0', '1', '0') /* 12 Y/CbCr 4:2:0 10-bit 4x4 macroblocks */ #define V4L2_PIX_FMT_NV12_8L128 v4l2_fourcc('A', 'T', '1', '2') /* Y/CbCr 4:2:0 8x128 tiles */ #define V4L2_PIX_FMT_NV12_10BE_8L128 v4l2_fourcc_be('A', 'X', '1', '2') /* Y/CbCr 4:2:0 10-bit 8x128 tiles */ From aa1e34c85b9e04ed7c4bb9798094799938eb0525 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 3 May 2023 09:34:30 +0100 Subject: [PATCH 231/253] media: verisilicon: Get bit depth for V4L2_PIX_FMT_NV15_4L4 Let's the driver knows that V4L2_PIX_FMT_NV15_4L4 is a 10bits pixel format. Signed-off-by: Benjamin Gaignard Reviewed-by: Nicolas Dufresne Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/verisilicon/hantro_v4l2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c index 61cfaaf4e927..4a4ab0b7627a 100644 --- a/drivers/media/platform/verisilicon/hantro_v4l2.c +++ b/drivers/media/platform/verisilicon/hantro_v4l2.c @@ -71,6 +71,7 @@ int hantro_get_format_depth(u32 fourcc) switch (fourcc) { case V4L2_PIX_FMT_P010: case V4L2_PIX_FMT_P010_4L4: + case V4L2_PIX_FMT_NV15_4L4: return 10; default: return 8; From 53421e73b6a20cf0952c9428d003c45a10435776 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 3 May 2023 09:34:31 +0100 Subject: [PATCH 232/253] media: verisilicon: Add AV1 decoder mode and controls Add AV1 decoder as new decoder mode to Hantro driver. Register needed AV1 controls for the decoder. Signed-off-by: Benjamin Gaignard Reviewed-by: Nicolas Dufresne Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/verisilicon/hantro.h | 3 +++ .../media/platform/verisilicon/hantro_drv.c | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h index 2989ebc631cc..61480825b856 100644 --- a/drivers/media/platform/verisilicon/hantro.h +++ b/drivers/media/platform/verisilicon/hantro.h @@ -38,6 +38,7 @@ struct hantro_postproc_ops; #define HANTRO_H264_DECODER BIT(18) #define HANTRO_HEVC_DECODER BIT(19) #define HANTRO_VP9_DECODER BIT(20) +#define HANTRO_AV1_DECODER BIT(21) #define HANTRO_DECODERS 0xffff0000 /** @@ -111,6 +112,7 @@ struct hantro_variant { * @HANTRO_MODE_VP8_DEC: VP8 decoder. * @HANTRO_MODE_HEVC_DEC: HEVC decoder. * @HANTRO_MODE_VP9_DEC: VP9 decoder. + * @HANTRO_MODE_AV1_DEC: AV1 decoder */ enum hantro_codec_mode { HANTRO_MODE_NONE = -1, @@ -120,6 +122,7 @@ enum hantro_codec_mode { HANTRO_MODE_VP8_DEC, HANTRO_MODE_HEVC_DEC, HANTRO_MODE_VP9_DEC, + HANTRO_MODE_AV1_DEC, }; /* diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c index 09c74a573ddb..8f6021e3953c 100644 --- a/drivers/media/platform/verisilicon/hantro_drv.c +++ b/drivers/media/platform/verisilicon/hantro_drv.c @@ -525,6 +525,27 @@ static const struct hantro_ctrl controls[] = { .cfg = { .id = V4L2_CID_STATELESS_VP9_COMPRESSED_HDR, }, + }, { + .codec = HANTRO_AV1_DECODER, + .cfg = { + .id = V4L2_CID_STATELESS_AV1_FRAME, + }, + }, { + .codec = HANTRO_AV1_DECODER, + .cfg = { + .id = V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY, + .dims = { V4L2_AV1_MAX_TILE_COUNT }, + }, + }, { + .codec = HANTRO_AV1_DECODER, + .cfg = { + .id = V4L2_CID_STATELESS_AV1_SEQUENCE, + }, + }, { + .codec = HANTRO_AV1_DECODER, + .cfg = { + .id = V4L2_CID_STATELESS_AV1_FILM_GRAIN, + }, }, }; From 7040ed4ee68cae6d4571ab5b7ce1311de13f74c1 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 3 May 2023 09:34:32 +0100 Subject: [PATCH 233/253] media: verisilicon: Check AV1 bitstreams bit depth The driver supports 8 and 10 bits bitstreams, make sure to discard other cases. It could happens that userland test if V4L2_CID_STATELESS_AV1_SEQUENCE exists without setting bit_depth field in this case use HANTRO_DEFAULT_BIT_DEPTH value. Signed-off-by: Benjamin Gaignard Reviewed-by: Nicolas Dufresne Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/verisilicon/hantro_drv.c | 36 +++++++++++++++++++ .../media/platform/verisilicon/hantro_v4l2.c | 4 +++ 2 files changed, 40 insertions(+) diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c index 8f6021e3953c..be1f06c21910 100644 --- a/drivers/media/platform/verisilicon/hantro_drv.c +++ b/drivers/media/platform/verisilicon/hantro_drv.c @@ -275,7 +275,13 @@ static int hantro_try_ctrl(struct v4l2_ctrl *ctrl) /* We only support profile 0 */ if (dec_params->profile != 0) return -EINVAL; + } else if (ctrl->id == V4L2_CID_STATELESS_AV1_SEQUENCE) { + const struct v4l2_ctrl_av1_sequence *sequence = ctrl->p_new.p_av1_sequence; + + if (sequence->bit_depth != 8 && sequence->bit_depth != 10) + return -EINVAL; } + return 0; } @@ -346,6 +352,30 @@ static int hantro_hevc_s_ctrl(struct v4l2_ctrl *ctrl) return 0; } +static int hantro_av1_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct hantro_ctx *ctx; + + ctx = container_of(ctrl->handler, + struct hantro_ctx, ctrl_handler); + + switch (ctrl->id) { + case V4L2_CID_STATELESS_AV1_SEQUENCE: + { + int bit_depth = ctrl->p_new.p_av1_sequence->bit_depth; + + if (ctx->bit_depth == bit_depth) + return 0; + + return hantro_reset_raw_fmt(ctx, bit_depth); + } + default: + return -EINVAL; + } + + return 0; +} + static const struct v4l2_ctrl_ops hantro_ctrl_ops = { .try_ctrl = hantro_try_ctrl, }; @@ -363,6 +393,11 @@ static const struct v4l2_ctrl_ops hantro_hevc_ctrl_ops = { .s_ctrl = hantro_hevc_s_ctrl, }; +static const struct v4l2_ctrl_ops hantro_av1_ctrl_ops = { + .try_ctrl = hantro_try_ctrl, + .s_ctrl = hantro_av1_s_ctrl, +}; + #define HANTRO_JPEG_ACTIVE_MARKERS (V4L2_JPEG_ACTIVE_MARKER_APP0 | \ V4L2_JPEG_ACTIVE_MARKER_COM | \ V4L2_JPEG_ACTIVE_MARKER_DQT | \ @@ -540,6 +575,7 @@ static const struct hantro_ctrl controls[] = { .codec = HANTRO_AV1_DECODER, .cfg = { .id = V4L2_CID_STATELESS_AV1_SEQUENCE, + .ops = &hantro_av1_ctrl_ops, }, }, { .codec = HANTRO_AV1_DECODER, diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c index 4a4ab0b7627a..35035b641e51 100644 --- a/drivers/media/platform/verisilicon/hantro_v4l2.c +++ b/drivers/media/platform/verisilicon/hantro_v4l2.c @@ -86,6 +86,10 @@ hantro_check_depth_match(const struct hantro_fmt *fmt, int bit_depth) if (!fmt->match_depth && !fmt->postprocessed) return true; + /* 0 means default depth, which is 8 */ + if (!bit_depth) + bit_depth = HANTRO_DEFAULT_BIT_DEPTH; + fmt_depth = hantro_get_format_depth(fmt->fourcc); /* From 1b9ef2744c5e7d68e940794827cc8f035e6460ef Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 3 May 2023 09:34:33 +0100 Subject: [PATCH 234/253] media: verisilicon: Compute motion vectors size for AV1 frames Compute the additional space required to store motion vectors at the end of the frames buffers. Signed-off-by: Benjamin Gaignard Reviewed-by: Nicolas Dufresne Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/verisilicon/hantro_hw.h | 13 +++++++++++++ .../media/platform/verisilicon/hantro_postproc.c | 3 +++ drivers/media/platform/verisilicon/hantro_v4l2.c | 5 +++++ 3 files changed, 21 insertions(+) diff --git a/drivers/media/platform/verisilicon/hantro_hw.h b/drivers/media/platform/verisilicon/hantro_hw.h index e83f0c523a30..bc61d4e051c7 100644 --- a/drivers/media/platform/verisilicon/hantro_hw.h +++ b/drivers/media/platform/verisilicon/hantro_hw.h @@ -417,6 +417,19 @@ hantro_hevc_mv_size(unsigned int width, unsigned int height) return width * height / 16; } +static inline unsigned short hantro_av1_num_sbs(unsigned short dimension) +{ + return DIV_ROUND_UP(dimension, 64); +} + +static inline size_t +hantro_av1_mv_size(unsigned int width, unsigned int height) +{ + size_t num_sbs = hantro_av1_num_sbs(width) * hantro_av1_num_sbs(height); + + return ALIGN(num_sbs * 384, 16) * 2 + 512; +} + int hantro_g1_mpeg2_dec_run(struct hantro_ctx *ctx); int rockchip_vpu2_mpeg2_dec_run(struct hantro_ctx *ctx); void hantro_mpeg2_dec_copy_qtable(u8 *qtable, diff --git a/drivers/media/platform/verisilicon/hantro_postproc.c b/drivers/media/platform/verisilicon/hantro_postproc.c index 6437423ccf3a..bb16af50719d 100644 --- a/drivers/media/platform/verisilicon/hantro_postproc.c +++ b/drivers/media/platform/verisilicon/hantro_postproc.c @@ -213,6 +213,9 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx) else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_HEVC_SLICE) buf_size += hantro_hevc_mv_size(pix_mp.width, pix_mp.height); + else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_AV1_FRAME) + buf_size += hantro_av1_mv_size(pix_mp.width, + pix_mp.height); for (i = 0; i < num_buffers; ++i) { struct hantro_aux_buf *priv = &ctx->postproc.dec_q[i]; diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c index 35035b641e51..3367aa956ba3 100644 --- a/drivers/media/platform/verisilicon/hantro_v4l2.c +++ b/drivers/media/platform/verisilicon/hantro_v4l2.c @@ -333,6 +333,11 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx, pix_mp->plane_fmt[0].sizeimage += hantro_hevc_mv_size(pix_mp->width, pix_mp->height); + else if (ctx->vpu_src_fmt->fourcc == V4L2_PIX_FMT_AV1_FRAME && + !hantro_needs_postproc(ctx, fmt)) + pix_mp->plane_fmt[0].sizeimage += + hantro_av1_mv_size(pix_mp->width, + pix_mp->height); } else if (!pix_mp->plane_fmt[0].sizeimage) { /* * For coded formats the application can specify From c0d0e579db4ee81a71fd1c81aad66caa236723fe Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 3 May 2023 09:34:34 +0100 Subject: [PATCH 235/253] media: verisilicon: Add AV1 entropy helpers AV1 hardware decoder needs entropy parameters to decode frames. They are computed from various arrays defined in AV1 section "9.4. Default CDF tables". Add helpers functions to init, store and get these parameters. Signed-off-by: Benjamin Gaignard Reviewed-by: Nicolas Dufresne Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/verisilicon/Makefile | 1 + drivers/media/platform/verisilicon/hantro.h | 2 + .../media/platform/verisilicon/hantro_hw.h | 20 + .../verisilicon/rockchip_av1_entropymode.c | 4424 +++++++++++++++++ .../verisilicon/rockchip_av1_entropymode.h | 272 + 5 files changed, 4719 insertions(+) create mode 100644 drivers/media/platform/verisilicon/rockchip_av1_entropymode.c create mode 100644 drivers/media/platform/verisilicon/rockchip_av1_entropymode.h diff --git a/drivers/media/platform/verisilicon/Makefile b/drivers/media/platform/verisilicon/Makefile index ebd5ede7bef7..d2b2679c00eb 100644 --- a/drivers/media/platform/verisilicon/Makefile +++ b/drivers/media/platform/verisilicon/Makefile @@ -18,6 +18,7 @@ hantro-vpu-y += \ rockchip_vpu2_hw_h264_dec.o \ rockchip_vpu2_hw_mpeg2_dec.o \ rockchip_vpu2_hw_vp8_dec.o \ + rockchip_av1_entropymode.o \ hantro_jpeg.o \ hantro_h264.o \ hantro_hevc.o \ diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h index 61480825b856..a98cb40a8d3b 100644 --- a/drivers/media/platform/verisilicon/hantro.h +++ b/drivers/media/platform/verisilicon/hantro.h @@ -240,6 +240,7 @@ struct hantro_dev { * @vp8_dec: VP8-decoding context. * @hevc_dec: HEVC-decoding context. * @vp9_dec: VP9-decoding context. + * @av1_dec: AV1-decoding context. */ struct hantro_ctx { struct hantro_dev *dev; @@ -268,6 +269,7 @@ struct hantro_ctx { struct hantro_vp8_dec_hw_ctx vp8_dec; struct hantro_hevc_dec_hw_ctx hevc_dec; struct hantro_vp9_dec_hw_ctx vp9_dec; + struct hantro_av1_dec_hw_ctx av1_dec; }; }; diff --git a/drivers/media/platform/verisilicon/hantro_hw.h b/drivers/media/platform/verisilicon/hantro_hw.h index bc61d4e051c7..d7641eced32e 100644 --- a/drivers/media/platform/verisilicon/hantro_hw.h +++ b/drivers/media/platform/verisilicon/hantro_hw.h @@ -15,6 +15,8 @@ #include #include +#include "rockchip_av1_entropymode.h" + #define DEC_8190_ALIGN_MASK 0x07U #define MB_DIM 16 @@ -247,6 +249,24 @@ struct hantro_vp9_dec_hw_ctx { s16 feature_data[8][4]; }; +/** + * hantro_av1_dec_hw_ctx + * @cdfs: current probabilities structure + * @cdfs_ndvc: current mv probabilities structure + * @default_cdfs: default probabilities structure + * @default_cdfs_ndvc: default mv probabilties structure + * @cdfs_last: stored probabilities structures + * @cdfs_last_ndvc: stored mv probabilities structures + */ +struct hantro_av1_dec_hw_ctx { + struct av1cdfs *cdfs; + struct mvcdfs *cdfs_ndvc; + struct av1cdfs default_cdfs; + struct mvcdfs default_cdfs_ndvc; + struct av1cdfs cdfs_last[NUM_REF_FRAMES]; + struct mvcdfs cdfs_last_ndvc[NUM_REF_FRAMES]; +}; + /** * struct hantro_postproc_ctx * diff --git a/drivers/media/platform/verisilicon/rockchip_av1_entropymode.c b/drivers/media/platform/verisilicon/rockchip_av1_entropymode.c new file mode 100644 index 000000000000..b1ae72ad675e --- /dev/null +++ b/drivers/media/platform/verisilicon/rockchip_av1_entropymode.c @@ -0,0 +1,4424 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Alliance for Open Media. All rights reserved + * + * This source code is subject to the terms of the BSD 2 Clause License and + * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License + * was not distributed with this source code in the LICENSE file, you can + * obtain it at www.aomedia.org/license/software. If the Alliance for Open + * Media Patent License 1.0 was not distributed with this source code in the + * PATENTS file, you can obtain it at www.aomedia.org/license/patent. + */ + +#include "hantro.h" +#include "rockchip_av1_entropymode.h" + +#define AOM_ICDF ICDF +#define AOM_CDF2(a0) AOM_ICDF(a0) +#define AOM_CDF3(a0, a1) \ + AOM_ICDF(a0), AOM_ICDF(a1) +#define AOM_CDF4(a0, a1, a2) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2) +#define AOM_CDF5(a0, a1, a2, a3) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3) +#define AOM_CDF6(a0, a1, a2, a3, a4) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4) +#define AOM_CDF7(a0, a1, a2, a3, a4, a5) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), \ + AOM_ICDF(a3), AOM_ICDF(a4), AOM_ICDF(a5) +#define AOM_CDF8(a0, a1, a2, a3, a4, a5, a6) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), \ + AOM_ICDF(a3), AOM_ICDF(a4), AOM_ICDF(a5), AOM_ICDF(a6) +#define AOM_CDF9(a0, a1, a2, a3, a4, a5, a6, a7) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), \ + AOM_ICDF(a4), AOM_ICDF(a5), AOM_ICDF(a6), AOM_ICDF(a7) +#define AOM_CDF10(a0, a1, a2, a3, a4, a5, a6, a7, a8) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), \ + AOM_ICDF(a4), AOM_ICDF(a5), AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8) +#define AOM_CDF11(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4), \ + AOM_ICDF(a5), AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8), AOM_ICDF(a9) +#define AOM_CDF12(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4), AOM_ICDF(a5), \ + AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8), AOM_ICDF(a9), AOM_ICDF(a10) +#define AOM_CDF13(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4), AOM_ICDF(a5), \ + AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8), AOM_ICDF(a9), AOM_ICDF(a10), AOM_ICDF(a11) +#define AOM_CDF14(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4), \ + AOM_ICDF(a5), AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8), AOM_ICDF(a9), \ + AOM_ICDF(a10), AOM_ICDF(a11), AOM_ICDF(a12) +#define AOM_CDF15(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4), \ + AOM_ICDF(a5), AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8), AOM_ICDF(a9), \ + AOM_ICDF(a10), AOM_ICDF(a11), AOM_ICDF(a12), AOM_ICDF(a13) +#define AOM_CDF16(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) \ + AOM_ICDF(a0), AOM_ICDF(a1), AOM_ICDF(a2), AOM_ICDF(a3), AOM_ICDF(a4), \ + AOM_ICDF(a5), AOM_ICDF(a6), AOM_ICDF(a7), AOM_ICDF(a8), AOM_ICDF(a9), \ + AOM_ICDF(a10), AOM_ICDF(a11), AOM_ICDF(a12), AOM_ICDF(a13), AOM_ICDF(a14) + +static const u16 default_kf_y_mode_cdf + [KF_MODE_CONTEXTS][KF_MODE_CONTEXTS][CDF_SIZE(AV1_INTRA_MODES)] = { + { + { + AOM_CDF13(15588, 17027, 19338, 20218, 20682, 21110, + 21825, 23244, 24189, 28165, 29093, 30466) + }, + { + AOM_CDF13(12016, 18066, 19516, 20303, 20719, 21444, + 21888, 23032, 24434, 28658, 30172, 31409) + }, + { + AOM_CDF13(10052, 10771, 22296, 22788, 23055, 23239, + 24133, 25620, 26160, 29336, 29929, 31567) + }, + { + AOM_CDF13(14091, 15406, 16442, 18808, 19136, 19546, + 19998, 22096, 24746, 29585, 30958, 32462) + }, + { + AOM_CDF13(12122, 13265, 15603, 16501, 18609, 20033, + 22391, 25583, 26437, 30261, 31073, 32475) + } + }, + { + { + AOM_CDF13(10023, 19585, 20848, 21440, 21832, 22760, + 23089, 24023, 25381, 29014, 30482, 31436) + }, + { + AOM_CDF13(5983, 24099, 24560, 24886, 25066, 25795, + 25913, 26423, 27610, 29905, 31276, 31794) + }, + { + AOM_CDF13(7444, 12781, 20177, 20728, 21077, 21607, + 22170, 23405, 24469, 27915, 29090, 30492) + }, + { + AOM_CDF13(8537, 14689, 15432, 17087, 17408, 18172, + 18408, 19825, 24649, 29153, 31096, 32210) + }, + { + AOM_CDF13(7543, 14231, 15496, 16195, 17905, 20717, + 21984, 24516, 26001, 29675, 30981, 31994) + } + }, + { + { + AOM_CDF13(12613, 13591, 21383, 22004, 22312, 22577, + 23401, 25055, 25729, 29538, 30305, 32077) + }, + { + AOM_CDF13(9687, 13470, 18506, 19230, 19604, 20147, + 20695, 22062, 23219, 27743, 29211, 30907) + }, + { + AOM_CDF13(6183, 6505, 26024, 26252, 26366, 26434, + 27082, 28354, 28555, 30467, 30794, 32086) + }, + { + AOM_CDF13(10718, 11734, 14954, 17224, 17565, 17924, + 18561, 21523, 23878, 28975, 30287, 32252) + }, + { + AOM_CDF13(9194, 9858, 16501, 17263, 18424, 19171, + 21563, 25961, 26561, 30072, 30737, 32463) + } + }, + { + { + AOM_CDF13(12602, 14399, 15488, 18381, 18778, 19315, + 19724, 21419, 25060, 29696, 30917, 32409) + }, + { + AOM_CDF13(8203, 13821, 14524, 17105, 17439, 18131, + 18404, 19468, 25225, 29485, 31158, 32342) + }, + { + AOM_CDF13(8451, 9731, 15004, 17643, 18012, 18425, + 19070, 21538, 24605, 29118, 30078, 32018) + }, + { + AOM_CDF13(7714, 9048, 9516, 16667, 16817, 16994, + 17153, 18767, 26743, 30389, 31536, 32528) + }, + { + AOM_CDF13(8843, 10280, 11496, 15317, 16652, 17943, + 19108, 22718, 25769, 29953, 30983, 32485) + } + }, + { + { + AOM_CDF13(12578, 13671, 15979, 16834, 19075, 20913, + 22989, 25449, 26219, 30214, 31150, 32477) + }, + { + AOM_CDF13(9563, 13626, 15080, 15892, 17756, 20863, + 22207, 24236, 25380, 29653, 31143, 32277) + }, + { + AOM_CDF13(8356, 8901, 17616, 18256, 19350, 20106, + 22598, 25947, 26466, 29900, 30523, 32261) + }, + { + AOM_CDF13(10835, 11815, 13124, 16042, 17018, 18039, + 18947, 22753, 24615, 29489, 30883, 32482) + }, + { + AOM_CDF13(7618, 8288, 9859, 10509, 15386, 18657, + 22903, 28776, 29180, 31355, 31802, 32593) + } + } +}; + +static const u16 default_angle_delta_cdf[DIRECTIONAL_MODES] + [CDF_SIZE(2 * MAX_ANGLE_DELTA + 1)] = { + { AOM_CDF7(2180, 5032, 7567, 22776, 26989, 30217) }, + { AOM_CDF7(2301, 5608, 8801, 23487, 26974, 30330) }, + { AOM_CDF7(3780, 11018, 13699, 19354, 23083, 31286) }, + { AOM_CDF7(4581, 11226, 15147, 17138, 21834, 28397) }, + { AOM_CDF7(1737, 10927, 14509, 19588, 22745, 28823) }, + { AOM_CDF7(2664, 10176, 12485, 17650, 21600, 30495) }, + { AOM_CDF7(2240, 11096, 15453, 20341, 22561, 28917) }, + { AOM_CDF7(3605, 10428, 12459, 17676, 21244, 30655) } +}; + +static const u16 default_if_y_mode_cdf[BLOCK_SIZE_GROUPS][CDF_SIZE(AV1_INTRA_MODES)] = { + { + AOM_CDF13(22801, 23489, 24293, 24756, 25601, 26123, + 26606, 27418, 27945, 29228, 29685, 30349) + }, + { + AOM_CDF13(18673, 19845, 22631, 23318, 23950, 24649, + 25527, 27364, 28152, 29701, 29984, 30852) + }, + { + AOM_CDF13(19770, 20979, 23396, 23939, 24241, 24654, + 25136, 27073, 27830, 29360, 29730, 30659) + }, + { + AOM_CDF13(20155, 21301, 22838, 23178, 23261, 23533, + 23703, 24804, 25352, 26575, 27016, 28049) + } +}; + +static const u16 default_uv_mode_cdf[CFL_ALLOWED_TYPES] + [AV1_INTRA_MODES][CDF_SIZE(UV_INTRA_MODES)] = { + { + { + AOM_CDF13(22631, 24152, 25378, 25661, 25986, 26520, + 27055, 27923, 28244, 30059, 30941, 31961) + }, + { + AOM_CDF13(9513, 26881, 26973, 27046, 27118, 27664, + 27739, 27824, 28359, 29505, 29800, 31796) + }, + { + AOM_CDF13(9845, 9915, 28663, 28704, 28757, 28780, + 29198, 29822, 29854, 30764, 31777, 32029) + }, + { + AOM_CDF13(13639, 13897, 14171, 25331, 25606, 25727, + 25953, 27148, 28577, 30612, 31355, 32493) + }, + { + AOM_CDF13(9764, 9835, 9930, 9954, 25386, 27053, + 27958, 28148, 28243, 31101, 31744, 32363) + }, + { + AOM_CDF13(11825, 13589, 13677, 13720, 15048, 29213, + 29301, 29458, 29711, 31161, 31441, 32550) + }, + { + AOM_CDF13(14175, 14399, 16608, 16821, 17718, 17775, + 28551, 30200, 30245, 31837, 32342, 32667) + }, + { + AOM_CDF13(12885, 13038, 14978, 15590, 15673, 15748, + 16176, 29128, 29267, 30643, 31961, 32461) + }, + { + AOM_CDF13(12026, 13661, 13874, 15305, 15490, 15726, + 15995, 16273, 28443, 30388, 30767, 32416) + }, + { + AOM_CDF13(19052, 19840, 20579, 20916, 21150, 21467, + 21885, 22719, 23174, 28861, 30379, 32175) + }, + { + AOM_CDF13(18627, 19649, 20974, 21219, 21492, 21816, + 22199, 23119, 23527, 27053, 31397, 32148) + }, + { + AOM_CDF13(17026, 19004, 19997, 20339, 20586, 21103, + 21349, 21907, 22482, 25896, 26541, 31819) + }, + { + AOM_CDF13(12124, 13759, 14959, 14992, 15007, 15051, + 15078, 15166, 15255, 15753, 16039, 16606) + } + }, + { + { + AOM_CDF14(10407, 11208, 12900, 13181, 13823, 14175, + 14899, 15656, 15986, 20086, 20995, 22455, + 24212) + }, + { + AOM_CDF14(4532, 19780, 20057, 20215, 20428, 21071, + 21199, 21451, 22099, 24228, 24693, 27032, + 29472) + }, + { + AOM_CDF14(5273, 5379, 20177, 20270, 20385, 20439, + 20949, 21695, 21774, 23138, 24256, 24703, + 26679) + }, + { + AOM_CDF14(6740, 7167, 7662, 14152, 14536, 14785, + 15034, 16741, 18371, 21520, 22206, 23389, + 24182) + }, + { + AOM_CDF14(4987, 5368, 5928, 6068, 19114, 20315, 21857, + 22253, 22411, 24911, 25380, 26027, 26376) + }, + { + AOM_CDF14(5370, 6889, 7247, 7393, 9498, 21114, 21402, + 21753, 21981, 24780, 25386, 26517, 27176) + }, + { + AOM_CDF14(4816, 4961, 7204, 7326, 8765, 8930, 20169, + 20682, 20803, 23188, 23763, 24455, 24940) + }, + { + AOM_CDF14(6608, 6740, 8529, 9049, 9257, 9356, 9735, + 18827, 19059, 22336, 23204, 23964, 24793) + }, + { + AOM_CDF14(5998, 7419, 7781, 8933, 9255, 9549, 9753, + 10417, 18898, 22494, 23139, 24764, 25989) + }, + { + AOM_CDF14(10660, 11298, 12550, 12957, 13322, 13624, + 14040, 15004, 15534, 20714, 21789, 23443, + 24861) + }, + { + AOM_CDF14(10522, 11530, 12552, 12963, 13378, 13779, + 14245, 15235, 15902, 20102, 22696, 23774, + 25838) + }, + { + AOM_CDF14(10099, 10691, 12639, 13049, 13386, 13665, + 14125, 15163, 15636, 19676, 20474, 23519, + 25208) + }, + { + AOM_CDF14(3144, 5087, 7382, 7504, 7593, 7690, 7801, + 8064, 8232, 9248, 9875, 10521, 29048) + } + } +}; + +static const u16 default_partition_cdf[13][16] = { + { + AOM_CDF4(19132, 25510, 30392), AOM_CDF4(13928, 19855, 28540), + AOM_CDF4(12522, 23679, 28629), AOM_CDF4(9896, 18783, 25853), + AOM_CDF2(11570), AOM_CDF2(16855), AOM_CDF3(9413, 22581) + }, + { + AOM_CDF10(15597, 20929, 24571, 26706, 27664, 28821, 29601, 30571, 31902) + }, + { + AOM_CDF10(7925, 11043, 16785, 22470, 23971, 25043, 26651, 28701, 29834) + }, + { + AOM_CDF10(5414, 13269, 15111, 20488, 22360, 24500, 25537, 26336, 32117) + }, + { + AOM_CDF10(2662, 6362, 8614, 20860, 23053, 24778, 26436, 27829, 31171) + }, + { + AOM_CDF10(18462, 20920, 23124, 27647, 28227, 29049, 29519, 30178, 31544) + }, + { + AOM_CDF10(7689, 9060, 12056, 24992, 25660, 26182, 26951, 28041, 29052) + }, + { + AOM_CDF10(6015, 9009, 10062, 24544, 25409, 26545, 27071, 27526, 32047) + }, + { + AOM_CDF10(1394, 2208, 2796, 28614, 29061, 29466, 29840, 30185, 31899) + }, + { + AOM_CDF10(20137, 21547, 23078, 29566, 29837, 30261, 30524, 30892, 31724), + AOM_CDF8(27899, 28219, 28529, 32484, 32539, 32619, 32639) + }, + { + AOM_CDF10(6732, 7490, 9497, 27944, 28250, 28515, 28969, 29630, 30104), + AOM_CDF8(6607, 6990, 8268, 32060, 32219, 32338, 32371) + }, + { + AOM_CDF10(5945, 7663, 8348, 28683, 29117, 29749, 30064, 30298, 32238), + AOM_CDF8(5429, 6676, 7122, 32027, 32227, 32531, 32582) + }, + { + AOM_CDF10(870, 1212, 1487, 31198, 31394, 31574, 31743, 31881, 32332), + AOM_CDF8(711, 966, 1172, 32448, 32538, 32617, 32664) + }, +}; + +static const u16 default_intra_ext_tx0_cdf[EXTTX_SIZES][AV1_INTRA_MODES][8] = { + { + { AOM_CDF7(1535, 8035, 9461, 12751, 23467, 27825)}, + { AOM_CDF7(564, 3335, 9709, 10870, 18143, 28094)}, + { AOM_CDF7(672, 3247, 3676, 11982, 19415, 23127)}, + { AOM_CDF7(5279, 13885, 15487, 18044, 23527, 30252)}, + { AOM_CDF7(4423, 6074, 7985, 10416, 25693, 29298)}, + { AOM_CDF7(1486, 4241, 9460, 10662, 16456, 27694)}, + { AOM_CDF7(439, 2838, 3522, 6737, 18058, 23754)}, + { AOM_CDF7(1190, 4233, 4855, 11670, 20281, 24377)}, + { AOM_CDF7(1045, 4312, 8647, 10159, 18644, 29335)}, + { AOM_CDF7(202, 3734, 4747, 7298, 17127, 24016)}, + { AOM_CDF7(447, 4312, 6819, 8884, 16010, 23858)}, + { AOM_CDF7(277, 4369, 5255, 8905, 16465, 22271)}, + { AOM_CDF7(3409, 5436, 10599, 15599, 19687, 24040)}, + }, + { + { AOM_CDF7(1870, 13742, 14530, 16498, 23770, 27698)}, + { AOM_CDF7(326, 8796, 14632, 15079, 19272, 27486)}, + { AOM_CDF7(484, 7576, 7712, 14443, 19159, 22591)}, + { AOM_CDF7(1126, 15340, 15895, 17023, 20896, 30279)}, + { AOM_CDF7(655, 4854, 5249, 5913, 22099, 27138)}, + { AOM_CDF7(1299, 6458, 8885, 9290, 14851, 25497)}, + { AOM_CDF7(311, 5295, 5552, 6885, 16107, 22672)}, + { AOM_CDF7(883, 8059, 8270, 11258, 17289, 21549)}, + { AOM_CDF7(741, 7580, 9318, 10345, 16688, 29046)}, + { AOM_CDF7(110, 7406, 7915, 9195, 16041, 23329)}, + { AOM_CDF7(363, 7974, 9357, 10673, 15629, 24474)}, + { AOM_CDF7(153, 7647, 8112, 9936, 15307, 19996)}, + { AOM_CDF7(3511, 6332, 11165, 15335, 19323, 23594)}, + }, + { + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + }, + { + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + { AOM_CDF7(4681, 9362, 14043, 18725, 23406, 28087)}, + }, +}; + +static const u16 default_intra_ext_tx1_cdf[EXTTX_SIZES][AV1_INTRA_MODES][4] = { + { + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + }, + { + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + }, + { + { AOM_CDF5(1127, 12814, 22772, 27483)}, + { AOM_CDF5(145, 6761, 11980, 26667)}, + { AOM_CDF5(362, 5887, 11678, 16725)}, + { AOM_CDF5(385, 15213, 18587, 30693)}, + { AOM_CDF5(25, 2914, 23134, 27903)}, + { AOM_CDF5(60, 4470, 11749, 23991)}, + { AOM_CDF5(37, 3332, 14511, 21448)}, + { AOM_CDF5(157, 6320, 13036, 17439)}, + { AOM_CDF5(119, 6719, 12906, 29396)}, + { AOM_CDF5(47, 5537, 12576, 21499)}, + { AOM_CDF5(269, 6076, 11258, 23115)}, + { AOM_CDF5(83, 5615, 12001, 17228)}, + { AOM_CDF5(1968, 5556, 12023, 18547)}, + }, + { + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + { AOM_CDF5(6554, 13107, 19661, 26214)}, + }, +}; + +static const u16 default_inter_ext_tx_cdf[2][EXTTX_SIZES][EXT_TX_TYPES] = { + { + { + AOM_CDF16(4458, 5560, 7695, 9709, 13330, 14789, 17537, 20266, + 21504, 22848, 23934, 25474, 27727, 28915, 30631) + }, + { + AOM_CDF16(1645, 2573, 4778, 5711, 7807, 8622, 10522, 15357, 17674, + 20408, 22517, 25010, 27116, 28856, 30749) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, + 18432, 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, + 18432, 20480, 22528, 24576, 26624, 28672, 30720) + }, + }, + { + { + AOM_CDF12(2731, 5461, 8192, 10923, 13653, 16384, 19115, 21845, + 24576, 27307, 30037), + AOM_CDF2(16384) + }, + { + AOM_CDF12(2731, 5461, 8192, 10923, 13653, 16384, 19115, 21845, + 24576, 27307, 30037), + AOM_CDF2(4167) + }, + { + AOM_CDF12(770, 2421, 5225, 12907, 15819, 18927, 21561, 24089, + 26595, 28526, 30529), + AOM_CDF2(1998) + }, + { + AOM_CDF12(2731, 5461, 8192, 10923, 13653, 16384, 19115, 21845, + 24576, 27307, 30037), + AOM_CDF2(748) + }, + } +}; + +static const u16 default_cfl_sign_cdf[CDF_SIZE(CFL_JOINT_SIGNS)] = { + AOM_CDF8(1418, 2123, 13340, 18405, 26972, 28343, 32294) +}; + +static const u16 default_cfl_alpha_cdf[CFL_ALPHA_CONTEXTS][CDF_SIZE(CFL_ALPHABET_SIZE)] = { + { + AOM_CDF16(7637, 20719, 31401, 32481, 32657, 32688, 32692, 32696, 32700, + 32704, 32708, 32712, 32716, 32720, 32724) + }, + { + AOM_CDF16(14365, 23603, 28135, 31168, 32167, 32395, 32487, 32573, + 32620, 32647, 32668, 32672, 32676, 32680, 32684) + }, + { + AOM_CDF16(11532, 22380, 28445, 31360, 32349, 32523, 32584, 32649, + 32673, 32677, 32681, 32685, 32689, 32693, 32697) + }, + { + AOM_CDF16(26990, 31402, 32282, 32571, 32692, 32696, 32700, 32704, + 32708, 32712, 32716, 32720, 32724, 32728, 32732) + }, + { + AOM_CDF16(17248, 26058, 28904, 30608, 31305, 31877, 32126, 32321, + 32394, 32464, 32516, 32560, 32576, 32593, 32622) + }, + { + AOM_CDF16(14738, 21678, 25779, 27901, 29024, 30302, 30980, 31843, + 32144, 32413, 32520, 32594, 32622, 32656, 32660) + } +}; + +static const u16 default_switchable_interp_cdf[SWITCHABLE_FILTER_CONTEXTS] + [CDF_SIZE(AV1_SWITCHABLE_FILTERS)] = { + { AOM_CDF3(31935, 32720) }, { AOM_CDF3(5568, 32719) }, + { AOM_CDF3(422, 2938) }, { AOM_CDF3(28244, 32608) }, + { AOM_CDF3(31206, 31953) }, { AOM_CDF3(4862, 32121) }, + { AOM_CDF3(770, 1152) }, { AOM_CDF3(20889, 25637) }, + { AOM_CDF3(31910, 32724) }, { AOM_CDF3(4120, 32712) }, + { AOM_CDF3(305, 2247) }, { AOM_CDF3(27403, 32636) }, + { AOM_CDF3(31022, 32009) }, { AOM_CDF3(2963, 32093) }, + { AOM_CDF3(601, 943) }, { AOM_CDF3(14969, 21398) } +}; + +static const u16 default_newmv_cdf[NEWMV_MODE_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(24035) }, { AOM_CDF2(16630) }, { AOM_CDF2(15339) }, + { AOM_CDF2(8386) }, { AOM_CDF2(12222) }, { AOM_CDF2(4676) } +}; + +static const u16 default_zeromv_cdf[GLOBALMV_MODE_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(2175) }, { AOM_CDF2(1054) } +}; + +static const u16 default_refmv_cdf[REFMV_MODE_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(23974) }, { AOM_CDF2(24188) }, { AOM_CDF2(17848) }, + { AOM_CDF2(28622) }, { AOM_CDF2(24312) }, { AOM_CDF2(19923) } +}; + +static const u16 default_drl_cdf[DRL_MODE_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(13104) }, { AOM_CDF2(24560) }, { AOM_CDF2(18945) } +}; + +static const u16 default_inter_compound_mode_cdf[AV1_INTER_MODE_CONTEXTS] + [CDF_SIZE(INTER_COMPOUND_MODES)] = { + { AOM_CDF8(7760, 13823, 15808, 17641, 19156, 20666, 26891) }, + { AOM_CDF8(10730, 19452, 21145, 22749, 24039, 25131, 28724) }, + { AOM_CDF8(10664, 20221, 21588, 22906, 24295, 25387, 28436) }, + { AOM_CDF8(13298, 16984, 20471, 24182, 25067, 25736, 26422) }, + { AOM_CDF8(18904, 23325, 25242, 27432, 27898, 28258, 30758) }, + { AOM_CDF8(10725, 17454, 20124, 22820, 24195, 25168, 26046) }, + { AOM_CDF8(17125, 24273, 25814, 27492, 28214, 28704, 30592) }, + { AOM_CDF8(13046, 23214, 24505, 25942, 27435, 28442, 29330) } +}; + +static const u16 default_interintra_cdf[BLOCK_SIZE_GROUPS][CDF_SIZE(2)] = { + { AOM_CDF2(16384) }, { AOM_CDF2(26887) }, { AOM_CDF2(27597) }, + { AOM_CDF2(30237) } +}; + +static const u16 default_interintra_mode_cdf[BLOCK_SIZE_GROUPS][CDF_SIZE(INTERINTRA_MODES)] = { + { AOM_CDF4(8192, 16384, 24576) }, + { AOM_CDF4(1875, 11082, 27332) }, + { AOM_CDF4(2473, 9996, 26388) }, + { AOM_CDF4(4238, 11537, 25926) } +}; + +static const u16 default_wedge_interintra_cdf[BLOCK_SIZES_ALL][CDF_SIZE(2)] = { + { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, + { AOM_CDF2(20036) }, { AOM_CDF2(24957) }, { AOM_CDF2(26704) }, + { AOM_CDF2(27530) }, { AOM_CDF2(29564) }, { AOM_CDF2(29444) }, + { AOM_CDF2(26872) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, + { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, + { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, + { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, + { AOM_CDF2(16384) } +}; + +static const u16 default_compound_type_cdf[BLOCK_SIZES_ALL][CDF_SIZE(COMPOUND_TYPES - 1)] = { + { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, + { AOM_CDF2(23431) }, + { AOM_CDF2(13171) }, { AOM_CDF2(11470) }, { AOM_CDF2(9770) }, + { AOM_CDF2(9100) }, + { AOM_CDF2(8233) }, { AOM_CDF2(6172) }, { AOM_CDF2(16384) }, + { AOM_CDF2(16384) }, + { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, + { AOM_CDF2(16384) }, + { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(11820) }, + { AOM_CDF2(7701) }, + { AOM_CDF2(16384) }, { AOM_CDF2(16384) } +}; + +static const u16 default_wedge_idx_cdf[BLOCK_SIZES_ALL][CDF_SIZE(16)] = { + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, + 18432, 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, + 18432, 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, + 18432, 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2438, 4440, 6599, 8663, 11005, 12874, 15751, 18094, + 20359, 22362, 24127, 25702, 27752, 29450, 31171) + }, + { + AOM_CDF16(806, 3266, 6005, 6738, 7218, 7367, 7771, 14588, 16323, + 17367, 18452, 19422, 22839, 26127, 29629) + }, + { + AOM_CDF16(2779, 3738, 4683, 7213, 7775, 8017, 8655, 14357, 17939, + 21332, 24520, 27470, 29456, 30529, 31656) + }, + { + AOM_CDF16(1684, 3625, 5675, 7108, 9302, 11274, 14429, 17144, 19163, + 20961, 22884, 24471, 26719, 28714, 30877) + }, + { + AOM_CDF16(1142, 3491, 6277, 7314, 8089, 8355, 9023, 13624, 15369, + 16730, 18114, 19313, 22521, 26012, 29550) + }, + { + AOM_CDF16(2742, 4195, 5727, 8035, 8980, 9336, 10146, 14124, 17270, + 20533, 23434, 25972, 27944, 29570, 31416) + }, + { + AOM_CDF16(1727, 3948, 6101, 7796, 9841, 12344, 15766, 18944, 20638, + 22038, 23963, 25311, 26988, 28766, 31012) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(154, 987, 1925, 2051, 2088, 2111, 2151, 23033, 23703, 24284, + 24985, 25684, 27259, 28883, 30911) + }, + { + AOM_CDF16(1135, 1322, 1493, 2635, 2696, 2737, 2770, 21016, 22935, + 25057, 27251, 29173, 30089, 30960, 31933) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + }, + { + AOM_CDF16(2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, + 20480, 22528, 24576, 26624, 28672, 30720) + } +}; + +static const u16 default_motion_mode_cdf[BLOCK_SIZES_ALL][CDF_SIZE(MOTION_MODES)] = { + { AOM_CDF3(10923, 21845) }, { AOM_CDF3(10923, 21845) }, + { AOM_CDF3(10923, 21845) }, { AOM_CDF3(7651, 24760) }, + { AOM_CDF3(4738, 24765) }, { AOM_CDF3(5391, 25528) }, + { AOM_CDF3(19419, 26810) }, { AOM_CDF3(5123, 23606) }, + { AOM_CDF3(11606, 24308) }, { AOM_CDF3(26260, 29116) }, + { AOM_CDF3(20360, 28062) }, { AOM_CDF3(21679, 26830) }, + { AOM_CDF3(29516, 30701) }, { AOM_CDF3(28898, 30397) }, + { AOM_CDF3(30878, 31335) }, { AOM_CDF3(32507, 32558) }, + { AOM_CDF3(10923, 21845) }, { AOM_CDF3(10923, 21845) }, + { AOM_CDF3(28799, 31390) }, { AOM_CDF3(26431, 30774) }, + { AOM_CDF3(28973, 31594) }, { AOM_CDF3(29742, 31203) } +}; + +static const u16 default_obmc_cdf[BLOCK_SIZES_ALL][CDF_SIZE(2)] = { + { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, + { AOM_CDF2(10437) }, + { AOM_CDF2(9371) }, { AOM_CDF2(9301) }, { AOM_CDF2(17432) }, + { AOM_CDF2(14423) }, + { AOM_CDF2(15142) }, { AOM_CDF2(25817) }, { AOM_CDF2(22823) }, + { AOM_CDF2(22083) }, + { AOM_CDF2(30128) }, { AOM_CDF2(31014) }, { AOM_CDF2(31560) }, + { AOM_CDF2(32638) }, + { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(23664) }, + { AOM_CDF2(20901) }, + { AOM_CDF2(24008) }, { AOM_CDF2(26879) } +}; + +static const u16 default_intra_inter_cdf[INTRA_INTER_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(806) }, + { AOM_CDF2(16662) }, + { AOM_CDF2(20186) }, + { AOM_CDF2(26538) } +}; + +static const u16 default_comp_inter_cdf[COMP_INTER_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(26828) }, + { AOM_CDF2(24035) }, + { AOM_CDF2(12031) }, + { AOM_CDF2(10640) }, + { AOM_CDF2(2901) } +}; + +static const u16 default_comp_ref_type_cdf[COMP_REF_TYPE_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(1198) }, + { AOM_CDF2(2070) }, + { AOM_CDF2(9166) }, + { AOM_CDF2(7499) }, + { AOM_CDF2(22475) } +}; + +static const u16 default_uni_comp_ref_cdf[UNI_COMP_REF_CONTEXTS] + [UNIDIR_COMP_REFS - 1][CDF_SIZE(2)] = { + { { AOM_CDF2(5284)}, { AOM_CDF2(3865)}, { AOM_CDF2(3128)} }, + { { AOM_CDF2(23152)}, { AOM_CDF2(14173)}, { AOM_CDF2(15270)} }, + { { AOM_CDF2(31774)}, { AOM_CDF2(25120)}, { AOM_CDF2(26710)} } +}; + +static const u16 default_single_ref_cdf[REF_CONTEXTS][SINGLE_REFS - 1][CDF_SIZE(2)] = { + { + { AOM_CDF2(4897)}, + { AOM_CDF2(1555)}, + { AOM_CDF2(4236)}, + { AOM_CDF2(8650)}, + { AOM_CDF2(904)}, + { AOM_CDF2(1444)} + }, + { + { AOM_CDF2(16973)}, + { AOM_CDF2(16751)}, + { AOM_CDF2(19647)}, + { AOM_CDF2(24773)}, + { AOM_CDF2(11014)}, + { AOM_CDF2(15087)} + }, + { + { AOM_CDF2(29744)}, + { AOM_CDF2(30279)}, + { AOM_CDF2(31194)}, + { AOM_CDF2(31895)}, + { AOM_CDF2(26875)}, + { AOM_CDF2(30304)} + } +}; + +static const u16 default_comp_ref_cdf[REF_CONTEXTS][FWD_REFS - 1][CDF_SIZE(2)] = { + { { AOM_CDF2(4946)}, { AOM_CDF2(9468)}, { AOM_CDF2(1503)} }, + { { AOM_CDF2(19891)}, { AOM_CDF2(22441)}, { AOM_CDF2(15160)} }, + { { AOM_CDF2(30731)}, { AOM_CDF2(31059)}, { AOM_CDF2(27544)} } +}; + +static const u16 default_comp_bwdref_cdf[REF_CONTEXTS][BWD_REFS - 1][CDF_SIZE(2)] = { + { { AOM_CDF2(2235)}, { AOM_CDF2(1423)} }, + { { AOM_CDF2(17182)}, { AOM_CDF2(15175)} }, + { { AOM_CDF2(30606)}, { AOM_CDF2(30489)} } +}; + +static const u16 default_palette_y_size_cdf[PALETTE_BLOCK_SIZES][CDF_SIZE(PALETTE_SIZES)] = { + { AOM_CDF7(7952, 13000, 18149, 21478, 25527, 29241) }, + { AOM_CDF7(7139, 11421, 16195, 19544, 23666, 28073) }, + { AOM_CDF7(7788, 12741, 17325, 20500, 24315, 28530) }, + { AOM_CDF7(8271, 14064, 18246, 21564, 25071, 28533) }, + { AOM_CDF7(12725, 19180, 21863, 24839, 27535, 30120) }, + { AOM_CDF7(9711, 14888, 16923, 21052, 25661, 27875) }, + { AOM_CDF7(14940, 20797, 21678, 24186, 27033, 28999) } +}; + +static const u16 default_palette_uv_size_cdf[PALETTE_BLOCK_SIZES][CDF_SIZE(PALETTE_SIZES)] = { + { AOM_CDF7(8713, 19979, 27128, 29609, 31331, 32272) }, + { AOM_CDF7(5839, 15573, 23581, 26947, 29848, 31700) }, + { AOM_CDF7(4426, 11260, 17999, 21483, 25863, 29430) }, + { AOM_CDF7(3228, 9464, 14993, 18089, 22523, 27420) }, + { AOM_CDF7(3768, 8886, 13091, 17852, 22495, 27207) }, + { AOM_CDF7(2464, 8451, 12861, 21632, 25525, 28555) }, + { AOM_CDF7(1269, 5435, 10433, 18963, 21700, 25865) } +}; + +static const u16 default_palette_y_mode_cdf[PALETTE_BLOCK_SIZES] + [PALETTE_Y_MODE_CONTEXTS][CDF_SIZE(2)] = { + { { AOM_CDF2(31676)}, { AOM_CDF2(3419)}, { AOM_CDF2(1261)} }, + { { AOM_CDF2(31912)}, { AOM_CDF2(2859)}, { AOM_CDF2(980)} }, + { { AOM_CDF2(31823)}, { AOM_CDF2(3400)}, { AOM_CDF2(781)} }, + { { AOM_CDF2(32030)}, { AOM_CDF2(3561)}, { AOM_CDF2(904)} }, + { { AOM_CDF2(32309)}, { AOM_CDF2(7337)}, { AOM_CDF2(1462)} }, + { { AOM_CDF2(32265)}, { AOM_CDF2(4015)}, { AOM_CDF2(1521)} }, + { { AOM_CDF2(32450)}, { AOM_CDF2(7946)}, { AOM_CDF2(129)} } +}; + +static const u16 default_palette_uv_mode_cdf[PALETTE_UV_MODE_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(32461) }, { AOM_CDF2(21488) } +}; + +static const u16 default_palette_y_color_index_cdf[PALETTE_IDX_CONTEXTS][8] = { + // Palette sizes 2 & 8 + { + AOM_CDF2(28710), + AOM_CDF8(21689, 23883, 25163, 26352, 27506, 28827, 30195) + }, + { + AOM_CDF2(16384), + AOM_CDF8(6892, 15385, 17840, 21606, 24287, 26753, 29204) + }, + { + AOM_CDF2(10553), + AOM_CDF8(5651, 23182, 25042, 26518, 27982, 29392, 30900) + }, + { + AOM_CDF2(27036), + AOM_CDF8(19349, 22578, 24418, 25994, 27524, 29031, 30448) + }, + { + AOM_CDF2(31603), + AOM_CDF8(31028, 31270, 31504, 31705, 31927, 32153, 32392) + }, + // Palette sizes 3 & 7 + { + AOM_CDF3(27877, 30490), + AOM_CDF7(23105, 25199, 26464, 27684, 28931, 30318) + }, + { + AOM_CDF3(11532, 25697), + AOM_CDF7(6950, 15447, 18952, 22681, 25567, 28563) + }, + { + AOM_CDF3(6544, 30234), + AOM_CDF7(7560, 23474, 25490, 27203, 28921, 30708) + }, + { + AOM_CDF3(23018, 28072), + AOM_CDF7(18544, 22373, 24457, 26195, 28119, 30045) + }, + { + AOM_CDF3(31915, 32385), + AOM_CDF7(31198, 31451, 31670, 31882, 32123, 32391) + }, + // Palette sizes 4 & 6 + { + AOM_CDF4(25572, 28046, 30045), + AOM_CDF6(23132, 25407, 26970, 28435, 30073) + }, + { + AOM_CDF4(9478, 21590, 27256), + AOM_CDF6(7443, 17242, 20717, 24762, 27982) + }, + { + AOM_CDF4(7248, 26837, 29824), + AOM_CDF6(6300, 24862, 26944, 28784, 30671) + }, + { + AOM_CDF4(19167, 24486, 28349), + AOM_CDF6(18916, 22895, 25267, 27435, 29652) + }, + { + AOM_CDF4(31400, 31825, 32250), + AOM_CDF6(31270, 31550, 31808, 32059, 32353) + }, + // Palette size 5 + { + AOM_CDF5(24779, 26955, 28576, 30282), + AOM_CDF5(8669, 20364, 24073, 28093) + }, + { + AOM_CDF5(4255, 27565, 29377, 31067), + AOM_CDF5(19864, 23674, 26716, 29530) + }, + { + AOM_CDF5(31646, 31893, 32147, 32426), + 0, 0, 0, 0 + } +}; + +static const u16 default_palette_uv_color_index_cdf[PALETTE_IDX_CONTEXTS][8] = { + // Palette sizes 2 & 8 + { + AOM_CDF2(29089), + AOM_CDF8(21442, 23288, 24758, 26246, 27649, 28980, 30563) + }, + { + AOM_CDF2(16384), + AOM_CDF8(5863, 14933, 17552, 20668, 23683, 26411, 29273) + }, + { + AOM_CDF2(8713), + AOM_CDF8(3415, 25810, 26877, 27990, 29223, 30394, 31618) + }, + { + AOM_CDF2(29257), + AOM_CDF8(17965, 20084, 22232, 23974, 26274, 28402, 30390) + }, + { + AOM_CDF2(31610), + AOM_CDF8(31190, 31329, 31516, 31679, 31825, 32026, 32322) + }, + // Palette sizes 3 & 7 + { + AOM_CDF3(25257, 29145), + AOM_CDF7(21239, 23168, 25044, 26962, 28705, 30506) + }, + { + AOM_CDF3(12287, 27293), + AOM_CDF7(6545, 15012, 18004, 21817, 25503, 28701) + }, + { + AOM_CDF3(7033, 27960), + AOM_CDF7(3448, 26295, 27437, 28704, 30126, 31442) + }, + { + AOM_CDF3(20145, 25405), + AOM_CDF7(15889, 18323, 21704, 24698, 26976, 29690) + }, + { + AOM_CDF3(30608, 31639), + AOM_CDF7(30988, 31204, 31479, 31734, 31983, 32325) + }, + // Palette sizes 4 & 6 + { + AOM_CDF4(24210, 27175, 29903), + AOM_CDF6(22217, 24567, 26637, 28683, 30548) + }, + { + AOM_CDF4(9888, 22386, 27214), + AOM_CDF6(7307, 16406, 19636, 24632, 28424) + }, + { + AOM_CDF4(5901, 26053, 29293), + AOM_CDF6(4441, 25064, 26879, 28942, 30919) + }, + { + AOM_CDF4(18318, 22152, 28333), + AOM_CDF6(17210, 20528, 23319, 26750, 29582) + }, + { + AOM_CDF4(30459, 31136, 31926), + AOM_CDF6(30674, 30953, 31396, 31735, 32207) + }, + // Palette size 5 + { + AOM_CDF5(22980, 25479, 27781, 29986), + AOM_CDF5(8413, 21408, 24859, 28874) + }, + { + AOM_CDF5(2257, 29449, 30594, 31598), + AOM_CDF5(19189, 21202, 25915, 28620) + }, + { + AOM_CDF5(31844, 32044, 32281, 32518), + 0, 0, 0, 0 + } +}; + +static const u16 default_txfm_partition_cdf[TXFM_PARTITION_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(28581) }, { AOM_CDF2(23846) }, { AOM_CDF2(20847) }, + { AOM_CDF2(24315) }, { AOM_CDF2(18196) }, { AOM_CDF2(12133) }, + { AOM_CDF2(18791) }, { AOM_CDF2(10887) }, { AOM_CDF2(11005) }, + { AOM_CDF2(27179) }, { AOM_CDF2(20004) }, { AOM_CDF2(11281) }, + { AOM_CDF2(26549) }, { AOM_CDF2(19308) }, { AOM_CDF2(14224) }, + { AOM_CDF2(28015) }, { AOM_CDF2(21546) }, { AOM_CDF2(14400) }, + { AOM_CDF2(28165) }, { AOM_CDF2(22401) }, { AOM_CDF2(16088) } +}; + +static const u16 default_skip_cdfs[SKIP_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(31671) }, { AOM_CDF2(16515) }, { AOM_CDF2(4576) } +}; + +static const u16 default_skip_mode_cdfs[SKIP_MODE_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(32621) }, { AOM_CDF2(20708) }, { AOM_CDF2(8127) } +}; + +static const u16 default_compound_idx_cdfs[COMP_INDEX_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(18244) }, { AOM_CDF2(12865) }, { AOM_CDF2(7053) }, + { AOM_CDF2(13259) }, { AOM_CDF2(9334) }, { AOM_CDF2(4644) } +}; + +static const u16 default_comp_group_idx_cdfs[COMP_GROUP_IDX_CONTEXTS][CDF_SIZE(2)] = { + { AOM_CDF2(26607) }, { AOM_CDF2(22891) }, { AOM_CDF2(18840) }, + { AOM_CDF2(24594) }, { AOM_CDF2(19934) }, { AOM_CDF2(22674) } +}; + +static const u16 default_intrabc_cdf[CDF_SIZE(2)] = { AOM_CDF2(30531) }; + +static const u16 default_filter_intra_mode_cdf[CDF_SIZE(FILTER_INTRA_MODES)] = { + AOM_CDF5(8949, 12776, 17211, 29558) +}; + +static const u16 default_filter_intra_cdfs[BLOCK_SIZES_ALL][CDF_SIZE(2)] = { + { AOM_CDF2(4621) }, { AOM_CDF2(6743) }, { AOM_CDF2(5893) }, { AOM_CDF2(7866) }, + { AOM_CDF2(12551) }, { AOM_CDF2(9394) }, { AOM_CDF2(12408) }, { AOM_CDF2(14301) }, + { AOM_CDF2(12756) }, { AOM_CDF2(22343) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, + { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, { AOM_CDF2(16384) }, + { AOM_CDF2(12770) }, { AOM_CDF2(10368) }, { AOM_CDF2(20229) }, { AOM_CDF2(18101) }, + { AOM_CDF2(16384) }, { AOM_CDF2(16384) } +}; + +static const u16 default_delta_q_cdf[CDF_SIZE(DELTA_Q_PROBS + 1)] = { + AOM_CDF4(28160, 32120, 32677) +}; + +static const u16 default_delta_lf_multi_cdf[FRAME_LF_COUNT][CDF_SIZE(DELTA_LF_PROBS + 1)] = { + { AOM_CDF4(28160, 32120, 32677) }, + { AOM_CDF4(28160, 32120, 32677) }, + { AOM_CDF4(28160, 32120, 32677) }, + { AOM_CDF4(28160, 32120, 32677) } +}; + +static const u16 default_delta_lf_cdf[CDF_SIZE(DELTA_LF_PROBS + 1)] = { + AOM_CDF4(28160, 32120, 32677) +}; + +static const u16 default_segment_pred_cdf[SEG_TEMPORAL_PRED_CTXS][CDF_SIZE(2)] = { + { AOM_CDF2(128 * 128) }, + { AOM_CDF2(128 * 128) }, + { AOM_CDF2(128 * 128) } +}; + +static const u16 default_spatial_pred_seg_tree_cdf[SPATIAL_PREDICTION_PROBS] + [CDF_SIZE(MAX_SEGMENTS)] = { + { + AOM_CDF8(5622, 7893, 16093, 18233, 27809, 28373, 32533), + }, + { + AOM_CDF8(14274, 18230, 22557, 24935, 29980, 30851, 32344), + }, + { + AOM_CDF8(27527, 28487, 28723, 28890, 32397, 32647, 32679), + }, +}; + +static const u16 default_tx_size_cdf[MAX_TX_CATS] + [AV1_TX_SIZE_CONTEXTS][CDF_SIZE(MAX_TX_DEPTH + 1)] = { + { + { AOM_CDF2(19968)}, + { AOM_CDF2(19968)}, + { AOM_CDF2(24320)} + }, + { + { AOM_CDF3(12272, 30172)}, + { AOM_CDF3(12272, 30172)}, + { AOM_CDF3(18677, 30848)} + }, + { + { AOM_CDF3(12986, 15180)}, + { AOM_CDF3(12986, 15180)}, + { AOM_CDF3(24302, 25602)} + }, + { + { AOM_CDF3(5782, 11475)}, + { AOM_CDF3(5782, 11475)}, + { AOM_CDF3(16803, 22759)} + }, +}; + +static const u16 av1_default_dc_sign_cdfs[TOKEN_CDF_Q_CTXS] + [PLANE_TYPES][DC_SIGN_CONTEXTS][CDF_SIZE(2)] = { + { + { + { AOM_CDF2(128 * 125)}, + { AOM_CDF2(128 * 102)}, + { AOM_CDF2(128 * 147)}, + }, + { + { AOM_CDF2(128 * 119)}, + { AOM_CDF2(128 * 101)}, + { AOM_CDF2(128 * 135)}, + } + }, + { + { + { AOM_CDF2(128 * 125)}, + { AOM_CDF2(128 * 102)}, + { AOM_CDF2(128 * 147)}, + }, + { + { AOM_CDF2(128 * 119)}, + { AOM_CDF2(128 * 101)}, + { AOM_CDF2(128 * 135)}, + } + }, + { + { + { AOM_CDF2(128 * 125)}, + { AOM_CDF2(128 * 102)}, + { AOM_CDF2(128 * 147)}, + }, + { + { AOM_CDF2(128 * 119)}, + { AOM_CDF2(128 * 101)}, + { AOM_CDF2(128 * 135)}, + } + }, + { + { + { AOM_CDF2(128 * 125)}, + { AOM_CDF2(128 * 102)}, + { AOM_CDF2(128 * 147)}, + }, + { + { AOM_CDF2(128 * 119)}, + { AOM_CDF2(128 * 101)}, + { AOM_CDF2(128 * 135)}, + } + }, +}; + +static const u16 av1_default_txb_skip_cdfs[TOKEN_CDF_Q_CTXS] + [TX_SIZES][TXB_SKIP_CONTEXTS][CDF_SIZE(2)] = { + { + { + { AOM_CDF2(31849)}, + { AOM_CDF2(5892)}, + { AOM_CDF2(12112)}, + { AOM_CDF2(21935)}, + { AOM_CDF2(20289)}, + { AOM_CDF2(27473)}, + { AOM_CDF2(32487)}, + { AOM_CDF2(7654)}, + { AOM_CDF2(19473)}, + { AOM_CDF2(29984)}, + { AOM_CDF2(9961)}, + { AOM_CDF2(30242)}, + { AOM_CDF2(32117)} + }, + { + { AOM_CDF2(31548)}, + { AOM_CDF2(1549)}, + { AOM_CDF2(10130)}, + { AOM_CDF2(16656)}, + { AOM_CDF2(18591)}, + { AOM_CDF2(26308)}, + { AOM_CDF2(32537)}, + { AOM_CDF2(5403)}, + { AOM_CDF2(18096)}, + { AOM_CDF2(30003)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(29957)}, + { AOM_CDF2(5391)}, + { AOM_CDF2(18039)}, + { AOM_CDF2(23566)}, + { AOM_CDF2(22431)}, + { AOM_CDF2(25822)}, + { AOM_CDF2(32197)}, + { AOM_CDF2(3778)}, + { AOM_CDF2(15336)}, + { AOM_CDF2(28981)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(17920)}, + { AOM_CDF2(1818)}, + { AOM_CDF2(7282)}, + { AOM_CDF2(25273)}, + { AOM_CDF2(10923)}, + { AOM_CDF2(31554)}, + { AOM_CDF2(32624)}, + { AOM_CDF2(1366)}, + { AOM_CDF2(15628)}, + { AOM_CDF2(30462)}, + { AOM_CDF2(146)}, + { AOM_CDF2(5132)}, + { AOM_CDF2(31657)} + }, + { + { AOM_CDF2(6308)}, + { AOM_CDF2(117)}, + { AOM_CDF2(1638)}, + { AOM_CDF2(2161)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(10923)}, + { AOM_CDF2(30247)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + } + }, + { + { + { AOM_CDF2(30371)}, + { AOM_CDF2(7570)}, + { AOM_CDF2(13155)}, + { AOM_CDF2(20751)}, + { AOM_CDF2(20969)}, + { AOM_CDF2(27067)}, + { AOM_CDF2(32013)}, + { AOM_CDF2(5495)}, + { AOM_CDF2(17942)}, + { AOM_CDF2(28280)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(31782)}, + { AOM_CDF2(1836)}, + { AOM_CDF2(10689)}, + { AOM_CDF2(17604)}, + { AOM_CDF2(21622)}, + { AOM_CDF2(27518)}, + { AOM_CDF2(32399)}, + { AOM_CDF2(4419)}, + { AOM_CDF2(16294)}, + { AOM_CDF2(28345)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(31901)}, + { AOM_CDF2(10311)}, + { AOM_CDF2(18047)}, + { AOM_CDF2(24806)}, + { AOM_CDF2(23288)}, + { AOM_CDF2(27914)}, + { AOM_CDF2(32296)}, + { AOM_CDF2(4215)}, + { AOM_CDF2(15756)}, + { AOM_CDF2(28341)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(26726)}, + { AOM_CDF2(1045)}, + { AOM_CDF2(11703)}, + { AOM_CDF2(20590)}, + { AOM_CDF2(18554)}, + { AOM_CDF2(25970)}, + { AOM_CDF2(31938)}, + { AOM_CDF2(5583)}, + { AOM_CDF2(21313)}, + { AOM_CDF2(29390)}, + { AOM_CDF2(641)}, + { AOM_CDF2(22265)}, + { AOM_CDF2(31452)} + }, + { + { AOM_CDF2(26584)}, + { AOM_CDF2(188)}, + { AOM_CDF2(8847)}, + { AOM_CDF2(24519)}, + { AOM_CDF2(22938)}, + { AOM_CDF2(30583)}, + { AOM_CDF2(32608)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + } + }, + { + { + { AOM_CDF2(29614)}, + { AOM_CDF2(9068)}, + { AOM_CDF2(12924)}, + { AOM_CDF2(19538)}, + { AOM_CDF2(17737)}, + { AOM_CDF2(24619)}, + { AOM_CDF2(30642)}, + { AOM_CDF2(4119)}, + { AOM_CDF2(16026)}, + { AOM_CDF2(25657)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(31957)}, + { AOM_CDF2(3230)}, + { AOM_CDF2(11153)}, + { AOM_CDF2(18123)}, + { AOM_CDF2(20143)}, + { AOM_CDF2(26536)}, + { AOM_CDF2(31986)}, + { AOM_CDF2(3050)}, + { AOM_CDF2(14603)}, + { AOM_CDF2(25155)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(32363)}, + { AOM_CDF2(10692)}, + { AOM_CDF2(19090)}, + { AOM_CDF2(24357)}, + { AOM_CDF2(24442)}, + { AOM_CDF2(28312)}, + { AOM_CDF2(32169)}, + { AOM_CDF2(3648)}, + { AOM_CDF2(15690)}, + { AOM_CDF2(26815)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(30669)}, + { AOM_CDF2(3832)}, + { AOM_CDF2(11663)}, + { AOM_CDF2(18889)}, + { AOM_CDF2(19782)}, + { AOM_CDF2(23313)}, + { AOM_CDF2(31330)}, + { AOM_CDF2(5124)}, + { AOM_CDF2(18719)}, + { AOM_CDF2(28468)}, + { AOM_CDF2(3082)}, + { AOM_CDF2(20982)}, + { AOM_CDF2(29443)} + }, + { + { AOM_CDF2(28573)}, + { AOM_CDF2(3183)}, + { AOM_CDF2(17802)}, + { AOM_CDF2(25977)}, + { AOM_CDF2(26677)}, + { AOM_CDF2(27832)}, + { AOM_CDF2(32387)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + } + }, + { + { + { AOM_CDF2(26887)}, + { AOM_CDF2(6729)}, + { AOM_CDF2(10361)}, + { AOM_CDF2(17442)}, + { AOM_CDF2(15045)}, + { AOM_CDF2(22478)}, + { AOM_CDF2(29072)}, + { AOM_CDF2(2713)}, + { AOM_CDF2(11861)}, + { AOM_CDF2(20773)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(31903)}, + { AOM_CDF2(2044)}, + { AOM_CDF2(7528)}, + { AOM_CDF2(14618)}, + { AOM_CDF2(16182)}, + { AOM_CDF2(24168)}, + { AOM_CDF2(31037)}, + { AOM_CDF2(2786)}, + { AOM_CDF2(11194)}, + { AOM_CDF2(20155)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(32510)}, + { AOM_CDF2(8430)}, + { AOM_CDF2(17318)}, + { AOM_CDF2(24154)}, + { AOM_CDF2(23674)}, + { AOM_CDF2(28789)}, + { AOM_CDF2(32139)}, + { AOM_CDF2(3440)}, + { AOM_CDF2(13117)}, + { AOM_CDF2(22702)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + }, + { + { AOM_CDF2(31671)}, + { AOM_CDF2(2056)}, + { AOM_CDF2(11746)}, + { AOM_CDF2(16852)}, + { AOM_CDF2(18635)}, + { AOM_CDF2(24715)}, + { AOM_CDF2(31484)}, + { AOM_CDF2(4656)}, + { AOM_CDF2(16074)}, + { AOM_CDF2(24704)}, + { AOM_CDF2(1806)}, + { AOM_CDF2(14645)}, + { AOM_CDF2(25336)} + }, + { + { AOM_CDF2(31539)}, + { AOM_CDF2(8433)}, + { AOM_CDF2(20576)}, + { AOM_CDF2(27904)}, + { AOM_CDF2(27852)}, + { AOM_CDF2(30026)}, + { AOM_CDF2(32441)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)} + } + } +}; + +static const u16 av1_default_eob_extra_cdfs[TOKEN_CDF_Q_CTXS][TX_SIZES][PLANE_TYPES] + [EOB_COEF_CONTEXTS][CDF_SIZE(2)] = { + { + { + { + { AOM_CDF2(16961)}, + { AOM_CDF2(17223)}, + { AOM_CDF2(7621)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(19069)}, + { AOM_CDF2(22525)}, + { AOM_CDF2(13377)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(20401)}, + { AOM_CDF2(17025)}, + { AOM_CDF2(12845)}, + { AOM_CDF2(12873)}, + { AOM_CDF2(14094)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(20681)}, + { AOM_CDF2(20701)}, + { AOM_CDF2(15250)}, + { AOM_CDF2(15017)}, + { AOM_CDF2(14928)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(23905)}, + { AOM_CDF2(17194)}, + { AOM_CDF2(16170)}, + { AOM_CDF2(17695)}, + { AOM_CDF2(13826)}, + { AOM_CDF2(15810)}, + { AOM_CDF2(12036)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(23959)}, + { AOM_CDF2(20799)}, + { AOM_CDF2(19021)}, + { AOM_CDF2(16203)}, + { AOM_CDF2(17886)}, + { AOM_CDF2(14144)}, + { AOM_CDF2(12010)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(27399)}, + { AOM_CDF2(16327)}, + { AOM_CDF2(18071)}, + { AOM_CDF2(19584)}, + { AOM_CDF2(20721)}, + { AOM_CDF2(18432)}, + { AOM_CDF2(19560)}, + { AOM_CDF2(10150)}, + { AOM_CDF2(8805)}, + }, + { + { AOM_CDF2(24932)}, + { AOM_CDF2(20833)}, + { AOM_CDF2(12027)}, + { AOM_CDF2(16670)}, + { AOM_CDF2(19914)}, + { AOM_CDF2(15106)}, + { AOM_CDF2(17662)}, + { AOM_CDF2(13783)}, + { AOM_CDF2(28756)}, + } + }, + { + { + { AOM_CDF2(23406)}, + { AOM_CDF2(21845)}, + { AOM_CDF2(18432)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(17096)}, + { AOM_CDF2(12561)}, + { AOM_CDF2(17320)}, + { AOM_CDF2(22395)}, + { AOM_CDF2(21370)}, + }, + { + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + } + }, + { + { + { + { AOM_CDF2(17471)}, + { AOM_CDF2(20223)}, + { AOM_CDF2(11357)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(20335)}, + { AOM_CDF2(21667)}, + { AOM_CDF2(14818)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(20430)}, + { AOM_CDF2(20662)}, + { AOM_CDF2(15367)}, + { AOM_CDF2(16970)}, + { AOM_CDF2(14657)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(22117)}, + { AOM_CDF2(22028)}, + { AOM_CDF2(18650)}, + { AOM_CDF2(16042)}, + { AOM_CDF2(15885)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(22409)}, + { AOM_CDF2(21012)}, + { AOM_CDF2(15650)}, + { AOM_CDF2(17395)}, + { AOM_CDF2(15469)}, + { AOM_CDF2(20205)}, + { AOM_CDF2(19511)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(24220)}, + { AOM_CDF2(22480)}, + { AOM_CDF2(17737)}, + { AOM_CDF2(18916)}, + { AOM_CDF2(19268)}, + { AOM_CDF2(18412)}, + { AOM_CDF2(18844)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(25991)}, + { AOM_CDF2(20314)}, + { AOM_CDF2(17731)}, + { AOM_CDF2(19678)}, + { AOM_CDF2(18649)}, + { AOM_CDF2(17307)}, + { AOM_CDF2(21798)}, + { AOM_CDF2(17549)}, + { AOM_CDF2(15630)}, + }, + { + { AOM_CDF2(26585)}, + { AOM_CDF2(21469)}, + { AOM_CDF2(20432)}, + { AOM_CDF2(17735)}, + { AOM_CDF2(19280)}, + { AOM_CDF2(15235)}, + { AOM_CDF2(20297)}, + { AOM_CDF2(22471)}, + { AOM_CDF2(28997)}, + } + }, + { + { + { AOM_CDF2(26605)}, + { AOM_CDF2(11304)}, + { AOM_CDF2(16726)}, + { AOM_CDF2(16560)}, + { AOM_CDF2(20866)}, + { AOM_CDF2(23524)}, + { AOM_CDF2(19878)}, + { AOM_CDF2(13469)}, + { AOM_CDF2(23084)}, + }, + { + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + } + }, + { + { + { + { AOM_CDF2(18983)}, + { AOM_CDF2(20512)}, + { AOM_CDF2(14885)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(20090)}, + { AOM_CDF2(19444)}, + { AOM_CDF2(17286)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(19139)}, + { AOM_CDF2(21487)}, + { AOM_CDF2(18959)}, + { AOM_CDF2(20910)}, + { AOM_CDF2(19089)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(20536)}, + { AOM_CDF2(20664)}, + { AOM_CDF2(20625)}, + { AOM_CDF2(19123)}, + { AOM_CDF2(14862)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(19833)}, + { AOM_CDF2(21502)}, + { AOM_CDF2(17485)}, + { AOM_CDF2(20267)}, + { AOM_CDF2(18353)}, + { AOM_CDF2(23329)}, + { AOM_CDF2(21478)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(22041)}, + { AOM_CDF2(23434)}, + { AOM_CDF2(20001)}, + { AOM_CDF2(20554)}, + { AOM_CDF2(20951)}, + { AOM_CDF2(20145)}, + { AOM_CDF2(15562)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(23312)}, + { AOM_CDF2(21607)}, + { AOM_CDF2(16526)}, + { AOM_CDF2(18957)}, + { AOM_CDF2(18034)}, + { AOM_CDF2(18934)}, + { AOM_CDF2(24247)}, + { AOM_CDF2(16921)}, + { AOM_CDF2(17080)}, + }, + { + { AOM_CDF2(26579)}, + { AOM_CDF2(24910)}, + { AOM_CDF2(18637)}, + { AOM_CDF2(19800)}, + { AOM_CDF2(20388)}, + { AOM_CDF2(9887)}, + { AOM_CDF2(15642)}, + { AOM_CDF2(30198)}, + { AOM_CDF2(24721)}, + } + }, + { + { + { AOM_CDF2(26998)}, + { AOM_CDF2(16737)}, + { AOM_CDF2(17838)}, + { AOM_CDF2(18922)}, + { AOM_CDF2(19515)}, + { AOM_CDF2(18636)}, + { AOM_CDF2(17333)}, + { AOM_CDF2(15776)}, + { AOM_CDF2(22658)}, + }, + { + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + } + }, + { + { + { + { AOM_CDF2(20177)}, + { AOM_CDF2(20789)}, + { AOM_CDF2(20262)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(21416)}, + { AOM_CDF2(20855)}, + { AOM_CDF2(23410)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(20238)}, + { AOM_CDF2(21057)}, + { AOM_CDF2(19159)}, + { AOM_CDF2(22337)}, + { AOM_CDF2(20159)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(20125)}, + { AOM_CDF2(20559)}, + { AOM_CDF2(21707)}, + { AOM_CDF2(22296)}, + { AOM_CDF2(17333)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(19941)}, + { AOM_CDF2(20527)}, + { AOM_CDF2(21470)}, + { AOM_CDF2(22487)}, + { AOM_CDF2(19558)}, + { AOM_CDF2(22354)}, + { AOM_CDF2(20331)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + }, + { + { AOM_CDF2(22752)}, + { AOM_CDF2(25006)}, + { AOM_CDF2(22075)}, + { AOM_CDF2(21576)}, + { AOM_CDF2(17740)}, + { AOM_CDF2(21690)}, + { AOM_CDF2(19211)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + }, + { + { + { AOM_CDF2(21442)}, + { AOM_CDF2(22358)}, + { AOM_CDF2(18503)}, + { AOM_CDF2(20291)}, + { AOM_CDF2(19945)}, + { AOM_CDF2(21294)}, + { AOM_CDF2(21178)}, + { AOM_CDF2(19400)}, + { AOM_CDF2(10556)}, + }, + { + { AOM_CDF2(24648)}, + { AOM_CDF2(24949)}, + { AOM_CDF2(20708)}, + { AOM_CDF2(23905)}, + { AOM_CDF2(20501)}, + { AOM_CDF2(9558)}, + { AOM_CDF2(9423)}, + { AOM_CDF2(30365)}, + { AOM_CDF2(19253)}, + } + }, + { + { + { AOM_CDF2(26064)}, + { AOM_CDF2(22098)}, + { AOM_CDF2(19613)}, + { AOM_CDF2(20525)}, + { AOM_CDF2(17595)}, + { AOM_CDF2(16618)}, + { AOM_CDF2(20497)}, + { AOM_CDF2(18989)}, + { AOM_CDF2(15513)}, + }, + { + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + { AOM_CDF2(16384)}, + } + } + } +}; + +static const u16 av1_default_eob_multi16_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][4] = { + { + { + { AOM_CDF5(840, 1039, 1980, 4895)}, + { AOM_CDF5(370, 671, 1883, 4471)} + }, + { + { AOM_CDF5(3247, 4950, 9688, 14563)}, + { AOM_CDF5(1904, 3354, 7763, 14647)} + } + }, + { + { + { AOM_CDF5(2125, 2551, 5165, 8946)}, + { AOM_CDF5(513, 765, 1859, 6339)} + }, + { + { AOM_CDF5(7637, 9498, 14259, 19108)}, + { AOM_CDF5(2497, 4096, 8866, 16993)} + } + }, + { + { + { AOM_CDF5(4016, 4897, 8881, 14968)}, + { AOM_CDF5(716, 1105, 2646, 10056)} + }, + { + { AOM_CDF5(11139, 13270, 18241, 23566)}, + { AOM_CDF5(3192, 5032, 10297, 19755)} + } + }, + { + { + { AOM_CDF5(6708, 8958, 14746, 22133)}, + { AOM_CDF5(1222, 2074, 4783, 15410)} + }, + { + { AOM_CDF5(19575, 21766, 26044, 29709)}, + { AOM_CDF5(7297, 10767, 19273, 28194)} + } + } +}; + +static const u16 av1_default_eob_multi32_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][8] = { + { + { + { AOM_CDF6(400, 520, 977, 2102, 6542)}, + { AOM_CDF6(210, 405, 1315, 3326, 7537)} + }, + { + { AOM_CDF6(2636, 4273, 7588, 11794, 20401)}, + { AOM_CDF6(1786, 3179, 6902, 11357, 19054)} + } + }, + { + { + { AOM_CDF6(989, 1249, 2019, 4151, 10785)}, + { AOM_CDF6(313, 441, 1099, 2917, 8562)} + }, + { + { AOM_CDF6(8394, 10352, 13932, 18855, 26014)}, + { AOM_CDF6(2578, 4124, 8181, 13670, 24234)} + } + }, + { + { + { AOM_CDF6(2515, 3003, 4452, 8162, 16041)}, + { AOM_CDF6(574, 821, 1836, 5089, 13128)} + }, + { + { AOM_CDF6(13468, 16303, 20361, 25105, 29281)}, + { AOM_CDF6(3542, 5502, 10415, 16760, 25644)} + } + }, + { + { + { AOM_CDF6(4617, 5709, 8446, 13584, 23135)}, + { AOM_CDF6(1156, 1702, 3675, 9274, 20539)} + }, + { + { AOM_CDF6(22086, 24282, 27010, 29770, 31743)}, + { AOM_CDF6(7699, 10897, 20891, 26926, 31628)} + } + } +}; + +static const u16 av1_default_eob_multi64_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][8] = { + { + { + { AOM_CDF7(329, 498, 1101, 1784, 3265, 7758)}, + { AOM_CDF7(335, 730, 1459, 5494, 8755, 12997)} + }, + { + { AOM_CDF7(3505, 5304, 10086, 13814, 17684, 23370)}, + { AOM_CDF7(1563, 2700, 4876, 10911, 14706, 22480)} + } + }, + { + { + { AOM_CDF7(1260, 1446, 2253, 3712, 6652, 13369)}, + { AOM_CDF7(401, 605, 1029, 2563, 5845, 12626)} + }, + { + { AOM_CDF7(8609, 10612, 14624, 18714, 22614, 29024)}, + { AOM_CDF7(1923, 3127, 5867, 9703, 14277, 27100)} + } + }, + { + { + { AOM_CDF7(2374, 2772, 4583, 7276, 12288, 19706)}, + { AOM_CDF7(497, 810, 1315, 3000, 7004, 15641)} + }, + { + { AOM_CDF7(15050, 17126, 21410, 24886, 28156, 30726)}, + { AOM_CDF7(4034, 6290, 10235, 14982, 21214, 28491)} + } + }, + { + { + { AOM_CDF7(6307, 7541, 12060, 16358, 22553, 27865)}, + { AOM_CDF7(1289, 2320, 3971, 7926, 14153, 24291)} + }, + { + { AOM_CDF7(24212, 25708, 28268, 30035, 31307, 32049)}, + { AOM_CDF7(8726, 12378, 19409, 26450, 30038, 32462)} + } + } +}; + +static const u16 av1_default_eob_multi128_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][8] = { + { + { + { AOM_CDF8(219, 482, 1140, 2091, 3680, 6028, 12586)}, + { AOM_CDF8(371, 699, 1254, 4830, 9479, 12562, 17497)} + }, + { + { AOM_CDF8(5245, 7456, 12880, 15852, 20033, 23932, 27608)}, + { AOM_CDF8(2054, 3472, 5869, 14232, 18242, 20590, 26752)} + } + }, + { + { + { AOM_CDF8(685, 933, 1488, 2714, 4766, 8562, 19254)}, + { AOM_CDF8(217, 352, 618, 2303, 5261, 9969, 17472)} + }, + { + { AOM_CDF8(8045, 11200, 15497, 19595, 23948, 27408, 30938)}, + { AOM_CDF8(2310, 4160, 7471, 14997, 17931, 20768, 30240)} + } + }, + { + { + { AOM_CDF8(1366, 1738, 2527, 5016, 9355, 15797, 24643)}, + { AOM_CDF8(354, 558, 944, 2760, 7287, 14037, 21779)} + }, + { + { AOM_CDF8(13627, 16246, 20173, 24429, 27948, 30415, 31863)}, + { AOM_CDF8(6275, 9889, 14769, 23164, 27988, 30493, 32272)} + } + }, + { + { + { AOM_CDF8(3472, 4885, 7489, 12481, 18517, 24536, 29635)}, + { AOM_CDF8(886, 1731, 3271, 8469, 15569, 22126, 28383)} + }, + { + { AOM_CDF8(24313, 26062, 28385, 30107, 31217, 31898, 32345)}, + { AOM_CDF8(9165, 13282, 21150, 30286, 31894, 32571, 32712)} + } + } +}; + +static const u16 av1_default_eob_multi256_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][8] = { + { + { + { AOM_CDF9(310, 584, 1887, 3589, 6168, 8611, 11352, 15652)}, + { AOM_CDF9(998, 1850, 2998, 5604, 17341, 19888, 22899, 25583)} + }, + { + { AOM_CDF9(2520, 3240, 5952, 8870, 12577, 17558, 19954, 24168)}, + { AOM_CDF9(2203, 4130, 7435, 10739, 20652, 23681, 25609, 27261)} + } + }, + { + { + { AOM_CDF9(1448, 2109, 4151, 6263, 9329, 13260, 17944, 23300)}, + { AOM_CDF9(399, 1019, 1749, 3038, 10444, 15546, 22739, 27294)} + }, + { + { AOM_CDF9(6402, 8148, 12623, 15072, 18728, 22847, 26447, 29377)}, + { AOM_CDF9(1674, 3252, 5734, 10159, 22397, 23802, 24821, 30940)} + } + }, + { + { + { AOM_CDF9(3089, 3920, 6038, 9460, 14266, 19881, 25766, 29176)}, + { AOM_CDF9(1084, 2358, 3488, 5122, 11483, 18103, 26023, 29799)} + }, + { + { AOM_CDF9(11514, 13794, 17480, 20754, 24361, 27378, 29492, 31277)}, + { AOM_CDF9(6571, 9610, 15516, 21826, 29092, 30829, 31842, 32708)} + } + }, + { + { + { AOM_CDF9(5348, 7113, 11820, 15924, 22106, 26777, 30334, 31757)}, + { AOM_CDF9(2453, 4474, 6307, 8777, 16474, 22975, 29000, 31547)} + }, + { + { AOM_CDF9(23110, 24597, 27140, 28894, 30167, 30927, 31392, 32094)}, + { AOM_CDF9(9998, 17661, 25178, 28097, 31308, 32038, 32403, 32695)} + } + } +}; + +static const u16 av1_default_eob_multi512_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][16] = { + { + { + { AOM_CDF10(641, 983, 3707, 5430, 10234, 14958, 18788, 23412, 26061)}, + { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + }, + { + { AOM_CDF10(5095, 6446, 9996, 13354, 16017, 17986, 20919, 26129, 29140)}, + { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + } + }, + { + { + { AOM_CDF10(1230, 2278, 5035, 7776, 11871, 15346, 19590, 24584, 28749)}, + { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + }, + { + { AOM_CDF10(7265, 9979, 15819, 19250, 21780, 23846, 26478, 28396, 31811)}, + { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + } + }, + { + { + { AOM_CDF10(2624, 3936, 6480, 9686, 13979, 17726, 23267, 28410, 31078)}, + { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + }, + { + { AOM_CDF10(12015, 14769, 19588, 22052, 24222, 25812, 27300, 29219, 32114)}, + { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + } + }, + { + { + { AOM_CDF10(5927, 7809, 10923, 14597, 19439, 24135, 28456, 31142, 32060)}, + { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + }, + { + { AOM_CDF10(21093, 23043, 25742, 27658, 29097, 29716, 30073, 30820, 31956)}, + { AOM_CDF10(3277, 6554, 9830, 13107, 16384, 19661, 22938, 26214, 29491)} + } + } +}; + +static const u16 av1_default_eob_multi1024_cdfs[TOKEN_CDF_Q_CTXS][PLANE_TYPES][2][16] = { + { + { + { AOM_CDF11(393, 421, 751, 1623, 3160, + 6352, 13345, 18047, 22571, 25830)}, + { AOM_CDF11(2979, 5958, 8937, 11916, 14895, + 17873, 20852, 23831, 26810, 29789)} + }, + { + { AOM_CDF11(1865, 1988, 2930, 4242, 10533, + 16538, 21354, 27255, 28546, 31784)}, + { AOM_CDF11(2979, 5958, 8937, 11916, 14895, + 17873, 20852, 23831, 26810, 29789)} + } + }, + { + { + { AOM_CDF11(696, 948, 3145, 5702, 9706, + 13217, 17851, 21856, 25692, 28034)}, + { AOM_CDF11(2979, 5958, 8937, 11916, 14895, + 17873, 20852, 23831, 26810, 29789)} + }, + { + { AOM_CDF11(2672, 3591, 9330, 17084, 22725, + 24284, 26527, 28027, 28377, 30876)}, + { AOM_CDF11(2979, 5958, 8937, 11916, 14895, + 17873, 20852, 23831, 26810, 29789)} + } + }, + { + { + { AOM_CDF11(2784, 3831, 7041, 10521, 14847, + 18844, 23155, 26682, 29229, 31045)}, + { AOM_CDF11(2979, 5958, 8937, 11916, 14895, + 17873, 20852, 23831, 26810, 29789)} + }, + { + { AOM_CDF11(9577, 12466, 17739, 20750, 22061, + 23215, 24601, 25483, 25843, 32056)}, + { AOM_CDF11(2979, 5958, 8937, 11916, 14895, + 17873, 20852, 23831, 26810, 29789)} + } + }, + { + { + { AOM_CDF11(6698, 8334, 11961, 15762, 20186, + 23862, 27434, 29326, 31082, 32050)}, + { AOM_CDF11(2979, 5958, 8937, 11916, 14895, + 17873, 20852, 23831, 26810, 29789)} + }, + { + { AOM_CDF11(20569, 22426, 25569, 26859, 28053, + 28913, 29486, 29724, 29807, 32570)}, + { AOM_CDF11(2979, 5958, 8937, 11916, 14895, + 17873, 20852, 23831, 26810, 29789)} + } + } +}; + +static const u16 av1_default_coeff_lps_multi_cdfs[TOKEN_CDF_Q_CTXS] + [TX_SIZES][PLANE_TYPES][LEVEL_CONTEXTS][CDF_SIZE(BR_CDF_SIZE) + 1] = { + { + { + { + { AOM_CDF4(14298, 20718, 24174)}, { AOM_CDF4(12536, 19601, 23789)}, + { AOM_CDF4(8712, 15051, 19503)}, { AOM_CDF4(6170, 11327, 15434)}, + { AOM_CDF4(4742, 8926, 12538)}, { AOM_CDF4(3803, 7317, 10546)}, + { AOM_CDF4(1696, 3317, 4871)}, { AOM_CDF4(14392, 19951, 22756)}, + { AOM_CDF4(15978, 23218, 26818)}, { AOM_CDF4(12187, 19474, 23889)}, + { AOM_CDF4(9176, 15640, 20259)}, { AOM_CDF4(7068, 12655, 17028)}, + { AOM_CDF4(5656, 10442, 14472)}, { AOM_CDF4(2580, 4992, 7244)}, + { AOM_CDF4(12136, 18049, 21426)}, { AOM_CDF4(13784, 20721, 24481)}, + { AOM_CDF4(10836, 17621, 21900)}, { AOM_CDF4(8372, 14444, 18847)}, + { AOM_CDF4(6523, 11779, 16000)}, { AOM_CDF4(5337, 9898, 13760)}, + { AOM_CDF4(3034, 5860, 8462)} + }, + { + { AOM_CDF4(15967, 22905, 26286)}, { AOM_CDF4(13534, 20654, 24579)}, + { AOM_CDF4(9504, 16092, 20535)}, { AOM_CDF4(6975, 12568, 16903)}, + { AOM_CDF4(5364, 10091, 14020)}, { AOM_CDF4(4357, 8370, 11857)}, + { AOM_CDF4(2506, 4934, 7218)}, { AOM_CDF4(23032, 28815, 30936)}, + { AOM_CDF4(19540, 26704, 29719)}, { AOM_CDF4(15158, 22969, 27097)}, + { AOM_CDF4(11408, 18865, 23650)}, { AOM_CDF4(8885, 15448, 20250)}, + { AOM_CDF4(7108, 12853, 17416)}, { AOM_CDF4(4231, 8041, 11480)}, + { AOM_CDF4(19823, 26490, 29156)}, { AOM_CDF4(18890, 25929, 28932)}, + { AOM_CDF4(15660, 23491, 27433)}, { AOM_CDF4(12147, 19776, 24488)}, + { AOM_CDF4(9728, 16774, 21649)}, { AOM_CDF4(7919, 14277, 19066)}, + { AOM_CDF4(5440, 10170, 14185)} + } + }, + { + { + { AOM_CDF4(14406, 20862, 24414)}, { AOM_CDF4(11824, 18907, 23109)}, + { AOM_CDF4(8257, 14393, 18803)}, { AOM_CDF4(5860, 10747, 14778)}, + { AOM_CDF4(4475, 8486, 11984)}, { AOM_CDF4(3606, 6954, 10043)}, + { AOM_CDF4(1736, 3410, 5048)}, { AOM_CDF4(14430, 20046, 22882)}, + { AOM_CDF4(15593, 22899, 26709)}, { AOM_CDF4(12102, 19368, 23811)}, + { AOM_CDF4(9059, 15584, 20262)}, { AOM_CDF4(6999, 12603, 17048)}, + { AOM_CDF4(5684, 10497, 14553)}, { AOM_CDF4(2822, 5438, 7862)}, + { AOM_CDF4(15785, 21585, 24359)}, { AOM_CDF4(18347, 25229, 28266)}, + { AOM_CDF4(14974, 22487, 26389)}, { AOM_CDF4(11423, 18681, 23271)}, + { AOM_CDF4(8863, 15350, 20008)}, { AOM_CDF4(7153, 12852, 17278)}, + { AOM_CDF4(3707, 7036, 9982)} + }, + { + { AOM_CDF4(15460, 21696, 25469)}, { AOM_CDF4(12170, 19249, 23191)}, + { AOM_CDF4(8723, 15027, 19332)}, { AOM_CDF4(6428, 11704, 15874)}, + { AOM_CDF4(4922, 9292, 13052)}, { AOM_CDF4(4139, 7695, 11010)}, + { AOM_CDF4(2291, 4508, 6598)}, { AOM_CDF4(19856, 26920, 29828)}, + { AOM_CDF4(17923, 25289, 28792)}, { AOM_CDF4(14278, 21968, 26297)}, + { AOM_CDF4(10910, 18136, 22950)}, { AOM_CDF4(8423, 14815, 19627)}, + { AOM_CDF4(6771, 12283, 16774)}, { AOM_CDF4(4074, 7750, 11081)}, + { AOM_CDF4(19852, 26074, 28672)}, { AOM_CDF4(19371, 26110, 28989)}, + { AOM_CDF4(16265, 23873, 27663)}, { AOM_CDF4(12758, 20378, 24952)}, + { AOM_CDF4(10095, 17098, 21961)}, { AOM_CDF4(8250, 14628, 19451)}, + { AOM_CDF4(5205, 9745, 13622)} + } + }, + { + { + { AOM_CDF4(10563, 16233, 19763)}, { AOM_CDF4(9794, 16022, 19804)}, + { AOM_CDF4(6750, 11945, 15759)}, { AOM_CDF4(4963, 9186, 12752)}, + { AOM_CDF4(3845, 7435, 10627)}, { AOM_CDF4(3051, 6085, 8834)}, + { AOM_CDF4(1311, 2596, 3830)}, { AOM_CDF4(11246, 16404, 19689)}, + { AOM_CDF4(12315, 18911, 22731)}, { AOM_CDF4(10557, 17095, 21289)}, + { AOM_CDF4(8136, 14006, 18249)}, { AOM_CDF4(6348, 11474, 15565)}, + { AOM_CDF4(5196, 9655, 13400)}, { AOM_CDF4(2349, 4526, 6587)}, + { AOM_CDF4(13337, 18730, 21569)}, { AOM_CDF4(19306, 26071, 28882)}, + { AOM_CDF4(15952, 23540, 27254)}, { AOM_CDF4(12409, 19934, 24430)}, + { AOM_CDF4(9760, 16706, 21389)}, { AOM_CDF4(8004, 14220, 18818)}, + { AOM_CDF4(4138, 7794, 10961)} + }, + { + { AOM_CDF4(10870, 16684, 20949)}, { AOM_CDF4(9664, 15230, 18680)}, + { AOM_CDF4(6886, 12109, 15408)}, { AOM_CDF4(4825, 8900, 12305)}, + { AOM_CDF4(3630, 7162, 10314)}, { AOM_CDF4(3036, 6429, 9387)}, + { AOM_CDF4(1671, 3296, 4940)}, { AOM_CDF4(13819, 19159, 23026)}, + { AOM_CDF4(11984, 19108, 23120)}, { AOM_CDF4(10690, 17210, 21663)}, + { AOM_CDF4(7984, 14154, 18333)}, { AOM_CDF4(6868, 12294, 16124)}, + { AOM_CDF4(5274, 8994, 12868)}, { AOM_CDF4(2988, 5771, 8424)}, + { AOM_CDF4(19736, 26647, 29141)}, { AOM_CDF4(18933, 26070, 28984)}, + { AOM_CDF4(15779, 23048, 27200)}, { AOM_CDF4(12638, 20061, 24532)}, + { AOM_CDF4(10692, 17545, 22220)}, { AOM_CDF4(9217, 15251, 20054)}, + { AOM_CDF4(5078, 9284, 12594)} + } + }, + { + { + { AOM_CDF4(2331, 3662, 5244)}, { AOM_CDF4(2891, 4771, 6145)}, + { AOM_CDF4(4598, 7623, 9729)}, { AOM_CDF4(3520, 6845, 9199)}, + { AOM_CDF4(3417, 6119, 9324)}, { AOM_CDF4(2601, 5412, 7385)}, + { AOM_CDF4(600, 1173, 1744)}, { AOM_CDF4(7672, 13286, 17469)}, + { AOM_CDF4(4232, 7792, 10793)}, { AOM_CDF4(2915, 5317, 7397)}, + { AOM_CDF4(2318, 4356, 6152)}, { AOM_CDF4(2127, 4000, 5554)}, + { AOM_CDF4(1850, 3478, 5275)}, { AOM_CDF4(977, 1933, 2843)}, + { AOM_CDF4(18280, 24387, 27989)}, { AOM_CDF4(15852, 22671, 26185)}, + { AOM_CDF4(13845, 20951, 24789)}, { AOM_CDF4(11055, 17966, 22129)}, + { AOM_CDF4(9138, 15422, 19801)}, { AOM_CDF4(7454, 13145, 17456)}, + { AOM_CDF4(3370, 6393, 9013)} + }, + { + { AOM_CDF4(5842, 9229, 10838)}, { AOM_CDF4(2313, 3491, 4276)}, + { AOM_CDF4(2998, 6104, 7496)}, { AOM_CDF4(2420, 7447, 9868)}, + { AOM_CDF4(3034, 8495, 10923)}, { AOM_CDF4(4076, 8937, 10975)}, + { AOM_CDF4(1086, 2370, 3299)}, { AOM_CDF4(9714, 17254, 20444)}, + { AOM_CDF4(8543, 13698, 17123)}, { AOM_CDF4(4918, 9007, 11910)}, + { AOM_CDF4(4129, 7532, 10553)}, { AOM_CDF4(2364, 5533, 8058)}, + { AOM_CDF4(1834, 3546, 5563)}, { AOM_CDF4(1473, 2908, 4133)}, + { AOM_CDF4(15405, 21193, 25619)}, { AOM_CDF4(15691, 21952, 26561)}, + { AOM_CDF4(12962, 19194, 24165)}, { AOM_CDF4(10272, 17855, 22129)}, + { AOM_CDF4(8588, 15270, 20718)}, { AOM_CDF4(8682, 14669, 19500)}, + { AOM_CDF4(4870, 9636, 13205)} + } + }, + { + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)} + } + } + }, + { + { + { + { AOM_CDF4(14995, 21341, 24749)}, { AOM_CDF4(13158, 20289, 24601)}, + { AOM_CDF4(8941, 15326, 19876)}, { AOM_CDF4(6297, 11541, 15807)}, + { AOM_CDF4(4817, 9029, 12776)}, { AOM_CDF4(3731, 7273, 10627)}, + { AOM_CDF4(1847, 3617, 5354)}, { AOM_CDF4(14472, 19659, 22343)}, + { AOM_CDF4(16806, 24162, 27533)}, { AOM_CDF4(12900, 20404, 24713)}, + { AOM_CDF4(9411, 16112, 20797)}, { AOM_CDF4(7056, 12697, 17148)}, + { AOM_CDF4(5544, 10339, 14460)}, { AOM_CDF4(2954, 5704, 8319)}, + { AOM_CDF4(12464, 18071, 21354)}, { AOM_CDF4(15482, 22528, 26034)}, + { AOM_CDF4(12070, 19269, 23624)}, { AOM_CDF4(8953, 15406, 20106)}, + { AOM_CDF4(7027, 12730, 17220)}, { AOM_CDF4(5887, 10913, 15140)}, + { AOM_CDF4(3793, 7278, 10447)} + }, + { + { AOM_CDF4(15571, 22232, 25749)}, { AOM_CDF4(14506, 21575, 25374)}, + { AOM_CDF4(10189, 17089, 21569)}, { AOM_CDF4(7316, 13301, 17915)}, + { AOM_CDF4(5783, 10912, 15190)}, { AOM_CDF4(4760, 9155, 13088)}, + { AOM_CDF4(2993, 5966, 8774)}, { AOM_CDF4(23424, 28903, 30778)}, + { AOM_CDF4(20775, 27666, 30290)}, { AOM_CDF4(16474, 24410, 28299)}, + { AOM_CDF4(12471, 20180, 24987)}, { AOM_CDF4(9410, 16487, 21439)}, + { AOM_CDF4(7536, 13614, 18529)}, { AOM_CDF4(5048, 9586, 13549)}, + { AOM_CDF4(21090, 27290, 29756)}, { AOM_CDF4(20796, 27402, 30026)}, + { AOM_CDF4(17819, 25485, 28969)}, { AOM_CDF4(13860, 21909, 26462)}, + { AOM_CDF4(11002, 18494, 23529)}, { AOM_CDF4(8953, 15929, 20897)}, + { AOM_CDF4(6448, 11918, 16454)} + } + }, + { + { + { AOM_CDF4(15999, 22208, 25449)}, { AOM_CDF4(13050, 19988, 24122)}, + { AOM_CDF4(8594, 14864, 19378)}, { AOM_CDF4(6033, 11079, 15238)}, + { AOM_CDF4(4554, 8683, 12347)}, { AOM_CDF4(3672, 7139, 10337)}, + { AOM_CDF4(1900, 3771, 5576)}, { AOM_CDF4(15788, 21340, 23949)}, + { AOM_CDF4(16825, 24235, 27758)}, { AOM_CDF4(12873, 20402, 24810)}, + { AOM_CDF4(9590, 16363, 21094)}, { AOM_CDF4(7352, 13209, 17733)}, + { AOM_CDF4(5960, 10989, 15184)}, { AOM_CDF4(3232, 6234, 9007)}, + { AOM_CDF4(15761, 20716, 23224)}, { AOM_CDF4(19318, 25989, 28759)}, + { AOM_CDF4(15529, 23094, 26929)}, { AOM_CDF4(11662, 18989, 23641)}, + { AOM_CDF4(8955, 15568, 20366)}, { AOM_CDF4(7281, 13106, 17708)}, + { AOM_CDF4(4248, 8059, 11440)} + }, + { + { AOM_CDF4(14899, 21217, 24503)}, { AOM_CDF4(13519, 20283, 24047)}, + { AOM_CDF4(9429, 15966, 20365)}, { AOM_CDF4(6700, 12355, 16652)}, + { AOM_CDF4(5088, 9704, 13716)}, { AOM_CDF4(4243, 8154, 11731)}, + { AOM_CDF4(2702, 5364, 7861)}, { AOM_CDF4(22745, 28388, 30454)}, + { AOM_CDF4(20235, 27146, 29922)}, { AOM_CDF4(15896, 23715, 27637)}, + { AOM_CDF4(11840, 19350, 24131)}, { AOM_CDF4(9122, 15932, 20880)}, + { AOM_CDF4(7488, 13581, 18362)}, { AOM_CDF4(5114, 9568, 13370)}, + { AOM_CDF4(20845, 26553, 28932)}, { AOM_CDF4(20981, 27372, 29884)}, + { AOM_CDF4(17781, 25335, 28785)}, { AOM_CDF4(13760, 21708, 26297)}, + { AOM_CDF4(10975, 18415, 23365)}, { AOM_CDF4(9045, 15789, 20686)}, + { AOM_CDF4(6130, 11199, 15423)} + } + }, + { + { + { AOM_CDF4(13549, 19724, 23158)}, { AOM_CDF4(11844, 18382, 22246)}, + { AOM_CDF4(7919, 13619, 17773)}, { AOM_CDF4(5486, 10143, 13946)}, + { AOM_CDF4(4166, 7983, 11324)}, { AOM_CDF4(3364, 6506, 9427)}, + { AOM_CDF4(1598, 3160, 4674)}, { AOM_CDF4(15281, 20979, 23781)}, + { AOM_CDF4(14939, 22119, 25952)}, { AOM_CDF4(11363, 18407, 22812)}, + { AOM_CDF4(8609, 14857, 19370)}, { AOM_CDF4(6737, 12184, 16480)}, + { AOM_CDF4(5506, 10263, 14262)}, { AOM_CDF4(2990, 5786, 8380)}, + { AOM_CDF4(20249, 25253, 27417)}, { AOM_CDF4(21070, 27518, 30001)}, + { AOM_CDF4(16854, 24469, 28074)}, { AOM_CDF4(12864, 20486, 25000)}, + { AOM_CDF4(9962, 16978, 21778)}, { AOM_CDF4(8074, 14338, 19048)}, + { AOM_CDF4(4494, 8479, 11906)} + }, + { + { AOM_CDF4(13960, 19617, 22829)}, { AOM_CDF4(11150, 17341, 21228)}, + { AOM_CDF4(7150, 12964, 17190)}, { AOM_CDF4(5331, 10002, 13867)}, + { AOM_CDF4(4167, 7744, 11057)}, { AOM_CDF4(3480, 6629, 9646)}, + { AOM_CDF4(1883, 3784, 5686)}, { AOM_CDF4(18752, 25660, 28912)}, + { AOM_CDF4(16968, 24586, 28030)}, { AOM_CDF4(13520, 21055, 25313)}, + { AOM_CDF4(10453, 17626, 22280)}, { AOM_CDF4(8386, 14505, 19116)}, + { AOM_CDF4(6742, 12595, 17008)}, { AOM_CDF4(4273, 8140, 11499)}, + { AOM_CDF4(22120, 27827, 30233)}, { AOM_CDF4(20563, 27358, 29895)}, + { AOM_CDF4(17076, 24644, 28153)}, { AOM_CDF4(13362, 20942, 25309)}, + { AOM_CDF4(10794, 17965, 22695)}, { AOM_CDF4(9014, 15652, 20319)}, + { AOM_CDF4(5708, 10512, 14497)} + } + }, + { + { + { AOM_CDF4(5705, 10930, 15725)}, { AOM_CDF4(7946, 12765, 16115)}, + { AOM_CDF4(6801, 12123, 16226)}, { AOM_CDF4(5462, 10135, 14200)}, + { AOM_CDF4(4189, 8011, 11507)}, { AOM_CDF4(3191, 6229, 9408)}, + { AOM_CDF4(1057, 2137, 3212)}, { AOM_CDF4(10018, 17067, 21491)}, + { AOM_CDF4(7380, 12582, 16453)}, { AOM_CDF4(6068, 10845, 14339)}, + { AOM_CDF4(5098, 9198, 12555)}, { AOM_CDF4(4312, 8010, 11119)}, + { AOM_CDF4(3700, 6966, 9781)}, { AOM_CDF4(1693, 3326, 4887)}, + { AOM_CDF4(18757, 24930, 27774)}, { AOM_CDF4(17648, 24596, 27817)}, + { AOM_CDF4(14707, 22052, 26026)}, { AOM_CDF4(11720, 18852, 23292)}, + { AOM_CDF4(9357, 15952, 20525)}, { AOM_CDF4(7810, 13753, 18210)}, + { AOM_CDF4(3879, 7333, 10328)} + }, + { + { AOM_CDF4(8278, 13242, 15922)}, { AOM_CDF4(10547, 15867, 18919)}, + { AOM_CDF4(9106, 15842, 20609)}, { AOM_CDF4(6833, 13007, 17218)}, + { AOM_CDF4(4811, 9712, 13923)}, { AOM_CDF4(3985, 7352, 11128)}, + { AOM_CDF4(1688, 3458, 5262)}, { AOM_CDF4(12951, 21861, 26510)}, + { AOM_CDF4(9788, 16044, 20276)}, { AOM_CDF4(6309, 11244, 14870)}, + { AOM_CDF4(5183, 9349, 12566)}, { AOM_CDF4(4389, 8229, 11492)}, + { AOM_CDF4(3633, 6945, 10620)}, { AOM_CDF4(3600, 6847, 9907)}, + { AOM_CDF4(21748, 28137, 30255)}, { AOM_CDF4(19436, 26581, 29560)}, + { AOM_CDF4(16359, 24201, 27953)}, { AOM_CDF4(13961, 21693, 25871)}, + { AOM_CDF4(11544, 18686, 23322)}, { AOM_CDF4(9372, 16462, 20952)}, + { AOM_CDF4(6138, 11210, 15390)} + } + }, + { + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)} + } + } + }, + { + { + { + { AOM_CDF4(16138, 22223, 25509)}, { AOM_CDF4(15347, 22430, 26332)}, + { AOM_CDF4(9614, 16736, 21332)}, { AOM_CDF4(6600, 12275, 16907)}, + { AOM_CDF4(4811, 9424, 13547)}, { AOM_CDF4(3748, 7809, 11420)}, + { AOM_CDF4(2254, 4587, 6890)}, { AOM_CDF4(15196, 20284, 23177)}, + { AOM_CDF4(18317, 25469, 28451)}, { AOM_CDF4(13918, 21651, 25842)}, + { AOM_CDF4(10052, 17150, 21995)}, { AOM_CDF4(7499, 13630, 18587)}, + { AOM_CDF4(6158, 11417, 16003)}, { AOM_CDF4(4014, 7785, 11252)}, + { AOM_CDF4(15048, 21067, 24384)}, { AOM_CDF4(18202, 25346, 28553)}, + { AOM_CDF4(14302, 22019, 26356)}, { AOM_CDF4(10839, 18139, 23166)}, + { AOM_CDF4(8715, 15744, 20806)}, { AOM_CDF4(7536, 13576, 18544)}, + { AOM_CDF4(5413, 10335, 14498)} + }, + { + { AOM_CDF4(17394, 24501, 27895)}, { AOM_CDF4(15889, 23420, 27185)}, + { AOM_CDF4(11561, 19133, 23870)}, { AOM_CDF4(8285, 14812, 19844)}, + { AOM_CDF4(6496, 12043, 16550)}, { AOM_CDF4(4771, 9574, 13677)}, + { AOM_CDF4(3603, 6830, 10144)}, { AOM_CDF4(21656, 27704, 30200)}, + { AOM_CDF4(21324, 27915, 30511)}, { AOM_CDF4(17327, 25336, 28997)}, + { AOM_CDF4(13417, 21381, 26033)}, { AOM_CDF4(10132, 17425, 22338)}, + { AOM_CDF4(8580, 15016, 19633)}, { AOM_CDF4(5694, 11477, 16411)}, + { AOM_CDF4(24116, 29780, 31450)}, { AOM_CDF4(23853, 29695, 31591)}, + { AOM_CDF4(20085, 27614, 30428)}, { AOM_CDF4(15326, 24335, 28575)}, + { AOM_CDF4(11814, 19472, 24810)}, { AOM_CDF4(10221, 18611, 24767)}, + { AOM_CDF4(7689, 14558, 20321)} + } + }, + { + { + { AOM_CDF4(16214, 22380, 25770)}, { AOM_CDF4(14213, 21304, 25295)}, + { AOM_CDF4(9213, 15823, 20455)}, { AOM_CDF4(6395, 11758, 16139)}, + { AOM_CDF4(4779, 9187, 13066)}, { AOM_CDF4(3821, 7501, 10953)}, + { AOM_CDF4(2293, 4567, 6795)}, { AOM_CDF4(15859, 21283, 23820)}, + { AOM_CDF4(18404, 25602, 28726)}, { AOM_CDF4(14325, 21980, 26206)}, + { AOM_CDF4(10669, 17937, 22720)}, { AOM_CDF4(8297, 14642, 19447)}, + { AOM_CDF4(6746, 12389, 16893)}, { AOM_CDF4(4324, 8251, 11770)}, + { AOM_CDF4(16532, 21631, 24475)}, { AOM_CDF4(20667, 27150, 29668)}, + { AOM_CDF4(16728, 24510, 28175)}, { AOM_CDF4(12861, 20645, 25332)}, + { AOM_CDF4(10076, 17361, 22417)}, { AOM_CDF4(8395, 14940, 19963)}, + { AOM_CDF4(5731, 10683, 14912)} + }, + { + { AOM_CDF4(14433, 21155, 24938)}, { AOM_CDF4(14658, 21716, 25545)}, + { AOM_CDF4(9923, 16824, 21557)}, { AOM_CDF4(6982, 13052, 17721)}, + { AOM_CDF4(5419, 10503, 15050)}, { AOM_CDF4(4852, 9162, 13014)}, + { AOM_CDF4(3271, 6395, 9630)}, { AOM_CDF4(22210, 27833, 30109)}, + { AOM_CDF4(20750, 27368, 29821)}, { AOM_CDF4(16894, 24828, 28573)}, + { AOM_CDF4(13247, 21276, 25757)}, { AOM_CDF4(10038, 17265, 22563)}, + { AOM_CDF4(8587, 14947, 20327)}, { AOM_CDF4(5645, 11371, 15252)}, + { AOM_CDF4(22027, 27526, 29714)}, { AOM_CDF4(23098, 29146, 31221)}, + { AOM_CDF4(19886, 27341, 30272)}, { AOM_CDF4(15609, 23747, 28046)}, + { AOM_CDF4(11993, 20065, 24939)}, { AOM_CDF4(9637, 18267, 23671)}, + { AOM_CDF4(7625, 13801, 19144)} + } + }, + { + { + { AOM_CDF4(14438, 20798, 24089)}, { AOM_CDF4(12621, 19203, 23097)}, + { AOM_CDF4(8177, 14125, 18402)}, { AOM_CDF4(5674, 10501, 14456)}, + { AOM_CDF4(4236, 8239, 11733)}, { AOM_CDF4(3447, 6750, 9806)}, + { AOM_CDF4(1986, 3950, 5864)}, { AOM_CDF4(16208, 22099, 24930)}, + { AOM_CDF4(16537, 24025, 27585)}, { AOM_CDF4(12780, 20381, 24867)}, + { AOM_CDF4(9767, 16612, 21416)}, { AOM_CDF4(7686, 13738, 18398)}, + { AOM_CDF4(6333, 11614, 15964)}, { AOM_CDF4(3941, 7571, 10836)}, + { AOM_CDF4(22819, 27422, 29202)}, { AOM_CDF4(22224, 28514, 30721)}, + { AOM_CDF4(17660, 25433, 28913)}, { AOM_CDF4(13574, 21482, 26002)}, + { AOM_CDF4(10629, 17977, 22938)}, { AOM_CDF4(8612, 15298, 20265)}, + { AOM_CDF4(5607, 10491, 14596)} + }, + { + { AOM_CDF4(13569, 19800, 23206)}, { AOM_CDF4(13128, 19924, 23869)}, + { AOM_CDF4(8329, 14841, 19403)}, { AOM_CDF4(6130, 10976, 15057)}, + { AOM_CDF4(4682, 8839, 12518)}, { AOM_CDF4(3656, 7409, 10588)}, + { AOM_CDF4(2577, 5099, 7412)}, { AOM_CDF4(22427, 28684, 30585)}, + { AOM_CDF4(20913, 27750, 30139)}, { AOM_CDF4(15840, 24109, 27834)}, + { AOM_CDF4(12308, 20029, 24569)}, { AOM_CDF4(10216, 16785, 21458)}, + { AOM_CDF4(8309, 14203, 19113)}, { AOM_CDF4(6043, 11168, 15307)}, + { AOM_CDF4(23166, 28901, 30998)}, { AOM_CDF4(21899, 28405, 30751)}, + { AOM_CDF4(18413, 26091, 29443)}, { AOM_CDF4(15233, 23114, 27352)}, + { AOM_CDF4(12683, 20472, 25288)}, { AOM_CDF4(10702, 18259, 23409)}, + { AOM_CDF4(8125, 14464, 19226)} + } + }, + { + { + { AOM_CDF4(9040, 14786, 18360)}, { AOM_CDF4(9979, 15718, 19415)}, + { AOM_CDF4(7913, 13918, 18311)}, { AOM_CDF4(5859, 10889, 15184)}, + { AOM_CDF4(4593, 8677, 12510)}, { AOM_CDF4(3820, 7396, 10791)}, + { AOM_CDF4(1730, 3471, 5192)}, { AOM_CDF4(11803, 18365, 22709)}, + { AOM_CDF4(11419, 18058, 22225)}, { AOM_CDF4(9418, 15774, 20243)}, + { AOM_CDF4(7539, 13325, 17657)}, { AOM_CDF4(6233, 11317, 15384)}, + { AOM_CDF4(5137, 9656, 13545)}, { AOM_CDF4(2977, 5774, 8349)}, + { AOM_CDF4(21207, 27246, 29640)}, { AOM_CDF4(19547, 26578, 29497)}, + { AOM_CDF4(16169, 23871, 27690)}, { AOM_CDF4(12820, 20458, 25018)}, + { AOM_CDF4(10224, 17332, 22214)}, { AOM_CDF4(8526, 15048, 19884)}, + { AOM_CDF4(5037, 9410, 13118)} + }, + { + { AOM_CDF4(12339, 17329, 20140)}, { AOM_CDF4(13505, 19895, 23225)}, + { AOM_CDF4(9847, 16944, 21564)}, { AOM_CDF4(7280, 13256, 18348)}, + { AOM_CDF4(4712, 10009, 14454)}, { AOM_CDF4(4361, 7914, 12477)}, + { AOM_CDF4(2870, 5628, 7995)}, { AOM_CDF4(20061, 25504, 28526)}, + { AOM_CDF4(15235, 22878, 26145)}, { AOM_CDF4(12985, 19958, 24155)}, + { AOM_CDF4(9782, 16641, 21403)}, { AOM_CDF4(9456, 16360, 20760)}, + { AOM_CDF4(6855, 12940, 18557)}, { AOM_CDF4(5661, 10564, 15002)}, + { AOM_CDF4(25656, 30602, 31894)}, { AOM_CDF4(22570, 29107, 31092)}, + { AOM_CDF4(18917, 26423, 29541)}, { AOM_CDF4(15940, 23649, 27754)}, + { AOM_CDF4(12803, 20581, 25219)}, { AOM_CDF4(11082, 18695, 23376)}, + { AOM_CDF4(7939, 14373, 19005)} + } + }, + { + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)} + } + } + }, + { + { + { + { AOM_CDF4(18315, 24289, 27551)}, { AOM_CDF4(16854, 24068, 27835)}, + { AOM_CDF4(10140, 17927, 23173)}, { AOM_CDF4(6722, 12982, 18267)}, + { AOM_CDF4(4661, 9826, 14706)}, { AOM_CDF4(3832, 8165, 12294)}, + { AOM_CDF4(2795, 6098, 9245)}, { AOM_CDF4(17145, 23326, 26672)}, + { AOM_CDF4(20733, 27680, 30308)}, { AOM_CDF4(16032, 24461, 28546)}, + { AOM_CDF4(11653, 20093, 25081)}, { AOM_CDF4(9290, 16429, 22086)}, + { AOM_CDF4(7796, 14598, 19982)}, { AOM_CDF4(6502, 12378, 17441)}, + { AOM_CDF4(21681, 27732, 30320)}, { AOM_CDF4(22389, 29044, 31261)}, + { AOM_CDF4(19027, 26731, 30087)}, { AOM_CDF4(14739, 23755, 28624)}, + { AOM_CDF4(11358, 20778, 25511)}, { AOM_CDF4(10995, 18073, 24190)}, + { AOM_CDF4(9162, 14990, 20617)} + }, + { + { AOM_CDF4(21425, 27952, 30388)}, { AOM_CDF4(18062, 25838, 29034)}, + { AOM_CDF4(11956, 19881, 24808)}, { AOM_CDF4(7718, 15000, 20980)}, + { AOM_CDF4(5702, 11254, 16143)}, { AOM_CDF4(4898, 9088, 16864)}, + { AOM_CDF4(3679, 6776, 11907)}, { AOM_CDF4(23294, 30160, 31663)}, + { AOM_CDF4(24397, 29896, 31836)}, { AOM_CDF4(19245, 27128, 30593)}, + { AOM_CDF4(13202, 19825, 26404)}, { AOM_CDF4(11578, 19297, 23957)}, + { AOM_CDF4(8073, 13297, 21370)}, { AOM_CDF4(5461, 10923, 19745)}, + { AOM_CDF4(27367, 30521, 31934)}, { AOM_CDF4(24904, 30671, 31940)}, + { AOM_CDF4(23075, 28460, 31299)}, { AOM_CDF4(14400, 23658, 30417)}, + { AOM_CDF4(13885, 23882, 28325)}, { AOM_CDF4(14746, 22938, 27853)}, + { AOM_CDF4(5461, 16384, 27307)} + } + }, + { + { + { AOM_CDF4(18274, 24813, 27890)}, { AOM_CDF4(15537, 23149, 27003)}, + { AOM_CDF4(9449, 16740, 21827)}, { AOM_CDF4(6700, 12498, 17261)}, + { AOM_CDF4(4988, 9866, 14198)}, { AOM_CDF4(4236, 8147, 11902)}, + { AOM_CDF4(2867, 5860, 8654)}, { AOM_CDF4(17124, 23171, 26101)}, + { AOM_CDF4(20396, 27477, 30148)}, { AOM_CDF4(16573, 24629, 28492)}, + { AOM_CDF4(12749, 20846, 25674)}, { AOM_CDF4(10233, 17878, 22818)}, + { AOM_CDF4(8525, 15332, 20363)}, { AOM_CDF4(6283, 11632, 16255)}, + { AOM_CDF4(20466, 26511, 29286)}, { AOM_CDF4(23059, 29174, 31191)}, + { AOM_CDF4(19481, 27263, 30241)}, { AOM_CDF4(15458, 23631, 28137)}, + { AOM_CDF4(12416, 20608, 25693)}, { AOM_CDF4(10261, 18011, 23261)}, + { AOM_CDF4(8016, 14655, 19666)} + }, + { + { AOM_CDF4(17616, 24586, 28112)}, { AOM_CDF4(15809, 23299, 27155)}, + { AOM_CDF4(10767, 18890, 23793)}, { AOM_CDF4(7727, 14255, 18865)}, + { AOM_CDF4(6129, 11926, 16882)}, { AOM_CDF4(4482, 9704, 14861)}, + { AOM_CDF4(3277, 7452, 11522)}, { AOM_CDF4(22956, 28551, 30730)}, + { AOM_CDF4(22724, 28937, 30961)}, { AOM_CDF4(18467, 26324, 29580)}, + { AOM_CDF4(13234, 20713, 25649)}, { AOM_CDF4(11181, 17592, 22481)}, + { AOM_CDF4(8291, 18358, 24576)}, { AOM_CDF4(7568, 11881, 14984)}, + { AOM_CDF4(24948, 29001, 31147)}, { AOM_CDF4(25674, 30619, 32151)}, + { AOM_CDF4(20841, 26793, 29603)}, { AOM_CDF4(14669, 24356, 28666)}, + { AOM_CDF4(11334, 23593, 28219)}, { AOM_CDF4(8922, 14762, 22873)}, + { AOM_CDF4(8301, 13544, 20535)} + } + }, + { + { + { AOM_CDF4(17113, 23733, 27081)}, { AOM_CDF4(14139, 21406, 25452)}, + { AOM_CDF4(8552, 15002, 19776)}, { AOM_CDF4(5871, 11120, 15378)}, + { AOM_CDF4(4455, 8616, 12253)}, { AOM_CDF4(3469, 6910, 10386)}, + { AOM_CDF4(2255, 4553, 6782)}, { AOM_CDF4(18224, 24376, 27053)}, + { AOM_CDF4(19290, 26710, 29614)}, { AOM_CDF4(14936, 22991, 27184)}, + { AOM_CDF4(11238, 18951, 23762)}, { AOM_CDF4(8786, 15617, 20588)}, + { AOM_CDF4(7317, 13228, 18003)}, { AOM_CDF4(5101, 9512, 13493)}, + { AOM_CDF4(22639, 28222, 30210)}, { AOM_CDF4(23216, 29331, 31307)}, + { AOM_CDF4(19075, 26762, 29895)}, { AOM_CDF4(15014, 23113, 27457)}, + { AOM_CDF4(11938, 19857, 24752)}, { AOM_CDF4(9942, 17280, 22282)}, + { AOM_CDF4(7167, 13144, 17752)} + }, + { + { AOM_CDF4(15820, 22738, 26488)}, { AOM_CDF4(13530, 20885, 25216)}, + { AOM_CDF4(8395, 15530, 20452)}, { AOM_CDF4(6574, 12321, 16380)}, + { AOM_CDF4(5353, 10419, 14568)}, { AOM_CDF4(4613, 8446, 12381)}, + { AOM_CDF4(3440, 7158, 9903)}, { AOM_CDF4(24247, 29051, 31224)}, + { AOM_CDF4(22118, 28058, 30369)}, { AOM_CDF4(16498, 24768, 28389)}, + { AOM_CDF4(12920, 21175, 26137)}, { AOM_CDF4(10730, 18619, 25352)}, + { AOM_CDF4(10187, 16279, 22791)}, { AOM_CDF4(9310, 14631, 22127)}, + { AOM_CDF4(24970, 30558, 32057)}, { AOM_CDF4(24801, 29942, 31698)}, + { AOM_CDF4(22432, 28453, 30855)}, { AOM_CDF4(19054, 25680, 29580)}, + { AOM_CDF4(14392, 23036, 28109)}, { AOM_CDF4(12495, 20947, 26650)}, + { AOM_CDF4(12442, 20326, 26214)} + } + }, + { + { + { AOM_CDF4(12162, 18785, 22648)}, { AOM_CDF4(12749, 19697, 23806)}, + { AOM_CDF4(8580, 15297, 20346)}, { AOM_CDF4(6169, 11749, 16543)}, + { AOM_CDF4(4836, 9391, 13448)}, { AOM_CDF4(3821, 7711, 11613)}, + { AOM_CDF4(2228, 4601, 7070)}, { AOM_CDF4(16319, 24725, 28280)}, + { AOM_CDF4(15698, 23277, 27168)}, { AOM_CDF4(12726, 20368, 25047)}, + { AOM_CDF4(9912, 17015, 21976)}, { AOM_CDF4(7888, 14220, 19179)}, + { AOM_CDF4(6777, 12284, 17018)}, { AOM_CDF4(4492, 8590, 12252)}, + { AOM_CDF4(23249, 28904, 30947)}, { AOM_CDF4(21050, 27908, 30512)}, + { AOM_CDF4(17440, 25340, 28949)}, { AOM_CDF4(14059, 22018, 26541)}, + { AOM_CDF4(11288, 18903, 23898)}, { AOM_CDF4(9411, 16342, 21428)}, + { AOM_CDF4(6278, 11588, 15944)} + }, + { + { AOM_CDF4(13981, 20067, 23226)}, { AOM_CDF4(16922, 23580, 26783)}, + { AOM_CDF4(11005, 19039, 24487)}, { AOM_CDF4(7389, 14218, 19798)}, + { AOM_CDF4(5598, 11505, 17206)}, { AOM_CDF4(6090, 11213, 15659)}, + { AOM_CDF4(3820, 7371, 10119)}, { AOM_CDF4(21082, 26925, 29675)}, + { AOM_CDF4(21262, 28627, 31128)}, { AOM_CDF4(18392, 26454, 30437)}, + { AOM_CDF4(14870, 22910, 27096)}, { AOM_CDF4(12620, 19484, 24908)}, + { AOM_CDF4(9290, 16553, 22802)}, { AOM_CDF4(6668, 14288, 20004)}, + { AOM_CDF4(27704, 31055, 31949)}, { AOM_CDF4(24709, 29978, 31788)}, + { AOM_CDF4(21668, 29264, 31657)}, { AOM_CDF4(18295, 26968, 30074)}, + { AOM_CDF4(16399, 24422, 29313)}, { AOM_CDF4(14347, 23026, 28104)}, + { AOM_CDF4(12370, 19806, 24477)} + } + }, + { + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)} + } + } + } +}; + +static const u16 av1_default_coeff_base_multi_cdfs + [TOKEN_CDF_Q_CTXS][TX_SIZES][PLANE_TYPES] + [SIG_COEF_CONTEXTS][CDF_SIZE(NUM_BASE_LEVELS + 2) + 1] = { + { + { + { + { AOM_CDF4(4034, 8930, 12727)}, { AOM_CDF4(18082, 29741, 31877)}, + { AOM_CDF4(12596, 26124, 30493)}, { AOM_CDF4(9446, 21118, 27005)}, + { AOM_CDF4(6308, 15141, 21279)}, { AOM_CDF4(2463, 6357, 9783)}, + { AOM_CDF4(20667, 30546, 31929)}, { AOM_CDF4(13043, 26123, 30134)}, + { AOM_CDF4(8151, 18757, 24778)}, { AOM_CDF4(5255, 12839, 18632)}, + { AOM_CDF4(2820, 7206, 11161)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(15736, 27553, 30604)}, + { AOM_CDF4(11210, 23794, 28787)}, { AOM_CDF4(5947, 13874, 19701)}, + { AOM_CDF4(4215, 9323, 13891)}, { AOM_CDF4(2833, 6462, 10059)}, + { AOM_CDF4(19605, 30393, 31582)}, { AOM_CDF4(13523, 26252, 30248)}, + { AOM_CDF4(8446, 18622, 24512)}, { AOM_CDF4(3818, 10343, 15974)}, + { AOM_CDF4(1481, 4117, 6796)}, { AOM_CDF4(22649, 31302, 32190)}, + { AOM_CDF4(14829, 27127, 30449)}, { AOM_CDF4(8313, 17702, 23304)}, + { AOM_CDF4(3022, 8301, 12786)}, { AOM_CDF4(1536, 4412, 7184)}, + { AOM_CDF4(22354, 29774, 31372)}, { AOM_CDF4(14723, 25472, 29214)}, + { AOM_CDF4(6673, 13745, 18662)}, { AOM_CDF4(2068, 5766, 9322)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(6302, 16444, 21761)}, { AOM_CDF4(23040, 31538, 32475)}, + { AOM_CDF4(15196, 28452, 31496)}, { AOM_CDF4(10020, 22946, 28514)}, + { AOM_CDF4(6533, 16862, 23501)}, { AOM_CDF4(3538, 9816, 15076)}, + { AOM_CDF4(24444, 31875, 32525)}, { AOM_CDF4(15881, 28924, 31635)}, + { AOM_CDF4(9922, 22873, 28466)}, { AOM_CDF4(6527, 16966, 23691)}, + { AOM_CDF4(4114, 11303, 17220)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(20201, 30770, 32209)}, + { AOM_CDF4(14754, 28071, 31258)}, { AOM_CDF4(8378, 20186, 26517)}, + { AOM_CDF4(5916, 15299, 21978)}, { AOM_CDF4(4268, 11583, 17901)}, + { AOM_CDF4(24361, 32025, 32581)}, { AOM_CDF4(18673, 30105, 31943)}, + { AOM_CDF4(10196, 22244, 27576)}, { AOM_CDF4(5495, 14349, 20417)}, + { AOM_CDF4(2676, 7415, 11498)}, { AOM_CDF4(24678, 31958, 32585)}, + { AOM_CDF4(18629, 29906, 31831)}, { AOM_CDF4(9364, 20724, 26315)}, + { AOM_CDF4(4641, 12318, 18094)}, { AOM_CDF4(2758, 7387, 11579)}, + { AOM_CDF4(25433, 31842, 32469)}, { AOM_CDF4(18795, 29289, 31411)}, + { AOM_CDF4(7644, 17584, 23592)}, { AOM_CDF4(3408, 9014, 15047)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(4536, 10072, 14001)}, { AOM_CDF4(25459, 31416, 32206)}, + { AOM_CDF4(16605, 28048, 30818)}, { AOM_CDF4(11008, 22857, 27719)}, + { AOM_CDF4(6915, 16268, 22315)}, { AOM_CDF4(2625, 6812, 10537)}, + { AOM_CDF4(24257, 31788, 32499)}, { AOM_CDF4(16880, 29454, 31879)}, + { AOM_CDF4(11958, 25054, 29778)}, { AOM_CDF4(7916, 18718, 25084)}, + { AOM_CDF4(3383, 8777, 13446)}, { AOM_CDF4(22720, 31603, 32393)}, + { AOM_CDF4(14960, 28125, 31335)}, { AOM_CDF4(9731, 22210, 27928)}, + { AOM_CDF4(6304, 15832, 22277)}, { AOM_CDF4(2910, 7818, 12166)}, + { AOM_CDF4(20375, 30627, 32131)}, { AOM_CDF4(13904, 27284, 30887)}, + { AOM_CDF4(9368, 21558, 27144)}, { AOM_CDF4(5937, 14966, 21119)}, + { AOM_CDF4(2667, 7225, 11319)}, { AOM_CDF4(23970, 31470, 32378)}, + { AOM_CDF4(17173, 29734, 32018)}, { AOM_CDF4(12795, 25441, 29965)}, + { AOM_CDF4(8981, 19680, 25893)}, { AOM_CDF4(4728, 11372, 16902)}, + { AOM_CDF4(24287, 31797, 32439)}, { AOM_CDF4(16703, 29145, 31696)}, + { AOM_CDF4(10833, 23554, 28725)}, { AOM_CDF4(6468, 16566, 23057)}, + { AOM_CDF4(2415, 6562, 10278)}, { AOM_CDF4(26610, 32395, 32659)}, + { AOM_CDF4(18590, 30498, 32117)}, { AOM_CDF4(12420, 25756, 29950)}, + { AOM_CDF4(7639, 18746, 24710)}, { AOM_CDF4(3001, 8086, 12347)}, + { AOM_CDF4(25076, 32064, 32580)}, { AOM_CDF4(17946, 30128, 32028)}, + { AOM_CDF4(12024, 24985, 29378)}, { AOM_CDF4(7517, 18390, 24304)}, + { AOM_CDF4(3243, 8781, 13331)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(6037, 16771, 21957)}, { AOM_CDF4(24774, 31704, 32426)}, + { AOM_CDF4(16830, 28589, 31056)}, { AOM_CDF4(10602, 22828, 27760)}, + { AOM_CDF4(6733, 16829, 23071)}, { AOM_CDF4(3250, 8914, 13556)}, + { AOM_CDF4(25582, 32220, 32668)}, { AOM_CDF4(18659, 30342, 32223)}, + { AOM_CDF4(12546, 26149, 30515)}, { AOM_CDF4(8420, 20451, 26801)}, + { AOM_CDF4(4636, 12420, 18344)}, { AOM_CDF4(27581, 32362, 32639)}, + { AOM_CDF4(18987, 30083, 31978)}, { AOM_CDF4(11327, 24248, 29084)}, + { AOM_CDF4(7264, 17719, 24120)}, { AOM_CDF4(3995, 10768, 16169)}, + { AOM_CDF4(25893, 31831, 32487)}, { AOM_CDF4(16577, 28587, 31379)}, + { AOM_CDF4(10189, 22748, 28182)}, { AOM_CDF4(6832, 17094, 23556)}, + { AOM_CDF4(3708, 10110, 15334)}, { AOM_CDF4(25904, 32282, 32656)}, + { AOM_CDF4(19721, 30792, 32276)}, { AOM_CDF4(12819, 26243, 30411)}, + { AOM_CDF4(8572, 20614, 26891)}, { AOM_CDF4(5364, 14059, 20467)}, + { AOM_CDF4(26580, 32438, 32677)}, { AOM_CDF4(20852, 31225, 32340)}, + { AOM_CDF4(12435, 25700, 29967)}, { AOM_CDF4(8691, 20825, 26976)}, + { AOM_CDF4(4446, 12209, 17269)}, { AOM_CDF4(27350, 32429, 32696)}, + { AOM_CDF4(21372, 30977, 32272)}, { AOM_CDF4(12673, 25270, 29853)}, + { AOM_CDF4(9208, 20925, 26640)}, { AOM_CDF4(5018, 13351, 18732)}, + { AOM_CDF4(27351, 32479, 32713)}, { AOM_CDF4(21398, 31209, 32387)}, + { AOM_CDF4(12162, 25047, 29842)}, { AOM_CDF4(7896, 18691, 25319)}, + { AOM_CDF4(4670, 12882, 18881)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(5487, 10460, 13708)}, { AOM_CDF4(21597, 28303, 30674)}, + { AOM_CDF4(11037, 21953, 26476)}, { AOM_CDF4(8147, 17962, 22952)}, + { AOM_CDF4(5242, 13061, 18532)}, { AOM_CDF4(1889, 5208, 8182)}, + { AOM_CDF4(26774, 32133, 32590)}, { AOM_CDF4(17844, 29564, 31767)}, + { AOM_CDF4(11690, 24438, 29171)}, { AOM_CDF4(7542, 18215, 24459)}, + { AOM_CDF4(2993, 8050, 12319)}, { AOM_CDF4(28023, 32328, 32591)}, + { AOM_CDF4(18651, 30126, 31954)}, { AOM_CDF4(12164, 25146, 29589)}, + { AOM_CDF4(7762, 18530, 24771)}, { AOM_CDF4(3492, 9183, 13920)}, + { AOM_CDF4(27591, 32008, 32491)}, { AOM_CDF4(17149, 28853, 31510)}, + { AOM_CDF4(11485, 24003, 28860)}, { AOM_CDF4(7697, 18086, 24210)}, + { AOM_CDF4(3075, 7999, 12218)}, { AOM_CDF4(28268, 32482, 32654)}, + { AOM_CDF4(19631, 31051, 32404)}, { AOM_CDF4(13860, 27260, 31020)}, + { AOM_CDF4(9605, 21613, 27594)}, { AOM_CDF4(4876, 12162, 17908)}, + { AOM_CDF4(27248, 32316, 32576)}, { AOM_CDF4(18955, 30457, 32075)}, + { AOM_CDF4(11824, 23997, 28795)}, { AOM_CDF4(7346, 18196, 24647)}, + { AOM_CDF4(3403, 9247, 14111)}, { AOM_CDF4(29711, 32655, 32735)}, + { AOM_CDF4(21169, 31394, 32417)}, { AOM_CDF4(13487, 27198, 30957)}, + { AOM_CDF4(8828, 21683, 27614)}, { AOM_CDF4(4270, 11451, 17038)}, + { AOM_CDF4(28708, 32578, 32731)}, { AOM_CDF4(20120, 31241, 32482)}, + { AOM_CDF4(13692, 27550, 31321)}, { AOM_CDF4(9418, 22514, 28439)}, + { AOM_CDF4(4999, 13283, 19462)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(5673, 14302, 19711)}, { AOM_CDF4(26251, 30701, 31834)}, + { AOM_CDF4(12782, 23783, 27803)}, { AOM_CDF4(9127, 20657, 25808)}, + { AOM_CDF4(6368, 16208, 21462)}, { AOM_CDF4(2465, 7177, 10822)}, + { AOM_CDF4(29961, 32563, 32719)}, { AOM_CDF4(18318, 29891, 31949)}, + { AOM_CDF4(11361, 24514, 29357)}, { AOM_CDF4(7900, 19603, 25607)}, + { AOM_CDF4(4002, 10590, 15546)}, { AOM_CDF4(29637, 32310, 32595)}, + { AOM_CDF4(18296, 29913, 31809)}, { AOM_CDF4(10144, 21515, 26871)}, + { AOM_CDF4(5358, 14322, 20394)}, { AOM_CDF4(3067, 8362, 13346)}, + { AOM_CDF4(28652, 32470, 32676)}, { AOM_CDF4(17538, 30771, 32209)}, + { AOM_CDF4(13924, 26882, 30494)}, { AOM_CDF4(10496, 22837, 27869)}, + { AOM_CDF4(7236, 16396, 21621)}, { AOM_CDF4(30743, 32687, 32746)}, + { AOM_CDF4(23006, 31676, 32489)}, { AOM_CDF4(14494, 27828, 31120)}, + { AOM_CDF4(10174, 22801, 28352)}, { AOM_CDF4(6242, 15281, 21043)}, + { AOM_CDF4(25817, 32243, 32720)}, { AOM_CDF4(18618, 31367, 32325)}, + { AOM_CDF4(13997, 28318, 31878)}, { AOM_CDF4(12255, 26534, 31383)}, + { AOM_CDF4(9561, 21588, 28450)}, { AOM_CDF4(28188, 32635, 32724)}, + { AOM_CDF4(22060, 32365, 32728)}, { AOM_CDF4(18102, 30690, 32528)}, + { AOM_CDF4(14196, 28864, 31999)}, { AOM_CDF4(12262, 25792, 30865)}, + { AOM_CDF4(24176, 32109, 32628)}, { AOM_CDF4(18280, 29681, 31963)}, + { AOM_CDF4(10205, 23703, 29664)}, { AOM_CDF4(7889, 20025, 27676)}, + { AOM_CDF4(6060, 16743, 23970)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(5141, 7096, 8260)}, { AOM_CDF4(27186, 29022, 29789)}, + { AOM_CDF4(6668, 12568, 15682)}, { AOM_CDF4(2172, 6181, 8638)}, + { AOM_CDF4(1126, 3379, 4531)}, { AOM_CDF4(443, 1361, 2254)}, + { AOM_CDF4(26083, 31153, 32436)}, { AOM_CDF4(13486, 24603, 28483)}, + { AOM_CDF4(6508, 14840, 19910)}, { AOM_CDF4(3386, 8800, 13286)}, + { AOM_CDF4(1530, 4322, 7054)}, { AOM_CDF4(29639, 32080, 32548)}, + { AOM_CDF4(15897, 27552, 30290)}, { AOM_CDF4(8588, 20047, 25383)}, + { AOM_CDF4(4889, 13339, 19269)}, { AOM_CDF4(2240, 6871, 10498)}, + { AOM_CDF4(28165, 32197, 32517)}, { AOM_CDF4(20735, 30427, 31568)}, + { AOM_CDF4(14325, 24671, 27692)}, { AOM_CDF4(5119, 12554, 17805)}, + { AOM_CDF4(1810, 5441, 8261)}, { AOM_CDF4(31212, 32724, 32748)}, + { AOM_CDF4(23352, 31766, 32545)}, { AOM_CDF4(14669, 27570, 31059)}, + { AOM_CDF4(8492, 20894, 27272)}, { AOM_CDF4(3644, 10194, 15204)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(2461, 7013, 9371)}, { AOM_CDF4(24749, 29600, 30986)}, + { AOM_CDF4(9466, 19037, 22417)}, { AOM_CDF4(3584, 9280, 14400)}, + { AOM_CDF4(1505, 3929, 5433)}, { AOM_CDF4(677, 1500, 2736)}, + { AOM_CDF4(23987, 30702, 32117)}, { AOM_CDF4(13554, 24571, 29263)}, + { AOM_CDF4(6211, 14556, 21155)}, { AOM_CDF4(3135, 10972, 15625)}, + { AOM_CDF4(2435, 7127, 11427)}, { AOM_CDF4(31300, 32532, 32550)}, + { AOM_CDF4(14757, 30365, 31954)}, { AOM_CDF4(4405, 11612, 18553)}, + { AOM_CDF4(580, 4132, 7322)}, { AOM_CDF4(1695, 10169, 14124)}, + { AOM_CDF4(30008, 32282, 32591)}, { AOM_CDF4(19244, 30108, 31748)}, + { AOM_CDF4(11180, 24158, 29555)}, { AOM_CDF4(5650, 14972, 19209)}, + { AOM_CDF4(2114, 5109, 8456)}, { AOM_CDF4(31856, 32716, 32748)}, + { AOM_CDF4(23012, 31664, 32572)}, { AOM_CDF4(13694, 26656, 30636)}, + { AOM_CDF4(8142, 19508, 26093)}, { AOM_CDF4(4253, 10955, 16724)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(601, 983, 1311)}, { AOM_CDF4(18725, 23406, 28087)}, + { AOM_CDF4(5461, 8192, 10923)}, { AOM_CDF4(3781, 15124, 21425)}, + { AOM_CDF4(2587, 7761, 12072)}, { AOM_CDF4(106, 458, 810)}, + { AOM_CDF4(22282, 29710, 31894)}, { AOM_CDF4(8508, 20926, 25984)}, + { AOM_CDF4(3726, 12713, 18083)}, { AOM_CDF4(1620, 7112, 10893)}, + { AOM_CDF4(729, 2236, 3495)}, { AOM_CDF4(30163, 32474, 32684)}, + { AOM_CDF4(18304, 30464, 32000)}, { AOM_CDF4(11443, 26526, 29647)}, + { AOM_CDF4(6007, 15292, 21299)}, { AOM_CDF4(2234, 6703, 8937)}, + { AOM_CDF4(30954, 32177, 32571)}, { AOM_CDF4(17363, 29562, 31076)}, + { AOM_CDF4(9686, 22464, 27410)}, { AOM_CDF4(8192, 16384, 21390)}, + { AOM_CDF4(1755, 8046, 11264)}, { AOM_CDF4(31168, 32734, 32748)}, + { AOM_CDF4(22486, 31441, 32471)}, { AOM_CDF4(12833, 25627, 29738)}, + { AOM_CDF4(6980, 17379, 23122)}, { AOM_CDF4(3111, 8887, 13479)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + } + }, + { + { + { + { AOM_CDF4(6041, 11854, 15927)}, { AOM_CDF4(20326, 30905, 32251)}, + { AOM_CDF4(14164, 26831, 30725)}, { AOM_CDF4(9760, 20647, 26585)}, + { AOM_CDF4(6416, 14953, 21219)}, { AOM_CDF4(2966, 7151, 10891)}, + { AOM_CDF4(23567, 31374, 32254)}, { AOM_CDF4(14978, 27416, 30946)}, + { AOM_CDF4(9434, 20225, 26254)}, { AOM_CDF4(6658, 14558, 20535)}, + { AOM_CDF4(3916, 8677, 12989)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(18088, 29545, 31587)}, + { AOM_CDF4(13062, 25843, 30073)}, { AOM_CDF4(8940, 16827, 22251)}, + { AOM_CDF4(7654, 13220, 17973)}, { AOM_CDF4(5733, 10316, 14456)}, + { AOM_CDF4(22879, 31388, 32114)}, { AOM_CDF4(15215, 27993, 30955)}, + { AOM_CDF4(9397, 19445, 24978)}, { AOM_CDF4(3442, 9813, 15344)}, + { AOM_CDF4(1368, 3936, 6532)}, { AOM_CDF4(25494, 32033, 32406)}, + { AOM_CDF4(16772, 27963, 30718)}, { AOM_CDF4(9419, 18165, 23260)}, + { AOM_CDF4(2677, 7501, 11797)}, { AOM_CDF4(1516, 4344, 7170)}, + { AOM_CDF4(26556, 31454, 32101)}, { AOM_CDF4(17128, 27035, 30108)}, + { AOM_CDF4(8324, 15344, 20249)}, { AOM_CDF4(1903, 5696, 9469)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8455, 19003, 24368)}, { AOM_CDF4(23563, 32021, 32604)}, + { AOM_CDF4(16237, 29446, 31935)}, { AOM_CDF4(10724, 23999, 29358)}, + { AOM_CDF4(6725, 17528, 24416)}, { AOM_CDF4(3927, 10927, 16825)}, + { AOM_CDF4(26313, 32288, 32634)}, { AOM_CDF4(17430, 30095, 32095)}, + { AOM_CDF4(11116, 24606, 29679)}, { AOM_CDF4(7195, 18384, 25269)}, + { AOM_CDF4(4726, 12852, 19315)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(22822, 31648, 32483)}, + { AOM_CDF4(16724, 29633, 31929)}, { AOM_CDF4(10261, 23033, 28725)}, + { AOM_CDF4(7029, 17840, 24528)}, { AOM_CDF4(4867, 13886, 21502)}, + { AOM_CDF4(25298, 31892, 32491)}, { AOM_CDF4(17809, 29330, 31512)}, + { AOM_CDF4(9668, 21329, 26579)}, { AOM_CDF4(4774, 12956, 18976)}, + { AOM_CDF4(2322, 7030, 11540)}, { AOM_CDF4(25472, 31920, 32543)}, + { AOM_CDF4(17957, 29387, 31632)}, { AOM_CDF4(9196, 20593, 26400)}, + { AOM_CDF4(4680, 12705, 19202)}, { AOM_CDF4(2917, 8456, 13436)}, + { AOM_CDF4(26471, 32059, 32574)}, { AOM_CDF4(18458, 29783, 31909)}, + { AOM_CDF4(8400, 19464, 25956)}, { AOM_CDF4(3812, 10973, 17206)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(6779, 13743, 17678)}, { AOM_CDF4(24806, 31797, 32457)}, + { AOM_CDF4(17616, 29047, 31372)}, { AOM_CDF4(11063, 23175, 28003)}, + { AOM_CDF4(6521, 16110, 22324)}, { AOM_CDF4(2764, 7504, 11654)}, + { AOM_CDF4(25266, 32367, 32637)}, { AOM_CDF4(19054, 30553, 32175)}, + { AOM_CDF4(12139, 25212, 29807)}, { AOM_CDF4(7311, 18162, 24704)}, + { AOM_CDF4(3397, 9164, 14074)}, { AOM_CDF4(25988, 32208, 32522)}, + { AOM_CDF4(16253, 28912, 31526)}, { AOM_CDF4(9151, 21387, 27372)}, + { AOM_CDF4(5688, 14915, 21496)}, { AOM_CDF4(2717, 7627, 12004)}, + { AOM_CDF4(23144, 31855, 32443)}, { AOM_CDF4(16070, 28491, 31325)}, + { AOM_CDF4(8702, 20467, 26517)}, { AOM_CDF4(5243, 13956, 20367)}, + { AOM_CDF4(2621, 7335, 11567)}, { AOM_CDF4(26636, 32340, 32630)}, + { AOM_CDF4(19990, 31050, 32341)}, { AOM_CDF4(13243, 26105, 30315)}, + { AOM_CDF4(8588, 19521, 25918)}, { AOM_CDF4(4717, 11585, 17304)}, + { AOM_CDF4(25844, 32292, 32582)}, { AOM_CDF4(19090, 30635, 32097)}, + { AOM_CDF4(11963, 24546, 28939)}, { AOM_CDF4(6218, 16087, 22354)}, + { AOM_CDF4(2340, 6608, 10426)}, { AOM_CDF4(28046, 32576, 32694)}, + { AOM_CDF4(21178, 31313, 32296)}, { AOM_CDF4(13486, 26184, 29870)}, + { AOM_CDF4(7149, 17871, 23723)}, { AOM_CDF4(2833, 7958, 12259)}, + { AOM_CDF4(27710, 32528, 32686)}, { AOM_CDF4(20674, 31076, 32268)}, + { AOM_CDF4(12413, 24955, 29243)}, { AOM_CDF4(6676, 16927, 23097)}, + { AOM_CDF4(2966, 8333, 12919)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8639, 19339, 24429)}, { AOM_CDF4(24404, 31837, 32525)}, + { AOM_CDF4(16997, 29425, 31784)}, { AOM_CDF4(11253, 24234, 29149)}, + { AOM_CDF4(6751, 17394, 24028)}, { AOM_CDF4(3490, 9830, 15191)}, + { AOM_CDF4(26283, 32471, 32714)}, { AOM_CDF4(19599, 31168, 32442)}, + { AOM_CDF4(13146, 26954, 30893)}, { AOM_CDF4(8214, 20588, 26890)}, + { AOM_CDF4(4699, 13081, 19300)}, { AOM_CDF4(28212, 32458, 32669)}, + { AOM_CDF4(18594, 30316, 32100)}, { AOM_CDF4(11219, 24408, 29234)}, + { AOM_CDF4(6865, 17656, 24149)}, { AOM_CDF4(3678, 10362, 16006)}, + { AOM_CDF4(25825, 32136, 32616)}, { AOM_CDF4(17313, 29853, 32021)}, + { AOM_CDF4(11197, 24471, 29472)}, { AOM_CDF4(6947, 17781, 24405)}, + { AOM_CDF4(3768, 10660, 16261)}, { AOM_CDF4(27352, 32500, 32706)}, + { AOM_CDF4(20850, 31468, 32469)}, { AOM_CDF4(14021, 27707, 31133)}, + { AOM_CDF4(8964, 21748, 27838)}, { AOM_CDF4(5437, 14665, 21187)}, + { AOM_CDF4(26304, 32492, 32698)}, { AOM_CDF4(20409, 31380, 32385)}, + { AOM_CDF4(13682, 27222, 30632)}, { AOM_CDF4(8974, 21236, 26685)}, + { AOM_CDF4(4234, 11665, 16934)}, { AOM_CDF4(26273, 32357, 32711)}, + { AOM_CDF4(20672, 31242, 32441)}, { AOM_CDF4(14172, 27254, 30902)}, + { AOM_CDF4(9870, 21898, 27275)}, { AOM_CDF4(5164, 13506, 19270)}, + { AOM_CDF4(26725, 32459, 32728)}, { AOM_CDF4(20991, 31442, 32527)}, + { AOM_CDF4(13071, 26434, 30811)}, { AOM_CDF4(8184, 20090, 26742)}, + { AOM_CDF4(4803, 13255, 19895)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(7555, 14942, 18501)}, { AOM_CDF4(24410, 31178, 32287)}, + { AOM_CDF4(14394, 26738, 30253)}, { AOM_CDF4(8413, 19554, 25195)}, + { AOM_CDF4(4766, 12924, 18785)}, { AOM_CDF4(2029, 5806, 9207)}, + { AOM_CDF4(26776, 32364, 32663)}, { AOM_CDF4(18732, 29967, 31931)}, + { AOM_CDF4(11005, 23786, 28852)}, { AOM_CDF4(6466, 16909, 23510)}, + { AOM_CDF4(3044, 8638, 13419)}, { AOM_CDF4(29208, 32582, 32704)}, + { AOM_CDF4(20068, 30857, 32208)}, { AOM_CDF4(12003, 25085, 29595)}, + { AOM_CDF4(6947, 17750, 24189)}, { AOM_CDF4(3245, 9103, 14007)}, + { AOM_CDF4(27359, 32465, 32669)}, { AOM_CDF4(19421, 30614, 32174)}, + { AOM_CDF4(11915, 25010, 29579)}, { AOM_CDF4(6950, 17676, 24074)}, + { AOM_CDF4(3007, 8473, 13096)}, { AOM_CDF4(29002, 32676, 32735)}, + { AOM_CDF4(22102, 31849, 32576)}, { AOM_CDF4(14408, 28009, 31405)}, + { AOM_CDF4(9027, 21679, 27931)}, { AOM_CDF4(4694, 12678, 18748)}, + { AOM_CDF4(28216, 32528, 32682)}, { AOM_CDF4(20849, 31264, 32318)}, + { AOM_CDF4(12756, 25815, 29751)}, { AOM_CDF4(7565, 18801, 24923)}, + { AOM_CDF4(3509, 9533, 14477)}, { AOM_CDF4(30133, 32687, 32739)}, + { AOM_CDF4(23063, 31910, 32515)}, { AOM_CDF4(14588, 28051, 31132)}, + { AOM_CDF4(9085, 21649, 27457)}, { AOM_CDF4(4261, 11654, 17264)}, + { AOM_CDF4(29518, 32691, 32748)}, { AOM_CDF4(22451, 31959, 32613)}, + { AOM_CDF4(14864, 28722, 31700)}, { AOM_CDF4(9695, 22964, 28716)}, + { AOM_CDF4(4932, 13358, 19502)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(6465, 16958, 21688)}, { AOM_CDF4(25199, 31514, 32360)}, + { AOM_CDF4(14774, 27149, 30607)}, { AOM_CDF4(9257, 21438, 26972)}, + { AOM_CDF4(5723, 15183, 21882)}, { AOM_CDF4(3150, 8879, 13731)}, + { AOM_CDF4(26989, 32262, 32682)}, { AOM_CDF4(17396, 29937, 32085)}, + { AOM_CDF4(11387, 24901, 29784)}, { AOM_CDF4(7289, 18821, 25548)}, + { AOM_CDF4(3734, 10577, 16086)}, { AOM_CDF4(29728, 32501, 32695)}, + { AOM_CDF4(17431, 29701, 31903)}, { AOM_CDF4(9921, 22826, 28300)}, + { AOM_CDF4(5896, 15434, 22068)}, { AOM_CDF4(3430, 9646, 14757)}, + { AOM_CDF4(28614, 32511, 32705)}, { AOM_CDF4(19364, 30638, 32263)}, + { AOM_CDF4(13129, 26254, 30402)}, { AOM_CDF4(8754, 20484, 26440)}, + { AOM_CDF4(4378, 11607, 17110)}, { AOM_CDF4(30292, 32671, 32744)}, + { AOM_CDF4(21780, 31603, 32501)}, { AOM_CDF4(14314, 27829, 31291)}, + { AOM_CDF4(9611, 22327, 28263)}, { AOM_CDF4(4890, 13087, 19065)}, + { AOM_CDF4(25862, 32567, 32733)}, { AOM_CDF4(20794, 32050, 32567)}, + { AOM_CDF4(17243, 30625, 32254)}, { AOM_CDF4(13283, 27628, 31474)}, + { AOM_CDF4(9669, 22532, 28918)}, { AOM_CDF4(27435, 32697, 32748)}, + { AOM_CDF4(24922, 32390, 32714)}, { AOM_CDF4(21449, 31504, 32536)}, + { AOM_CDF4(16392, 29729, 31832)}, { AOM_CDF4(11692, 24884, 29076)}, + { AOM_CDF4(24193, 32290, 32735)}, { AOM_CDF4(18909, 31104, 32563)}, + { AOM_CDF4(12236, 26841, 31403)}, { AOM_CDF4(8171, 21840, 29082)}, + { AOM_CDF4(7224, 17280, 25275)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(3078, 6839, 9890)}, { AOM_CDF4(13837, 20450, 24479)}, + { AOM_CDF4(5914, 14222, 19328)}, { AOM_CDF4(3866, 10267, 14762)}, + { AOM_CDF4(2612, 7208, 11042)}, { AOM_CDF4(1067, 2991, 4776)}, + { AOM_CDF4(25817, 31646, 32529)}, { AOM_CDF4(13708, 26338, 30385)}, + { AOM_CDF4(7328, 18585, 24870)}, { AOM_CDF4(4691, 13080, 19276)}, + { AOM_CDF4(1825, 5253, 8352)}, { AOM_CDF4(29386, 32315, 32624)}, + { AOM_CDF4(17160, 29001, 31360)}, { AOM_CDF4(9602, 21862, 27396)}, + { AOM_CDF4(5915, 15772, 22148)}, { AOM_CDF4(2786, 7779, 12047)}, + { AOM_CDF4(29246, 32450, 32663)}, { AOM_CDF4(18696, 29929, 31818)}, + { AOM_CDF4(10510, 23369, 28560)}, { AOM_CDF4(6229, 16499, 23125)}, + { AOM_CDF4(2608, 7448, 11705)}, { AOM_CDF4(30753, 32710, 32748)}, + { AOM_CDF4(21638, 31487, 32503)}, { AOM_CDF4(12937, 26854, 30870)}, + { AOM_CDF4(8182, 20596, 26970)}, { AOM_CDF4(3637, 10269, 15497)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(5244, 12150, 16906)}, { AOM_CDF4(20486, 26858, 29701)}, + { AOM_CDF4(7756, 18317, 23735)}, { AOM_CDF4(3452, 9256, 13146)}, + { AOM_CDF4(2020, 5206, 8229)}, { AOM_CDF4(1801, 4993, 7903)}, + { AOM_CDF4(27051, 31858, 32531)}, { AOM_CDF4(15988, 27531, 30619)}, + { AOM_CDF4(9188, 21484, 26719)}, { AOM_CDF4(6273, 17186, 23800)}, + { AOM_CDF4(3108, 9355, 14764)}, { AOM_CDF4(31076, 32520, 32680)}, + { AOM_CDF4(18119, 30037, 31850)}, { AOM_CDF4(10244, 22969, 27472)}, + { AOM_CDF4(4692, 14077, 19273)}, { AOM_CDF4(3694, 11677, 17556)}, + { AOM_CDF4(30060, 32581, 32720)}, { AOM_CDF4(21011, 30775, 32120)}, + { AOM_CDF4(11931, 24820, 29289)}, { AOM_CDF4(7119, 17662, 24356)}, + { AOM_CDF4(3833, 10706, 16304)}, { AOM_CDF4(31954, 32731, 32748)}, + { AOM_CDF4(23913, 31724, 32489)}, { AOM_CDF4(15520, 28060, 31286)}, + { AOM_CDF4(11517, 23008, 28571)}, { AOM_CDF4(6193, 14508, 20629)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(1035, 2807, 4156)}, { AOM_CDF4(13162, 18138, 20939)}, + { AOM_CDF4(2696, 6633, 8755)}, { AOM_CDF4(1373, 4161, 6853)}, + { AOM_CDF4(1099, 2746, 4716)}, { AOM_CDF4(340, 1021, 1599)}, + { AOM_CDF4(22826, 30419, 32135)}, { AOM_CDF4(10395, 21762, 26942)}, + { AOM_CDF4(4726, 12407, 17361)}, { AOM_CDF4(2447, 7080, 10593)}, + { AOM_CDF4(1227, 3717, 6011)}, { AOM_CDF4(28156, 31424, 31934)}, + { AOM_CDF4(16915, 27754, 30373)}, { AOM_CDF4(9148, 20990, 26431)}, + { AOM_CDF4(5950, 15515, 21148)}, { AOM_CDF4(2492, 7327, 11526)}, + { AOM_CDF4(30602, 32477, 32670)}, { AOM_CDF4(20026, 29955, 31568)}, + { AOM_CDF4(11220, 23628, 28105)}, { AOM_CDF4(6652, 17019, 22973)}, + { AOM_CDF4(3064, 8536, 13043)}, { AOM_CDF4(31769, 32724, 32748)}, + { AOM_CDF4(22230, 30887, 32373)}, { AOM_CDF4(12234, 25079, 29731)}, + { AOM_CDF4(7326, 18816, 25353)}, { AOM_CDF4(3933, 10907, 16616)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + } + }, + { + { + { + { AOM_CDF4(8896, 16227, 20630)}, { AOM_CDF4(23629, 31782, 32527)}, + { AOM_CDF4(15173, 27755, 31321)}, { AOM_CDF4(10158, 21233, 27382)}, + { AOM_CDF4(6420, 14857, 21558)}, { AOM_CDF4(3269, 8155, 12646)}, + { AOM_CDF4(24835, 32009, 32496)}, { AOM_CDF4(16509, 28421, 31579)}, + { AOM_CDF4(10957, 21514, 27418)}, { AOM_CDF4(7881, 15930, 22096)}, + { AOM_CDF4(5388, 10960, 15918)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(20745, 30773, 32093)}, + { AOM_CDF4(15200, 27221, 30861)}, { AOM_CDF4(13032, 20873, 25667)}, + { AOM_CDF4(12285, 18663, 23494)}, { AOM_CDF4(11563, 17481, 21489)}, + { AOM_CDF4(26260, 31982, 32320)}, { AOM_CDF4(15397, 28083, 31100)}, + { AOM_CDF4(9742, 19217, 24824)}, { AOM_CDF4(3261, 9629, 15362)}, + { AOM_CDF4(1480, 4322, 7499)}, { AOM_CDF4(27599, 32256, 32460)}, + { AOM_CDF4(16857, 27659, 30774)}, { AOM_CDF4(9551, 18290, 23748)}, + { AOM_CDF4(3052, 8933, 14103)}, { AOM_CDF4(2021, 5910, 9787)}, + { AOM_CDF4(29005, 32015, 32392)}, { AOM_CDF4(17677, 27694, 30863)}, + { AOM_CDF4(9204, 17356, 23219)}, { AOM_CDF4(2403, 7516, 12814)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(10808, 22056, 26896)}, { AOM_CDF4(25739, 32313, 32676)}, + { AOM_CDF4(17288, 30203, 32221)}, { AOM_CDF4(11359, 24878, 29896)}, + { AOM_CDF4(6949, 17767, 24893)}, { AOM_CDF4(4287, 11796, 18071)}, + { AOM_CDF4(27880, 32521, 32705)}, { AOM_CDF4(19038, 31004, 32414)}, + { AOM_CDF4(12564, 26345, 30768)}, { AOM_CDF4(8269, 19947, 26779)}, + { AOM_CDF4(5674, 14657, 21674)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(25742, 32319, 32671)}, + { AOM_CDF4(19557, 31164, 32454)}, { AOM_CDF4(13381, 26381, 30755)}, + { AOM_CDF4(10101, 21466, 26722)}, { AOM_CDF4(9209, 19650, 26825)}, + { AOM_CDF4(27107, 31917, 32432)}, { AOM_CDF4(18056, 28893, 31203)}, + { AOM_CDF4(10200, 21434, 26764)}, { AOM_CDF4(4660, 12913, 19502)}, + { AOM_CDF4(2368, 6930, 12504)}, { AOM_CDF4(26960, 32158, 32613)}, + { AOM_CDF4(18628, 30005, 32031)}, { AOM_CDF4(10233, 22442, 28232)}, + { AOM_CDF4(5471, 14630, 21516)}, { AOM_CDF4(3235, 10767, 17109)}, + { AOM_CDF4(27696, 32440, 32692)}, { AOM_CDF4(20032, 31167, 32438)}, + { AOM_CDF4(8700, 21341, 28442)}, { AOM_CDF4(5662, 14831, 21795)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(9704, 17294, 21132)}, { AOM_CDF4(26762, 32278, 32633)}, + { AOM_CDF4(18382, 29620, 31819)}, { AOM_CDF4(10891, 23475, 28723)}, + { AOM_CDF4(6358, 16583, 23309)}, { AOM_CDF4(3248, 9118, 14141)}, + { AOM_CDF4(27204, 32573, 32699)}, { AOM_CDF4(19818, 30824, 32329)}, + { AOM_CDF4(11772, 25120, 30041)}, { AOM_CDF4(6995, 18033, 25039)}, + { AOM_CDF4(3752, 10442, 16098)}, { AOM_CDF4(27222, 32256, 32559)}, + { AOM_CDF4(15356, 28399, 31475)}, { AOM_CDF4(8821, 20635, 27057)}, + { AOM_CDF4(5511, 14404, 21239)}, { AOM_CDF4(2935, 8222, 13051)}, + { AOM_CDF4(24875, 32120, 32529)}, { AOM_CDF4(15233, 28265, 31445)}, + { AOM_CDF4(8605, 20570, 26932)}, { AOM_CDF4(5431, 14413, 21196)}, + { AOM_CDF4(2994, 8341, 13223)}, { AOM_CDF4(28201, 32604, 32700)}, + { AOM_CDF4(21041, 31446, 32456)}, { AOM_CDF4(13221, 26213, 30475)}, + { AOM_CDF4(8255, 19385, 26037)}, { AOM_CDF4(4930, 12585, 18830)}, + { AOM_CDF4(28768, 32448, 32627)}, { AOM_CDF4(19705, 30561, 32021)}, + { AOM_CDF4(11572, 23589, 28220)}, { AOM_CDF4(5532, 15034, 21446)}, + { AOM_CDF4(2460, 7150, 11456)}, { AOM_CDF4(29874, 32619, 32699)}, + { AOM_CDF4(21621, 31071, 32201)}, { AOM_CDF4(12511, 24747, 28992)}, + { AOM_CDF4(6281, 16395, 22748)}, { AOM_CDF4(3246, 9278, 14497)}, + { AOM_CDF4(29715, 32625, 32712)}, { AOM_CDF4(20958, 31011, 32283)}, + { AOM_CDF4(11233, 23671, 28806)}, { AOM_CDF4(6012, 16128, 22868)}, + { AOM_CDF4(3427, 9851, 15414)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(11016, 22111, 26794)}, { AOM_CDF4(25946, 32357, 32677)}, + { AOM_CDF4(17890, 30452, 32252)}, { AOM_CDF4(11678, 25142, 29816)}, + { AOM_CDF4(6720, 17534, 24584)}, { AOM_CDF4(4230, 11665, 17820)}, + { AOM_CDF4(28400, 32623, 32747)}, { AOM_CDF4(21164, 31668, 32575)}, + { AOM_CDF4(13572, 27388, 31182)}, { AOM_CDF4(8234, 20750, 27358)}, + { AOM_CDF4(5065, 14055, 20897)}, { AOM_CDF4(28981, 32547, 32705)}, + { AOM_CDF4(18681, 30543, 32239)}, { AOM_CDF4(10919, 24075, 29286)}, + { AOM_CDF4(6431, 17199, 24077)}, { AOM_CDF4(3819, 10464, 16618)}, + { AOM_CDF4(26870, 32467, 32693)}, { AOM_CDF4(19041, 30831, 32347)}, + { AOM_CDF4(11794, 25211, 30016)}, { AOM_CDF4(6888, 18019, 24970)}, + { AOM_CDF4(4370, 12363, 18992)}, { AOM_CDF4(29578, 32670, 32744)}, + { AOM_CDF4(23159, 32007, 32613)}, { AOM_CDF4(15315, 28669, 31676)}, + { AOM_CDF4(9298, 22607, 28782)}, { AOM_CDF4(6144, 15913, 22968)}, + { AOM_CDF4(28110, 32499, 32669)}, { AOM_CDF4(21574, 30937, 32015)}, + { AOM_CDF4(12759, 24818, 28727)}, { AOM_CDF4(6545, 16761, 23042)}, + { AOM_CDF4(3649, 10597, 16833)}, { AOM_CDF4(28163, 32552, 32728)}, + { AOM_CDF4(22101, 31469, 32464)}, { AOM_CDF4(13160, 25472, 30143)}, + { AOM_CDF4(7303, 18684, 25468)}, { AOM_CDF4(5241, 13975, 20955)}, + { AOM_CDF4(28400, 32631, 32744)}, { AOM_CDF4(22104, 31793, 32603)}, + { AOM_CDF4(13557, 26571, 30846)}, { AOM_CDF4(7749, 19861, 26675)}, + { AOM_CDF4(4873, 14030, 21234)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(9800, 17635, 21073)}, { AOM_CDF4(26153, 31885, 32527)}, + { AOM_CDF4(15038, 27852, 31006)}, { AOM_CDF4(8718, 20564, 26486)}, + { AOM_CDF4(5128, 14076, 20514)}, { AOM_CDF4(2636, 7566, 11925)}, + { AOM_CDF4(27551, 32504, 32701)}, { AOM_CDF4(18310, 30054, 32100)}, + { AOM_CDF4(10211, 23420, 29082)}, { AOM_CDF4(6222, 16876, 23916)}, + { AOM_CDF4(3462, 9954, 15498)}, { AOM_CDF4(29991, 32633, 32721)}, + { AOM_CDF4(19883, 30751, 32201)}, { AOM_CDF4(11141, 24184, 29285)}, + { AOM_CDF4(6420, 16940, 23774)}, { AOM_CDF4(3392, 9753, 15118)}, + { AOM_CDF4(28465, 32616, 32712)}, { AOM_CDF4(19850, 30702, 32244)}, + { AOM_CDF4(10983, 24024, 29223)}, { AOM_CDF4(6294, 16770, 23582)}, + { AOM_CDF4(3244, 9283, 14509)}, { AOM_CDF4(30023, 32717, 32748)}, + { AOM_CDF4(22940, 32032, 32626)}, { AOM_CDF4(14282, 27928, 31473)}, + { AOM_CDF4(8562, 21327, 27914)}, { AOM_CDF4(4846, 13393, 19919)}, + { AOM_CDF4(29981, 32590, 32695)}, { AOM_CDF4(20465, 30963, 32166)}, + { AOM_CDF4(11479, 23579, 28195)}, { AOM_CDF4(5916, 15648, 22073)}, + { AOM_CDF4(3031, 8605, 13398)}, { AOM_CDF4(31146, 32691, 32739)}, + { AOM_CDF4(23106, 31724, 32444)}, { AOM_CDF4(13783, 26738, 30439)}, + { AOM_CDF4(7852, 19468, 25807)}, { AOM_CDF4(3860, 11124, 16853)}, + { AOM_CDF4(31014, 32724, 32748)}, { AOM_CDF4(23629, 32109, 32628)}, + { AOM_CDF4(14747, 28115, 31403)}, { AOM_CDF4(8545, 21242, 27478)}, + { AOM_CDF4(4574, 12781, 19067)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(9185, 19694, 24688)}, { AOM_CDF4(26081, 31985, 32621)}, + { AOM_CDF4(16015, 29000, 31787)}, { AOM_CDF4(10542, 23690, 29206)}, + { AOM_CDF4(6732, 17945, 24677)}, { AOM_CDF4(3916, 11039, 16722)}, + { AOM_CDF4(28224, 32566, 32744)}, { AOM_CDF4(19100, 31138, 32485)}, + { AOM_CDF4(12528, 26620, 30879)}, { AOM_CDF4(7741, 20277, 26885)}, + { AOM_CDF4(4566, 12845, 18990)}, { AOM_CDF4(29933, 32593, 32718)}, + { AOM_CDF4(17670, 30333, 32155)}, { AOM_CDF4(10385, 23600, 28909)}, + { AOM_CDF4(6243, 16236, 22407)}, { AOM_CDF4(3976, 10389, 16017)}, + { AOM_CDF4(28377, 32561, 32738)}, { AOM_CDF4(19366, 31175, 32482)}, + { AOM_CDF4(13327, 27175, 31094)}, { AOM_CDF4(8258, 20769, 27143)}, + { AOM_CDF4(4703, 13198, 19527)}, { AOM_CDF4(31086, 32706, 32748)}, + { AOM_CDF4(22853, 31902, 32583)}, { AOM_CDF4(14759, 28186, 31419)}, + { AOM_CDF4(9284, 22382, 28348)}, { AOM_CDF4(5585, 15192, 21868)}, + { AOM_CDF4(28291, 32652, 32746)}, { AOM_CDF4(19849, 32107, 32571)}, + { AOM_CDF4(14834, 26818, 29214)}, { AOM_CDF4(10306, 22594, 28672)}, + { AOM_CDF4(6615, 17384, 23384)}, { AOM_CDF4(28947, 32604, 32745)}, + { AOM_CDF4(25625, 32289, 32646)}, { AOM_CDF4(18758, 28672, 31403)}, + { AOM_CDF4(10017, 23430, 28523)}, { AOM_CDF4(6862, 15269, 22131)}, + { AOM_CDF4(23933, 32509, 32739)}, { AOM_CDF4(19927, 31495, 32631)}, + { AOM_CDF4(11903, 26023, 30621)}, { AOM_CDF4(7026, 20094, 27252)}, + { AOM_CDF4(5998, 18106, 24437)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(4456, 11274, 15533)}, { AOM_CDF4(21219, 29079, 31616)}, + { AOM_CDF4(11173, 23774, 28567)}, { AOM_CDF4(7282, 18293, 24263)}, + { AOM_CDF4(4890, 13286, 19115)}, { AOM_CDF4(1890, 5508, 8659)}, + { AOM_CDF4(26651, 32136, 32647)}, { AOM_CDF4(14630, 28254, 31455)}, + { AOM_CDF4(8716, 21287, 27395)}, { AOM_CDF4(5615, 15331, 22008)}, + { AOM_CDF4(2675, 7700, 12150)}, { AOM_CDF4(29954, 32526, 32690)}, + { AOM_CDF4(16126, 28982, 31633)}, { AOM_CDF4(9030, 21361, 27352)}, + { AOM_CDF4(5411, 14793, 21271)}, { AOM_CDF4(2943, 8422, 13163)}, + { AOM_CDF4(29539, 32601, 32730)}, { AOM_CDF4(18125, 30385, 32201)}, + { AOM_CDF4(10422, 24090, 29468)}, { AOM_CDF4(6468, 17487, 24438)}, + { AOM_CDF4(2970, 8653, 13531)}, { AOM_CDF4(30912, 32715, 32748)}, + { AOM_CDF4(20666, 31373, 32497)}, { AOM_CDF4(12509, 26640, 30917)}, + { AOM_CDF4(8058, 20629, 27290)}, { AOM_CDF4(4231, 12006, 18052)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(10202, 20633, 25484)}, { AOM_CDF4(27336, 31445, 32352)}, + { AOM_CDF4(12420, 24384, 28552)}, { AOM_CDF4(7648, 18115, 23856)}, + { AOM_CDF4(5662, 14341, 19902)}, { AOM_CDF4(3611, 10328, 15390)}, + { AOM_CDF4(30945, 32616, 32736)}, { AOM_CDF4(18682, 30505, 32253)}, + { AOM_CDF4(11513, 25336, 30203)}, { AOM_CDF4(7449, 19452, 26148)}, + { AOM_CDF4(4482, 13051, 18886)}, { AOM_CDF4(32022, 32690, 32747)}, + { AOM_CDF4(18578, 30501, 32146)}, { AOM_CDF4(11249, 23368, 28631)}, + { AOM_CDF4(5645, 16958, 22158)}, { AOM_CDF4(5009, 11444, 16637)}, + { AOM_CDF4(31357, 32710, 32748)}, { AOM_CDF4(21552, 31494, 32504)}, + { AOM_CDF4(13891, 27677, 31340)}, { AOM_CDF4(9051, 22098, 28172)}, + { AOM_CDF4(5190, 13377, 19486)}, { AOM_CDF4(32364, 32740, 32748)}, + { AOM_CDF4(24839, 31907, 32551)}, { AOM_CDF4(17160, 28779, 31696)}, + { AOM_CDF4(12452, 24137, 29602)}, { AOM_CDF4(6165, 15389, 22477)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(2575, 7281, 11077)}, { AOM_CDF4(14002, 20866, 25402)}, + { AOM_CDF4(6343, 15056, 19658)}, { AOM_CDF4(4474, 11858, 17041)}, + { AOM_CDF4(2865, 8299, 12534)}, { AOM_CDF4(1344, 3949, 6391)}, + { AOM_CDF4(24720, 31239, 32459)}, { AOM_CDF4(12585, 25356, 29968)}, + { AOM_CDF4(7181, 18246, 24444)}, { AOM_CDF4(5025, 13667, 19885)}, + { AOM_CDF4(2521, 7304, 11605)}, { AOM_CDF4(29908, 32252, 32584)}, + { AOM_CDF4(17421, 29156, 31575)}, { AOM_CDF4(9889, 22188, 27782)}, + { AOM_CDF4(5878, 15647, 22123)}, { AOM_CDF4(2814, 8665, 13323)}, + { AOM_CDF4(30183, 32568, 32713)}, { AOM_CDF4(18528, 30195, 32049)}, + { AOM_CDF4(10982, 24606, 29657)}, { AOM_CDF4(6957, 18165, 25231)}, + { AOM_CDF4(3508, 10118, 15468)}, { AOM_CDF4(31761, 32736, 32748)}, + { AOM_CDF4(21041, 31328, 32546)}, { AOM_CDF4(12568, 26732, 31166)}, + { AOM_CDF4(8052, 20720, 27733)}, { AOM_CDF4(4336, 12192, 18396)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + } + }, + { + { + { + { AOM_CDF4(7062, 16472, 22319)}, { AOM_CDF4(24538, 32261, 32674)}, + { AOM_CDF4(13675, 28041, 31779)}, { AOM_CDF4(8590, 20674, 27631)}, + { AOM_CDF4(5685, 14675, 22013)}, { AOM_CDF4(3655, 9898, 15731)}, + { AOM_CDF4(26493, 32418, 32658)}, { AOM_CDF4(16376, 29342, 32090)}, + { AOM_CDF4(10594, 22649, 28970)}, { AOM_CDF4(8176, 17170, 24303)}, + { AOM_CDF4(5605, 12694, 19139)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(23888, 31902, 32542)}, + { AOM_CDF4(18612, 29687, 31987)}, { AOM_CDF4(16245, 24852, 29249)}, + { AOM_CDF4(15765, 22608, 27559)}, { AOM_CDF4(19895, 24699, 27510)}, + { AOM_CDF4(28401, 32212, 32457)}, { AOM_CDF4(15274, 27825, 30980)}, + { AOM_CDF4(9364, 18128, 24332)}, { AOM_CDF4(2283, 8193, 15082)}, + { AOM_CDF4(1228, 3972, 7881)}, { AOM_CDF4(29455, 32469, 32620)}, + { AOM_CDF4(17981, 28245, 31388)}, { AOM_CDF4(10921, 20098, 26240)}, + { AOM_CDF4(3743, 11829, 18657)}, { AOM_CDF4(2374, 9593, 15715)}, + { AOM_CDF4(31068, 32466, 32635)}, { AOM_CDF4(20321, 29572, 31971)}, + { AOM_CDF4(10771, 20255, 27119)}, { AOM_CDF4(2795, 10410, 17361)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(9320, 22102, 27840)}, { AOM_CDF4(27057, 32464, 32724)}, + { AOM_CDF4(16331, 30268, 32309)}, { AOM_CDF4(10319, 23935, 29720)}, + { AOM_CDF4(6189, 16448, 24106)}, { AOM_CDF4(3589, 10884, 18808)}, + { AOM_CDF4(29026, 32624, 32748)}, { AOM_CDF4(19226, 31507, 32587)}, + { AOM_CDF4(12692, 26921, 31203)}, { AOM_CDF4(7049, 19532, 27635)}, + { AOM_CDF4(7727, 15669, 23252)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(28056, 32625, 32748)}, + { AOM_CDF4(22383, 32075, 32669)}, { AOM_CDF4(15417, 27098, 31749)}, + { AOM_CDF4(18127, 26493, 27190)}, { AOM_CDF4(5461, 16384, 21845)}, + { AOM_CDF4(27982, 32091, 32584)}, { AOM_CDF4(19045, 29868, 31972)}, + { AOM_CDF4(10397, 22266, 27932)}, { AOM_CDF4(5990, 13697, 21500)}, + { AOM_CDF4(1792, 6912, 15104)}, { AOM_CDF4(28198, 32501, 32718)}, + { AOM_CDF4(21534, 31521, 32569)}, { AOM_CDF4(11109, 25217, 30017)}, + { AOM_CDF4(5671, 15124, 26151)}, { AOM_CDF4(4681, 14043, 18725)}, + { AOM_CDF4(28688, 32580, 32741)}, { AOM_CDF4(22576, 32079, 32661)}, + { AOM_CDF4(10627, 22141, 28340)}, { AOM_CDF4(9362, 14043, 28087)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(7754, 16948, 22142)}, { AOM_CDF4(25670, 32330, 32691)}, + { AOM_CDF4(15663, 29225, 31994)}, { AOM_CDF4(9878, 23288, 29158)}, + { AOM_CDF4(6419, 17088, 24336)}, { AOM_CDF4(3859, 11003, 17039)}, + { AOM_CDF4(27562, 32595, 32725)}, { AOM_CDF4(17575, 30588, 32399)}, + { AOM_CDF4(10819, 24838, 30309)}, { AOM_CDF4(7124, 18686, 25916)}, + { AOM_CDF4(4479, 12688, 19340)}, { AOM_CDF4(28385, 32476, 32673)}, + { AOM_CDF4(15306, 29005, 31938)}, { AOM_CDF4(8937, 21615, 28322)}, + { AOM_CDF4(5982, 15603, 22786)}, { AOM_CDF4(3620, 10267, 16136)}, + { AOM_CDF4(27280, 32464, 32667)}, { AOM_CDF4(15607, 29160, 32004)}, + { AOM_CDF4(9091, 22135, 28740)}, { AOM_CDF4(6232, 16632, 24020)}, + { AOM_CDF4(4047, 11377, 17672)}, { AOM_CDF4(29220, 32630, 32718)}, + { AOM_CDF4(19650, 31220, 32462)}, { AOM_CDF4(13050, 26312, 30827)}, + { AOM_CDF4(9228, 20870, 27468)}, { AOM_CDF4(6146, 15149, 21971)}, + { AOM_CDF4(30169, 32481, 32623)}, { AOM_CDF4(17212, 29311, 31554)}, + { AOM_CDF4(9911, 21311, 26882)}, { AOM_CDF4(4487, 13314, 20372)}, + { AOM_CDF4(2570, 7772, 12889)}, { AOM_CDF4(30924, 32613, 32708)}, + { AOM_CDF4(19490, 30206, 32107)}, { AOM_CDF4(11232, 23998, 29276)}, + { AOM_CDF4(6769, 17955, 25035)}, { AOM_CDF4(4398, 12623, 19214)}, + { AOM_CDF4(30609, 32627, 32722)}, { AOM_CDF4(19370, 30582, 32287)}, + { AOM_CDF4(10457, 23619, 29409)}, { AOM_CDF4(6443, 17637, 24834)}, + { AOM_CDF4(4645, 13236, 20106)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8626, 20271, 26216)}, { AOM_CDF4(26707, 32406, 32711)}, + { AOM_CDF4(16999, 30329, 32286)}, { AOM_CDF4(11445, 25123, 30286)}, + { AOM_CDF4(6411, 18828, 25601)}, { AOM_CDF4(6801, 12458, 20248)}, + { AOM_CDF4(29918, 32682, 32748)}, { AOM_CDF4(20649, 31739, 32618)}, + { AOM_CDF4(12879, 27773, 31581)}, { AOM_CDF4(7896, 21751, 28244)}, + { AOM_CDF4(5260, 14870, 23698)}, { AOM_CDF4(29252, 32593, 32731)}, + { AOM_CDF4(17072, 30460, 32294)}, { AOM_CDF4(10653, 24143, 29365)}, + { AOM_CDF4(6536, 17490, 23983)}, { AOM_CDF4(4929, 13170, 20085)}, + { AOM_CDF4(28137, 32518, 32715)}, { AOM_CDF4(18171, 30784, 32407)}, + { AOM_CDF4(11437, 25436, 30459)}, { AOM_CDF4(7252, 18534, 26176)}, + { AOM_CDF4(4126, 13353, 20978)}, { AOM_CDF4(31162, 32726, 32748)}, + { AOM_CDF4(23017, 32222, 32701)}, { AOM_CDF4(15629, 29233, 32046)}, + { AOM_CDF4(9387, 22621, 29480)}, { AOM_CDF4(6922, 17616, 25010)}, + { AOM_CDF4(28838, 32265, 32614)}, { AOM_CDF4(19701, 30206, 31920)}, + { AOM_CDF4(11214, 22410, 27933)}, { AOM_CDF4(5320, 14177, 23034)}, + { AOM_CDF4(5049, 12881, 17827)}, { AOM_CDF4(27484, 32471, 32734)}, + { AOM_CDF4(21076, 31526, 32561)}, { AOM_CDF4(12707, 26303, 31211)}, + { AOM_CDF4(8169, 21722, 28219)}, { AOM_CDF4(6045, 19406, 27042)}, + { AOM_CDF4(27753, 32572, 32745)}, { AOM_CDF4(20832, 31878, 32653)}, + { AOM_CDF4(13250, 27356, 31674)}, { AOM_CDF4(7718, 21508, 29858)}, + { AOM_CDF4(7209, 18350, 25559)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(7876, 16901, 21741)}, { AOM_CDF4(24001, 31898, 32625)}, + { AOM_CDF4(14529, 27959, 31451)}, { AOM_CDF4(8273, 20818, 27258)}, + { AOM_CDF4(5278, 14673, 21510)}, { AOM_CDF4(2983, 8843, 14039)}, + { AOM_CDF4(28016, 32574, 32732)}, { AOM_CDF4(17471, 30306, 32301)}, + { AOM_CDF4(10224, 24063, 29728)}, { AOM_CDF4(6602, 17954, 25052)}, + { AOM_CDF4(4002, 11585, 17759)}, { AOM_CDF4(30190, 32634, 32739)}, + { AOM_CDF4(17497, 30282, 32270)}, { AOM_CDF4(10229, 23729, 29538)}, + { AOM_CDF4(6344, 17211, 24440)}, { AOM_CDF4(3849, 11189, 17108)}, + { AOM_CDF4(28570, 32583, 32726)}, { AOM_CDF4(17521, 30161, 32238)}, + { AOM_CDF4(10153, 23565, 29378)}, { AOM_CDF4(6455, 17341, 24443)}, + { AOM_CDF4(3907, 11042, 17024)}, { AOM_CDF4(30689, 32715, 32748)}, + { AOM_CDF4(21546, 31840, 32610)}, { AOM_CDF4(13547, 27581, 31459)}, + { AOM_CDF4(8912, 21757, 28309)}, { AOM_CDF4(5548, 15080, 22046)}, + { AOM_CDF4(30783, 32540, 32685)}, { AOM_CDF4(17540, 29528, 31668)}, + { AOM_CDF4(10160, 21468, 26783)}, { AOM_CDF4(4724, 13393, 20054)}, + { AOM_CDF4(2702, 8174, 13102)}, { AOM_CDF4(31648, 32686, 32742)}, + { AOM_CDF4(20954, 31094, 32337)}, { AOM_CDF4(12420, 25698, 30179)}, + { AOM_CDF4(7304, 19320, 26248)}, { AOM_CDF4(4366, 12261, 18864)}, + { AOM_CDF4(31581, 32723, 32748)}, { AOM_CDF4(21373, 31586, 32525)}, + { AOM_CDF4(12744, 26625, 30885)}, { AOM_CDF4(7431, 20322, 26950)}, + { AOM_CDF4(4692, 13323, 20111)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(7833, 18369, 24095)}, { AOM_CDF4(26650, 32273, 32702)}, + { AOM_CDF4(16371, 29961, 32191)}, { AOM_CDF4(11055, 24082, 29629)}, + { AOM_CDF4(6892, 18644, 25400)}, { AOM_CDF4(5006, 13057, 19240)}, + { AOM_CDF4(29834, 32666, 32748)}, { AOM_CDF4(19577, 31335, 32570)}, + { AOM_CDF4(12253, 26509, 31122)}, { AOM_CDF4(7991, 20772, 27711)}, + { AOM_CDF4(5677, 15910, 23059)}, { AOM_CDF4(30109, 32532, 32720)}, + { AOM_CDF4(16747, 30166, 32252)}, { AOM_CDF4(10134, 23542, 29184)}, + { AOM_CDF4(5791, 16176, 23556)}, { AOM_CDF4(4362, 10414, 17284)}, + { AOM_CDF4(29492, 32626, 32748)}, { AOM_CDF4(19894, 31402, 32525)}, + { AOM_CDF4(12942, 27071, 30869)}, { AOM_CDF4(8346, 21216, 27405)}, + { AOM_CDF4(6572, 17087, 23859)}, { AOM_CDF4(32035, 32735, 32748)}, + { AOM_CDF4(22957, 31838, 32618)}, { AOM_CDF4(14724, 28572, 31772)}, + { AOM_CDF4(10364, 23999, 29553)}, { AOM_CDF4(7004, 18433, 25655)}, + { AOM_CDF4(27528, 32277, 32681)}, { AOM_CDF4(16959, 31171, 32096)}, + { AOM_CDF4(10486, 23593, 27962)}, { AOM_CDF4(8192, 16384, 23211)}, + { AOM_CDF4(8937, 17873, 20852)}, { AOM_CDF4(27715, 32002, 32615)}, + { AOM_CDF4(15073, 29491, 31676)}, { AOM_CDF4(11264, 24576, 28672)}, + { AOM_CDF4(2341, 18725, 23406)}, { AOM_CDF4(7282, 18204, 25486)}, + { AOM_CDF4(28547, 32213, 32657)}, { AOM_CDF4(20788, 29773, 32239)}, + { AOM_CDF4(6780, 21469, 30508)}, { AOM_CDF4(5958, 14895, 23831)}, + { AOM_CDF4(16384, 21845, 27307)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(5992, 14304, 19765)}, { AOM_CDF4(22612, 31238, 32456)}, + { AOM_CDF4(13456, 27162, 31087)}, { AOM_CDF4(8001, 20062, 26504)}, + { AOM_CDF4(5168, 14105, 20764)}, { AOM_CDF4(2632, 7771, 12385)}, + { AOM_CDF4(27034, 32344, 32709)}, { AOM_CDF4(15850, 29415, 31997)}, + { AOM_CDF4(9494, 22776, 28841)}, { AOM_CDF4(6151, 16830, 23969)}, + { AOM_CDF4(3461, 10039, 15722)}, { AOM_CDF4(30134, 32569, 32731)}, + { AOM_CDF4(15638, 29422, 31945)}, { AOM_CDF4(9150, 21865, 28218)}, + { AOM_CDF4(5647, 15719, 22676)}, { AOM_CDF4(3402, 9772, 15477)}, + { AOM_CDF4(28530, 32586, 32735)}, { AOM_CDF4(17139, 30298, 32292)}, + { AOM_CDF4(10200, 24039, 29685)}, { AOM_CDF4(6419, 17674, 24786)}, + { AOM_CDF4(3544, 10225, 15824)}, { AOM_CDF4(31333, 32726, 32748)}, + { AOM_CDF4(20618, 31487, 32544)}, { AOM_CDF4(12901, 27217, 31232)}, + { AOM_CDF4(8624, 21734, 28171)}, { AOM_CDF4(5104, 14191, 20748)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(11206, 21090, 26561)}, { AOM_CDF4(28759, 32279, 32671)}, + { AOM_CDF4(14171, 27952, 31569)}, { AOM_CDF4(9743, 22907, 29141)}, + { AOM_CDF4(6871, 17886, 24868)}, { AOM_CDF4(4960, 13152, 19315)}, + { AOM_CDF4(31077, 32661, 32748)}, { AOM_CDF4(19400, 31195, 32515)}, + { AOM_CDF4(12752, 26858, 31040)}, { AOM_CDF4(8370, 22098, 28591)}, + { AOM_CDF4(5457, 15373, 22298)}, { AOM_CDF4(31697, 32706, 32748)}, + { AOM_CDF4(17860, 30657, 32333)}, { AOM_CDF4(12510, 24812, 29261)}, + { AOM_CDF4(6180, 19124, 24722)}, { AOM_CDF4(5041, 13548, 17959)}, + { AOM_CDF4(31552, 32716, 32748)}, { AOM_CDF4(21908, 31769, 32623)}, + { AOM_CDF4(14470, 28201, 31565)}, { AOM_CDF4(9493, 22982, 28608)}, + { AOM_CDF4(6858, 17240, 24137)}, { AOM_CDF4(32543, 32752, 32756)}, + { AOM_CDF4(24286, 32097, 32666)}, { AOM_CDF4(15958, 29217, 32024)}, + { AOM_CDF4(10207, 24234, 29958)}, { AOM_CDF4(6929, 18305, 25652)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + }, + { + { + { AOM_CDF4(4137, 10847, 15682)}, { AOM_CDF4(17824, 27001, 30058)}, + { AOM_CDF4(10204, 22796, 28291)}, { AOM_CDF4(6076, 15935, 22125)}, + { AOM_CDF4(3852, 10937, 16816)}, { AOM_CDF4(2252, 6324, 10131)}, + { AOM_CDF4(25840, 32016, 32662)}, { AOM_CDF4(15109, 28268, 31531)}, + { AOM_CDF4(9385, 22231, 28340)}, { AOM_CDF4(6082, 16672, 23479)}, + { AOM_CDF4(3318, 9427, 14681)}, { AOM_CDF4(30594, 32574, 32718)}, + { AOM_CDF4(16836, 29552, 31859)}, { AOM_CDF4(9556, 22542, 28356)}, + { AOM_CDF4(6305, 16725, 23540)}, { AOM_CDF4(3376, 9895, 15184)}, + { AOM_CDF4(29383, 32617, 32745)}, { AOM_CDF4(18891, 30809, 32401)}, + { AOM_CDF4(11688, 25942, 30687)}, { AOM_CDF4(7468, 19469, 26651)}, + { AOM_CDF4(3909, 11358, 17012)}, { AOM_CDF4(31564, 32736, 32748)}, + { AOM_CDF4(20906, 31611, 32600)}, { AOM_CDF4(13191, 27621, 31537)}, + { AOM_CDF4(8768, 22029, 28676)}, { AOM_CDF4(5079, 14109, 20906)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + }, + { + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)}, + { AOM_CDF4(8192, 16384, 24576)}, { AOM_CDF4(8192, 16384, 24576)} + } + } + } +}; + +static const u16 av1_default_coeff_base_eob_multi_cdfs[TOKEN_CDF_Q_CTXS][TX_SIZES] + [PLANE_TYPES][SIG_COEF_CONTEXTS_EOB][CDF_SIZE(NUM_BASE_LEVELS + 1)] = { + { + { + { + { AOM_CDF3(17837, 29055)}, + { AOM_CDF3(29600, 31446)}, + { AOM_CDF3(30844, 31878)}, + { AOM_CDF3(24926, 28948)} + }, + { + { AOM_CDF3(21365, 30026)}, + { AOM_CDF3(30512, 32423)}, + { AOM_CDF3(31658, 32621)}, + { AOM_CDF3(29630, 31881)} + } + }, + { + { + { AOM_CDF3(5717, 26477)}, + { AOM_CDF3(30491, 31703)}, + { AOM_CDF3(31550, 32158)}, + { AOM_CDF3(29648, 31491)} + }, + { + { AOM_CDF3(12608, 27820)}, + { AOM_CDF3(30680, 32225)}, + { AOM_CDF3(30809, 32335)}, + { AOM_CDF3(31299, 32423)} + } + }, + { + { + { AOM_CDF3(1786, 12612)}, + { AOM_CDF3(30663, 31625)}, + { AOM_CDF3(32339, 32468)}, + { AOM_CDF3(31148, 31833)} + }, + { + { AOM_CDF3(18857, 23865)}, + { AOM_CDF3(31428, 32428)}, + { AOM_CDF3(31744, 32373)}, + { AOM_CDF3(31775, 32526)} + } + }, + { + { + { AOM_CDF3(1787, 2532)}, + { AOM_CDF3(30832, 31662)}, + { AOM_CDF3(31824, 32682)}, + { AOM_CDF3(32133, 32569)} + }, + { + { AOM_CDF3(13751, 22235)}, + { AOM_CDF3(32089, 32409)}, + { AOM_CDF3(27084, 27920)}, + { AOM_CDF3(29291, 32594)} + } + }, + { + { + { AOM_CDF3(1725, 3449)}, + { AOM_CDF3(31102, 31935)}, + { AOM_CDF3(32457, 32613)}, + { AOM_CDF3(32412, 32649)} + }, + { + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)} + } + } + }, + { + { + { + { AOM_CDF3(17560, 29888)}, + { AOM_CDF3(29671, 31549)}, + { AOM_CDF3(31007, 32056)}, + { AOM_CDF3(27286, 30006)} + }, + { + { AOM_CDF3(26594, 31212)}, + { AOM_CDF3(31208, 32582)}, + { AOM_CDF3(31835, 32637)}, + { AOM_CDF3(30595, 32206)} + } + }, + { + { + { AOM_CDF3(15239, 29932)}, + { AOM_CDF3(31315, 32095)}, + { AOM_CDF3(32130, 32434)}, + { AOM_CDF3(30864, 31996)} + }, + { + { AOM_CDF3(26279, 30968)}, + { AOM_CDF3(31142, 32495)}, + { AOM_CDF3(31713, 32540)}, + { AOM_CDF3(31929, 32594)} + } + }, + { + { + { AOM_CDF3(2644, 25198)}, + { AOM_CDF3(32038, 32451)}, + { AOM_CDF3(32639, 32695)}, + { AOM_CDF3(32166, 32518)} + }, + { + { AOM_CDF3(17187, 27668)}, + { AOM_CDF3(31714, 32550)}, + { AOM_CDF3(32283, 32678)}, + { AOM_CDF3(31930, 32563)} + } + }, + { + { + { AOM_CDF3(1044, 2257)}, + { AOM_CDF3(30755, 31923)}, + { AOM_CDF3(32208, 32693)}, + { AOM_CDF3(32244, 32615)} + }, + { + { AOM_CDF3(21317, 26207)}, + { AOM_CDF3(29133, 30868)}, + { AOM_CDF3(29311, 31231)}, + { AOM_CDF3(29657, 31087)} + } + }, + { + { + { AOM_CDF3(478, 1834)}, + { AOM_CDF3(31005, 31987)}, + { AOM_CDF3(32317, 32724)}, + { AOM_CDF3(30865, 32648)} + }, + { + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)} + } + } + }, + { + { + { + { AOM_CDF3(20092, 30774)}, + { AOM_CDF3(30695, 32020)}, + { AOM_CDF3(31131, 32103)}, + { AOM_CDF3(28666, 30870)} + }, + { + { AOM_CDF3(27258, 31095)}, + { AOM_CDF3(31804, 32623)}, + { AOM_CDF3(31763, 32528)}, + { AOM_CDF3(31438, 32506)} + } + }, + { + { + { AOM_CDF3(18049, 30489)}, + { AOM_CDF3(31706, 32286)}, + { AOM_CDF3(32163, 32473)}, + { AOM_CDF3(31550, 32184)} + }, + { + { AOM_CDF3(27116, 30842)}, + { AOM_CDF3(31971, 32598)}, + { AOM_CDF3(32088, 32576)}, + { AOM_CDF3(32067, 32664)} + } + }, + { + { + { AOM_CDF3(12854, 29093)}, + { AOM_CDF3(32272, 32558)}, + { AOM_CDF3(32667, 32729)}, + { AOM_CDF3(32306, 32585)} + }, + { + { AOM_CDF3(25476, 30366)}, + { AOM_CDF3(32169, 32687)}, + { AOM_CDF3(32479, 32689)}, + { AOM_CDF3(31673, 32634)} + } + }, + { + { + { AOM_CDF3(2809, 19301)}, + { AOM_CDF3(32205, 32622)}, + { AOM_CDF3(32338, 32730)}, + { AOM_CDF3(31786, 32616)} + }, + { + { AOM_CDF3(22737, 29105)}, + { AOM_CDF3(30810, 32362)}, + { AOM_CDF3(30014, 32627)}, + { AOM_CDF3(30528, 32574)} + } + }, + { + { + { AOM_CDF3(935, 3382)}, + { AOM_CDF3(30789, 31909)}, + { AOM_CDF3(32466, 32756)}, + { AOM_CDF3(30860, 32513)} + }, + { + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)} + } + } + }, + { + { + { + { AOM_CDF3(22497, 31198)}, + { AOM_CDF3(31715, 32495)}, + { AOM_CDF3(31606, 32337)}, + { AOM_CDF3(30388, 31990)} + }, + { + { AOM_CDF3(27877, 31584)}, + { AOM_CDF3(32170, 32728)}, + { AOM_CDF3(32155, 32688)}, + { AOM_CDF3(32219, 32702)} + } + }, + { + { + { AOM_CDF3(21457, 31043)}, + { AOM_CDF3(31951, 32483)}, + { AOM_CDF3(32153, 32562)}, + { AOM_CDF3(31473, 32215)} + }, + { + { AOM_CDF3(27558, 31151)}, + { AOM_CDF3(32020, 32640)}, + { AOM_CDF3(32097, 32575)}, + { AOM_CDF3(32242, 32719)} + } + }, + { + { + { AOM_CDF3(19980, 30591)}, + { AOM_CDF3(32219, 32597)}, + { AOM_CDF3(32581, 32706)}, + { AOM_CDF3(31803, 32287)} + }, + { + { AOM_CDF3(26473, 30507)}, + { AOM_CDF3(32431, 32723)}, + { AOM_CDF3(32196, 32611)}, + { AOM_CDF3(31588, 32528)} + } + }, + { + { + { AOM_CDF3(24647, 30463)}, + { AOM_CDF3(32412, 32695)}, + { AOM_CDF3(32468, 32720)}, + { AOM_CDF3(31269, 32523)} + }, + { + { AOM_CDF3(28482, 31505)}, + { AOM_CDF3(32152, 32701)}, + { AOM_CDF3(31732, 32598)}, + { AOM_CDF3(31767, 32712)} + } + }, + { + { + { AOM_CDF3(12358, 24977)}, + { AOM_CDF3(31331, 32385)}, + { AOM_CDF3(32634, 32756)}, + { AOM_CDF3(30411, 32548)} + }, + { + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)}, + { AOM_CDF3(10923, 21845)} + } + } + } +}; + +static const u16 default_joint_cdf[] = { ICDF(4096), ICDF(11264), ICDF(19328)}; +static const u16 default_clsss_cdf[][10] = { + // Vertical component + { + ICDF(28672), ICDF(30976), ICDF(31858), ICDF(32320), ICDF(32551), + ICDF(32656), ICDF(32740), ICDF(32757), ICDF(32762), ICDF(32767) + }, + // Horizontal component + { + ICDF(28672), ICDF(30976), ICDF(31858), ICDF(32320), ICDF(32551), + ICDF(32656), ICDF(32740), ICDF(32757), ICDF(32762), ICDF(32767) + } +}; + +static const u16 default_clsss0_fp_cdf[][2][3] = { + // Vertical component + { + { ICDF(16384), ICDF(24576), ICDF(26624)}, + { ICDF(12288), ICDF(21248), ICDF(24128)} + }, + // Horizontal component + { + { ICDF(16384), ICDF(24576), ICDF(26624)}, + { ICDF(12288), ICDF(21248), ICDF(24128)} + } +}; + +static const u16 default_fp_cdf[][3] = { + // Vertical component + { + ICDF(8192), ICDF(17408), ICDF(21248) + }, + // Horizontal component + { + ICDF(8192), ICDF(17408), ICDF(21248) + } +}; + +static const u16 default_sign_cdf[] = { ICDF(128 * 128), ICDF(128 * 128)}; +static const u16 default_class0_hp_cdf[] = { ICDF(160 * 128), ICDF(160 * 128)}; +static const u16 default_hp_cdf[] = { ICDF(128 * 128), ICDF(128 * 128)}; +static const u16 default_class0_cdf[] = { ICDF(216 * 128), ICDF(216 * 128)}; +static const u16 default_bits_cdf[][10] = { + { + ICDF(128 * 136), ICDF(128 * 140), ICDF(128 * 148), ICDF(128 * 160), + ICDF(128 * 176), ICDF(128 * 192), ICDF(128 * 224), ICDF(128 * 234), + ICDF(128 * 234), ICDF(128 * 240) + }, + { + ICDF(128 * 136), ICDF(128 * 140), ICDF(128 * 148), ICDF(128 * 160), + ICDF(128 * 176), ICDF(128 * 192), ICDF(128 * 224), ICDF(128 * 234), + ICDF(128 * 234), ICDF(128 * 240) + } +}; + +static int rockchip_av1_get_q_ctx(int q) +{ + if (q <= 20) + return 0; + if (q <= 60) + return 1; + if (q <= 120) + return 2; + return 3; +} + +void rockchip_av1_default_coeff_probs(u32 base_qindex, void *ptr) +{ + struct av1cdfs *cdfs = (struct av1cdfs *)ptr; + const int index = rockchip_av1_get_q_ctx(base_qindex); + + memcpy(cdfs->txb_skip_cdf, av1_default_txb_skip_cdfs[index], + sizeof(av1_default_txb_skip_cdfs[0])); + memcpy(cdfs->eob_extra_cdf, av1_default_eob_extra_cdfs[index], + sizeof(av1_default_eob_extra_cdfs[0])); + memcpy(cdfs->dc_sign_cdf, av1_default_dc_sign_cdfs[index], + sizeof(av1_default_dc_sign_cdfs[0])); + memcpy(cdfs->coeff_br_cdf, av1_default_coeff_lps_multi_cdfs[index], + sizeof(av1_default_coeff_lps_multi_cdfs[0])); + memcpy(cdfs->coeff_base_cdf, av1_default_coeff_base_multi_cdfs[index], + sizeof(av1_default_coeff_base_multi_cdfs[0])); + memcpy(cdfs->coeff_base_eob_cdf, + av1_default_coeff_base_eob_multi_cdfs[index], + sizeof(av1_default_coeff_base_eob_multi_cdfs[0])); + memcpy(cdfs->eob_flag_cdf16, av1_default_eob_multi16_cdfs[index], + sizeof(av1_default_eob_multi16_cdfs[0])); + memcpy(cdfs->eob_flag_cdf32, av1_default_eob_multi32_cdfs[index], + sizeof(av1_default_eob_multi32_cdfs[0])); + memcpy(cdfs->eob_flag_cdf64, av1_default_eob_multi64_cdfs[index], + sizeof(av1_default_eob_multi64_cdfs[0])); + memcpy(cdfs->eob_flag_cdf128, av1_default_eob_multi128_cdfs[index], + sizeof(av1_default_eob_multi128_cdfs[0])); + memcpy(cdfs->eob_flag_cdf256, av1_default_eob_multi256_cdfs[index], + sizeof(av1_default_eob_multi256_cdfs[0])); + memcpy(cdfs->eob_flag_cdf512, av1_default_eob_multi512_cdfs[index], + sizeof(av1_default_eob_multi512_cdfs[0])); + memcpy(cdfs->eob_flag_cdf1024, av1_default_eob_multi1024_cdfs[index], + sizeof(av1_default_eob_multi1024_cdfs[0])); +} + +void rockchip_av1_set_default_cdfs(struct av1cdfs *cdfs, + struct mvcdfs *cdfs_ndvc) +{ + memcpy(cdfs->partition_cdf, default_partition_cdf, + sizeof(cdfs->partition_cdf)); + + memcpy(cdfs->tx_type_intra0_cdf, default_intra_ext_tx0_cdf, + sizeof(cdfs->tx_type_intra0_cdf)); + memcpy(cdfs->tx_type_intra1_cdf, default_intra_ext_tx1_cdf, + sizeof(cdfs->tx_type_intra1_cdf)); + memcpy(cdfs->tx_type_inter_cdf, default_inter_ext_tx_cdf, + sizeof(cdfs->tx_type_inter_cdf)); + + memcpy(cdfs->vartx_part_cdf, default_txfm_partition_cdf, + sizeof(cdfs->vartx_part_cdf)); + memcpy(cdfs->mbskip_cdf, default_skip_cdfs, sizeof(cdfs->mbskip_cdf)); + memcpy(cdfs->delta_q_cdf, default_delta_q_cdf, + sizeof(cdfs->delta_q_cdf)); + memcpy(cdfs->delta_lf_multi_cdf, default_delta_lf_multi_cdf, + sizeof(cdfs->delta_lf_multi_cdf)); + memcpy(cdfs->delta_lf_cdf, default_delta_lf_cdf, + sizeof(cdfs->delta_lf_cdf)); + + memcpy(cdfs->segment_pred_cdf, default_segment_pred_cdf, + sizeof(cdfs->segment_pred_cdf)); + + memcpy(cdfs->spatial_pred_seg_tree_cdf, + default_spatial_pred_seg_tree_cdf, + sizeof(cdfs->spatial_pred_seg_tree_cdf)); + + memcpy(cdfs->skip_mode_cdf, default_skip_mode_cdfs, + sizeof(cdfs->skip_mode_cdf)); + + memcpy(cdfs->tx_size_cdf, default_tx_size_cdf, + sizeof(cdfs->tx_size_cdf)); + + memcpy(cdfs->kf_ymode_cdf, default_kf_y_mode_cdf, + sizeof(cdfs->kf_ymode_cdf)); + memcpy(cdfs->uv_mode_cdf, default_uv_mode_cdf, + sizeof(cdfs->uv_mode_cdf)); + memcpy(cdfs->if_ymode_cdf, default_if_y_mode_cdf, + sizeof(cdfs->if_ymode_cdf)); + + memcpy(cdfs->intra_inter_cdf, default_intra_inter_cdf, + sizeof(cdfs->intra_inter_cdf)); + + memcpy(cdfs->comp_ref_cdf, default_comp_ref_cdf, + sizeof(cdfs->comp_ref_cdf)); + memcpy(cdfs->comp_bwdref_cdf, default_comp_bwdref_cdf, + sizeof(cdfs->comp_bwdref_cdf)); + + memcpy(cdfs->comp_inter_cdf, default_comp_inter_cdf, + sizeof(cdfs->comp_inter_cdf)); + + memcpy(cdfs->single_ref_cdf, default_single_ref_cdf, + sizeof(cdfs->single_ref_cdf)); + memcpy(cdfs->comp_ref_type_cdf, default_comp_ref_type_cdf, + sizeof(cdfs->comp_ref_type_cdf)); + memcpy(cdfs->uni_comp_ref_cdf, default_uni_comp_ref_cdf, + sizeof(cdfs->uni_comp_ref_cdf)); + + memcpy(cdfs->newmv_cdf, default_newmv_cdf, sizeof(cdfs->newmv_cdf)); + memcpy(cdfs->zeromv_cdf, default_zeromv_cdf, sizeof(cdfs->zeromv_cdf)); + memcpy(cdfs->refmv_cdf, default_refmv_cdf, sizeof(cdfs->refmv_cdf)); + memcpy(cdfs->drl_cdf, default_drl_cdf, sizeof(cdfs->drl_cdf)); + + memcpy(cdfs->interp_filter_cdf, default_switchable_interp_cdf, + sizeof(cdfs->interp_filter_cdf)); + + // Regular MV cdfs + memcpy(cdfs->mv_cdf.joint_cdf, default_joint_cdf, + sizeof(cdfs->mv_cdf.joint_cdf)); + memcpy(cdfs->mv_cdf.sign_cdf, default_sign_cdf, + sizeof(cdfs->mv_cdf.sign_cdf)); + memcpy(cdfs->mv_cdf.clsss_cdf, default_clsss_cdf, + sizeof(cdfs->mv_cdf.clsss_cdf)); + memcpy(cdfs->mv_cdf.clsss0_fp_cdf, default_clsss0_fp_cdf, + sizeof(cdfs->mv_cdf.clsss0_fp_cdf)); + memcpy(cdfs->mv_cdf.fp_cdf, default_fp_cdf, + sizeof(cdfs->mv_cdf.fp_cdf)); + memcpy(cdfs->mv_cdf.class0_hp_cdf, default_class0_hp_cdf, + sizeof(cdfs->mv_cdf.class0_hp_cdf)); + memcpy(cdfs->mv_cdf.hp_cdf, default_hp_cdf, + sizeof(cdfs->mv_cdf.hp_cdf)); + memcpy(cdfs->mv_cdf.class0_cdf, default_class0_cdf, + sizeof(cdfs->mv_cdf.class0_cdf)); + memcpy(cdfs->mv_cdf.bits_cdf, default_bits_cdf, + sizeof(cdfs->mv_cdf.bits_cdf)); + + // Intrabc cdfs + memcpy(cdfs_ndvc->joint_cdf, default_joint_cdf, + sizeof(cdfs_ndvc->joint_cdf)); + memcpy(cdfs_ndvc->sign_cdf, default_sign_cdf, + sizeof(cdfs_ndvc->sign_cdf)); + memcpy(cdfs_ndvc->clsss_cdf, default_clsss_cdf, + sizeof(cdfs_ndvc->clsss_cdf)); + memcpy(cdfs_ndvc->clsss0_fp_cdf, default_clsss0_fp_cdf, + sizeof(cdfs_ndvc->clsss0_fp_cdf)); + memcpy(cdfs_ndvc->fp_cdf, default_fp_cdf, sizeof(cdfs_ndvc->fp_cdf)); + memcpy(cdfs_ndvc->class0_hp_cdf, default_class0_hp_cdf, + sizeof(cdfs_ndvc->class0_hp_cdf)); + memcpy(cdfs_ndvc->hp_cdf, default_hp_cdf, sizeof(cdfs_ndvc->hp_cdf)); + memcpy(cdfs_ndvc->class0_cdf, default_class0_cdf, + sizeof(cdfs_ndvc->class0_cdf)); + memcpy(cdfs_ndvc->bits_cdf, default_bits_cdf, + sizeof(cdfs_ndvc->bits_cdf)); + + memcpy(cdfs->obmc_cdf, default_obmc_cdf, sizeof(cdfs->obmc_cdf)); + memcpy(cdfs->motion_mode_cdf, default_motion_mode_cdf, + sizeof(cdfs->motion_mode_cdf)); + + memcpy(cdfs->inter_compound_mode_cdf, default_inter_compound_mode_cdf, + sizeof(cdfs->inter_compound_mode_cdf)); + memcpy(cdfs->compound_type_cdf, default_compound_type_cdf, + sizeof(cdfs->compound_type_cdf)); + memcpy(cdfs->interintra_cdf, default_interintra_cdf, + sizeof(cdfs->interintra_cdf)); + memcpy(cdfs->interintra_mode_cdf, default_interintra_mode_cdf, + sizeof(cdfs->interintra_mode_cdf)); + memcpy(cdfs->wedge_interintra_cdf, default_wedge_interintra_cdf, + sizeof(cdfs->wedge_interintra_cdf)); + memcpy(cdfs->wedge_idx_cdf, default_wedge_idx_cdf, + sizeof(cdfs->wedge_idx_cdf)); + + memcpy(cdfs->palette_y_mode_cdf, default_palette_y_mode_cdf, + sizeof(cdfs->palette_y_mode_cdf)); + memcpy(cdfs->palette_uv_mode_cdf, default_palette_uv_mode_cdf, + sizeof(cdfs->palette_uv_mode_cdf)); + memcpy(cdfs->palette_y_size_cdf, default_palette_y_size_cdf, + sizeof(cdfs->palette_y_size_cdf)); + memcpy(cdfs->palette_uv_size_cdf, default_palette_uv_size_cdf, + sizeof(cdfs->palette_uv_size_cdf)); + memcpy(cdfs->palette_y_color_index_cdf, + default_palette_y_color_index_cdf, + sizeof(cdfs->palette_y_color_index_cdf)); + memcpy(cdfs->palette_uv_color_index_cdf, + default_palette_uv_color_index_cdf, + sizeof(cdfs->palette_uv_color_index_cdf)); + + memcpy(cdfs->cfl_sign_cdf, default_cfl_sign_cdf, + sizeof(cdfs->cfl_sign_cdf)); + memcpy(cdfs->cfl_alpha_cdf, default_cfl_alpha_cdf, + sizeof(cdfs->cfl_alpha_cdf)); + + memcpy(cdfs->intrabc_cdf, default_intrabc_cdf, + sizeof(cdfs->intrabc_cdf)); + memcpy(cdfs->angle_delta_cdf, default_angle_delta_cdf, + sizeof(cdfs->angle_delta_cdf)); + memcpy(cdfs->filter_intra_mode_cdf, default_filter_intra_mode_cdf, + sizeof(cdfs->filter_intra_mode_cdf)); + memcpy(cdfs->filter_intra_cdf, default_filter_intra_cdfs, + sizeof(cdfs->filter_intra_cdf)); + memcpy(cdfs->comp_group_idx_cdf, default_comp_group_idx_cdfs, + sizeof(cdfs->comp_group_idx_cdf)); + memcpy(cdfs->compound_idx_cdf, default_compound_idx_cdfs, + sizeof(cdfs->compound_idx_cdf)); +} + +void rockchip_av1_get_cdfs(struct hantro_ctx *ctx, u32 ref_idx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + + av1_dec->cdfs = &av1_dec->cdfs_last[ref_idx]; + av1_dec->cdfs_ndvc = &av1_dec->cdfs_last_ndvc[ref_idx]; +} + +void rockchip_av1_store_cdfs(struct hantro_ctx *ctx, + u32 refresh_frame_flags) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + int i; + + for (i = 0; i < NUM_REF_FRAMES; i++) { + if (refresh_frame_flags & (1 << i)) { + if (&av1_dec->cdfs_last[i] != av1_dec->cdfs) { + av1_dec->cdfs_last[i] = *av1_dec->cdfs; + av1_dec->cdfs_last_ndvc[i] = + *av1_dec->cdfs_ndvc; + } + } + } +} diff --git a/drivers/media/platform/verisilicon/rockchip_av1_entropymode.h b/drivers/media/platform/verisilicon/rockchip_av1_entropymode.h new file mode 100644 index 000000000000..bbf8424c7d2c --- /dev/null +++ b/drivers/media/platform/verisilicon/rockchip_av1_entropymode.h @@ -0,0 +1,272 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _ROCKCHIP_AV1_ENTROPYMODE_H_ +#define _ROCKCHIP_AV1_ENTROPYMODE_H_ + +#include + +struct hantro_ctx; + +#define AV1_INTER_MODE_CONTEXTS 15 +#define AV1_INTRA_MODES 13 +#define AV1_REF_CONTEXTS 3 +#define AV1_SWITCHABLE_FILTERS 3 /* number of switchable filters */ +#define AV1_TX_SIZE_CONTEXTS 3 +#define BLOCK_SIZE_GROUPS 4 +#define BR_CDF_SIZE 4 +#define BWD_REFS 3 +#define CFL_ALLOWED_TYPES 2 +#define CFL_ALPHA_CONTEXTS 6 +#define CFL_ALPHABET_SIZE 16 +#define CFL_JOINT_SIGNS 8 +#define CDF_SIZE(x) ((x) - 1) +#define COMP_GROUP_IDX_CONTEXTS 7 +#define COMP_INDEX_CONTEXTS 6 +#define COMP_INTER_CONTEXTS 5 +#define COMP_REF_TYPE_CONTEXTS 5 +#define COMPOUND_TYPES 3 +#define DC_SIGN_CONTEXTS 3 +#define DELTA_LF_PROBS 3 +#define DELTA_Q_PROBS 3 +#define DIRECTIONAL_MODES 8 +#define DRL_MODE_CONTEXTS 3 +#define EOB_COEF_CONTEXTS 9 +#define EXT_TX_SIZES 3 +#define EXT_TX_TYPES 16 +#define EXTTX_SIZES 4 +#define FRAME_LF_COUNT 4 +#define FWD_REFS 4 +#define GLOBALMV_MODE_CONTEXTS 2 +#define ICDF(x) (32768U - (x)) +#define INTER_COMPOUND_MODES 8 +#define INTERINTRA_MODES 4 +#define INTRA_INTER_CONTEXTS 4 +#define KF_MODE_CONTEXTS 5 +#define LEVEL_CONTEXTS 21 +#define MAX_ANGLE_DELTA 3 +#define MAX_MB_SEGMENTS 8 +#define MAX_SEGMENTS 8 +#define MAX_TX_CATS 4 +#define MAX_TX_DEPTH 2 +#define MBSKIP_CONTEXTS 3 +#define MOTION_MODES 3 +#define MOTION_MODE_CONTEXTS 10 +#define NEWMV_MODE_CONTEXTS 6 +#define NUM_BASE_LEVELS 2 +#define NUM_REF_FRAMES 8 +#define PALETTE_BLOCK_SIZES 7 +#define PALETTE_IDX_CONTEXTS 18 +#define PALETTE_SIZES 7 +#define PALETTE_UV_MODE_CONTEXTS 2 +#define PALETTE_Y_MODE_CONTEXTS 3 +#define PARTITION_PLOFFSET 4 +#define NUM_PARTITION_CONTEXTS (4 * PARTITION_PLOFFSET) +#define PLANE_TYPES 2 +#define PREDICTION_PROBS 3 +#define REF_CONTEXTS 5 +#define REFMV_MODE_CONTEXTS 9 +#define SEG_TEMPORAL_PRED_CTXS 3 +#define SIG_COEF_CONTEXTS 42 +#define SIG_COEF_CONTEXTS_EOB 4 +#define SINGLE_REFS 7 +#define SKIP_CONTEXTS 3 +#define SKIP_MODE_CONTEXTS 3 +#define SPATIAL_PREDICTION_PROBS 3 +#define SWITCHABLE_FILTER_CONTEXTS ((AV1_SWITCHABLE_FILTERS + 1) * 4) +#define TOKEN_CDF_Q_CTXS 4 +#define TX_SIZES 5 +#define TX_SIZE_CONTEXTS 2 +#define TX_TYPES 4 +#define TXB_SKIP_CONTEXTS 13 +#define TXFM_PARTITION_CONTEXTS 22 +#define UNI_COMP_REF_CONTEXTS 3 +#define UNIDIR_COMP_REFS 4 +#define UV_INTRA_MODES 14 +#define VARTX_PART_CONTEXTS 22 +#define ZEROMV_MODE_CONTEXTS 2 + +enum blocksizetype { + BLOCK_SIZE_AB4X4, + BLOCK_SIZE_SB4X8, + BLOCK_SIZE_SB8X4, + BLOCK_SIZE_SB8X8, + BLOCK_SIZE_SB8X16, + BLOCK_SIZE_SB16X8, + BLOCK_SIZE_MB16X16, + BLOCK_SIZE_SB16X32, + BLOCK_SIZE_SB32X16, + BLOCK_SIZE_SB32X32, + BLOCK_SIZE_SB32X64, + BLOCK_SIZE_SB64X32, + BLOCK_SIZE_SB64X64, + BLOCK_SIZE_SB64X128, + BLOCK_SIZE_SB128X64, + BLOCK_SIZE_SB128X128, + BLOCK_SIZE_SB4X16, + BLOCK_SIZE_SB16X4, + BLOCK_SIZE_SB8X32, + BLOCK_SIZE_SB32X8, + BLOCK_SIZE_SB16X64, + BLOCK_SIZE_SB64X16, + BLOCK_SIZE_TYPES, + BLOCK_SIZES_ALL = BLOCK_SIZE_TYPES +}; + +enum filterintramodetype { + FILTER_DC_PRED, + FILTER_V_PRED, + FILTER_H_PRED, + FILTER_D153_PRED, + FILTER_PAETH_PRED, + FILTER_INTRA_MODES, + FILTER_INTRA_UNUSED = 7 +}; + +enum frametype { + KEY_FRAME = 0, + INTER_FRAME = 1, + NUM_FRAME_TYPES, +}; + +enum txsize { + TX_4X4 = 0, + TX_8X8 = 1, + TX_16X16 = 2, + TX_32X32 = 3, + TX_SIZE_MAX_SB, +}; + +enum { SIMPLE_TRANSLATION, OBMC_CAUSAL, MOTION_MODE_COUNT }; + +enum mb_prediction_mode { + DC_PRED, /* average of above and left pixels */ + V_PRED, /* vertical prediction */ + H_PRED, /* horizontal prediction */ + D45_PRED, /* Directional 45 deg prediction [anti-clockwise from 0 deg hor] */ + D135_PRED, /* Directional 135 deg prediction [anti-clockwise from 0 deg hor] */ + D117_PRED, /* Directional 112 deg prediction [anti-clockwise from 0 deg hor] */ + D153_PRED, /* Directional 157 deg prediction [anti-clockwise from 0 deg hor] */ + D27_PRED, /* Directional 22 deg prediction [anti-clockwise from 0 deg hor] */ + D63_PRED, /* Directional 67 deg prediction [anti-clockwise from 0 deg hor] */ + SMOOTH_PRED, + TM_PRED_AV1 = SMOOTH_PRED, + SMOOTH_V_PRED, // Vertical interpolation + SMOOTH_H_PRED, // Horizontal interpolation + TM_PRED, /* Truemotion prediction */ + PAETH_PRED = TM_PRED, + NEARESTMV, + NEARMV, + ZEROMV, + NEWMV, + NEAREST_NEARESTMV, + NEAR_NEARMV, + NEAREST_NEWMV, + NEW_NEARESTMV, + NEAR_NEWMV, + NEW_NEARMV, + ZERO_ZEROMV, + NEW_NEWMV, + SPLITMV, + MB_MODE_COUNT +}; + +enum partitiontype { + PARTITION_NONE, + PARTITION_HORZ, + PARTITION_VERT, + PARTITION_SPLIT, + PARTITION_TYPES +}; + +struct mvcdfs { + u16 joint_cdf[3]; + u16 sign_cdf[2]; + u16 clsss_cdf[2][10]; + u16 clsss0_fp_cdf[2][2][3]; + u16 fp_cdf[2][3]; + u16 class0_hp_cdf[2]; + u16 hp_cdf[2]; + u16 class0_cdf[2]; + u16 bits_cdf[2][10]; +}; + +struct av1cdfs { + u16 partition_cdf[13][16]; + u16 kf_ymode_cdf[KF_MODE_CONTEXTS][KF_MODE_CONTEXTS][AV1_INTRA_MODES - 1]; + u16 segment_pred_cdf[PREDICTION_PROBS]; + u16 spatial_pred_seg_tree_cdf[SPATIAL_PREDICTION_PROBS][MAX_MB_SEGMENTS - 1]; + u16 mbskip_cdf[MBSKIP_CONTEXTS]; + u16 delta_q_cdf[DELTA_Q_PROBS]; + u16 delta_lf_multi_cdf[FRAME_LF_COUNT][DELTA_LF_PROBS]; + u16 delta_lf_cdf[DELTA_LF_PROBS]; + u16 skip_mode_cdf[SKIP_MODE_CONTEXTS]; + u16 vartx_part_cdf[VARTX_PART_CONTEXTS][1]; + u16 tx_size_cdf[MAX_TX_CATS][AV1_TX_SIZE_CONTEXTS][MAX_TX_DEPTH]; + u16 if_ymode_cdf[BLOCK_SIZE_GROUPS][AV1_INTRA_MODES - 1]; + u16 uv_mode_cdf[2][AV1_INTRA_MODES][AV1_INTRA_MODES - 1 + 1]; + u16 intra_inter_cdf[INTRA_INTER_CONTEXTS]; + u16 comp_inter_cdf[COMP_INTER_CONTEXTS]; + u16 single_ref_cdf[AV1_REF_CONTEXTS][SINGLE_REFS - 1]; + u16 comp_ref_type_cdf[COMP_REF_TYPE_CONTEXTS][1]; + u16 uni_comp_ref_cdf[UNI_COMP_REF_CONTEXTS][UNIDIR_COMP_REFS - 1][1]; + u16 comp_ref_cdf[AV1_REF_CONTEXTS][FWD_REFS - 1]; + u16 comp_bwdref_cdf[AV1_REF_CONTEXTS][BWD_REFS - 1]; + u16 newmv_cdf[NEWMV_MODE_CONTEXTS]; + u16 zeromv_cdf[ZEROMV_MODE_CONTEXTS]; + u16 refmv_cdf[REFMV_MODE_CONTEXTS]; + u16 drl_cdf[DRL_MODE_CONTEXTS]; + u16 interp_filter_cdf[SWITCHABLE_FILTER_CONTEXTS][AV1_SWITCHABLE_FILTERS - 1]; + struct mvcdfs mv_cdf; + u16 obmc_cdf[BLOCK_SIZE_TYPES]; + u16 motion_mode_cdf[BLOCK_SIZE_TYPES][2]; + u16 inter_compound_mode_cdf[AV1_INTER_MODE_CONTEXTS][INTER_COMPOUND_MODES - 1]; + u16 compound_type_cdf[BLOCK_SIZE_TYPES][CDF_SIZE(COMPOUND_TYPES - 1)]; + u16 interintra_cdf[BLOCK_SIZE_GROUPS]; + u16 interintra_mode_cdf[BLOCK_SIZE_GROUPS][INTERINTRA_MODES - 1]; + u16 wedge_interintra_cdf[BLOCK_SIZE_TYPES]; + u16 wedge_idx_cdf[BLOCK_SIZE_TYPES][CDF_SIZE(16)]; + u16 palette_y_mode_cdf[PALETTE_BLOCK_SIZES][PALETTE_Y_MODE_CONTEXTS][1]; + u16 palette_uv_mode_cdf[PALETTE_UV_MODE_CONTEXTS][1]; + u16 palette_y_size_cdf[PALETTE_BLOCK_SIZES][PALETTE_SIZES - 1]; + u16 palette_uv_size_cdf[PALETTE_BLOCK_SIZES][PALETTE_SIZES - 1]; + u16 cfl_sign_cdf[CFL_JOINT_SIGNS - 1]; + u16 cfl_alpha_cdf[CFL_ALPHA_CONTEXTS][CFL_ALPHABET_SIZE - 1]; + u16 intrabc_cdf[1]; + u16 angle_delta_cdf[DIRECTIONAL_MODES][6]; + u16 filter_intra_mode_cdf[FILTER_INTRA_MODES - 1]; + u16 filter_intra_cdf[BLOCK_SIZES_ALL]; + u16 comp_group_idx_cdf[COMP_GROUP_IDX_CONTEXTS][CDF_SIZE(2)]; + u16 compound_idx_cdf[COMP_INDEX_CONTEXTS][CDF_SIZE(2)]; + u16 dummy0[14]; + // Palette index contexts; sizes 1/7, 2/6, 3/5 packed together + u16 palette_y_color_index_cdf[PALETTE_IDX_CONTEXTS][8]; + u16 palette_uv_color_index_cdf[PALETTE_IDX_CONTEXTS][8]; + u16 tx_type_intra0_cdf[EXTTX_SIZES][AV1_INTRA_MODES][8]; + u16 tx_type_intra1_cdf[EXTTX_SIZES][AV1_INTRA_MODES][4]; + u16 tx_type_inter_cdf[2][EXTTX_SIZES][EXT_TX_TYPES]; + u16 txb_skip_cdf[TX_SIZES][TXB_SKIP_CONTEXTS][CDF_SIZE(2)]; + u16 eob_extra_cdf[TX_SIZES][PLANE_TYPES][EOB_COEF_CONTEXTS][CDF_SIZE(2)]; + u16 dummy1[5]; + u16 eob_flag_cdf16[PLANE_TYPES][2][4]; + u16 eob_flag_cdf32[PLANE_TYPES][2][8]; + u16 eob_flag_cdf64[PLANE_TYPES][2][8]; + u16 eob_flag_cdf128[PLANE_TYPES][2][8]; + u16 eob_flag_cdf256[PLANE_TYPES][2][8]; + u16 eob_flag_cdf512[PLANE_TYPES][2][16]; + u16 eob_flag_cdf1024[PLANE_TYPES][2][16]; + u16 coeff_base_eob_cdf[TX_SIZES][PLANE_TYPES][SIG_COEF_CONTEXTS_EOB][CDF_SIZE(3)]; + u16 coeff_base_cdf[TX_SIZES][PLANE_TYPES][SIG_COEF_CONTEXTS][CDF_SIZE(4) + 1]; + u16 dc_sign_cdf[PLANE_TYPES][DC_SIGN_CONTEXTS][CDF_SIZE(2)]; + u16 dummy2[2]; + u16 coeff_br_cdf[TX_SIZES][PLANE_TYPES][LEVEL_CONTEXTS][CDF_SIZE(BR_CDF_SIZE) + 1]; + u16 dummy3[16]; +}; + +void rockchip_av1_store_cdfs(struct hantro_ctx *ctx, + u32 refresh_frame_flags); +void rockchip_av1_get_cdfs(struct hantro_ctx *ctx, u32 ref_idx); +void rockchip_av1_set_default_cdfs(struct av1cdfs *cdfs, + struct mvcdfs *cdfs_ndvc); +void rockchip_av1_default_coeff_probs(u32 base_qindex, void *ptr); + +#endif /* _ROCKCHIP_AV1_ENTROPYMODE_H_ */ From 727a400686a2c0d25015c9e44916a59b72882f83 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 3 May 2023 09:34:35 +0100 Subject: [PATCH 236/253] media: verisilicon: Add Rockchip AV1 decoder Implement AV1 stateless decoder for rockchip VPU981. It decode 8 and 10 bits AV1 bitstreams. AV1 scaling feature is done by the postprocessor. Signed-off-by: Benjamin Gaignard Reviewed-by: Nicolas Dufresne Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/verisilicon/Makefile | 1 + .../media/platform/verisilicon/hantro_hw.h | 68 +- .../verisilicon/rockchip_vpu981_hw_av1_dec.c | 2022 +++++++++++++++++ .../verisilicon/rockchip_vpu981_regs.h | 477 ++++ 4 files changed, 2566 insertions(+), 2 deletions(-) create mode 100644 drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c create mode 100644 drivers/media/platform/verisilicon/rockchip_vpu981_regs.h diff --git a/drivers/media/platform/verisilicon/Makefile b/drivers/media/platform/verisilicon/Makefile index d2b2679c00eb..c9a9806ab8c5 100644 --- a/drivers/media/platform/verisilicon/Makefile +++ b/drivers/media/platform/verisilicon/Makefile @@ -18,6 +18,7 @@ hantro-vpu-y += \ rockchip_vpu2_hw_h264_dec.o \ rockchip_vpu2_hw_mpeg2_dec.o \ rockchip_vpu2_hw_vp8_dec.o \ + rockchip_vpu981_hw_av1_dec.o \ rockchip_av1_entropymode.o \ hantro_jpeg.o \ hantro_h264.o \ diff --git a/drivers/media/platform/verisilicon/hantro_hw.h b/drivers/media/platform/verisilicon/hantro_hw.h index d7641eced32e..84af70616100 100644 --- a/drivers/media/platform/verisilicon/hantro_hw.h +++ b/drivers/media/platform/verisilicon/hantro_hw.h @@ -37,6 +37,8 @@ #define NUM_REF_PICTURES (V4L2_HEVC_DPB_ENTRIES_NUM_MAX + 1) +#define AV1_MAX_FRAME_BUF_COUNT (V4L2_AV1_TOTAL_REFS_PER_FRAME + 1) + struct hantro_dev; struct hantro_ctx; struct hantro_buf; @@ -250,23 +252,81 @@ struct hantro_vp9_dec_hw_ctx { }; /** - * hantro_av1_dec_hw_ctx + * struct hantro_av1_dec_ctrls + * @sequence: AV1 Sequence + * @tile_group_entry: AV1 Tile Group entry + * @frame: AV1 Frame Header OBU + * @film_grain: AV1 Film Grain + */ +struct hantro_av1_dec_ctrls { + const struct v4l2_ctrl_av1_sequence *sequence; + const struct v4l2_ctrl_av1_tile_group_entry *tile_group_entry; + const struct v4l2_ctrl_av1_frame *frame; + const struct v4l2_ctrl_av1_film_grain *film_grain; +}; + +struct hantro_av1_frame_ref { + int width; + int height; + int mi_cols; + int mi_rows; + u64 timestamp; + enum v4l2_av1_frame_type frame_type; + bool used; + u32 order_hint; + u32 order_hints[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + struct vb2_v4l2_buffer *vb2_ref; +}; + +/** + * struct hantro_av1_dec_hw_ctx + * @db_data_col: db tile col data buffer + * @db_ctrl_col: db tile col ctrl buffer + * @cdef_col: cdef tile col buffer + * @sr_col: sr tile col buffer + * @lr_col: lr tile col buffer + * @global_model: global model buffer + * @tile_info: tile info buffer + * @segment: segmentation info buffer + * @prob_tbl: probability table + * @prob_tbl_out: probability table output + * @tile_buf: tile buffer + * @ctrls: V4L2 controls attached to a run + * @frame_refs: reference frames info slots + * @ref_frame_sign_bias: array of sign bias + * @num_tile_cols_allocated: number of allocated tiles * @cdfs: current probabilities structure * @cdfs_ndvc: current mv probabilities structure * @default_cdfs: default probabilities structure * @default_cdfs_ndvc: default mv probabilties structure * @cdfs_last: stored probabilities structures * @cdfs_last_ndvc: stored mv probabilities structures + * @current_frame_index: index of the current in frame_refs array */ struct hantro_av1_dec_hw_ctx { + struct hantro_aux_buf db_data_col; + struct hantro_aux_buf db_ctrl_col; + struct hantro_aux_buf cdef_col; + struct hantro_aux_buf sr_col; + struct hantro_aux_buf lr_col; + struct hantro_aux_buf global_model; + struct hantro_aux_buf tile_info; + struct hantro_aux_buf segment; + struct hantro_aux_buf prob_tbl; + struct hantro_aux_buf prob_tbl_out; + struct hantro_aux_buf tile_buf; + struct hantro_av1_dec_ctrls ctrls; + struct hantro_av1_frame_ref frame_refs[AV1_MAX_FRAME_BUF_COUNT]; + u32 ref_frame_sign_bias[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + unsigned int num_tile_cols_allocated; struct av1cdfs *cdfs; struct mvcdfs *cdfs_ndvc; struct av1cdfs default_cdfs; struct mvcdfs default_cdfs_ndvc; struct av1cdfs cdfs_last[NUM_REF_FRAMES]; struct mvcdfs cdfs_last_ndvc[NUM_REF_FRAMES]; + int current_frame_index; }; - /** * struct hantro_postproc_ctx * @@ -381,6 +441,10 @@ void hantro_hevc_ref_init(struct hantro_ctx *ctx); dma_addr_t hantro_hevc_get_ref_buf(struct hantro_ctx *ctx, s32 poc); int hantro_hevc_add_ref_buf(struct hantro_ctx *ctx, int poc, dma_addr_t addr); +int rockchip_vpu981_av1_dec_init(struct hantro_ctx *ctx); +void rockchip_vpu981_av1_dec_exit(struct hantro_ctx *ctx); +int rockchip_vpu981_av1_dec_run(struct hantro_ctx *ctx); +void rockchip_vpu981_av1_dec_done(struct hantro_ctx *ctx); static inline unsigned short hantro_vp9_num_sbs(unsigned short dimension) { diff --git a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c new file mode 100644 index 000000000000..bf175072a07b --- /dev/null +++ b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c @@ -0,0 +1,2022 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023, Collabora + * + * Author: Benjamin Gaignard + */ + +#include +#include "hantro.h" +#include "hantro_v4l2.h" +#include "rockchip_vpu981_regs.h" + +#define AV1_DEC_MODE 17 +#define GM_GLOBAL_MODELS_PER_FRAME 7 +#define GLOBAL_MODEL_TOTAL_SIZE (6 * 4 + 4 * 2) +#define GLOBAL_MODEL_SIZE ALIGN(GM_GLOBAL_MODELS_PER_FRAME * GLOBAL_MODEL_TOTAL_SIZE, 2048) +#define AV1_MAX_TILES 128 +#define AV1_TILE_INFO_SIZE (AV1_MAX_TILES * 16) +#define AV1DEC_MAX_PIC_BUFFERS 24 +#define AV1_REF_SCALE_SHIFT 14 +#define AV1_INVALID_IDX -1 +#define MAX_FRAME_DISTANCE 31 +#define AV1_PRIMARY_REF_NONE 7 +#define AV1_TILE_SIZE ALIGN(32 * 128, 4096) +/* + * These 3 values aren't defined enum v4l2_av1_segment_feature because + * they are not part of the specification + */ +#define V4L2_AV1_SEG_LVL_ALT_LF_Y_H 2 +#define V4L2_AV1_SEG_LVL_ALT_LF_U 3 +#define V4L2_AV1_SEG_LVL_ALT_LF_V 4 + +#define SUPERRES_SCALE_BITS 3 +#define SCALE_NUMERATOR 8 +#define SUPERRES_SCALE_DENOMINATOR_MIN (SCALE_NUMERATOR + 1) + +#define RS_SUBPEL_BITS 6 +#define RS_SUBPEL_MASK ((1 << RS_SUBPEL_BITS) - 1) +#define RS_SCALE_SUBPEL_BITS 14 +#define RS_SCALE_SUBPEL_MASK ((1 << RS_SCALE_SUBPEL_BITS) - 1) +#define RS_SCALE_EXTRA_BITS (RS_SCALE_SUBPEL_BITS - RS_SUBPEL_BITS) +#define RS_SCALE_EXTRA_OFF (1 << (RS_SCALE_EXTRA_BITS - 1)) + +#define IS_INTRA(type) ((type == V4L2_AV1_KEY_FRAME) || (type == V4L2_AV1_INTRA_ONLY_FRAME)) + +#define LST_BUF_IDX (V4L2_AV1_REF_LAST_FRAME - V4L2_AV1_REF_LAST_FRAME) +#define LST2_BUF_IDX (V4L2_AV1_REF_LAST2_FRAME - V4L2_AV1_REF_LAST_FRAME) +#define LST3_BUF_IDX (V4L2_AV1_REF_LAST3_FRAME - V4L2_AV1_REF_LAST_FRAME) +#define GLD_BUF_IDX (V4L2_AV1_REF_GOLDEN_FRAME - V4L2_AV1_REF_LAST_FRAME) +#define BWD_BUF_IDX (V4L2_AV1_REF_BWDREF_FRAME - V4L2_AV1_REF_LAST_FRAME) +#define ALT2_BUF_IDX (V4L2_AV1_REF_ALTREF2_FRAME - V4L2_AV1_REF_LAST_FRAME) +#define ALT_BUF_IDX (V4L2_AV1_REF_ALTREF_FRAME - V4L2_AV1_REF_LAST_FRAME) + +#define DIV_LUT_PREC_BITS 14 +#define DIV_LUT_BITS 8 +#define DIV_LUT_NUM BIT(DIV_LUT_BITS) +#define WARP_PARAM_REDUCE_BITS 6 +#define WARPEDMODEL_PREC_BITS 16 + +#define AV1_DIV_ROUND_UP_POW2(value, n) \ +({ \ + typeof(n) _n = n; \ + typeof(value) _value = value; \ + (_value + (BIT(_n) >> 1)) >> _n; \ +}) + +#define AV1_DIV_ROUND_UP_POW2_SIGNED(value, n) \ +({ \ + typeof(n) _n_ = n; \ + typeof(value) _value_ = value; \ + (((_value_) < 0) ? -AV1_DIV_ROUND_UP_POW2(-(_value_), (_n_)) \ + : AV1_DIV_ROUND_UP_POW2((_value_), (_n_))); \ +}) + +struct rockchip_av1_film_grain { + u8 scaling_lut_y[256]; + u8 scaling_lut_cb[256]; + u8 scaling_lut_cr[256]; + s16 cropped_luma_grain_block[4096]; + s16 cropped_chroma_grain_block[1024 * 2]; +}; + +static const short div_lut[DIV_LUT_NUM + 1] = { + 16384, 16320, 16257, 16194, 16132, 16070, 16009, 15948, 15888, 15828, 15768, + 15709, 15650, 15592, 15534, 15477, 15420, 15364, 15308, 15252, 15197, 15142, + 15087, 15033, 14980, 14926, 14873, 14821, 14769, 14717, 14665, 14614, 14564, + 14513, 14463, 14413, 14364, 14315, 14266, 14218, 14170, 14122, 14075, 14028, + 13981, 13935, 13888, 13843, 13797, 13752, 13707, 13662, 13618, 13574, 13530, + 13487, 13443, 13400, 13358, 13315, 13273, 13231, 13190, 13148, 13107, 13066, + 13026, 12985, 12945, 12906, 12866, 12827, 12788, 12749, 12710, 12672, 12633, + 12596, 12558, 12520, 12483, 12446, 12409, 12373, 12336, 12300, 12264, 12228, + 12193, 12157, 12122, 12087, 12053, 12018, 11984, 11950, 11916, 11882, 11848, + 11815, 11782, 11749, 11716, 11683, 11651, 11619, 11586, 11555, 11523, 11491, + 11460, 11429, 11398, 11367, 11336, 11305, 11275, 11245, 11215, 11185, 11155, + 11125, 11096, 11067, 11038, 11009, 10980, 10951, 10923, 10894, 10866, 10838, + 10810, 10782, 10755, 10727, 10700, 10673, 10645, 10618, 10592, 10565, 10538, + 10512, 10486, 10460, 10434, 10408, 10382, 10356, 10331, 10305, 10280, 10255, + 10230, 10205, 10180, 10156, 10131, 10107, 10082, 10058, 10034, 10010, 9986, + 9963, 9939, 9916, 9892, 9869, 9846, 9823, 9800, 9777, 9754, 9732, + 9709, 9687, 9664, 9642, 9620, 9598, 9576, 9554, 9533, 9511, 9489, + 9468, 9447, 9425, 9404, 9383, 9362, 9341, 9321, 9300, 9279, 9259, + 9239, 9218, 9198, 9178, 9158, 9138, 9118, 9098, 9079, 9059, 9039, + 9020, 9001, 8981, 8962, 8943, 8924, 8905, 8886, 8867, 8849, 8830, + 8812, 8793, 8775, 8756, 8738, 8720, 8702, 8684, 8666, 8648, 8630, + 8613, 8595, 8577, 8560, 8542, 8525, 8508, 8490, 8473, 8456, 8439, + 8422, 8405, 8389, 8372, 8355, 8339, 8322, 8306, 8289, 8273, 8257, + 8240, 8224, 8208, 8192, +}; + +static int rockchip_vpu981_get_frame_index(struct hantro_ctx *ctx, int ref) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + u64 timestamp; + int i, idx = frame->ref_frame_idx[ref]; + + if (idx >= V4L2_AV1_TOTAL_REFS_PER_FRAME || idx < 0) + return AV1_INVALID_IDX; + + timestamp = frame->reference_frame_ts[idx]; + for (i = 0; i < AV1_MAX_FRAME_BUF_COUNT; i++) { + if (!av1_dec->frame_refs[i].used) + continue; + if (av1_dec->frame_refs[i].timestamp == timestamp) + return i; + } + + return AV1_INVALID_IDX; +} + +static int rockchip_vpu981_get_order_hint(struct hantro_ctx *ctx, int ref) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + int idx = rockchip_vpu981_get_frame_index(ctx, ref); + + if (idx != AV1_INVALID_IDX) + return av1_dec->frame_refs[idx].order_hint; + + return 0; +} + +static int rockchip_vpu981_av1_dec_frame_ref(struct hantro_ctx *ctx, + u64 timestamp) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + int i; + + for (i = 0; i < AV1_MAX_FRAME_BUF_COUNT; i++) { + int j; + + if (av1_dec->frame_refs[i].used) + continue; + + av1_dec->frame_refs[i].width = frame->frame_width_minus_1 + 1; + av1_dec->frame_refs[i].height = frame->frame_height_minus_1 + 1; + av1_dec->frame_refs[i].mi_cols = DIV_ROUND_UP(frame->frame_width_minus_1 + 1, 8); + av1_dec->frame_refs[i].mi_rows = DIV_ROUND_UP(frame->frame_height_minus_1 + 1, 8); + av1_dec->frame_refs[i].timestamp = timestamp; + av1_dec->frame_refs[i].frame_type = frame->frame_type; + av1_dec->frame_refs[i].order_hint = frame->order_hint; + if (!av1_dec->frame_refs[i].vb2_ref) + av1_dec->frame_refs[i].vb2_ref = hantro_get_dst_buf(ctx); + + for (j = 0; j < V4L2_AV1_TOTAL_REFS_PER_FRAME; j++) + av1_dec->frame_refs[i].order_hints[j] = frame->order_hints[j]; + av1_dec->frame_refs[i].used = true; + av1_dec->current_frame_index = i; + + return i; + } + + return AV1_INVALID_IDX; +} + +static void rockchip_vpu981_av1_dec_frame_unref(struct hantro_ctx *ctx, int idx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + + if (idx >= 0) + av1_dec->frame_refs[idx].used = false; +} + +static void rockchip_vpu981_av1_dec_clean_refs(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + + int ref, idx; + + for (idx = 0; idx < AV1_MAX_FRAME_BUF_COUNT; idx++) { + u64 timestamp = av1_dec->frame_refs[idx].timestamp; + bool used = false; + + if (!av1_dec->frame_refs[idx].used) + continue; + + for (ref = 0; ref < V4L2_AV1_TOTAL_REFS_PER_FRAME; ref++) { + if (ctrls->frame->reference_frame_ts[ref] == timestamp) + used = true; + } + + if (!used) + rockchip_vpu981_av1_dec_frame_unref(ctx, idx); + } +} + +static size_t rockchip_vpu981_av1_dec_luma_size(struct hantro_ctx *ctx) +{ + return ctx->dst_fmt.width * ctx->dst_fmt.height * ctx->bit_depth / 8; +} + +static size_t rockchip_vpu981_av1_dec_chroma_size(struct hantro_ctx *ctx) +{ + size_t cr_offset = rockchip_vpu981_av1_dec_luma_size(ctx); + + return ALIGN((cr_offset * 3) / 2, 64); +} + +static void rockchip_vpu981_av1_dec_tiles_free(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + + if (av1_dec->db_data_col.cpu) + dma_free_coherent(vpu->dev, av1_dec->db_data_col.size, + av1_dec->db_data_col.cpu, + av1_dec->db_data_col.dma); + av1_dec->db_data_col.cpu = NULL; + + if (av1_dec->db_ctrl_col.cpu) + dma_free_coherent(vpu->dev, av1_dec->db_ctrl_col.size, + av1_dec->db_ctrl_col.cpu, + av1_dec->db_ctrl_col.dma); + av1_dec->db_ctrl_col.cpu = NULL; + + if (av1_dec->cdef_col.cpu) + dma_free_coherent(vpu->dev, av1_dec->cdef_col.size, + av1_dec->cdef_col.cpu, av1_dec->cdef_col.dma); + av1_dec->cdef_col.cpu = NULL; + + if (av1_dec->sr_col.cpu) + dma_free_coherent(vpu->dev, av1_dec->sr_col.size, + av1_dec->sr_col.cpu, av1_dec->sr_col.dma); + av1_dec->sr_col.cpu = NULL; + + if (av1_dec->lr_col.cpu) + dma_free_coherent(vpu->dev, av1_dec->lr_col.size, + av1_dec->lr_col.cpu, av1_dec->lr_col.dma); + av1_dec->lr_col.cpu = NULL; +} + +static int rockchip_vpu981_av1_dec_tiles_reallocate(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + unsigned int num_tile_cols = 1 << ctrls->tile_group_entry->tile_col; + unsigned int height = ALIGN(ctrls->frame->frame_height_minus_1 + 1, 64); + unsigned int height_in_sb = height / 64; + unsigned int stripe_num = ((height + 8) + 63) / 64; + size_t size; + + if (av1_dec->db_data_col.size >= + ALIGN(height * 12 * ctx->bit_depth / 8, 128) * num_tile_cols) + return 0; + + rockchip_vpu981_av1_dec_tiles_free(ctx); + + size = ALIGN(height * 12 * ctx->bit_depth / 8, 128) * num_tile_cols; + av1_dec->db_data_col.cpu = dma_alloc_coherent(vpu->dev, size, + &av1_dec->db_data_col.dma, + GFP_KERNEL); + if (!av1_dec->db_data_col.cpu) + goto buffer_allocation_error; + av1_dec->db_data_col.size = size; + + size = ALIGN(height * 2 * 16 / 4, 128) * num_tile_cols; + av1_dec->db_ctrl_col.cpu = dma_alloc_coherent(vpu->dev, size, + &av1_dec->db_ctrl_col.dma, + GFP_KERNEL); + if (!av1_dec->db_ctrl_col.cpu) + goto buffer_allocation_error; + av1_dec->db_ctrl_col.size = size; + + size = ALIGN(height_in_sb * 44 * ctx->bit_depth * 16 / 8, 128) * num_tile_cols; + av1_dec->cdef_col.cpu = dma_alloc_coherent(vpu->dev, size, + &av1_dec->cdef_col.dma, + GFP_KERNEL); + if (!av1_dec->cdef_col.cpu) + goto buffer_allocation_error; + av1_dec->cdef_col.size = size; + + size = ALIGN(height_in_sb * (3040 + 1280), 128) * num_tile_cols; + av1_dec->sr_col.cpu = dma_alloc_coherent(vpu->dev, size, + &av1_dec->sr_col.dma, + GFP_KERNEL); + if (!av1_dec->sr_col.cpu) + goto buffer_allocation_error; + av1_dec->sr_col.size = size; + + size = ALIGN(stripe_num * 1536 * ctx->bit_depth / 8, 128) * num_tile_cols; + av1_dec->lr_col.cpu = dma_alloc_coherent(vpu->dev, size, + &av1_dec->lr_col.dma, + GFP_KERNEL); + if (!av1_dec->lr_col.cpu) + goto buffer_allocation_error; + av1_dec->lr_col.size = size; + + av1_dec->num_tile_cols_allocated = num_tile_cols; + return 0; + +buffer_allocation_error: + rockchip_vpu981_av1_dec_tiles_free(ctx); + return -ENOMEM; +} + +void rockchip_vpu981_av1_dec_exit(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + + if (av1_dec->global_model.cpu) + dma_free_coherent(vpu->dev, av1_dec->global_model.size, + av1_dec->global_model.cpu, + av1_dec->global_model.dma); + av1_dec->global_model.cpu = NULL; + + if (av1_dec->tile_info.cpu) + dma_free_coherent(vpu->dev, av1_dec->tile_info.size, + av1_dec->tile_info.cpu, + av1_dec->tile_info.dma); + av1_dec->tile_info.cpu = NULL; + + if (av1_dec->prob_tbl.cpu) + dma_free_coherent(vpu->dev, av1_dec->prob_tbl.size, + av1_dec->prob_tbl.cpu, av1_dec->prob_tbl.dma); + av1_dec->prob_tbl.cpu = NULL; + + if (av1_dec->prob_tbl_out.cpu) + dma_free_coherent(vpu->dev, av1_dec->prob_tbl_out.size, + av1_dec->prob_tbl_out.cpu, + av1_dec->prob_tbl_out.dma); + av1_dec->prob_tbl_out.cpu = NULL; + + if (av1_dec->tile_buf.cpu) + dma_free_coherent(vpu->dev, av1_dec->tile_buf.size, + av1_dec->tile_buf.cpu, av1_dec->tile_buf.dma); + av1_dec->tile_buf.cpu = NULL; + + rockchip_vpu981_av1_dec_tiles_free(ctx); +} + +int rockchip_vpu981_av1_dec_init(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + + memset(av1_dec, 0, sizeof(*av1_dec)); + + av1_dec->global_model.cpu = dma_alloc_coherent(vpu->dev, GLOBAL_MODEL_SIZE, + &av1_dec->global_model.dma, + GFP_KERNEL); + if (!av1_dec->global_model.cpu) + return -ENOMEM; + av1_dec->global_model.size = GLOBAL_MODEL_SIZE; + + av1_dec->tile_info.cpu = dma_alloc_coherent(vpu->dev, AV1_MAX_TILES, + &av1_dec->tile_info.dma, + GFP_KERNEL); + if (!av1_dec->tile_info.cpu) + return -ENOMEM; + av1_dec->tile_info.size = AV1_MAX_TILES; + + av1_dec->prob_tbl.cpu = dma_alloc_coherent(vpu->dev, + ALIGN(sizeof(struct av1cdfs), 2048), + &av1_dec->prob_tbl.dma, + GFP_KERNEL); + if (!av1_dec->prob_tbl.cpu) + return -ENOMEM; + av1_dec->prob_tbl.size = ALIGN(sizeof(struct av1cdfs), 2048); + + av1_dec->prob_tbl_out.cpu = dma_alloc_coherent(vpu->dev, + ALIGN(sizeof(struct av1cdfs), 2048), + &av1_dec->prob_tbl_out.dma, + GFP_KERNEL); + if (!av1_dec->prob_tbl_out.cpu) + return -ENOMEM; + av1_dec->prob_tbl_out.size = ALIGN(sizeof(struct av1cdfs), 2048); + av1_dec->cdfs = &av1_dec->default_cdfs; + av1_dec->cdfs_ndvc = &av1_dec->default_cdfs_ndvc; + + rockchip_av1_set_default_cdfs(av1_dec->cdfs, av1_dec->cdfs_ndvc); + + av1_dec->tile_buf.cpu = dma_alloc_coherent(vpu->dev, + AV1_TILE_SIZE, + &av1_dec->tile_buf.dma, + GFP_KERNEL); + if (!av1_dec->tile_buf.cpu) + return -ENOMEM; + av1_dec->tile_buf.size = AV1_TILE_SIZE; + + return 0; +} + +static int rockchip_vpu981_av1_dec_prepare_run(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + + ctrls->sequence = hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_SEQUENCE); + if (WARN_ON(!ctrls->sequence)) + return -EINVAL; + + ctrls->tile_group_entry = + hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY); + if (WARN_ON(!ctrls->tile_group_entry)) + return -EINVAL; + + ctrls->frame = hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_FRAME); + if (WARN_ON(!ctrls->frame)) + return -EINVAL; + + ctrls->film_grain = + hantro_get_ctrl(ctx, V4L2_CID_STATELESS_AV1_FILM_GRAIN); + + return rockchip_vpu981_av1_dec_tiles_reallocate(ctx); +} + +static inline int rockchip_vpu981_av1_dec_get_msb(u32 n) +{ + if (n == 0) + return 0; + return 31 ^ __builtin_clz(n); +} + +static short rockchip_vpu981_av1_dec_resolve_divisor_32(u32 d, short *shift) +{ + int f; + u64 e; + + *shift = rockchip_vpu981_av1_dec_get_msb(d); + /* e is obtained from D after resetting the most significant 1 bit. */ + e = d - ((u32)1 << *shift); + /* Get the most significant DIV_LUT_BITS (8) bits of e into f */ + if (*shift > DIV_LUT_BITS) + f = AV1_DIV_ROUND_UP_POW2(e, *shift - DIV_LUT_BITS); + else + f = e << (DIV_LUT_BITS - *shift); + if (f > DIV_LUT_NUM) + return -1; + *shift += DIV_LUT_PREC_BITS; + /* Use f as lookup into the precomputed table of multipliers */ + return div_lut[f]; +} + +static void +rockchip_vpu981_av1_dec_get_shear_params(const u32 *params, s64 *alpha, + s64 *beta, s64 *gamma, s64 *delta) +{ + const int *mat = params; + short shift; + short y; + long long gv, dv; + + if (mat[2] <= 0) + return; + + *alpha = clamp_val(mat[2] - (1 << WARPEDMODEL_PREC_BITS), S16_MIN, S16_MAX); + *beta = clamp_val(mat[3], S16_MIN, S16_MAX); + + y = rockchip_vpu981_av1_dec_resolve_divisor_32(abs(mat[2]), &shift) * (mat[2] < 0 ? -1 : 1); + + gv = ((long long)mat[4] * (1 << WARPEDMODEL_PREC_BITS)) * y; + + *gamma = clamp_val((int)AV1_DIV_ROUND_UP_POW2_SIGNED(gv, shift), S16_MIN, S16_MAX); + + dv = ((long long)mat[3] * mat[4]) * y; + *delta = clamp_val(mat[5] - + (int)AV1_DIV_ROUND_UP_POW2_SIGNED(dv, shift) - (1 << WARPEDMODEL_PREC_BITS), + S16_MIN, S16_MAX); + + *alpha = AV1_DIV_ROUND_UP_POW2_SIGNED(*alpha, WARP_PARAM_REDUCE_BITS) + * (1 << WARP_PARAM_REDUCE_BITS); + *beta = AV1_DIV_ROUND_UP_POW2_SIGNED(*beta, WARP_PARAM_REDUCE_BITS) + * (1 << WARP_PARAM_REDUCE_BITS); + *gamma = AV1_DIV_ROUND_UP_POW2_SIGNED(*gamma, WARP_PARAM_REDUCE_BITS) + * (1 << WARP_PARAM_REDUCE_BITS); + *delta = AV1_DIV_ROUND_UP_POW2_SIGNED(*delta, WARP_PARAM_REDUCE_BITS) + * (1 << WARP_PARAM_REDUCE_BITS); +} + +static void rockchip_vpu981_av1_dec_set_global_model(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + const struct v4l2_av1_global_motion *gm = &frame->global_motion; + u8 *dst = av1_dec->global_model.cpu; + struct hantro_dev *vpu = ctx->dev; + int ref_frame, i; + + memset(dst, 0, GLOBAL_MODEL_SIZE); + for (ref_frame = 0; ref_frame < V4L2_AV1_REFS_PER_FRAME; ++ref_frame) { + s64 alpha = 0, beta = 0, gamma = 0, delta = 0; + + for (i = 0; i < 6; ++i) { + if (i == 2) + *(s32 *)dst = + gm->params[V4L2_AV1_REF_LAST_FRAME + ref_frame][3]; + else if (i == 3) + *(s32 *)dst = + gm->params[V4L2_AV1_REF_LAST_FRAME + ref_frame][2]; + else + *(s32 *)dst = + gm->params[V4L2_AV1_REF_LAST_FRAME + ref_frame][i]; + dst += 4; + } + + if (gm->type[V4L2_AV1_REF_LAST_FRAME + ref_frame] <= V4L2_AV1_WARP_MODEL_AFFINE) + rockchip_vpu981_av1_dec_get_shear_params(&gm->params[V4L2_AV1_REF_LAST_FRAME + ref_frame][0], + &alpha, &beta, &gamma, &delta); + + *(s16 *)dst = alpha; + dst += 2; + *(s16 *)dst = beta; + dst += 2; + *(s16 *)dst = gamma; + dst += 2; + *(s16 *)dst = delta; + dst += 2; + } + + hantro_write_addr(vpu, AV1_GLOBAL_MODEL, av1_dec->global_model.dma); +} + +static int rockchip_vpu981_av1_tile_log2(int target) +{ + int k; + + /* + * returns the smallest value for k such that 1 << k is greater + * than or equal to target + */ + for (k = 0; (1 << k) < target; k++); + + return k; +} + +static void rockchip_vpu981_av1_dec_set_tile_info(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_av1_tile_info *tile_info = &ctrls->frame->tile_info; + const struct v4l2_ctrl_av1_tile_group_entry *group_entry = + ctrls->tile_group_entry; + int context_update_y = + tile_info->context_update_tile_id / tile_info->tile_cols; + int context_update_x = + tile_info->context_update_tile_id % tile_info->tile_cols; + int context_update_tile_id = + context_update_x * tile_info->tile_rows + context_update_y; + u8 *dst = av1_dec->tile_info.cpu; + struct hantro_dev *vpu = ctx->dev; + int tile0, tile1; + + memset(dst, 0, av1_dec->tile_info.size); + + for (tile0 = 0; tile0 < tile_info->tile_cols; tile0++) { + for (tile1 = 0; tile1 < tile_info->tile_rows; tile1++) { + int tile_id = tile1 * tile_info->tile_cols + tile0; + u32 start, end; + u32 y0 = + tile_info->height_in_sbs_minus_1[tile1] + 1; + u32 x0 = tile_info->width_in_sbs_minus_1[tile0] + 1; + + /* tile size in SB units (width,height) */ + *dst++ = x0; + *dst++ = 0; + *dst++ = 0; + *dst++ = 0; + *dst++ = y0; + *dst++ = 0; + *dst++ = 0; + *dst++ = 0; + + /* tile start position */ + start = group_entry[tile_id].tile_offset - group_entry[0].tile_offset; + *dst++ = start & 255; + *dst++ = (start >> 8) & 255; + *dst++ = (start >> 16) & 255; + *dst++ = (start >> 24) & 255; + + /* number of bytes in tile data */ + end = start + group_entry[tile_id].tile_size; + *dst++ = end & 255; + *dst++ = (end >> 8) & 255; + *dst++ = (end >> 16) & 255; + *dst++ = (end >> 24) & 255; + } + } + + hantro_reg_write(vpu, &av1_multicore_expect_context_update, !!(context_update_x == 0)); + hantro_reg_write(vpu, &av1_tile_enable, + !!((tile_info->tile_cols > 1) || (tile_info->tile_rows > 1))); + hantro_reg_write(vpu, &av1_num_tile_cols_8k, tile_info->tile_cols); + hantro_reg_write(vpu, &av1_num_tile_rows_8k, tile_info->tile_rows); + hantro_reg_write(vpu, &av1_context_update_tile_id, context_update_tile_id); + hantro_reg_write(vpu, &av1_tile_transpose, 1); + if (rockchip_vpu981_av1_tile_log2(tile_info->tile_cols) || + rockchip_vpu981_av1_tile_log2(tile_info->tile_rows)) + hantro_reg_write(vpu, &av1_dec_tile_size_mag, tile_info->tile_size_bytes - 1); + else + hantro_reg_write(vpu, &av1_dec_tile_size_mag, 3); + + hantro_write_addr(vpu, AV1_TILE_BASE, av1_dec->tile_info.dma); +} + +static int rockchip_vpu981_av1_dec_get_dist(struct hantro_ctx *ctx, + int a, int b) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + int bits = ctrls->sequence->order_hint_bits - 1; + int diff, m; + + if (!ctrls->sequence->order_hint_bits) + return 0; + + diff = a - b; + m = 1 << bits; + diff = (diff & (m - 1)) - (diff & m); + + return diff; +} + +static void rockchip_vpu981_av1_dec_set_frame_sign_bias(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + const struct v4l2_ctrl_av1_sequence *sequence = ctrls->sequence; + int i; + + if (!sequence->order_hint_bits || IS_INTRA(frame->frame_type)) { + for (i = 0; i < V4L2_AV1_TOTAL_REFS_PER_FRAME; i++) + av1_dec->ref_frame_sign_bias[i] = 0; + + return; + } + // Identify the nearest forward and backward references. + for (i = 0; i < V4L2_AV1_TOTAL_REFS_PER_FRAME - 1; i++) { + if (rockchip_vpu981_get_frame_index(ctx, i) >= 0) { + int rel_off = + rockchip_vpu981_av1_dec_get_dist(ctx, + rockchip_vpu981_get_order_hint(ctx, i), + frame->order_hint); + av1_dec->ref_frame_sign_bias[i + 1] = (rel_off <= 0) ? 0 : 1; + } + } +} + +static bool +rockchip_vpu981_av1_dec_set_ref(struct hantro_ctx *ctx, int ref, int idx, + int width, int height) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + struct hantro_dev *vpu = ctx->dev; + struct hantro_decoded_buffer *dst; + dma_addr_t luma_addr, chroma_addr, mv_addr = 0; + size_t cr_offset = rockchip_vpu981_av1_dec_luma_size(ctx); + size_t mv_offset = rockchip_vpu981_av1_dec_chroma_size(ctx); + int cur_width = frame->frame_width_minus_1 + 1; + int cur_height = frame->frame_height_minus_1 + 1; + int scale_width = + ((width << AV1_REF_SCALE_SHIFT) + cur_width / 2) / cur_width; + int scale_height = + ((height << AV1_REF_SCALE_SHIFT) + cur_height / 2) / cur_height; + + switch (ref) { + case 0: + hantro_reg_write(vpu, &av1_ref0_height, height); + hantro_reg_write(vpu, &av1_ref0_width, width); + hantro_reg_write(vpu, &av1_ref0_ver_scale, scale_width); + hantro_reg_write(vpu, &av1_ref0_hor_scale, scale_height); + break; + case 1: + hantro_reg_write(vpu, &av1_ref1_height, height); + hantro_reg_write(vpu, &av1_ref1_width, width); + hantro_reg_write(vpu, &av1_ref1_ver_scale, scale_width); + hantro_reg_write(vpu, &av1_ref1_hor_scale, scale_height); + break; + case 2: + hantro_reg_write(vpu, &av1_ref2_height, height); + hantro_reg_write(vpu, &av1_ref2_width, width); + hantro_reg_write(vpu, &av1_ref2_ver_scale, scale_width); + hantro_reg_write(vpu, &av1_ref2_hor_scale, scale_height); + break; + case 3: + hantro_reg_write(vpu, &av1_ref3_height, height); + hantro_reg_write(vpu, &av1_ref3_width, width); + hantro_reg_write(vpu, &av1_ref3_ver_scale, scale_width); + hantro_reg_write(vpu, &av1_ref3_hor_scale, scale_height); + break; + case 4: + hantro_reg_write(vpu, &av1_ref4_height, height); + hantro_reg_write(vpu, &av1_ref4_width, width); + hantro_reg_write(vpu, &av1_ref4_ver_scale, scale_width); + hantro_reg_write(vpu, &av1_ref4_hor_scale, scale_height); + break; + case 5: + hantro_reg_write(vpu, &av1_ref5_height, height); + hantro_reg_write(vpu, &av1_ref5_width, width); + hantro_reg_write(vpu, &av1_ref5_ver_scale, scale_width); + hantro_reg_write(vpu, &av1_ref5_hor_scale, scale_height); + break; + case 6: + hantro_reg_write(vpu, &av1_ref6_height, height); + hantro_reg_write(vpu, &av1_ref6_width, width); + hantro_reg_write(vpu, &av1_ref6_ver_scale, scale_width); + hantro_reg_write(vpu, &av1_ref6_hor_scale, scale_height); + break; + default: + pr_warn("AV1 invalid reference frame index\n"); + } + + dst = vb2_to_hantro_decoded_buf(&av1_dec->frame_refs[idx].vb2_ref->vb2_buf); + luma_addr = hantro_get_dec_buf_addr(ctx, &dst->base.vb.vb2_buf); + chroma_addr = luma_addr + cr_offset; + mv_addr = luma_addr + mv_offset; + + hantro_write_addr(vpu, AV1_REFERENCE_Y(ref), luma_addr); + hantro_write_addr(vpu, AV1_REFERENCE_CB(ref), chroma_addr); + hantro_write_addr(vpu, AV1_REFERENCE_MV(ref), mv_addr); + + return (scale_width != (1 << AV1_REF_SCALE_SHIFT)) || + (scale_height != (1 << AV1_REF_SCALE_SHIFT)); +} + +static void rockchip_vpu981_av1_dec_set_sign_bias(struct hantro_ctx *ctx, + int ref, int val) +{ + struct hantro_dev *vpu = ctx->dev; + + switch (ref) { + case 0: + hantro_reg_write(vpu, &av1_ref0_sign_bias, val); + break; + case 1: + hantro_reg_write(vpu, &av1_ref1_sign_bias, val); + break; + case 2: + hantro_reg_write(vpu, &av1_ref2_sign_bias, val); + break; + case 3: + hantro_reg_write(vpu, &av1_ref3_sign_bias, val); + break; + case 4: + hantro_reg_write(vpu, &av1_ref4_sign_bias, val); + break; + case 5: + hantro_reg_write(vpu, &av1_ref5_sign_bias, val); + break; + case 6: + hantro_reg_write(vpu, &av1_ref6_sign_bias, val); + break; + default: + pr_warn("AV1 invalid sign bias index\n"); + break; + } +} + +static void rockchip_vpu981_av1_dec_set_segmentation(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + const struct v4l2_av1_segmentation *seg = &frame->segmentation; + u32 segval[V4L2_AV1_MAX_SEGMENTS][V4L2_AV1_SEG_LVL_MAX] = { 0 }; + struct hantro_dev *vpu = ctx->dev; + u8 segsign = 0, preskip_segid = 0, last_active_seg = 0, i, j; + + if (!!(seg->flags & V4L2_AV1_SEGMENTATION_FLAG_ENABLED) && + frame->primary_ref_frame < V4L2_AV1_REFS_PER_FRAME) { + int idx = rockchip_vpu981_get_frame_index(ctx, frame->primary_ref_frame); + + if (idx >= 0) { + dma_addr_t luma_addr, mv_addr = 0; + struct hantro_decoded_buffer *seg; + size_t mv_offset = rockchip_vpu981_av1_dec_chroma_size(ctx); + + seg = vb2_to_hantro_decoded_buf(&av1_dec->frame_refs[idx].vb2_ref->vb2_buf); + luma_addr = hantro_get_dec_buf_addr(ctx, &seg->base.vb.vb2_buf); + mv_addr = luma_addr + mv_offset; + + hantro_write_addr(vpu, AV1_SEGMENTATION, mv_addr); + hantro_reg_write(vpu, &av1_use_temporal3_mvs, 1); + } + } + + hantro_reg_write(vpu, &av1_segment_temp_upd_e, + !!(seg->flags & V4L2_AV1_SEGMENTATION_FLAG_TEMPORAL_UPDATE)); + hantro_reg_write(vpu, &av1_segment_upd_e, + !!(seg->flags & V4L2_AV1_SEGMENTATION_FLAG_UPDATE_MAP)); + hantro_reg_write(vpu, &av1_segment_e, + !!(seg->flags & V4L2_AV1_SEGMENTATION_FLAG_ENABLED)); + + hantro_reg_write(vpu, &av1_error_resilient, + !!(frame->flags & V4L2_AV1_FRAME_FLAG_ERROR_RESILIENT_MODE)); + + if (IS_INTRA(frame->frame_type) || + !!(frame->flags & V4L2_AV1_FRAME_FLAG_ERROR_RESILIENT_MODE)) { + hantro_reg_write(vpu, &av1_use_temporal3_mvs, 0); + } + + if (seg->flags & V4L2_AV1_SEGMENTATION_FLAG_ENABLED) { + int s; + + for (s = 0; s < V4L2_AV1_MAX_SEGMENTS; s++) { + if (seg->feature_enabled[s] & + V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_ALT_Q)) { + segval[s][V4L2_AV1_SEG_LVL_ALT_Q] = + clamp(abs(seg->feature_data[s][V4L2_AV1_SEG_LVL_ALT_Q]), + 0, 255); + segsign |= + (seg->feature_data[s][V4L2_AV1_SEG_LVL_ALT_Q] < 0) << s; + } + + if (seg->feature_enabled[s] & + V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_ALT_LF_Y_V)) + segval[s][V4L2_AV1_SEG_LVL_ALT_LF_Y_V] = + clamp(abs(seg->feature_data[s][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]), + -63, 63); + + if (seg->feature_enabled[s] & + V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_ALT_LF_Y_H)) + segval[s][V4L2_AV1_SEG_LVL_ALT_LF_Y_H] = + clamp(abs(seg->feature_data[s][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]), + -63, 63); + + if (seg->feature_enabled[s] & + V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_ALT_LF_U)) + segval[s][V4L2_AV1_SEG_LVL_ALT_LF_U] = + clamp(abs(seg->feature_data[s][V4L2_AV1_SEG_LVL_ALT_LF_U]), + -63, 63); + + if (seg->feature_enabled[s] & + V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_ALT_LF_V)) + segval[s][V4L2_AV1_SEG_LVL_ALT_LF_V] = + clamp(abs(seg->feature_data[s][V4L2_AV1_SEG_LVL_ALT_LF_V]), + -63, 63); + + if (frame->frame_type && seg->feature_enabled[s] & + V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_REF_FRAME)) + segval[s][V4L2_AV1_SEG_LVL_REF_FRAME]++; + + if (seg->feature_enabled[s] & + V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_REF_SKIP)) + segval[s][V4L2_AV1_SEG_LVL_REF_SKIP] = 1; + + if (seg->feature_enabled[s] & + V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_REF_GLOBALMV)) + segval[s][V4L2_AV1_SEG_LVL_REF_GLOBALMV] = 1; + } + } + + for (i = 0; i < V4L2_AV1_MAX_SEGMENTS; i++) { + for (j = 0; j < V4L2_AV1_SEG_LVL_MAX; j++) { + if (seg->feature_enabled[i] + & V4L2_AV1_SEGMENT_FEATURE_ENABLED(j)) { + preskip_segid |= (j >= V4L2_AV1_SEG_LVL_REF_FRAME); + last_active_seg = max(i, last_active_seg); + } + } + } + + hantro_reg_write(vpu, &av1_last_active_seg, last_active_seg); + hantro_reg_write(vpu, &av1_preskip_segid, preskip_segid); + + hantro_reg_write(vpu, &av1_seg_quant_sign, segsign); + + /* Write QP, filter level, ref frame and skip for every segment */ + hantro_reg_write(vpu, &av1_quant_seg0, + segval[0][V4L2_AV1_SEG_LVL_ALT_Q]); + hantro_reg_write(vpu, &av1_filt_level_delta0_seg0, + segval[0][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]); + hantro_reg_write(vpu, &av1_filt_level_delta1_seg0, + segval[0][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]); + hantro_reg_write(vpu, &av1_filt_level_delta2_seg0, + segval[0][V4L2_AV1_SEG_LVL_ALT_LF_U]); + hantro_reg_write(vpu, &av1_filt_level_delta3_seg0, + segval[0][V4L2_AV1_SEG_LVL_ALT_LF_V]); + hantro_reg_write(vpu, &av1_refpic_seg0, + segval[0][V4L2_AV1_SEG_LVL_REF_FRAME]); + hantro_reg_write(vpu, &av1_skip_seg0, + segval[0][V4L2_AV1_SEG_LVL_REF_SKIP]); + hantro_reg_write(vpu, &av1_global_mv_seg0, + segval[0][V4L2_AV1_SEG_LVL_REF_GLOBALMV]); + + hantro_reg_write(vpu, &av1_quant_seg1, + segval[1][V4L2_AV1_SEG_LVL_ALT_Q]); + hantro_reg_write(vpu, &av1_filt_level_delta0_seg1, + segval[1][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]); + hantro_reg_write(vpu, &av1_filt_level_delta1_seg1, + segval[1][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]); + hantro_reg_write(vpu, &av1_filt_level_delta2_seg1, + segval[1][V4L2_AV1_SEG_LVL_ALT_LF_U]); + hantro_reg_write(vpu, &av1_filt_level_delta3_seg1, + segval[1][V4L2_AV1_SEG_LVL_ALT_LF_V]); + hantro_reg_write(vpu, &av1_refpic_seg1, + segval[1][V4L2_AV1_SEG_LVL_REF_FRAME]); + hantro_reg_write(vpu, &av1_skip_seg1, + segval[1][V4L2_AV1_SEG_LVL_REF_SKIP]); + hantro_reg_write(vpu, &av1_global_mv_seg1, + segval[1][V4L2_AV1_SEG_LVL_REF_GLOBALMV]); + + hantro_reg_write(vpu, &av1_quant_seg2, + segval[2][V4L2_AV1_SEG_LVL_ALT_Q]); + hantro_reg_write(vpu, &av1_filt_level_delta0_seg2, + segval[2][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]); + hantro_reg_write(vpu, &av1_filt_level_delta1_seg2, + segval[2][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]); + hantro_reg_write(vpu, &av1_filt_level_delta2_seg2, + segval[2][V4L2_AV1_SEG_LVL_ALT_LF_U]); + hantro_reg_write(vpu, &av1_filt_level_delta3_seg2, + segval[2][V4L2_AV1_SEG_LVL_ALT_LF_V]); + hantro_reg_write(vpu, &av1_refpic_seg2, + segval[2][V4L2_AV1_SEG_LVL_REF_FRAME]); + hantro_reg_write(vpu, &av1_skip_seg2, + segval[2][V4L2_AV1_SEG_LVL_REF_SKIP]); + hantro_reg_write(vpu, &av1_global_mv_seg2, + segval[2][V4L2_AV1_SEG_LVL_REF_GLOBALMV]); + + hantro_reg_write(vpu, &av1_quant_seg3, + segval[3][V4L2_AV1_SEG_LVL_ALT_Q]); + hantro_reg_write(vpu, &av1_filt_level_delta0_seg3, + segval[3][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]); + hantro_reg_write(vpu, &av1_filt_level_delta1_seg3, + segval[3][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]); + hantro_reg_write(vpu, &av1_filt_level_delta2_seg3, + segval[3][V4L2_AV1_SEG_LVL_ALT_LF_U]); + hantro_reg_write(vpu, &av1_filt_level_delta3_seg3, + segval[3][V4L2_AV1_SEG_LVL_ALT_LF_V]); + hantro_reg_write(vpu, &av1_refpic_seg3, + segval[3][V4L2_AV1_SEG_LVL_REF_FRAME]); + hantro_reg_write(vpu, &av1_skip_seg3, + segval[3][V4L2_AV1_SEG_LVL_REF_SKIP]); + hantro_reg_write(vpu, &av1_global_mv_seg3, + segval[3][V4L2_AV1_SEG_LVL_REF_GLOBALMV]); + + hantro_reg_write(vpu, &av1_quant_seg4, + segval[4][V4L2_AV1_SEG_LVL_ALT_Q]); + hantro_reg_write(vpu, &av1_filt_level_delta0_seg4, + segval[4][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]); + hantro_reg_write(vpu, &av1_filt_level_delta1_seg4, + segval[4][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]); + hantro_reg_write(vpu, &av1_filt_level_delta2_seg4, + segval[4][V4L2_AV1_SEG_LVL_ALT_LF_U]); + hantro_reg_write(vpu, &av1_filt_level_delta3_seg4, + segval[4][V4L2_AV1_SEG_LVL_ALT_LF_V]); + hantro_reg_write(vpu, &av1_refpic_seg4, + segval[4][V4L2_AV1_SEG_LVL_REF_FRAME]); + hantro_reg_write(vpu, &av1_skip_seg4, + segval[4][V4L2_AV1_SEG_LVL_REF_SKIP]); + hantro_reg_write(vpu, &av1_global_mv_seg4, + segval[4][V4L2_AV1_SEG_LVL_REF_GLOBALMV]); + + hantro_reg_write(vpu, &av1_quant_seg5, + segval[5][V4L2_AV1_SEG_LVL_ALT_Q]); + hantro_reg_write(vpu, &av1_filt_level_delta0_seg5, + segval[5][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]); + hantro_reg_write(vpu, &av1_filt_level_delta1_seg5, + segval[5][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]); + hantro_reg_write(vpu, &av1_filt_level_delta2_seg5, + segval[5][V4L2_AV1_SEG_LVL_ALT_LF_U]); + hantro_reg_write(vpu, &av1_filt_level_delta3_seg5, + segval[5][V4L2_AV1_SEG_LVL_ALT_LF_V]); + hantro_reg_write(vpu, &av1_refpic_seg5, + segval[5][V4L2_AV1_SEG_LVL_REF_FRAME]); + hantro_reg_write(vpu, &av1_skip_seg5, + segval[5][V4L2_AV1_SEG_LVL_REF_SKIP]); + hantro_reg_write(vpu, &av1_global_mv_seg5, + segval[5][V4L2_AV1_SEG_LVL_REF_GLOBALMV]); + + hantro_reg_write(vpu, &av1_quant_seg6, + segval[6][V4L2_AV1_SEG_LVL_ALT_Q]); + hantro_reg_write(vpu, &av1_filt_level_delta0_seg6, + segval[6][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]); + hantro_reg_write(vpu, &av1_filt_level_delta1_seg6, + segval[6][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]); + hantro_reg_write(vpu, &av1_filt_level_delta2_seg6, + segval[6][V4L2_AV1_SEG_LVL_ALT_LF_U]); + hantro_reg_write(vpu, &av1_filt_level_delta3_seg6, + segval[6][V4L2_AV1_SEG_LVL_ALT_LF_V]); + hantro_reg_write(vpu, &av1_refpic_seg6, + segval[6][V4L2_AV1_SEG_LVL_REF_FRAME]); + hantro_reg_write(vpu, &av1_skip_seg6, + segval[6][V4L2_AV1_SEG_LVL_REF_SKIP]); + hantro_reg_write(vpu, &av1_global_mv_seg6, + segval[6][V4L2_AV1_SEG_LVL_REF_GLOBALMV]); + + hantro_reg_write(vpu, &av1_quant_seg7, + segval[7][V4L2_AV1_SEG_LVL_ALT_Q]); + hantro_reg_write(vpu, &av1_filt_level_delta0_seg7, + segval[7][V4L2_AV1_SEG_LVL_ALT_LF_Y_V]); + hantro_reg_write(vpu, &av1_filt_level_delta1_seg7, + segval[7][V4L2_AV1_SEG_LVL_ALT_LF_Y_H]); + hantro_reg_write(vpu, &av1_filt_level_delta2_seg7, + segval[7][V4L2_AV1_SEG_LVL_ALT_LF_U]); + hantro_reg_write(vpu, &av1_filt_level_delta3_seg7, + segval[7][V4L2_AV1_SEG_LVL_ALT_LF_V]); + hantro_reg_write(vpu, &av1_refpic_seg7, + segval[7][V4L2_AV1_SEG_LVL_REF_FRAME]); + hantro_reg_write(vpu, &av1_skip_seg7, + segval[7][V4L2_AV1_SEG_LVL_REF_SKIP]); + hantro_reg_write(vpu, &av1_global_mv_seg7, + segval[7][V4L2_AV1_SEG_LVL_REF_GLOBALMV]); +} + +static bool rockchip_vpu981_av1_dec_is_lossless(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + const struct v4l2_av1_segmentation *segmentation = &frame->segmentation; + const struct v4l2_av1_quantization *quantization = &frame->quantization; + int i; + + for (i = 0; i < V4L2_AV1_MAX_SEGMENTS; i++) { + int qindex = quantization->base_q_idx; + + if (segmentation->feature_enabled[i] & + V4L2_AV1_SEGMENT_FEATURE_ENABLED(V4L2_AV1_SEG_LVL_ALT_Q)) { + qindex += segmentation->feature_data[i][V4L2_AV1_SEG_LVL_ALT_Q]; + } + qindex = clamp(qindex, 0, 255); + + if (qindex || + quantization->delta_q_y_dc || + quantization->delta_q_u_dc || + quantization->delta_q_u_ac || + quantization->delta_q_v_dc || + quantization->delta_q_v_ac) + return false; + } + return true; +} + +static void rockchip_vpu981_av1_dec_set_loopfilter(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + const struct v4l2_av1_loop_filter *loop_filter = &frame->loop_filter; + bool filtering_dis = (loop_filter->level[0] == 0) && (loop_filter->level[1] == 0); + struct hantro_dev *vpu = ctx->dev; + + hantro_reg_write(vpu, &av1_filtering_dis, filtering_dis); + hantro_reg_write(vpu, &av1_filt_level_base_gt32, loop_filter->level[0] > 32); + hantro_reg_write(vpu, &av1_filt_sharpness, loop_filter->sharpness); + + hantro_reg_write(vpu, &av1_filt_level0, loop_filter->level[0]); + hantro_reg_write(vpu, &av1_filt_level1, loop_filter->level[1]); + hantro_reg_write(vpu, &av1_filt_level2, loop_filter->level[2]); + hantro_reg_write(vpu, &av1_filt_level3, loop_filter->level[3]); + + if (loop_filter->flags & V4L2_AV1_LOOP_FILTER_FLAG_DELTA_ENABLED && + !rockchip_vpu981_av1_dec_is_lossless(ctx) && + !(frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_INTRABC)) { + hantro_reg_write(vpu, &av1_filt_ref_adj_0, + loop_filter->ref_deltas[0]); + hantro_reg_write(vpu, &av1_filt_ref_adj_1, + loop_filter->ref_deltas[1]); + hantro_reg_write(vpu, &av1_filt_ref_adj_2, + loop_filter->ref_deltas[2]); + hantro_reg_write(vpu, &av1_filt_ref_adj_3, + loop_filter->ref_deltas[3]); + hantro_reg_write(vpu, &av1_filt_ref_adj_4, + loop_filter->ref_deltas[4]); + hantro_reg_write(vpu, &av1_filt_ref_adj_5, + loop_filter->ref_deltas[5]); + hantro_reg_write(vpu, &av1_filt_ref_adj_6, + loop_filter->ref_deltas[6]); + hantro_reg_write(vpu, &av1_filt_ref_adj_7, + loop_filter->ref_deltas[7]); + hantro_reg_write(vpu, &av1_filt_mb_adj_0, + loop_filter->mode_deltas[0]); + hantro_reg_write(vpu, &av1_filt_mb_adj_1, + loop_filter->mode_deltas[1]); + } else { + hantro_reg_write(vpu, &av1_filt_ref_adj_0, 0); + hantro_reg_write(vpu, &av1_filt_ref_adj_1, 0); + hantro_reg_write(vpu, &av1_filt_ref_adj_2, 0); + hantro_reg_write(vpu, &av1_filt_ref_adj_3, 0); + hantro_reg_write(vpu, &av1_filt_ref_adj_4, 0); + hantro_reg_write(vpu, &av1_filt_ref_adj_5, 0); + hantro_reg_write(vpu, &av1_filt_ref_adj_6, 0); + hantro_reg_write(vpu, &av1_filt_ref_adj_7, 0); + hantro_reg_write(vpu, &av1_filt_mb_adj_0, 0); + hantro_reg_write(vpu, &av1_filt_mb_adj_1, 0); + } + + hantro_write_addr(vpu, AV1_DB_DATA_COL, av1_dec->db_data_col.dma); + hantro_write_addr(vpu, AV1_DB_CTRL_COL, av1_dec->db_ctrl_col.dma); +} + +static void rockchip_vpu981_av1_dec_update_prob(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + bool frame_is_intra = IS_INTRA(frame->frame_type); + struct av1cdfs *out_cdfs = (struct av1cdfs *)av1_dec->prob_tbl_out.cpu; + int i; + + if (frame->flags & V4L2_AV1_FRAME_FLAG_DISABLE_FRAME_END_UPDATE_CDF) + return; + + for (i = 0; i < NUM_REF_FRAMES; i++) { + if (frame->refresh_frame_flags & BIT(i)) { + struct mvcdfs stored_mv_cdf; + + rockchip_av1_get_cdfs(ctx, i); + stored_mv_cdf = av1_dec->cdfs->mv_cdf; + *av1_dec->cdfs = *out_cdfs; + if (frame_is_intra) { + av1_dec->cdfs->mv_cdf = stored_mv_cdf; + *av1_dec->cdfs_ndvc = out_cdfs->mv_cdf; + } + rockchip_av1_store_cdfs(ctx, + frame->refresh_frame_flags); + break; + } + } +} + +void rockchip_vpu981_av1_dec_done(struct hantro_ctx *ctx) +{ + rockchip_vpu981_av1_dec_update_prob(ctx); +} + +static void rockchip_vpu981_av1_dec_set_prob(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + const struct v4l2_av1_quantization *quantization = &frame->quantization; + struct hantro_dev *vpu = ctx->dev; + bool error_resilient_mode = + !!(frame->flags & V4L2_AV1_FRAME_FLAG_ERROR_RESILIENT_MODE); + bool frame_is_intra = IS_INTRA(frame->frame_type); + + if (error_resilient_mode || frame_is_intra || + frame->primary_ref_frame == AV1_PRIMARY_REF_NONE) { + av1_dec->cdfs = &av1_dec->default_cdfs; + av1_dec->cdfs_ndvc = &av1_dec->default_cdfs_ndvc; + rockchip_av1_default_coeff_probs(quantization->base_q_idx, + av1_dec->cdfs); + } else { + rockchip_av1_get_cdfs(ctx, frame->ref_frame_idx[frame->primary_ref_frame]); + } + rockchip_av1_store_cdfs(ctx, frame->refresh_frame_flags); + + memcpy(av1_dec->prob_tbl.cpu, av1_dec->cdfs, sizeof(struct av1cdfs)); + + if (frame_is_intra) { + int mv_offset = offsetof(struct av1cdfs, mv_cdf); + /* Overwrite MV context area with intrabc MV context */ + memcpy(av1_dec->prob_tbl.cpu + mv_offset, av1_dec->cdfs_ndvc, + sizeof(struct mvcdfs)); + } + + hantro_write_addr(vpu, AV1_PROP_TABLE_OUT, av1_dec->prob_tbl_out.dma); + hantro_write_addr(vpu, AV1_PROP_TABLE, av1_dec->prob_tbl.dma); +} + +static void rockchip_vpu981_av1_dec_set_cdef(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + const struct v4l2_av1_cdef *cdef = &frame->cdef; + struct hantro_dev *vpu = ctx->dev; + u32 luma_pri_strength = 0; + u16 luma_sec_strength = 0; + u32 chroma_pri_strength = 0; + u16 chroma_sec_strength = 0; + int i; + + hantro_reg_write(vpu, &av1_cdef_bits, cdef->bits); + hantro_reg_write(vpu, &av1_cdef_damping, cdef->damping_minus_3); + + for (i = 0; i < BIT(cdef->bits); i++) { + luma_pri_strength |= cdef->y_pri_strength[i] << (i * 4); + if (cdef->y_sec_strength[i] == 4) + luma_sec_strength |= 3 << (i * 2); + else + luma_sec_strength |= cdef->y_sec_strength[i] << (i * 2); + + chroma_pri_strength |= cdef->uv_pri_strength[i] << (i * 4); + if (cdef->uv_sec_strength[i] == 4) + chroma_sec_strength |= 3 << (i * 2); + else + chroma_sec_strength |= cdef->uv_sec_strength[i] << (i * 2); + } + + hantro_reg_write(vpu, &av1_cdef_luma_primary_strength, + luma_pri_strength); + hantro_reg_write(vpu, &av1_cdef_luma_secondary_strength, + luma_sec_strength); + hantro_reg_write(vpu, &av1_cdef_chroma_primary_strength, + chroma_pri_strength); + hantro_reg_write(vpu, &av1_cdef_chroma_secondary_strength, + chroma_sec_strength); + + hantro_write_addr(vpu, AV1_CDEF_COL, av1_dec->cdef_col.dma); +} + +static void rockchip_vpu981_av1_dec_set_lr(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + const struct v4l2_av1_loop_restoration *loop_restoration = + &frame->loop_restoration; + struct hantro_dev *vpu = ctx->dev; + u16 lr_type = 0, lr_unit_size = 0; + u8 restoration_unit_size[V4L2_AV1_NUM_PLANES_MAX] = { 3, 3, 3 }; + int i; + + if (loop_restoration->flags & V4L2_AV1_LOOP_RESTORATION_FLAG_USES_LR) { + restoration_unit_size[0] = 1 + loop_restoration->lr_unit_shift; + restoration_unit_size[1] = + 1 + loop_restoration->lr_unit_shift - loop_restoration->lr_uv_shift; + restoration_unit_size[2] = + 1 + loop_restoration->lr_unit_shift - loop_restoration->lr_uv_shift; + } + + for (i = 0; i < V4L2_AV1_NUM_PLANES_MAX; i++) { + lr_type |= + loop_restoration->frame_restoration_type[i] << (i * 2); + lr_unit_size |= restoration_unit_size[i] << (i * 2); + } + + hantro_reg_write(vpu, &av1_lr_type, lr_type); + hantro_reg_write(vpu, &av1_lr_unit_size, lr_unit_size); + hantro_write_addr(vpu, AV1_LR_COL, av1_dec->lr_col.dma); +} + +static void rockchip_vpu981_av1_dec_set_superres_params(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + struct hantro_dev *vpu = ctx->dev; + u8 superres_scale_denominator = SCALE_NUMERATOR; + int superres_luma_step = RS_SCALE_SUBPEL_BITS; + int superres_chroma_step = RS_SCALE_SUBPEL_BITS; + int superres_luma_step_invra = RS_SCALE_SUBPEL_BITS; + int superres_chroma_step_invra = RS_SCALE_SUBPEL_BITS; + int superres_init_luma_subpel_x = 0; + int superres_init_chroma_subpel_x = 0; + int superres_is_scaled = 0; + int min_w = min_t(uint32_t, 16, frame->upscaled_width); + int upscaled_luma, downscaled_luma; + int downscaled_chroma, upscaled_chroma; + int step_luma, step_chroma; + int err_luma, err_chroma; + int initial_luma, initial_chroma; + int width = 0; + + if (frame->flags & V4L2_AV1_FRAME_FLAG_USE_SUPERRES) + superres_scale_denominator = frame->superres_denom; + + if (superres_scale_denominator <= SCALE_NUMERATOR) + goto set_regs; + + width = (frame->upscaled_width * SCALE_NUMERATOR + + (superres_scale_denominator / 2)) / superres_scale_denominator; + + if (width < min_w) + width = min_w; + + if (width == frame->upscaled_width) + goto set_regs; + + superres_is_scaled = 1; + upscaled_luma = frame->upscaled_width; + downscaled_luma = width; + downscaled_chroma = (downscaled_luma + 1) >> 1; + upscaled_chroma = (upscaled_luma + 1) >> 1; + step_luma = + ((downscaled_luma << RS_SCALE_SUBPEL_BITS) + + (upscaled_luma / 2)) / upscaled_luma; + step_chroma = + ((downscaled_chroma << RS_SCALE_SUBPEL_BITS) + + (upscaled_chroma / 2)) / upscaled_chroma; + err_luma = + (upscaled_luma * step_luma) + - (downscaled_luma << RS_SCALE_SUBPEL_BITS); + err_chroma = + (upscaled_chroma * step_chroma) + - (downscaled_chroma << RS_SCALE_SUBPEL_BITS); + initial_luma = + ((-((upscaled_luma - downscaled_luma) << (RS_SCALE_SUBPEL_BITS - 1)) + + upscaled_luma / 2) + / upscaled_luma + (1 << (RS_SCALE_EXTRA_BITS - 1)) - err_luma / 2) + & RS_SCALE_SUBPEL_MASK; + initial_chroma = + ((-((upscaled_chroma - downscaled_chroma) << (RS_SCALE_SUBPEL_BITS - 1)) + + upscaled_chroma / 2) + / upscaled_chroma + (1 << (RS_SCALE_EXTRA_BITS - 1)) - err_chroma / 2) + & RS_SCALE_SUBPEL_MASK; + superres_luma_step = step_luma; + superres_chroma_step = step_chroma; + superres_luma_step_invra = + ((upscaled_luma << RS_SCALE_SUBPEL_BITS) + (downscaled_luma / 2)) + / downscaled_luma; + superres_chroma_step_invra = + ((upscaled_chroma << RS_SCALE_SUBPEL_BITS) + (downscaled_chroma / 2)) + / downscaled_chroma; + superres_init_luma_subpel_x = initial_luma; + superres_init_chroma_subpel_x = initial_chroma; + +set_regs: + hantro_reg_write(vpu, &av1_superres_pic_width, frame->upscaled_width); + + if (frame->flags & V4L2_AV1_FRAME_FLAG_USE_SUPERRES) + hantro_reg_write(vpu, &av1_scale_denom_minus9, + frame->superres_denom - SUPERRES_SCALE_DENOMINATOR_MIN); + else + hantro_reg_write(vpu, &av1_scale_denom_minus9, frame->superres_denom); + + hantro_reg_write(vpu, &av1_superres_luma_step, superres_luma_step); + hantro_reg_write(vpu, &av1_superres_chroma_step, superres_chroma_step); + hantro_reg_write(vpu, &av1_superres_luma_step_invra, + superres_luma_step_invra); + hantro_reg_write(vpu, &av1_superres_chroma_step_invra, + superres_chroma_step_invra); + hantro_reg_write(vpu, &av1_superres_init_luma_subpel_x, + superres_init_luma_subpel_x); + hantro_reg_write(vpu, &av1_superres_init_chroma_subpel_x, + superres_init_chroma_subpel_x); + hantro_reg_write(vpu, &av1_superres_is_scaled, superres_is_scaled); + + hantro_write_addr(vpu, AV1_SR_COL, av1_dec->sr_col.dma); +} + +static void rockchip_vpu981_av1_dec_set_picture_dimensions(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + struct hantro_dev *vpu = ctx->dev; + int pic_width_in_cbs = DIV_ROUND_UP(frame->frame_width_minus_1 + 1, 8); + int pic_height_in_cbs = DIV_ROUND_UP(frame->frame_height_minus_1 + 1, 8); + int pic_width_pad = ALIGN(frame->frame_width_minus_1 + 1, 8) + - (frame->frame_width_minus_1 + 1); + int pic_height_pad = ALIGN(frame->frame_height_minus_1 + 1, 8) + - (frame->frame_height_minus_1 + 1); + + hantro_reg_write(vpu, &av1_pic_width_in_cbs, pic_width_in_cbs); + hantro_reg_write(vpu, &av1_pic_height_in_cbs, pic_height_in_cbs); + hantro_reg_write(vpu, &av1_pic_width_pad, pic_width_pad); + hantro_reg_write(vpu, &av1_pic_height_pad, pic_height_pad); + + rockchip_vpu981_av1_dec_set_superres_params(ctx); +} + +static void rockchip_vpu981_av1_dec_set_other_frames(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + struct hantro_dev *vpu = ctx->dev; + bool use_ref_frame_mvs = + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_USE_REF_FRAME_MVS); + int cur_frame_offset = frame->order_hint; + int alt_frame_offset = 0; + int gld_frame_offset = 0; + int bwd_frame_offset = 0; + int alt2_frame_offset = 0; + int refs_selected[3] = { 0, 0, 0 }; + int cur_mi_cols = DIV_ROUND_UP(frame->frame_width_minus_1 + 1, 8); + int cur_mi_rows = DIV_ROUND_UP(frame->frame_height_minus_1 + 1, 8); + int cur_offset[V4L2_AV1_TOTAL_REFS_PER_FRAME - 1]; + int cur_roffset[V4L2_AV1_TOTAL_REFS_PER_FRAME - 1]; + int mf_types[3] = { 0, 0, 0 }; + int ref_stamp = 2; + int ref_ind = 0; + int rf, idx; + + alt_frame_offset = rockchip_vpu981_get_order_hint(ctx, ALT_BUF_IDX); + gld_frame_offset = rockchip_vpu981_get_order_hint(ctx, GLD_BUF_IDX); + bwd_frame_offset = rockchip_vpu981_get_order_hint(ctx, BWD_BUF_IDX); + alt2_frame_offset = rockchip_vpu981_get_order_hint(ctx, ALT2_BUF_IDX); + + idx = rockchip_vpu981_get_frame_index(ctx, LST_BUF_IDX); + if (idx >= 0) { + int alt_frame_offset_in_lst = + av1_dec->frame_refs[idx].order_hints[V4L2_AV1_REF_ALTREF_FRAME]; + bool is_lst_overlay = + (alt_frame_offset_in_lst == gld_frame_offset); + + if (!is_lst_overlay) { + int lst_mi_cols = av1_dec->frame_refs[idx].mi_cols; + int lst_mi_rows = av1_dec->frame_refs[idx].mi_rows; + bool lst_intra_only = + IS_INTRA(av1_dec->frame_refs[idx].frame_type); + + if (lst_mi_cols == cur_mi_cols && + lst_mi_rows == cur_mi_rows && !lst_intra_only) { + mf_types[ref_ind] = V4L2_AV1_REF_LAST_FRAME; + refs_selected[ref_ind++] = LST_BUF_IDX; + } + } + ref_stamp--; + } + + idx = rockchip_vpu981_get_frame_index(ctx, BWD_BUF_IDX); + if (rockchip_vpu981_av1_dec_get_dist(ctx, bwd_frame_offset, cur_frame_offset) > 0) { + int bwd_mi_cols = av1_dec->frame_refs[idx].mi_cols; + int bwd_mi_rows = av1_dec->frame_refs[idx].mi_rows; + bool bwd_intra_only = + IS_INTRA(av1_dec->frame_refs[idx].frame_type); + + if (bwd_mi_cols == cur_mi_cols && bwd_mi_rows == cur_mi_rows && + !bwd_intra_only) { + mf_types[ref_ind] = V4L2_AV1_REF_BWDREF_FRAME; + refs_selected[ref_ind++] = BWD_BUF_IDX; + ref_stamp--; + } + } + + idx = rockchip_vpu981_get_frame_index(ctx, ALT2_BUF_IDX); + if (rockchip_vpu981_av1_dec_get_dist(ctx, alt2_frame_offset, cur_frame_offset) > 0) { + int alt2_mi_cols = av1_dec->frame_refs[idx].mi_cols; + int alt2_mi_rows = av1_dec->frame_refs[idx].mi_rows; + bool alt2_intra_only = + IS_INTRA(av1_dec->frame_refs[idx].frame_type); + + if (alt2_mi_cols == cur_mi_cols && alt2_mi_rows == cur_mi_rows && + !alt2_intra_only) { + mf_types[ref_ind] = V4L2_AV1_REF_ALTREF2_FRAME; + refs_selected[ref_ind++] = ALT2_BUF_IDX; + ref_stamp--; + } + } + + idx = rockchip_vpu981_get_frame_index(ctx, ALT_BUF_IDX); + if (rockchip_vpu981_av1_dec_get_dist(ctx, alt_frame_offset, cur_frame_offset) > 0 && + ref_stamp >= 0) { + int alt_mi_cols = av1_dec->frame_refs[idx].mi_cols; + int alt_mi_rows = av1_dec->frame_refs[idx].mi_rows; + bool alt_intra_only = + IS_INTRA(av1_dec->frame_refs[idx].frame_type); + + if (alt_mi_cols == cur_mi_cols && alt_mi_rows == cur_mi_rows && + !alt_intra_only) { + mf_types[ref_ind] = V4L2_AV1_REF_ALTREF_FRAME; + refs_selected[ref_ind++] = ALT_BUF_IDX; + ref_stamp--; + } + } + + idx = rockchip_vpu981_get_frame_index(ctx, LST2_BUF_IDX); + if (idx >= 0 && ref_stamp >= 0) { + int lst2_mi_cols = av1_dec->frame_refs[idx].mi_cols; + int lst2_mi_rows = av1_dec->frame_refs[idx].mi_rows; + bool lst2_intra_only = + IS_INTRA(av1_dec->frame_refs[idx].frame_type); + + if (lst2_mi_cols == cur_mi_cols && lst2_mi_rows == cur_mi_rows && + !lst2_intra_only) { + mf_types[ref_ind] = V4L2_AV1_REF_LAST2_FRAME; + refs_selected[ref_ind++] = LST2_BUF_IDX; + ref_stamp--; + } + } + + for (rf = 0; rf < V4L2_AV1_TOTAL_REFS_PER_FRAME - 1; ++rf) { + idx = rockchip_vpu981_get_frame_index(ctx, rf); + if (idx >= 0) { + int rf_order_hint = rockchip_vpu981_get_order_hint(ctx, rf); + + cur_offset[rf] = + rockchip_vpu981_av1_dec_get_dist(ctx, cur_frame_offset, rf_order_hint); + cur_roffset[rf] = + rockchip_vpu981_av1_dec_get_dist(ctx, rf_order_hint, cur_frame_offset); + } else { + cur_offset[rf] = 0; + cur_roffset[rf] = 0; + } + } + + hantro_reg_write(vpu, &av1_use_temporal0_mvs, 0); + hantro_reg_write(vpu, &av1_use_temporal1_mvs, 0); + hantro_reg_write(vpu, &av1_use_temporal2_mvs, 0); + hantro_reg_write(vpu, &av1_use_temporal3_mvs, 0); + + hantro_reg_write(vpu, &av1_mf1_last_offset, 0); + hantro_reg_write(vpu, &av1_mf1_last2_offset, 0); + hantro_reg_write(vpu, &av1_mf1_last3_offset, 0); + hantro_reg_write(vpu, &av1_mf1_golden_offset, 0); + hantro_reg_write(vpu, &av1_mf1_bwdref_offset, 0); + hantro_reg_write(vpu, &av1_mf1_altref2_offset, 0); + hantro_reg_write(vpu, &av1_mf1_altref_offset, 0); + + if (use_ref_frame_mvs && ref_ind > 0 && + cur_offset[mf_types[0] - V4L2_AV1_REF_LAST_FRAME] <= MAX_FRAME_DISTANCE && + cur_offset[mf_types[0] - V4L2_AV1_REF_LAST_FRAME] >= -MAX_FRAME_DISTANCE) { + int rf = rockchip_vpu981_get_order_hint(ctx, refs_selected[0]); + int idx = rockchip_vpu981_get_frame_index(ctx, refs_selected[0]); + u32 *oh = av1_dec->frame_refs[idx].order_hints; + int val; + + hantro_reg_write(vpu, &av1_use_temporal0_mvs, 1); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST_FRAME]); + hantro_reg_write(vpu, &av1_mf1_last_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST2_FRAME]); + hantro_reg_write(vpu, &av1_mf1_last2_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST3_FRAME]); + hantro_reg_write(vpu, &av1_mf1_last3_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_GOLDEN_FRAME]); + hantro_reg_write(vpu, &av1_mf1_golden_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_BWDREF_FRAME]); + hantro_reg_write(vpu, &av1_mf1_bwdref_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_ALTREF2_FRAME]); + hantro_reg_write(vpu, &av1_mf1_altref2_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_ALTREF_FRAME]); + hantro_reg_write(vpu, &av1_mf1_altref_offset, val); + } + + hantro_reg_write(vpu, &av1_mf2_last_offset, 0); + hantro_reg_write(vpu, &av1_mf2_last2_offset, 0); + hantro_reg_write(vpu, &av1_mf2_last3_offset, 0); + hantro_reg_write(vpu, &av1_mf2_golden_offset, 0); + hantro_reg_write(vpu, &av1_mf2_bwdref_offset, 0); + hantro_reg_write(vpu, &av1_mf2_altref2_offset, 0); + hantro_reg_write(vpu, &av1_mf2_altref_offset, 0); + + if (use_ref_frame_mvs && ref_ind > 1 && + cur_offset[mf_types[1] - V4L2_AV1_REF_LAST_FRAME] <= MAX_FRAME_DISTANCE && + cur_offset[mf_types[1] - V4L2_AV1_REF_LAST_FRAME] >= -MAX_FRAME_DISTANCE) { + int rf = rockchip_vpu981_get_order_hint(ctx, refs_selected[1]); + int idx = rockchip_vpu981_get_frame_index(ctx, refs_selected[1]); + u32 *oh = av1_dec->frame_refs[idx].order_hints; + int val; + + hantro_reg_write(vpu, &av1_use_temporal1_mvs, 1); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST_FRAME]); + hantro_reg_write(vpu, &av1_mf2_last_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST2_FRAME]); + hantro_reg_write(vpu, &av1_mf2_last2_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST3_FRAME]); + hantro_reg_write(vpu, &av1_mf2_last3_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_GOLDEN_FRAME]); + hantro_reg_write(vpu, &av1_mf2_golden_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_BWDREF_FRAME]); + hantro_reg_write(vpu, &av1_mf2_bwdref_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_ALTREF2_FRAME]); + hantro_reg_write(vpu, &av1_mf2_altref2_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_ALTREF_FRAME]); + hantro_reg_write(vpu, &av1_mf2_altref_offset, val); + } + + hantro_reg_write(vpu, &av1_mf3_last_offset, 0); + hantro_reg_write(vpu, &av1_mf3_last2_offset, 0); + hantro_reg_write(vpu, &av1_mf3_last3_offset, 0); + hantro_reg_write(vpu, &av1_mf3_golden_offset, 0); + hantro_reg_write(vpu, &av1_mf3_bwdref_offset, 0); + hantro_reg_write(vpu, &av1_mf3_altref2_offset, 0); + hantro_reg_write(vpu, &av1_mf3_altref_offset, 0); + + if (use_ref_frame_mvs && ref_ind > 2 && + cur_offset[mf_types[2] - V4L2_AV1_REF_LAST_FRAME] <= MAX_FRAME_DISTANCE && + cur_offset[mf_types[2] - V4L2_AV1_REF_LAST_FRAME] >= -MAX_FRAME_DISTANCE) { + int rf = rockchip_vpu981_get_order_hint(ctx, refs_selected[2]); + int idx = rockchip_vpu981_get_frame_index(ctx, refs_selected[2]); + u32 *oh = av1_dec->frame_refs[idx].order_hints; + int val; + + hantro_reg_write(vpu, &av1_use_temporal2_mvs, 1); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST_FRAME]); + hantro_reg_write(vpu, &av1_mf3_last_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST2_FRAME]); + hantro_reg_write(vpu, &av1_mf3_last2_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_LAST3_FRAME]); + hantro_reg_write(vpu, &av1_mf3_last3_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_GOLDEN_FRAME]); + hantro_reg_write(vpu, &av1_mf3_golden_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_BWDREF_FRAME]); + hantro_reg_write(vpu, &av1_mf3_bwdref_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_ALTREF2_FRAME]); + hantro_reg_write(vpu, &av1_mf3_altref2_offset, val); + + val = rockchip_vpu981_av1_dec_get_dist(ctx, rf, oh[V4L2_AV1_REF_ALTREF_FRAME]); + hantro_reg_write(vpu, &av1_mf3_altref_offset, val); + } + + hantro_reg_write(vpu, &av1_cur_last_offset, cur_offset[0]); + hantro_reg_write(vpu, &av1_cur_last2_offset, cur_offset[1]); + hantro_reg_write(vpu, &av1_cur_last3_offset, cur_offset[2]); + hantro_reg_write(vpu, &av1_cur_golden_offset, cur_offset[3]); + hantro_reg_write(vpu, &av1_cur_bwdref_offset, cur_offset[4]); + hantro_reg_write(vpu, &av1_cur_altref2_offset, cur_offset[5]); + hantro_reg_write(vpu, &av1_cur_altref_offset, cur_offset[6]); + + hantro_reg_write(vpu, &av1_cur_last_roffset, cur_roffset[0]); + hantro_reg_write(vpu, &av1_cur_last2_roffset, cur_roffset[1]); + hantro_reg_write(vpu, &av1_cur_last3_roffset, cur_roffset[2]); + hantro_reg_write(vpu, &av1_cur_golden_roffset, cur_roffset[3]); + hantro_reg_write(vpu, &av1_cur_bwdref_roffset, cur_roffset[4]); + hantro_reg_write(vpu, &av1_cur_altref2_roffset, cur_roffset[5]); + hantro_reg_write(vpu, &av1_cur_altref_roffset, cur_roffset[6]); + + hantro_reg_write(vpu, &av1_mf1_type, mf_types[0] - V4L2_AV1_REF_LAST_FRAME); + hantro_reg_write(vpu, &av1_mf2_type, mf_types[1] - V4L2_AV1_REF_LAST_FRAME); + hantro_reg_write(vpu, &av1_mf3_type, mf_types[2] - V4L2_AV1_REF_LAST_FRAME); +} + +static void rockchip_vpu981_av1_dec_set_reference_frames(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_frame *frame = ctrls->frame; + int frame_type = frame->frame_type; + bool allow_intrabc = !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_INTRABC); + int ref_count[AV1DEC_MAX_PIC_BUFFERS] = { 0 }; + struct hantro_dev *vpu = ctx->dev; + int i, ref_frames = 0; + bool scale_enable = false; + + if (IS_INTRA(frame_type) && !allow_intrabc) + return; + + if (!allow_intrabc) { + for (i = 0; i < V4L2_AV1_REFS_PER_FRAME; i++) { + int idx = rockchip_vpu981_get_frame_index(ctx, i); + + if (idx >= 0) + ref_count[idx]++; + } + + for (i = 0; i < AV1DEC_MAX_PIC_BUFFERS; i++) { + if (ref_count[i]) + ref_frames++; + } + } else { + ref_frames = 1; + } + hantro_reg_write(vpu, &av1_ref_frames, ref_frames); + + rockchip_vpu981_av1_dec_set_frame_sign_bias(ctx); + + for (i = V4L2_AV1_REF_LAST_FRAME; i < V4L2_AV1_TOTAL_REFS_PER_FRAME; i++) { + u32 ref = i - 1; + int idx = 0; + int width, height; + + if (allow_intrabc) { + idx = av1_dec->current_frame_index; + width = frame->frame_width_minus_1 + 1; + height = frame->frame_height_minus_1 + 1; + } else { + if (rockchip_vpu981_get_frame_index(ctx, ref) > 0) + idx = rockchip_vpu981_get_frame_index(ctx, ref); + width = av1_dec->frame_refs[idx].width; + height = av1_dec->frame_refs[idx].height; + } + + scale_enable |= + rockchip_vpu981_av1_dec_set_ref(ctx, ref, idx, width, + height); + + rockchip_vpu981_av1_dec_set_sign_bias(ctx, ref, + av1_dec->ref_frame_sign_bias[i]); + } + hantro_reg_write(vpu, &av1_ref_scaling_enable, scale_enable); + + hantro_reg_write(vpu, &av1_ref0_gm_mode, + frame->global_motion.type[V4L2_AV1_REF_LAST_FRAME]); + hantro_reg_write(vpu, &av1_ref1_gm_mode, + frame->global_motion.type[V4L2_AV1_REF_LAST2_FRAME]); + hantro_reg_write(vpu, &av1_ref2_gm_mode, + frame->global_motion.type[V4L2_AV1_REF_LAST3_FRAME]); + hantro_reg_write(vpu, &av1_ref3_gm_mode, + frame->global_motion.type[V4L2_AV1_REF_GOLDEN_FRAME]); + hantro_reg_write(vpu, &av1_ref4_gm_mode, + frame->global_motion.type[V4L2_AV1_REF_BWDREF_FRAME]); + hantro_reg_write(vpu, &av1_ref5_gm_mode, + frame->global_motion.type[V4L2_AV1_REF_ALTREF2_FRAME]); + hantro_reg_write(vpu, &av1_ref6_gm_mode, + frame->global_motion.type[V4L2_AV1_REF_ALTREF_FRAME]); + + rockchip_vpu981_av1_dec_set_other_frames(ctx); +} + +static void rockchip_vpu981_av1_dec_set_parameters(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + + hantro_reg_write(vpu, &av1_skip_mode, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_SKIP_MODE_PRESENT)); + hantro_reg_write(vpu, &av1_tempor_mvp_e, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_USE_REF_FRAME_MVS)); + hantro_reg_write(vpu, &av1_delta_lf_res_log, + ctrls->frame->loop_filter.delta_lf_res); + hantro_reg_write(vpu, &av1_delta_lf_multi, + !!(ctrls->frame->loop_filter.flags + & V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_MULTI)); + hantro_reg_write(vpu, &av1_delta_lf_present, + !!(ctrls->frame->loop_filter.flags + & V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_PRESENT)); + hantro_reg_write(vpu, &av1_disable_cdf_update, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_DISABLE_CDF_UPDATE)); + hantro_reg_write(vpu, &av1_allow_warp, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_WARPED_MOTION)); + hantro_reg_write(vpu, &av1_show_frame, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_SHOW_FRAME)); + hantro_reg_write(vpu, &av1_switchable_motion_mode, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_IS_MOTION_MODE_SWITCHABLE)); + hantro_reg_write(vpu, &av1_enable_cdef, + !!(ctrls->sequence->flags & V4L2_AV1_SEQUENCE_FLAG_ENABLE_CDEF)); + hantro_reg_write(vpu, &av1_allow_masked_compound, + !!(ctrls->sequence->flags + & V4L2_AV1_SEQUENCE_FLAG_ENABLE_MASKED_COMPOUND)); + hantro_reg_write(vpu, &av1_allow_interintra, + !!(ctrls->sequence->flags + & V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTERINTRA_COMPOUND)); + hantro_reg_write(vpu, &av1_enable_intra_edge_filter, + !!(ctrls->sequence->flags + & V4L2_AV1_SEQUENCE_FLAG_ENABLE_INTRA_EDGE_FILTER)); + hantro_reg_write(vpu, &av1_allow_filter_intra, + !!(ctrls->sequence->flags & V4L2_AV1_SEQUENCE_FLAG_ENABLE_FILTER_INTRA)); + hantro_reg_write(vpu, &av1_enable_jnt_comp, + !!(ctrls->sequence->flags & V4L2_AV1_SEQUENCE_FLAG_ENABLE_JNT_COMP)); + hantro_reg_write(vpu, &av1_enable_dual_filter, + !!(ctrls->sequence->flags & V4L2_AV1_SEQUENCE_FLAG_ENABLE_DUAL_FILTER)); + hantro_reg_write(vpu, &av1_reduced_tx_set_used, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_REDUCED_TX_SET)); + hantro_reg_write(vpu, &av1_allow_screen_content_tools, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_SCREEN_CONTENT_TOOLS)); + hantro_reg_write(vpu, &av1_allow_intrabc, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_INTRABC)); + + if (!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_SCREEN_CONTENT_TOOLS)) + hantro_reg_write(vpu, &av1_force_interger_mv, 0); + else + hantro_reg_write(vpu, &av1_force_interger_mv, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_FORCE_INTEGER_MV)); + + hantro_reg_write(vpu, &av1_blackwhite_e, 0); + hantro_reg_write(vpu, &av1_delta_q_res_log, ctrls->frame->quantization.delta_q_res); + hantro_reg_write(vpu, &av1_delta_q_present, + !!(ctrls->frame->quantization.flags + & V4L2_AV1_QUANTIZATION_FLAG_DELTA_Q_PRESENT)); + + hantro_reg_write(vpu, &av1_idr_pic_e, !ctrls->frame->frame_type); + hantro_reg_write(vpu, &av1_quant_base_qindex, ctrls->frame->quantization.base_q_idx); + hantro_reg_write(vpu, &av1_bit_depth_y_minus8, ctx->bit_depth - 8); + hantro_reg_write(vpu, &av1_bit_depth_c_minus8, ctx->bit_depth - 8); + + hantro_reg_write(vpu, &av1_mcomp_filt_type, ctrls->frame->interpolation_filter); + hantro_reg_write(vpu, &av1_high_prec_mv_e, + !!(ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_ALLOW_HIGH_PRECISION_MV)); + hantro_reg_write(vpu, &av1_comp_pred_mode, + (ctrls->frame->flags & V4L2_AV1_FRAME_FLAG_REFERENCE_SELECT) ? 2 : 0); + hantro_reg_write(vpu, &av1_transform_mode, (ctrls->frame->tx_mode == 1) ? 3 : 4); + hantro_reg_write(vpu, &av1_max_cb_size, + (ctrls->sequence->flags + & V4L2_AV1_SEQUENCE_FLAG_USE_128X128_SUPERBLOCK) ? 7 : 6); + hantro_reg_write(vpu, &av1_min_cb_size, 3); + + hantro_reg_write(vpu, &av1_comp_pred_fixed_ref, 0); + hantro_reg_write(vpu, &av1_comp_pred_var_ref0_av1, 0); + hantro_reg_write(vpu, &av1_comp_pred_var_ref1_av1, 0); + hantro_reg_write(vpu, &av1_filt_level_seg0, 0); + hantro_reg_write(vpu, &av1_filt_level_seg1, 0); + hantro_reg_write(vpu, &av1_filt_level_seg2, 0); + hantro_reg_write(vpu, &av1_filt_level_seg3, 0); + hantro_reg_write(vpu, &av1_filt_level_seg4, 0); + hantro_reg_write(vpu, &av1_filt_level_seg5, 0); + hantro_reg_write(vpu, &av1_filt_level_seg6, 0); + hantro_reg_write(vpu, &av1_filt_level_seg7, 0); + + hantro_reg_write(vpu, &av1_qp_delta_y_dc_av1, ctrls->frame->quantization.delta_q_y_dc); + hantro_reg_write(vpu, &av1_qp_delta_ch_dc_av1, ctrls->frame->quantization.delta_q_u_dc); + hantro_reg_write(vpu, &av1_qp_delta_ch_ac_av1, ctrls->frame->quantization.delta_q_u_ac); + if (ctrls->frame->quantization.flags & V4L2_AV1_QUANTIZATION_FLAG_USING_QMATRIX) { + hantro_reg_write(vpu, &av1_qmlevel_y, ctrls->frame->quantization.qm_y); + hantro_reg_write(vpu, &av1_qmlevel_u, ctrls->frame->quantization.qm_u); + hantro_reg_write(vpu, &av1_qmlevel_v, ctrls->frame->quantization.qm_v); + } else { + hantro_reg_write(vpu, &av1_qmlevel_y, 0xff); + hantro_reg_write(vpu, &av1_qmlevel_u, 0xff); + hantro_reg_write(vpu, &av1_qmlevel_v, 0xff); + } + + hantro_reg_write(vpu, &av1_lossless_e, rockchip_vpu981_av1_dec_is_lossless(ctx)); + hantro_reg_write(vpu, &av1_quant_delta_v_dc, ctrls->frame->quantization.delta_q_v_dc); + hantro_reg_write(vpu, &av1_quant_delta_v_ac, ctrls->frame->quantization.delta_q_v_ac); + + hantro_reg_write(vpu, &av1_skip_ref0, + (ctrls->frame->skip_mode_frame[0]) ? ctrls->frame->skip_mode_frame[0] : 1); + hantro_reg_write(vpu, &av1_skip_ref1, + (ctrls->frame->skip_mode_frame[1]) ? ctrls->frame->skip_mode_frame[1] : 1); + + hantro_write_addr(vpu, AV1_MC_SYNC_CURR, av1_dec->tile_buf.dma); + hantro_write_addr(vpu, AV1_MC_SYNC_LEFT, av1_dec->tile_buf.dma); +} + +static void +rockchip_vpu981_av1_dec_set_input_buffer(struct hantro_ctx *ctx, + struct vb2_v4l2_buffer *vb2_src) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_tile_group_entry *group_entry = + ctrls->tile_group_entry; + struct hantro_dev *vpu = ctx->dev; + dma_addr_t src_dma; + u32 src_len, src_buf_len; + int start_bit, offset; + + src_dma = vb2_dma_contig_plane_dma_addr(&vb2_src->vb2_buf, 0); + src_len = vb2_get_plane_payload(&vb2_src->vb2_buf, 0); + src_buf_len = vb2_plane_size(&vb2_src->vb2_buf, 0); + + start_bit = (group_entry[0].tile_offset & 0xf) * 8; + offset = group_entry[0].tile_offset & ~0xf; + + hantro_reg_write(vpu, &av1_strm_buffer_len, src_buf_len); + hantro_reg_write(vpu, &av1_strm_start_bit, start_bit); + hantro_reg_write(vpu, &av1_stream_len, src_len); + hantro_reg_write(vpu, &av1_strm_start_offset, 0); + hantro_write_addr(vpu, AV1_INPUT_STREAM, src_dma + offset); +} + +static void +rockchip_vpu981_av1_dec_set_output_buffer(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_dev *vpu = ctx->dev; + struct hantro_decoded_buffer *dst; + struct vb2_v4l2_buffer *vb2_dst; + dma_addr_t luma_addr, chroma_addr, mv_addr = 0; + size_t cr_offset = rockchip_vpu981_av1_dec_luma_size(ctx); + size_t mv_offset = rockchip_vpu981_av1_dec_chroma_size(ctx); + + vb2_dst = av1_dec->frame_refs[av1_dec->current_frame_index].vb2_ref; + dst = vb2_to_hantro_decoded_buf(&vb2_dst->vb2_buf); + luma_addr = hantro_get_dec_buf_addr(ctx, &dst->base.vb.vb2_buf); + chroma_addr = luma_addr + cr_offset; + mv_addr = luma_addr + mv_offset; + + hantro_write_addr(vpu, AV1_TILE_OUT_LU, luma_addr); + hantro_write_addr(vpu, AV1_TILE_OUT_CH, chroma_addr); + hantro_write_addr(vpu, AV1_TILE_OUT_MV, mv_addr); +} + +int rockchip_vpu981_av1_dec_run(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + struct vb2_v4l2_buffer *vb2_src; + int ret; + + hantro_start_prepare_run(ctx); + + ret = rockchip_vpu981_av1_dec_prepare_run(ctx); + if (ret) + goto prepare_error; + + vb2_src = hantro_get_src_buf(ctx); + if (!vb2_src) { + ret = -EINVAL; + goto prepare_error; + } + + rockchip_vpu981_av1_dec_clean_refs(ctx); + rockchip_vpu981_av1_dec_frame_ref(ctx, vb2_src->vb2_buf.timestamp); + + rockchip_vpu981_av1_dec_set_parameters(ctx); + rockchip_vpu981_av1_dec_set_global_model(ctx); + rockchip_vpu981_av1_dec_set_tile_info(ctx); + rockchip_vpu981_av1_dec_set_reference_frames(ctx); + rockchip_vpu981_av1_dec_set_segmentation(ctx); + rockchip_vpu981_av1_dec_set_loopfilter(ctx); + rockchip_vpu981_av1_dec_set_picture_dimensions(ctx); + rockchip_vpu981_av1_dec_set_cdef(ctx); + rockchip_vpu981_av1_dec_set_lr(ctx); + rockchip_vpu981_av1_dec_set_prob(ctx); + + hantro_reg_write(vpu, &av1_dec_mode, AV1_DEC_MODE); + hantro_reg_write(vpu, &av1_dec_out_ec_byte_word, 0); + hantro_reg_write(vpu, &av1_write_mvs_e, 1); + hantro_reg_write(vpu, &av1_dec_out_ec_bypass, 1); + hantro_reg_write(vpu, &av1_dec_clk_gate_e, 1); + + hantro_reg_write(vpu, &av1_dec_abort_e, 0); + hantro_reg_write(vpu, &av1_dec_tile_int_e, 0); + + hantro_reg_write(vpu, &av1_dec_alignment, 64); + hantro_reg_write(vpu, &av1_apf_disable, 0); + hantro_reg_write(vpu, &av1_apf_threshold, 8); + hantro_reg_write(vpu, &av1_dec_buswidth, 2); + hantro_reg_write(vpu, &av1_dec_max_burst, 16); + hantro_reg_write(vpu, &av1_error_conceal_e, 0); + hantro_reg_write(vpu, &av1_axi_rd_ostd_threshold, 64); + hantro_reg_write(vpu, &av1_axi_wr_ostd_threshold, 64); + + hantro_reg_write(vpu, &av1_ext_timeout_cycles, 0xfffffff); + hantro_reg_write(vpu, &av1_ext_timeout_override_e, 1); + hantro_reg_write(vpu, &av1_timeout_cycles, 0xfffffff); + hantro_reg_write(vpu, &av1_timeout_override_e, 1); + + rockchip_vpu981_av1_dec_set_output_buffer(ctx); + rockchip_vpu981_av1_dec_set_input_buffer(ctx, vb2_src); + + hantro_end_prepare_run(ctx); + + hantro_reg_write(vpu, &av1_dec_e, 1); + + return 0; + +prepare_error: + hantro_end_prepare_run(ctx); + hantro_irq_done(vpu, VB2_BUF_STATE_ERROR); + return ret; +} + +static void rockchip_vpu981_postproc_enable(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + int width = ctx->dst_fmt.width; + int height = ctx->dst_fmt.height; + struct vb2_v4l2_buffer *vb2_dst; + size_t chroma_offset; + dma_addr_t dst_dma; + + vb2_dst = hantro_get_dst_buf(ctx); + + dst_dma = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0); + chroma_offset = ctx->dst_fmt.plane_fmt[0].bytesperline * + ctx->dst_fmt.height; + + /* enable post processor */ + hantro_reg_write(vpu, &av1_pp_out_e, 1); + hantro_reg_write(vpu, &av1_pp_in_format, 0); + hantro_reg_write(vpu, &av1_pp0_dup_hor, 1); + hantro_reg_write(vpu, &av1_pp0_dup_ver, 1); + + hantro_reg_write(vpu, &av1_pp_in_height, height / 2); + hantro_reg_write(vpu, &av1_pp_in_width, width / 2); + hantro_reg_write(vpu, &av1_pp_out_height, height); + hantro_reg_write(vpu, &av1_pp_out_width, width); + hantro_reg_write(vpu, &av1_pp_out_y_stride, + ctx->dst_fmt.plane_fmt[0].bytesperline); + hantro_reg_write(vpu, &av1_pp_out_c_stride, + ctx->dst_fmt.plane_fmt[0].bytesperline); + switch (ctx->dst_fmt.pixelformat) { + case V4L2_PIX_FMT_P010: + hantro_reg_write(vpu, &av1_pp_out_format, 1); + break; + case V4L2_PIX_FMT_NV12: + hantro_reg_write(vpu, &av1_pp_out_format, 3); + break; + default: + hantro_reg_write(vpu, &av1_pp_out_format, 0); + } + + hantro_reg_write(vpu, &av1_ppd_blend_exist, 0); + hantro_reg_write(vpu, &av1_ppd_dith_exist, 0); + hantro_reg_write(vpu, &av1_ablend_crop_e, 0); + hantro_reg_write(vpu, &av1_pp_format_customer1_e, 0); + hantro_reg_write(vpu, &av1_pp_crop_exist, 0); + hantro_reg_write(vpu, &av1_pp_up_level, 0); + hantro_reg_write(vpu, &av1_pp_down_level, 0); + hantro_reg_write(vpu, &av1_pp_exist, 0); + + hantro_write_addr(vpu, AV1_PP_OUT_LU, dst_dma); + hantro_write_addr(vpu, AV1_PP_OUT_CH, dst_dma + chroma_offset); +} + +static void rockchip_vpu981_postproc_disable(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + + /* disable post processor */ + hantro_reg_write(vpu, &av1_pp_out_e, 0); +} + +const struct hantro_postproc_ops rockchip_vpu981_postproc_ops = { + .enable = rockchip_vpu981_postproc_enable, + .disable = rockchip_vpu981_postproc_disable, +}; diff --git a/drivers/media/platform/verisilicon/rockchip_vpu981_regs.h b/drivers/media/platform/verisilicon/rockchip_vpu981_regs.h new file mode 100644 index 000000000000..182e6c830ff6 --- /dev/null +++ b/drivers/media/platform/verisilicon/rockchip_vpu981_regs.h @@ -0,0 +1,477 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022, Collabora + * + * Author: Benjamin Gaignard + */ + +#ifndef _ROCKCHIP_VPU981_REGS_H_ +#define _ROCKCHIP_VPU981_REGS_H_ + +#include "hantro.h" + +#define AV1_SWREG(nr) ((nr) * 4) + +#define AV1_DEC_REG(b, s, m) \ + ((const struct hantro_reg) { \ + .base = AV1_SWREG(b), \ + .shift = s, \ + .mask = m, \ + }) + +#define AV1_REG_INTERRUPT AV1_SWREG(1) +#define AV1_REG_INTERRUPT_DEC_RDY_INT BIT(12) + +#define AV1_REG_CONFIG AV1_SWREG(2) +#define AV1_REG_CONFIG_DEC_CLK_GATE_E BIT(10) + +#define av1_dec_e AV1_DEC_REG(1, 0, 0x1) +#define av1_dec_abort_e AV1_DEC_REG(1, 5, 0x1) +#define av1_dec_tile_int_e AV1_DEC_REG(1, 7, 0x1) + +#define av1_dec_clk_gate_e AV1_DEC_REG(2, 10, 0x1) + +#define av1_dec_out_ec_bypass AV1_DEC_REG(3, 8, 0x1) +#define av1_write_mvs_e AV1_DEC_REG(3, 12, 0x1) +#define av1_filtering_dis AV1_DEC_REG(3, 14, 0x1) +#define av1_dec_out_dis AV1_DEC_REG(3, 15, 0x1) +#define av1_dec_out_ec_byte_word AV1_DEC_REG(3, 16, 0x1) +#define av1_skip_mode AV1_DEC_REG(3, 26, 0x1) +#define av1_dec_mode AV1_DEC_REG(3, 27, 0x1f) + +#define av1_ref_frames AV1_DEC_REG(4, 0, 0xf) +#define av1_pic_height_in_cbs AV1_DEC_REG(4, 6, 0x1fff) +#define av1_pic_width_in_cbs AV1_DEC_REG(4, 19, 0x1fff) + +#define av1_ref_scaling_enable AV1_DEC_REG(5, 0, 0x1) +#define av1_filt_level_base_gt32 AV1_DEC_REG(5, 1, 0x1) +#define av1_error_resilient AV1_DEC_REG(5, 2, 0x1) +#define av1_force_interger_mv AV1_DEC_REG(5, 3, 0x1) +#define av1_allow_intrabc AV1_DEC_REG(5, 4, 0x1) +#define av1_allow_screen_content_tools AV1_DEC_REG(5, 5, 0x1) +#define av1_reduced_tx_set_used AV1_DEC_REG(5, 6, 0x1) +#define av1_enable_dual_filter AV1_DEC_REG(5, 7, 0x1) +#define av1_enable_jnt_comp AV1_DEC_REG(5, 8, 0x1) +#define av1_allow_filter_intra AV1_DEC_REG(5, 9, 0x1) +#define av1_enable_intra_edge_filter AV1_DEC_REG(5, 10, 0x1) +#define av1_tempor_mvp_e AV1_DEC_REG(5, 11, 0x1) +#define av1_allow_interintra AV1_DEC_REG(5, 12, 0x1) +#define av1_allow_masked_compound AV1_DEC_REG(5, 13, 0x1) +#define av1_enable_cdef AV1_DEC_REG(5, 14, 0x1) +#define av1_switchable_motion_mode AV1_DEC_REG(5, 15, 0x1) +#define av1_show_frame AV1_DEC_REG(5, 16, 0x1) +#define av1_superres_is_scaled AV1_DEC_REG(5, 17, 0x1) +#define av1_allow_warp AV1_DEC_REG(5, 18, 0x1) +#define av1_disable_cdf_update AV1_DEC_REG(5, 19, 0x1) +#define av1_preskip_segid AV1_DEC_REG(5, 20, 0x1) +#define av1_delta_lf_present AV1_DEC_REG(5, 21, 0x1) +#define av1_delta_lf_multi AV1_DEC_REG(5, 22, 0x1) +#define av1_delta_lf_res_log AV1_DEC_REG(5, 23, 0x3) +#define av1_strm_start_bit AV1_DEC_REG(5, 25, 0x7f) + +#define av1_stream_len AV1_DEC_REG(6, 0, 0xffffffff) + +#define av1_delta_q_present AV1_DEC_REG(7, 0, 0x1) +#define av1_delta_q_res_log AV1_DEC_REG(7, 1, 0x3) +#define av1_cdef_damping AV1_DEC_REG(7, 3, 0x3) +#define av1_cdef_bits AV1_DEC_REG(7, 5, 0x3) +#define av1_apply_grain AV1_DEC_REG(7, 7, 0x1) +#define av1_num_y_points_b AV1_DEC_REG(7, 8, 0x1) +#define av1_num_cb_points_b AV1_DEC_REG(7, 9, 0x1) +#define av1_num_cr_points_b AV1_DEC_REG(7, 10, 0x1) +#define av1_overlap_flag AV1_DEC_REG(7, 11, 0x1) +#define av1_clip_to_restricted_range AV1_DEC_REG(7, 12, 0x1) +#define av1_chroma_scaling_from_luma AV1_DEC_REG(7, 13, 0x1) +#define av1_random_seed AV1_DEC_REG(7, 14, 0xffff) +#define av1_blackwhite_e AV1_DEC_REG(7, 30, 0x1) + +#define av1_scaling_shift AV1_DEC_REG(8, 0, 0xf) +#define av1_bit_depth_c_minus8 AV1_DEC_REG(8, 4, 0x3) +#define av1_bit_depth_y_minus8 AV1_DEC_REG(8, 6, 0x3) +#define av1_quant_base_qindex AV1_DEC_REG(8, 8, 0xff) +#define av1_idr_pic_e AV1_DEC_REG(8, 16, 0x1) +#define av1_superres_pic_width AV1_DEC_REG(8, 17, 0x7fff) + +#define av1_ref4_sign_bias AV1_DEC_REG(9, 2, 0x1) +#define av1_ref5_sign_bias AV1_DEC_REG(9, 3, 0x1) +#define av1_ref6_sign_bias AV1_DEC_REG(9, 4, 0x1) +#define av1_mf1_type AV1_DEC_REG(9, 5, 0x7) +#define av1_mf2_type AV1_DEC_REG(9, 8, 0x7) +#define av1_mf3_type AV1_DEC_REG(9, 11, 0x7) +#define av1_scale_denom_minus9 AV1_DEC_REG(9, 14, 0x7) +#define av1_last_active_seg AV1_DEC_REG(9, 17, 0x7) +#define av1_context_update_tile_id AV1_DEC_REG(9, 20, 0xfff) + +#define av1_tile_transpose AV1_DEC_REG(10, 0, 0x1) +#define av1_tile_enable AV1_DEC_REG(10, 1, 0x1) +#define av1_multicore_full_width AV1_DEC_REG(10, 2, 0xff) +#define av1_num_tile_rows_8k AV1_DEC_REG(10, 10, 0x7f) +#define av1_num_tile_cols_8k AV1_DEC_REG(10, 17, 0x7f) +#define av1_multicore_tile_start_x AV1_DEC_REG(10, 24, 0xff) + +#define av1_use_temporal3_mvs AV1_DEC_REG(11, 0, 0x1) +#define av1_use_temporal2_mvs AV1_DEC_REG(11, 1, 0x1) +#define av1_use_temporal1_mvs AV1_DEC_REG(11, 2, 0x1) +#define av1_use_temporal0_mvs AV1_DEC_REG(11, 3, 0x1) +#define av1_comp_pred_mode AV1_DEC_REG(11, 4, 0x3) +#define av1_high_prec_mv_e AV1_DEC_REG(11, 7, 0x1) +#define av1_mcomp_filt_type AV1_DEC_REG(11, 8, 0x7) +#define av1_multicore_expect_context_update AV1_DEC_REG(11, 11, 0x1) +#define av1_multicore_sbx_offset AV1_DEC_REG(11, 12, 0x7f) +#define av1_ulticore_tile_col AV1_DEC_REG(11, 19, 0x7f) +#define av1_transform_mode AV1_DEC_REG(11, 27, 0x7) +#define av1_dec_tile_size_mag AV1_DEC_REG(11, 30, 0x3) + +#define av1_seg_quant_sign AV1_DEC_REG(12, 2, 0xff) +#define av1_max_cb_size AV1_DEC_REG(12, 10, 0x7) +#define av1_min_cb_size AV1_DEC_REG(12, 13, 0x7) +#define av1_comp_pred_fixed_ref AV1_DEC_REG(12, 16, 0x7) +#define av1_multicore_tile_width AV1_DEC_REG(12, 19, 0x7f) +#define av1_pic_height_pad AV1_DEC_REG(12, 26, 0x7) +#define av1_pic_width_pad AV1_DEC_REG(12, 29, 0x7) + +#define av1_segment_e AV1_DEC_REG(13, 0, 0x1) +#define av1_segment_upd_e AV1_DEC_REG(13, 1, 0x1) +#define av1_segment_temp_upd_e AV1_DEC_REG(13, 2, 0x1) +#define av1_comp_pred_var_ref0_av1 AV1_DEC_REG(13, 3, 0x7) +#define av1_comp_pred_var_ref1_av1 AV1_DEC_REG(13, 6, 0x7) +#define av1_lossless_e AV1_DEC_REG(13, 9, 0x1) +#define av1_qp_delta_ch_ac_av1 AV1_DEC_REG(13, 11, 0x7f) +#define av1_qp_delta_ch_dc_av1 AV1_DEC_REG(13, 18, 0x7f) +#define av1_qp_delta_y_dc_av1 AV1_DEC_REG(13, 25, 0x7f) + +#define av1_quant_seg0 AV1_DEC_REG(14, 0, 0xff) +#define av1_filt_level_seg0 AV1_DEC_REG(14, 8, 0x3f) +#define av1_skip_seg0 AV1_DEC_REG(14, 14, 0x1) +#define av1_refpic_seg0 AV1_DEC_REG(14, 15, 0xf) +#define av1_filt_level_delta0_seg0 AV1_DEC_REG(14, 19, 0x7f) +#define av1_filt_level0 AV1_DEC_REG(14, 26, 0x3f) + +#define av1_quant_seg1 AV1_DEC_REG(15, 0, 0xff) +#define av1_filt_level_seg1 AV1_DEC_REG(15, 8, 0x3f) +#define av1_skip_seg1 AV1_DEC_REG(15, 14, 0x1) +#define av1_refpic_seg1 AV1_DEC_REG(15, 15, 0xf) +#define av1_filt_level_delta0_seg1 AV1_DEC_REG(15, 19, 0x7f) +#define av1_filt_level1 AV1_DEC_REG(15, 26, 0x3f) + +#define av1_quant_seg2 AV1_DEC_REG(16, 0, 0xff) +#define av1_filt_level_seg2 AV1_DEC_REG(16, 8, 0x3f) +#define av1_skip_seg2 AV1_DEC_REG(16, 14, 0x1) +#define av1_refpic_seg2 AV1_DEC_REG(16, 15, 0xf) +#define av1_filt_level_delta0_seg2 AV1_DEC_REG(16, 19, 0x7f) +#define av1_filt_level2 AV1_DEC_REG(16, 26, 0x3f) + +#define av1_quant_seg3 AV1_DEC_REG(17, 0, 0xff) +#define av1_filt_level_seg3 AV1_DEC_REG(17, 8, 0x3f) +#define av1_skip_seg3 AV1_DEC_REG(17, 14, 0x1) +#define av1_refpic_seg3 AV1_DEC_REG(17, 15, 0xf) +#define av1_filt_level_delta0_seg3 AV1_DEC_REG(17, 19, 0x7f) +#define av1_filt_level3 AV1_DEC_REG(17, 26, 0x3f) + +#define av1_quant_seg4 AV1_DEC_REG(18, 0, 0xff) +#define av1_filt_level_seg4 AV1_DEC_REG(18, 8, 0x3f) +#define av1_skip_seg4 AV1_DEC_REG(18, 14, 0x1) +#define av1_refpic_seg4 AV1_DEC_REG(18, 15, 0xf) +#define av1_filt_level_delta0_seg4 AV1_DEC_REG(18, 19, 0x7f) +#define av1_lr_type AV1_DEC_REG(18, 26, 0x3f) + +#define av1_quant_seg5 AV1_DEC_REG(19, 0, 0xff) +#define av1_filt_level_seg5 AV1_DEC_REG(19, 8, 0x3f) +#define av1_skip_seg5 AV1_DEC_REG(19, 14, 0x1) +#define av1_refpic_seg5 AV1_DEC_REG(19, 15, 0xf) +#define av1_filt_level_delta0_seg5 AV1_DEC_REG(19, 19, 0x7f) +#define av1_lr_unit_size AV1_DEC_REG(19, 26, 0x3f) + +#define av1_filt_level_delta1_seg0 AV1_DEC_REG(20, 0, 0x7f) +#define av1_filt_level_delta2_seg0 AV1_DEC_REG(20, 7, 0x7f) +#define av1_filt_level_delta3_seg0 AV1_DEC_REG(20, 14, 0x7f) +#define av1_global_mv_seg0 AV1_DEC_REG(20, 21, 0x1) +#define av1_mf1_last_offset AV1_DEC_REG(20, 22, 0x1ff) + +#define av1_filt_level_delta1_seg1 AV1_DEC_REG(21, 0, 0x7f) +#define av1_filt_level_delta2_seg1 AV1_DEC_REG(21, 7, 0x7f) +#define av1_filt_level_delta3_seg1 AV1_DEC_REG(21, 14, 0x7f) +#define av1_global_mv_seg1 AV1_DEC_REG(21, 21, 0x1) +#define av1_mf1_last2_offset AV1_DEC_REG(21, 22, 0x1ff) + +#define av1_filt_level_delta1_seg2 AV1_DEC_REG(22, 0, 0x7f) +#define av1_filt_level_delta2_seg2 AV1_DEC_REG(22, 7, 0x7f) +#define av1_filt_level_delta3_seg2 AV1_DEC_REG(22, 14, 0x7f) +#define av1_global_mv_seg2 AV1_DEC_REG(22, 21, 0x1) +#define av1_mf1_last3_offset AV1_DEC_REG(22, 22, 0x1ff) + +#define av1_filt_level_delta1_seg3 AV1_DEC_REG(23, 0, 0x7f) +#define av1_filt_level_delta2_seg3 AV1_DEC_REG(23, 7, 0x7f) +#define av1_filt_level_delta3_seg3 AV1_DEC_REG(23, 14, 0x7f) +#define av1_global_mv_seg3 AV1_DEC_REG(23, 21, 0x1) +#define av1_mf1_golden_offset AV1_DEC_REG(23, 22, 0x1ff) + +#define av1_filt_level_delta1_seg4 AV1_DEC_REG(24, 0, 0x7f) +#define av1_filt_level_delta2_seg4 AV1_DEC_REG(24, 7, 0x7f) +#define av1_filt_level_delta3_seg4 AV1_DEC_REG(24, 14, 0x7f) +#define av1_global_mv_seg4 AV1_DEC_REG(24, 21, 0x1) +#define av1_mf1_bwdref_offset AV1_DEC_REG(24, 22, 0x1ff) + +#define av1_filt_level_delta1_seg5 AV1_DEC_REG(25, 0, 0x7f) +#define av1_filt_level_delta2_seg5 AV1_DEC_REG(25, 7, 0x7f) +#define av1_filt_level_delta3_seg5 AV1_DEC_REG(25, 14, 0x7f) +#define av1_global_mv_seg5 AV1_DEC_REG(25, 21, 0x1) +#define av1_mf1_altref2_offset AV1_DEC_REG(25, 22, 0x1ff) + +#define av1_filt_level_delta1_seg6 AV1_DEC_REG(26, 0, 0x7f) +#define av1_filt_level_delta2_seg6 AV1_DEC_REG(26, 7, 0x7f) +#define av1_filt_level_delta3_seg6 AV1_DEC_REG(26, 14, 0x7f) +#define av1_global_mv_seg6 AV1_DEC_REG(26, 21, 0x1) +#define av1_mf1_altref_offset AV1_DEC_REG(26, 22, 0x1ff) + +#define av1_filt_level_delta1_seg7 AV1_DEC_REG(27, 0, 0x7f) +#define av1_filt_level_delta2_seg7 AV1_DEC_REG(27, 7, 0x7f) +#define av1_filt_level_delta3_seg7 AV1_DEC_REG(27, 14, 0x7f) +#define av1_global_mv_seg7 AV1_DEC_REG(27, 21, 0x1) +#define av1_mf2_last_offset AV1_DEC_REG(27, 22, 0x1ff) + +#define av1_cb_offset AV1_DEC_REG(28, 0, 0x1ff) +#define av1_cb_luma_mult AV1_DEC_REG(28, 9, 0xff) +#define av1_cb_mult AV1_DEC_REG(28, 17, 0xff) +#define av1_quant_delta_v_dc AV1_DEC_REG(28, 25, 0x7f) + +#define av1_cr_offset AV1_DEC_REG(29, 0, 0x1ff) +#define av1_cr_luma_mult AV1_DEC_REG(29, 9, 0xff) +#define av1_cr_mult AV1_DEC_REG(29, 17, 0xff) +#define av1_quant_delta_v_ac AV1_DEC_REG(29, 25, 0x7f) + +#define av1_filt_ref_adj_5 AV1_DEC_REG(30, 0, 0x7f) +#define av1_filt_ref_adj_4 AV1_DEC_REG(30, 7, 0x7f) +#define av1_filt_mb_adj_1 AV1_DEC_REG(30, 14, 0x7f) +#define av1_filt_mb_adj_0 AV1_DEC_REG(30, 21, 0x7f) +#define av1_filt_sharpness AV1_DEC_REG(30, 28, 0x7) + +#define av1_quant_seg6 AV1_DEC_REG(31, 0, 0xff) +#define av1_filt_level_seg6 AV1_DEC_REG(31, 8, 0x3f) +#define av1_skip_seg6 AV1_DEC_REG(31, 14, 0x1) +#define av1_refpic_seg6 AV1_DEC_REG(31, 15, 0xf) +#define av1_filt_level_delta0_seg6 AV1_DEC_REG(31, 19, 0x7f) +#define av1_skip_ref0 AV1_DEC_REG(31, 26, 0xf) + +#define av1_quant_seg7 AV1_DEC_REG(32, 0, 0xff) +#define av1_filt_level_seg7 AV1_DEC_REG(32, 8, 0x3f) +#define av1_skip_seg7 AV1_DEC_REG(32, 14, 0x1) +#define av1_refpic_seg7 AV1_DEC_REG(32, 15, 0xf) +#define av1_filt_level_delta0_seg7 AV1_DEC_REG(32, 19, 0x7f) +#define av1_skip_ref1 AV1_DEC_REG(32, 26, 0xf) + +#define av1_ref0_height AV1_DEC_REG(33, 0, 0xffff) +#define av1_ref0_width AV1_DEC_REG(33, 16, 0xffff) + +#define av1_ref1_height AV1_DEC_REG(34, 0, 0xffff) +#define av1_ref1_width AV1_DEC_REG(34, 16, 0xffff) + +#define av1_ref2_height AV1_DEC_REG(35, 0, 0xffff) +#define av1_ref2_width AV1_DEC_REG(35, 16, 0xffff) + +#define av1_ref0_ver_scale AV1_DEC_REG(36, 0, 0xffff) +#define av1_ref0_hor_scale AV1_DEC_REG(36, 16, 0xffff) + +#define av1_ref1_ver_scale AV1_DEC_REG(37, 0, 0xffff) +#define av1_ref1_hor_scale AV1_DEC_REG(37, 16, 0xffff) + +#define av1_ref2_ver_scale AV1_DEC_REG(38, 0, 0xffff) +#define av1_ref2_hor_scale AV1_DEC_REG(38, 16, 0xffff) + +#define av1_ref3_ver_scale AV1_DEC_REG(39, 0, 0xffff) +#define av1_ref3_hor_scale AV1_DEC_REG(39, 16, 0xffff) + +#define av1_ref4_ver_scale AV1_DEC_REG(40, 0, 0xffff) +#define av1_ref4_hor_scale AV1_DEC_REG(40, 16, 0xffff) + +#define av1_ref5_ver_scale AV1_DEC_REG(41, 0, 0xffff) +#define av1_ref5_hor_scale AV1_DEC_REG(41, 16, 0xffff) + +#define av1_ref6_ver_scale AV1_DEC_REG(42, 0, 0xffff) +#define av1_ref6_hor_scale AV1_DEC_REG(42, 16, 0xffff) + +#define av1_ref3_height AV1_DEC_REG(43, 0, 0xffff) +#define av1_ref3_width AV1_DEC_REG(43, 16, 0xffff) + +#define av1_ref4_height AV1_DEC_REG(44, 0, 0xffff) +#define av1_ref4_width AV1_DEC_REG(44, 16, 0xffff) + +#define av1_ref5_height AV1_DEC_REG(45, 0, 0xffff) +#define av1_ref5_width AV1_DEC_REG(45, 16, 0xffff) + +#define av1_ref6_height AV1_DEC_REG(46, 0, 0xffff) +#define av1_ref6_width AV1_DEC_REG(46, 16, 0xffff) + +#define av1_mf2_last2_offset AV1_DEC_REG(47, 0, 0x1ff) +#define av1_mf2_last3_offset AV1_DEC_REG(47, 9, 0x1ff) +#define av1_mf2_golden_offset AV1_DEC_REG(47, 18, 0x1ff) +#define av1_qmlevel_y AV1_DEC_REG(47, 27, 0xf) + +#define av1_mf2_bwdref_offset AV1_DEC_REG(48, 0, 0x1ff) +#define av1_mf2_altref2_offset AV1_DEC_REG(48, 9, 0x1ff) +#define av1_mf2_altref_offset AV1_DEC_REG(48, 18, 0x1ff) +#define av1_qmlevel_u AV1_DEC_REG(48, 27, 0xf) + +#define av1_filt_ref_adj_6 AV1_DEC_REG(49, 0, 0x7f) +#define av1_filt_ref_adj_7 AV1_DEC_REG(49, 7, 0x7f) +#define av1_qmlevel_v AV1_DEC_REG(49, 14, 0xf) + +#define av1_superres_chroma_step AV1_DEC_REG(51, 0, 0x3fff) +#define av1_superres_luma_step AV1_DEC_REG(51, 14, 0x3fff) + +#define av1_superres_init_chroma_subpel_x AV1_DEC_REG(52, 0, 0x3fff) +#define av1_superres_init_luma_subpel_x AV1_DEC_REG(52, 14, 0x3fff) + +#define av1_cdef_chroma_secondary_strength AV1_DEC_REG(53, 0, 0xffff) +#define av1_cdef_luma_secondary_strength AV1_DEC_REG(53, 16, 0xffff) + +#define av1_apf_threshold AV1_DEC_REG(55, 0, 0xffff) +#define av1_apf_single_pu_mode AV1_DEC_REG(55, 30, 0x1) +#define av1_apf_disable AV1_DEC_REG(55, 30, 0x1) + +#define av1_dec_max_burst AV1_DEC_REG(58, 0, 0xff) +#define av1_dec_buswidth AV1_DEC_REG(58, 8, 0x7) +#define av1_dec_multicore_mode AV1_DEC_REG(58, 11, 0x3) +#define av1_dec_axi_wd_id_e AV1_DEC_REG(58, 13, 0x1) +#define av1_dec_axi_rd_id_e AV1_DEC_REG(58, 14, 0x1) +#define av1_dec_mc_polltime AV1_DEC_REG(58, 17, 0x3ff) +#define av1_dec_mc_pollmode AV1_DEC_REG(58, 27, 0x3) + +#define av1_filt_ref_adj_3 AV1_DEC_REG(59, 0, 0x3f) +#define av1_filt_ref_adj_2 AV1_DEC_REG(59, 7, 0x3f) +#define av1_filt_ref_adj_1 AV1_DEC_REG(59, 14, 0x3f) +#define av1_filt_ref_adj_0 AV1_DEC_REG(59, 21, 0x3f) +#define av1_ref0_sign_bias AV1_DEC_REG(59, 28, 0x1) +#define av1_ref1_sign_bias AV1_DEC_REG(59, 29, 0x1) +#define av1_ref2_sign_bias AV1_DEC_REG(59, 30, 0x1) +#define av1_ref3_sign_bias AV1_DEC_REG(59, 31, 0x1) + +#define av1_cur_last_roffset AV1_DEC_REG(184, 0, 0x1ff) +#define av1_cur_last_offset AV1_DEC_REG(184, 9, 0x1ff) +#define av1_mf3_last_offset AV1_DEC_REG(184, 18, 0x1ff) +#define av1_ref0_gm_mode AV1_DEC_REG(184, 27, 0x3) + +#define av1_cur_last2_roffset AV1_DEC_REG(185, 0, 0x1ff) +#define av1_cur_last2_offset AV1_DEC_REG(185, 9, 0x1ff) +#define av1_mf3_last2_offset AV1_DEC_REG(185, 18, 0x1ff) +#define av1_ref1_gm_mode AV1_DEC_REG(185, 27, 0x3) + +#define av1_cur_last3_roffset AV1_DEC_REG(186, 0, 0x1ff) +#define av1_cur_last3_offset AV1_DEC_REG(186, 9, 0x1ff) +#define av1_mf3_last3_offset AV1_DEC_REG(186, 18, 0x1ff) +#define av1_ref2_gm_mode AV1_DEC_REG(186, 27, 0x3) + +#define av1_cur_golden_roffset AV1_DEC_REG(187, 0, 0x1ff) +#define av1_cur_golden_offset AV1_DEC_REG(187, 9, 0x1ff) +#define av1_mf3_golden_offset AV1_DEC_REG(187, 18, 0x1ff) +#define av1_ref3_gm_mode AV1_DEC_REG(187, 27, 0x3) + +#define av1_cur_bwdref_roffset AV1_DEC_REG(188, 0, 0x1ff) +#define av1_cur_bwdref_offset AV1_DEC_REG(188, 9, 0x1ff) +#define av1_mf3_bwdref_offset AV1_DEC_REG(188, 18, 0x1ff) +#define av1_ref4_gm_mode AV1_DEC_REG(188, 27, 0x3) + +#define av1_cur_altref2_roffset AV1_DEC_REG(257, 0, 0x1ff) +#define av1_cur_altref2_offset AV1_DEC_REG(257, 9, 0x1ff) +#define av1_mf3_altref2_offset AV1_DEC_REG(257, 18, 0x1ff) +#define av1_ref5_gm_mode AV1_DEC_REG(257, 27, 0x3) + +#define av1_strm_buffer_len AV1_DEC_REG(258, 0, 0xffffffff) + +#define av1_strm_start_offset AV1_DEC_REG(259, 0, 0xffffffff) + +#define av1_ppd_blend_exist AV1_DEC_REG(260, 21, 0x1) +#define av1_ppd_dith_exist AV1_DEC_REG(260, 23, 0x1) +#define av1_ablend_crop_e AV1_DEC_REG(260, 24, 0x1) +#define av1_pp_format_p010_e AV1_DEC_REG(260, 25, 0x1) +#define av1_pp_format_customer1_e AV1_DEC_REG(260, 26, 0x1) +#define av1_pp_crop_exist AV1_DEC_REG(260, 27, 0x1) +#define av1_pp_up_level AV1_DEC_REG(260, 28, 0x1) +#define av1_pp_down_level AV1_DEC_REG(260, 29, 0x3) +#define av1_pp_exist AV1_DEC_REG(260, 31, 0x1) + +#define av1_cur_altref_roffset AV1_DEC_REG(262, 0, 0x1ff) +#define av1_cur_altref_offset AV1_DEC_REG(262, 9, 0x1ff) +#define av1_mf3_altref_offset AV1_DEC_REG(262, 18, 0x1ff) +#define av1_ref6_gm_mode AV1_DEC_REG(262, 27, 0x3) + +#define av1_cdef_luma_primary_strength AV1_DEC_REG(263, 0, 0xffffffff) + +#define av1_cdef_chroma_primary_strength AV1_DEC_REG(264, 0, 0xffffffff) + +#define av1_axi_arqos AV1_DEC_REG(265, 0, 0xf) +#define av1_axi_awqos AV1_DEC_REG(265, 4, 0xf) +#define av1_axi_wr_ostd_threshold AV1_DEC_REG(265, 8, 0x3ff) +#define av1_axi_rd_ostd_threshold AV1_DEC_REG(265, 18, 0x3ff) +#define av1_axi_wr_4k_dis AV1_DEC_REG(265, 31, 0x1) + +#define av1_128bit_mode AV1_DEC_REG(266, 5, 0x1) +#define av1_wr_shaper_bypass AV1_DEC_REG(266, 10, 0x1) +#define av1_error_conceal_e AV1_DEC_REG(266, 30, 0x1) + +#define av1_superres_chroma_step_invra AV1_DEC_REG(298, 0, 0xffff) +#define av1_superres_luma_step_invra AV1_DEC_REG(298, 16, 0xffff) + +#define av1_dec_alignment AV1_DEC_REG(314, 0, 0xffff) + +#define av1_ext_timeout_cycles AV1_DEC_REG(318, 0, 0x7fffffff) +#define av1_ext_timeout_override_e AV1_DEC_REG(318, 31, 0x1) + +#define av1_timeout_cycles AV1_DEC_REG(319, 0, 0x7fffffff) +#define av1_timeout_override_e AV1_DEC_REG(319, 31, 0x1) + +#define av1_pp_out_e AV1_DEC_REG(320, 0, 0x1) +#define av1_pp_cr_first AV1_DEC_REG(320, 1, 0x1) +#define av1_pp_out_mode AV1_DEC_REG(320, 2, 0x1) +#define av1_pp_out_tile_e AV1_DEC_REG(320, 3, 0x1) +#define av1_pp_status AV1_DEC_REG(320, 4, 0xf) +#define av1_pp_in_blk_size AV1_DEC_REG(320, 8, 0x7) +#define av1_pp_out_p010_fmt AV1_DEC_REG(320, 11, 0x3) +#define av1_pp_out_rgb_fmt AV1_DEC_REG(320, 13, 0x1f) +#define av1_rgb_range_max AV1_DEC_REG(320, 18, 0xfff) +#define av1_pp_rgb_planar AV1_DEC_REG(320, 30, 0x1) + +#define av1_scale_hratio AV1_DEC_REG(322, 0, 0x3ffff) +#define av1_pp_out_format AV1_DEC_REG(322, 18, 0x1f) +#define av1_ver_scale_mode AV1_DEC_REG(322, 23, 0x3) +#define av1_hor_scale_mode AV1_DEC_REG(322, 25, 0x3) +#define av1_pp_in_format AV1_DEC_REG(322, 27, 0x1f) + +#define av1_pp_out_c_stride AV1_DEC_REG(329, 0, 0xffff) +#define av1_pp_out_y_stride AV1_DEC_REG(329, 16, 0xffff) + +#define av1_pp_in_height AV1_DEC_REG(331, 0, 0xffff) +#define av1_pp_in_width AV1_DEC_REG(331, 16, 0xffff) + +#define av1_pp_out_height AV1_DEC_REG(332, 0, 0xffff) +#define av1_pp_out_width AV1_DEC_REG(332, 16, 0xffff) + +#define av1_pp1_dup_ver AV1_DEC_REG(394, 0, 0xff) +#define av1_pp1_dup_hor AV1_DEC_REG(394, 8, 0xff) +#define av1_pp0_dup_ver AV1_DEC_REG(394, 16, 0xff) +#define av1_pp0_dup_hor AV1_DEC_REG(394, 24, 0xff) + +#define AV1_TILE_OUT_LU (AV1_SWREG(65)) +#define AV1_REFERENCE_Y(i) (AV1_SWREG(67) + ((i) * 0x8)) +#define AV1_SEGMENTATION (AV1_SWREG(81)) +#define AV1_GLOBAL_MODEL (AV1_SWREG(83)) +#define AV1_CDEF_COL (AV1_SWREG(85)) +#define AV1_SR_COL (AV1_SWREG(89)) +#define AV1_LR_COL (AV1_SWREG(91)) +#define AV1_FILM_GRAIN (AV1_SWREG(95)) +#define AV1_TILE_OUT_CH (AV1_SWREG(99)) +#define AV1_REFERENCE_CB(i) (AV1_SWREG(101) + ((i) * 0x8)) +#define AV1_TILE_OUT_MV (AV1_SWREG(133)) +#define AV1_REFERENCE_MV(i) (AV1_SWREG(135) + ((i) * 0x8)) +#define AV1_TILE_BASE (AV1_SWREG(167)) +#define AV1_INPUT_STREAM (AV1_SWREG(169)) +#define AV1_PROP_TABLE_OUT (AV1_SWREG(171)) +#define AV1_PROP_TABLE (AV1_SWREG(173)) +#define AV1_MC_SYNC_CURR (AV1_SWREG(175)) +#define AV1_MC_SYNC_LEFT (AV1_SWREG(177)) +#define AV1_DB_DATA_COL (AV1_SWREG(179)) +#define AV1_DB_CTRL_COL (AV1_SWREG(183)) +#define AV1_PP_OUT_LU (AV1_SWREG(326)) +#define AV1_PP_OUT_CH (AV1_SWREG(328)) + +#endif /* _ROCKCHIP_VPU981_REGS_H_ */ From d8ebe59e7b36bce848426c43cd2ccacc03c82c0a Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 3 May 2023 09:34:36 +0100 Subject: [PATCH 237/253] media: verisilicon: Add film grain feature to AV1 driver Film grain feature add "old style" grain noise on decoded streams. Grain noise is applied after decoding by the postprocessor. The level of grain is based on gaussian sequence. Signed-off-by: Benjamin Gaignard Reviewed-by: Nicolas Dufresne Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/verisilicon/Makefile | 1 + .../media/platform/verisilicon/hantro_hw.h | 3 + .../verisilicon/rockchip_av1_filmgrain.c | 401 ++++++++++++++++++ .../verisilicon/rockchip_av1_filmgrain.h | 36 ++ .../verisilicon/rockchip_vpu981_hw_av1_dec.c | 210 +++++++++ 5 files changed, 651 insertions(+) create mode 100644 drivers/media/platform/verisilicon/rockchip_av1_filmgrain.c create mode 100644 drivers/media/platform/verisilicon/rockchip_av1_filmgrain.h diff --git a/drivers/media/platform/verisilicon/Makefile b/drivers/media/platform/verisilicon/Makefile index c9a9806ab8c5..6ad2ef885920 100644 --- a/drivers/media/platform/verisilicon/Makefile +++ b/drivers/media/platform/verisilicon/Makefile @@ -19,6 +19,7 @@ hantro-vpu-y += \ rockchip_vpu2_hw_mpeg2_dec.o \ rockchip_vpu2_hw_vp8_dec.o \ rockchip_vpu981_hw_av1_dec.o \ + rockchip_av1_filmgrain.o \ rockchip_av1_entropymode.o \ hantro_jpeg.o \ hantro_h264.o \ diff --git a/drivers/media/platform/verisilicon/hantro_hw.h b/drivers/media/platform/verisilicon/hantro_hw.h index 84af70616100..021fad15d66f 100644 --- a/drivers/media/platform/verisilicon/hantro_hw.h +++ b/drivers/media/platform/verisilicon/hantro_hw.h @@ -16,6 +16,7 @@ #include #include "rockchip_av1_entropymode.h" +#include "rockchip_av1_filmgrain.h" #define DEC_8190_ALIGN_MASK 0x07U @@ -288,6 +289,7 @@ struct hantro_av1_frame_ref { * @global_model: global model buffer * @tile_info: tile info buffer * @segment: segmentation info buffer + * @film_grain: film grain buffer * @prob_tbl: probability table * @prob_tbl_out: probability table output * @tile_buf: tile buffer @@ -312,6 +314,7 @@ struct hantro_av1_dec_hw_ctx { struct hantro_aux_buf global_model; struct hantro_aux_buf tile_info; struct hantro_aux_buf segment; + struct hantro_aux_buf film_grain; struct hantro_aux_buf prob_tbl; struct hantro_aux_buf prob_tbl_out; struct hantro_aux_buf tile_buf; diff --git a/drivers/media/platform/verisilicon/rockchip_av1_filmgrain.c b/drivers/media/platform/verisilicon/rockchip_av1_filmgrain.c new file mode 100644 index 000000000000..f2ae84f0b436 --- /dev/null +++ b/drivers/media/platform/verisilicon/rockchip_av1_filmgrain.c @@ -0,0 +1,401 @@ +// SPDX-License-Identifier: GPL-2.0-only or Apache-2.0 + +#include "rockchip_av1_filmgrain.h" + +static const s32 gaussian_sequence[2048] = { + 56, 568, -180, 172, 124, -84, 172, -64, -900, 24, 820, + 224, 1248, 996, 272, -8, -916, -388, -732, -104, -188, 800, + 112, -652, -320, -376, 140, -252, 492, -168, 44, -788, 588, + -584, 500, -228, 12, 680, 272, -476, 972, -100, 652, 368, + 432, -196, -720, -192, 1000, -332, 652, -136, -552, -604, -4, + 192, -220, -136, 1000, -52, 372, -96, -624, 124, -24, 396, + 540, -12, -104, 640, 464, 244, -208, -84, 368, -528, -740, + 248, -968, -848, 608, 376, -60, -292, -40, -156, 252, -292, + 248, 224, -280, 400, -244, 244, -60, 76, -80, 212, 532, + 340, 128, -36, 824, -352, -60, -264, -96, -612, 416, -704, + 220, -204, 640, -160, 1220, -408, 900, 336, 20, -336, -96, + -792, 304, 48, -28, -1232, -1172, -448, 104, -292, -520, 244, + 60, -948, 0, -708, 268, 108, 356, -548, 488, -344, -136, + 488, -196, -224, 656, -236, -1128, 60, 4, 140, 276, -676, + -376, 168, -108, 464, 8, 564, 64, 240, 308, -300, -400, + -456, -136, 56, 120, -408, -116, 436, 504, -232, 328, 844, + -164, -84, 784, -168, 232, -224, 348, -376, 128, 568, 96, + -1244, -288, 276, 848, 832, -360, 656, 464, -384, -332, -356, + 728, -388, 160, -192, 468, 296, 224, 140, -776, -100, 280, + 4, 196, 44, -36, -648, 932, 16, 1428, 28, 528, 808, + 772, 20, 268, 88, -332, -284, 124, -384, -448, 208, -228, + -1044, -328, 660, 380, -148, -300, 588, 240, 540, 28, 136, + -88, -436, 256, 296, -1000, 1400, 0, -48, 1056, -136, 264, + -528, -1108, 632, -484, -592, -344, 796, 124, -668, -768, 388, + 1296, -232, -188, -200, -288, -4, 308, 100, -168, 256, -500, + 204, -508, 648, -136, 372, -272, -120, -1004, -552, -548, -384, + 548, -296, 428, -108, -8, -912, -324, -224, -88, -112, -220, + -100, 996, -796, 548, 360, -216, 180, 428, -200, -212, 148, + 96, 148, 284, 216, -412, -320, 120, -300, -384, -604, -572, + -332, -8, -180, -176, 696, 116, -88, 628, 76, 44, -516, + 240, -208, -40, 100, -592, 344, -308, -452, -228, 20, 916, + -1752, -136, -340, -804, 140, 40, 512, 340, 248, 184, -492, + 896, -156, 932, -628, 328, -688, -448, -616, -752, -100, 560, + -1020, 180, -800, -64, 76, 576, 1068, 396, 660, 552, -108, + -28, 320, -628, 312, -92, -92, -472, 268, 16, 560, 516, + -672, -52, 492, -100, 260, 384, 284, 292, 304, -148, 88, + -152, 1012, 1064, -228, 164, -376, -684, 592, -392, 156, 196, + -524, -64, -884, 160, -176, 636, 648, 404, -396, -436, 864, + 424, -728, 988, -604, 904, -592, 296, -224, 536, -176, -920, + 436, -48, 1176, -884, 416, -776, -824, -884, 524, -548, -564, + -68, -164, -96, 692, 364, -692, -1012, -68, 260, -480, 876, + -1116, 452, -332, -352, 892, -1088, 1220, -676, 12, -292, 244, + 496, 372, -32, 280, 200, 112, -440, -96, 24, -644, -184, + 56, -432, 224, -980, 272, -260, 144, -436, 420, 356, 364, + -528, 76, 172, -744, -368, 404, -752, -416, 684, -688, 72, + 540, 416, 92, 444, 480, -72, -1416, 164, -1172, -68, 24, + 424, 264, 1040, 128, -912, -524, -356, 64, 876, -12, 4, + -88, 532, 272, -524, 320, 276, -508, 940, 24, -400, -120, + 756, 60, 236, -412, 100, 376, -484, 400, -100, -740, -108, + -260, 328, -268, 224, -200, -416, 184, -604, -564, -20, 296, + 60, 892, -888, 60, 164, 68, -760, 216, -296, 904, -336, + -28, 404, -356, -568, -208, -1480, -512, 296, 328, -360, -164, + -1560, -776, 1156, -428, 164, -504, -112, 120, -216, -148, -264, + 308, 32, 64, -72, 72, 116, 176, -64, -272, 460, -536, + -784, -280, 348, 108, -752, -132, 524, -540, -776, 116, -296, + -1196, -288, -560, 1040, -472, 116, -848, -1116, 116, 636, 696, + 284, -176, 1016, 204, -864, -648, -248, 356, 972, -584, -204, + 264, 880, 528, -24, -184, 116, 448, -144, 828, 524, 212, + -212, 52, 12, 200, 268, -488, -404, -880, 824, -672, -40, + 908, -248, 500, 716, -576, 492, -576, 16, 720, -108, 384, + 124, 344, 280, 576, -500, 252, 104, -308, 196, -188, -8, + 1268, 296, 1032, -1196, 436, 316, 372, -432, -200, -660, 704, + -224, 596, -132, 268, 32, -452, 884, 104, -1008, 424, -1348, + -280, 4, -1168, 368, 476, 696, 300, -8, 24, 180, -592, + -196, 388, 304, 500, 724, -160, 244, -84, 272, -256, -420, + 320, 208, -144, -156, 156, 364, 452, 28, 540, 316, 220, + -644, -248, 464, 72, 360, 32, -388, 496, -680, -48, 208, + -116, -408, 60, -604, -392, 548, -840, 784, -460, 656, -544, + -388, -264, 908, -800, -628, -612, -568, 572, -220, 164, 288, + -16, -308, 308, -112, -636, -760, 280, -668, 432, 364, 240, + -196, 604, 340, 384, 196, 592, -44, -500, 432, -580, -132, + 636, -76, 392, 4, -412, 540, 508, 328, -356, -36, 16, + -220, -64, -248, -60, 24, -192, 368, 1040, 92, -24, -1044, + -32, 40, 104, 148, 192, -136, -520, 56, -816, -224, 732, + 392, 356, 212, -80, -424, -1008, -324, 588, -1496, 576, 460, + -816, -848, 56, -580, -92, -1372, -112, -496, 200, 364, 52, + -140, 48, -48, -60, 84, 72, 40, 132, -356, -268, -104, + -284, -404, 732, -520, 164, -304, -540, 120, 328, -76, -460, + 756, 388, 588, 236, -436, -72, -176, -404, -316, -148, 716, + -604, 404, -72, -88, -888, -68, 944, 88, -220, -344, 960, + 472, 460, -232, 704, 120, 832, -228, 692, -508, 132, -476, + 844, -748, -364, -44, 1116, -1104, -1056, 76, 428, 552, -692, + 60, 356, 96, -384, -188, -612, -576, 736, 508, 892, 352, + -1132, 504, -24, -352, 324, 332, -600, -312, 292, 508, -144, + -8, 484, 48, 284, -260, -240, 256, -100, -292, -204, -44, + 472, -204, 908, -188, -1000, -256, 92, 1164, -392, 564, 356, + 652, -28, -884, 256, 484, -192, 760, -176, 376, -524, -452, + -436, 860, -736, 212, 124, 504, -476, 468, 76, -472, 552, + -692, -944, -620, 740, -240, 400, 132, 20, 192, -196, 264, + -668, -1012, -60, 296, -316, -828, 76, -156, 284, -768, -448, + -832, 148, 248, 652, 616, 1236, 288, -328, -400, -124, 588, + 220, 520, -696, 1032, 768, -740, -92, -272, 296, 448, -464, + 412, -200, 392, 440, -200, 264, -152, -260, 320, 1032, 216, + 320, -8, -64, 156, -1016, 1084, 1172, 536, 484, -432, 132, + 372, -52, -256, 84, 116, -352, 48, 116, 304, -384, 412, + 924, -300, 528, 628, 180, 648, 44, -980, -220, 1320, 48, + 332, 748, 524, -268, -720, 540, -276, 564, -344, -208, -196, + 436, 896, 88, -392, 132, 80, -964, -288, 568, 56, -48, + -456, 888, 8, 552, -156, -292, 948, 288, 128, -716, -292, + 1192, -152, 876, 352, -600, -260, -812, -468, -28, -120, -32, + -44, 1284, 496, 192, 464, 312, -76, -516, -380, -456, -1012, + -48, 308, -156, 36, 492, -156, -808, 188, 1652, 68, -120, + -116, 316, 160, -140, 352, 808, -416, 592, 316, -480, 56, + 528, -204, -568, 372, -232, 752, -344, 744, -4, 324, -416, + -600, 768, 268, -248, -88, -132, -420, -432, 80, -288, 404, + -316, -1216, -588, 520, -108, 92, -320, 368, -480, -216, -92, + 1688, -300, 180, 1020, -176, 820, -68, -228, -260, 436, -904, + 20, 40, -508, 440, -736, 312, 332, 204, 760, -372, 728, + 96, -20, -632, -520, -560, 336, 1076, -64, -532, 776, 584, + 192, 396, -728, -520, 276, -188, 80, -52, -612, -252, -48, + 648, 212, -688, 228, -52, -260, 428, -412, -272, -404, 180, + 816, -796, 48, 152, 484, -88, -216, 988, 696, 188, -528, + 648, -116, -180, 316, 476, 12, -564, 96, 476, -252, -364, + -376, -392, 556, -256, -576, 260, -352, 120, -16, -136, -260, + -492, 72, 556, 660, 580, 616, 772, 436, 424, -32, -324, + -1268, 416, -324, -80, 920, 160, 228, 724, 32, -516, 64, + 384, 68, -128, 136, 240, 248, -204, -68, 252, -932, -120, + -480, -628, -84, 192, 852, -404, -288, -132, 204, 100, 168, + -68, -196, -868, 460, 1080, 380, -80, 244, 0, 484, -888, + 64, 184, 352, 600, 460, 164, 604, -196, 320, -64, 588, + -184, 228, 12, 372, 48, -848, -344, 224, 208, -200, 484, + 128, -20, 272, -468, -840, 384, 256, -720, -520, -464, -580, + 112, -120, 644, -356, -208, -608, -528, 704, 560, -424, 392, + 828, 40, 84, 200, -152, 0, -144, 584, 280, -120, 80, + -556, -972, -196, -472, 724, 80, 168, -32, 88, 160, -688, + 0, 160, 356, 372, -776, 740, -128, 676, -248, -480, 4, + -364, 96, 544, 232, -1032, 956, 236, 356, 20, -40, 300, + 24, -676, -596, 132, 1120, -104, 532, -1096, 568, 648, 444, + 508, 380, 188, -376, -604, 1488, 424, 24, 756, -220, -192, + 716, 120, 920, 688, 168, 44, -460, 568, 284, 1144, 1160, + 600, 424, 888, 656, -356, -320, 220, 316, -176, -724, -188, + -816, -628, -348, -228, -380, 1012, -452, -660, 736, 928, 404, + -696, -72, -268, -892, 128, 184, -344, -780, 360, 336, 400, + 344, 428, 548, -112, 136, -228, -216, -820, -516, 340, 92, + -136, 116, -300, 376, -244, 100, -316, -520, -284, -12, 824, + 164, -548, -180, -128, 116, -924, -828, 268, -368, -580, 620, + 192, 160, 0, -1676, 1068, 424, -56, -360, 468, -156, 720, + 288, -528, 556, -364, 548, -148, 504, 316, 152, -648, -620, + -684, -24, -376, -384, -108, -920, -1032, 768, 180, -264, -508, + -1268, -260, -60, 300, -240, 988, 724, -376, -576, -212, -736, + 556, 192, 1092, -620, -880, 376, -56, -4, -216, -32, 836, + 268, 396, 1332, 864, -600, 100, 56, -412, -92, 356, 180, + 884, -468, -436, 292, -388, -804, -704, -840, 368, -348, 140, + -724, 1536, 940, 372, 112, -372, 436, -480, 1136, 296, -32, + -228, 132, -48, -220, 868, -1016, -60, -1044, -464, 328, 916, + 244, 12, -736, -296, 360, 468, -376, -108, -92, 788, 368, + -56, 544, 400, -672, -420, 728, 16, 320, 44, -284, -380, + -796, 488, 132, 204, -596, -372, 88, -152, -908, -636, -572, + -624, -116, -692, -200, -56, 276, -88, 484, -324, 948, 864, + 1000, -456, -184, -276, 292, -296, 156, 676, 320, 160, 908, + -84, -1236, -288, -116, 260, -372, -644, 732, -756, -96, 84, + 344, -520, 348, -688, 240, -84, 216, -1044, -136, -676, -396, + -1500, 960, -40, 176, 168, 1516, 420, -504, -344, -364, -360, + 1216, -940, -380, -212, 252, -660, -708, 484, -444, -152, 928, + -120, 1112, 476, -260, 560, -148, -344, 108, -196, 228, -288, + 504, 560, -328, -88, 288, -1008, 460, -228, 468, -836, -196, + 76, 388, 232, 412, -1168, -716, -644, 756, -172, -356, -504, + 116, 432, 528, 48, 476, -168, -608, 448, 160, -532, -272, + 28, -676, -12, 828, 980, 456, 520, 104, -104, 256, -344, + -4, -28, -368, -52, -524, -572, -556, -200, 768, 1124, -208, + -512, 176, 232, 248, -148, -888, 604, -600, -304, 804, -156, + -212, 488, -192, -804, -256, 368, -360, -916, -328, 228, -240, + -448, -472, 856, -556, -364, 572, -12, -156, -368, -340, 432, + 252, -752, -152, 288, 268, -580, -848, -592, 108, -76, 244, + 312, -716, 592, -80, 436, 360, 4, -248, 160, 516, 584, + 732, 44, -468, -280, -292, -156, -588, 28, 308, 912, 24, + 124, 156, 180, -252, 944, -924, -772, -520, -428, -624, 300, + -212, -1144, 32, -724, 800, -1128, -212, -1288, -848, 180, -416, + 440, 192, -576, -792, -76, -1080, 80, -532, -352, -132, 380, + -820, 148, 1112, 128, 164, 456, 700, -924, 144, -668, -384, + 648, -832, 508, 552, -52, -100, -656, 208, -568, 748, -88, + 680, 232, 300, 192, -408, -1012, -152, -252, -268, 272, -876, + -664, -648, -332, -136, 16, 12, 1152, -28, 332, -536, 320, + -672, -460, -316, 532, -260, 228, -40, 1052, -816, 180, 88, + -496, -556, -672, -368, 428, 92, 356, 404, -408, 252, 196, + -176, -556, 792, 268, 32, 372, 40, 96, -332, 328, 120, + 372, -900, -40, 472, -264, -592, 952, 128, 656, 112, 664, + -232, 420, 4, -344, -464, 556, 244, -416, -32, 252, 0, + -412, 188, -696, 508, -476, 324, -1096, 656, -312, 560, 264, + -136, 304, 160, -64, -580, 248, 336, -720, 560, -348, -288, + -276, -196, -500, 852, -544, -236, -1128, -992, -776, 116, 56, + 52, 860, 884, 212, -12, 168, 1020, 512, -552, 924, -148, + 716, 188, 164, -340, -520, -184, 880, -152, -680, -208, -1156, + -300, -528, -472, 364, 100, -744, -1056, -32, 540, 280, 144, + -676, -32, -232, -280, -224, 96, 568, -76, 172, 148, 148, + 104, 32, -296, -32, 788, -80, 32, -16, 280, 288, 944, + 428, -484 +}; + +static inline s32 clamp(s32 value, s32 low, s32 high) +{ + return value < low ? low : (value > high ? high : value); +} + +static inline s32 round_power_of_two(const s32 val, s32 n) +{ + const s32 a = (s32)1 << (n - 1); + + return (val + a) >> n; +} + +static void rockchip_av1_init_random_generator(u8 luma_num, u16 seed, + u16 *random_register) +{ + u16 random_reg = seed; + + random_reg ^= ((luma_num * 37 + 178) & 255) << 8; + random_reg ^= ((luma_num * 173 + 105) & 255); + *random_register = random_reg; +} + +static inline void rockchip_av1_update_random_register(u16 *random_register) +{ + u16 bit; + u16 random_reg = *random_register; + + bit = ((random_reg >> 0) ^ (random_reg >> 1) ^ (random_reg >> 3) ^ + (random_reg >> 12)) & 1; + *random_register = (random_reg >> 1) | (bit << 15); +} + +static inline s32 rockchip_av1_get_random_number(u16 random_register) +{ + return (random_register >> 5) & ((1 << 11) - 1); +} + +void rockchip_av1_generate_luma_grain_block(s32 (*luma_grain_block)[73][82], + s32 bitdepth, + u8 num_y_points, + s32 grain_scale_shift, + s32 ar_coeff_lag, + s32 (*ar_coeffs_y)[24], + s32 ar_coeff_shift, + s32 grain_min, + s32 grain_max, + u16 random_seed) +{ + s32 gauss_sec_shift = 12 - bitdepth + grain_scale_shift; + u16 grain_random_register = random_seed; + s32 i, j; + + for (i = 0; i < 73; i++) { + for (j = 0; j < 82; j++) { + if (num_y_points > 0) { + rockchip_av1_update_random_register + (&grain_random_register); + (*luma_grain_block)[i][j] = + round_power_of_two(gaussian_sequence + [rockchip_av1_get_random_number + (grain_random_register)], + gauss_sec_shift); + } else { + (*luma_grain_block)[i][j] = 0; + } + } + } + + for (i = 3; i < 73; i++) + for (j = 3; j < 82 - 3; j++) { + s32 pos = 0; + s32 wsum = 0; + s32 deltarow, deltacol; + + for (deltarow = -ar_coeff_lag; deltarow <= 0; + deltarow++) { + for (deltacol = -ar_coeff_lag; + deltacol <= ar_coeff_lag; deltacol++) { + if (deltarow == 0 && deltacol == 0) + break; + wsum = wsum + (*ar_coeffs_y)[pos] * + (*luma_grain_block)[i + deltarow][j + deltacol]; + ++pos; + } + } + (*luma_grain_block)[i][j] = + clamp((*luma_grain_block)[i][j] + + round_power_of_two(wsum, ar_coeff_shift), + grain_min, grain_max); + } +} + +// Calculate chroma grain noise once per frame +void rockchip_av1_generate_chroma_grain_block(s32 (*luma_grain_block)[73][82], + s32 (*cb_grain_block)[38][44], + s32 (*cr_grain_block)[38][44], + s32 bitdepth, + u8 num_y_points, + u8 num_cb_points, + u8 num_cr_points, + s32 grain_scale_shift, + s32 ar_coeff_lag, + s32 (*ar_coeffs_cb)[25], + s32 (*ar_coeffs_cr)[25], + s32 ar_coeff_shift, + s32 grain_min, + s32 grain_max, + u8 chroma_scaling_from_luma, + u16 random_seed) +{ + s32 gauss_sec_shift = 12 - bitdepth + grain_scale_shift; + u16 grain_random_register = 0; + s32 i, j; + + rockchip_av1_init_random_generator(7, random_seed, + &grain_random_register); + for (i = 0; i < 38; i++) { + for (j = 0; j < 44; j++) { + if (num_cb_points || chroma_scaling_from_luma) { + rockchip_av1_update_random_register + (&grain_random_register); + (*cb_grain_block)[i][j] = + round_power_of_two(gaussian_sequence + [rockchip_av1_get_random_number + (grain_random_register)], + gauss_sec_shift); + } else { + (*cb_grain_block)[i][j] = 0; + } + } + } + + rockchip_av1_init_random_generator(11, random_seed, + &grain_random_register); + for (i = 0; i < 38; i++) { + for (j = 0; j < 44; j++) { + if (num_cr_points || chroma_scaling_from_luma) { + rockchip_av1_update_random_register + (&grain_random_register); + (*cr_grain_block)[i][j] = + round_power_of_two(gaussian_sequence + [rockchip_av1_get_random_number + (grain_random_register)], + gauss_sec_shift); + } else { + (*cr_grain_block)[i][j] = 0; + } + } + } + + for (i = 3; i < 38; i++) { + for (j = 3; j < 44 - 3; j++) { + s32 wsum_cb = 0; + s32 wsum_cr = 0; + s32 pos = 0; + s32 deltarow, deltacol; + + for (deltarow = -ar_coeff_lag; deltarow <= 0; + deltarow++) { + for (deltacol = -ar_coeff_lag; + deltacol <= ar_coeff_lag; deltacol++) { + if (deltarow == 0 && deltacol == 0) + break; + wsum_cb = wsum_cb + (*ar_coeffs_cb)[pos] * + (*cb_grain_block)[i + deltarow][j + deltacol]; + wsum_cr = + wsum_cr + + (*ar_coeffs_cr)[pos] * + (*cr_grain_block)[i + deltarow][j + deltacol]; + ++pos; + } + } + + if (num_y_points > 0) { + s32 av_luma = 0; + s32 luma_coord_y = (i << 1) - 3; + s32 luma_coord_x = (j << 1) - 3; + + av_luma += + (*luma_grain_block)[luma_coord_y][luma_coord_x]; + av_luma += + (*luma_grain_block)[luma_coord_y][luma_coord_x + 1]; + av_luma += + (*luma_grain_block)[luma_coord_y + 1][luma_coord_x]; + av_luma += + (*luma_grain_block)[(luma_coord_y + 1)][luma_coord_x + 1]; + av_luma = round_power_of_two(av_luma, 2); + + wsum_cb = wsum_cb + (*ar_coeffs_cb)[pos] * av_luma; + wsum_cr = wsum_cr + (*ar_coeffs_cr)[pos] * av_luma; + } + + if (num_cb_points || chroma_scaling_from_luma) { + (*cb_grain_block)[i][j] = + clamp((*cb_grain_block)[i][j] + + round_power_of_two(wsum_cb, ar_coeff_shift), + grain_min, grain_max); + } + if (num_cr_points || chroma_scaling_from_luma) { + (*cr_grain_block)[i][j] = + clamp((*cr_grain_block)[i][j] + + round_power_of_two(wsum_cr, ar_coeff_shift), + grain_min, grain_max); + } + } + } +} diff --git a/drivers/media/platform/verisilicon/rockchip_av1_filmgrain.h b/drivers/media/platform/verisilicon/rockchip_av1_filmgrain.h new file mode 100644 index 000000000000..31a8b7920c31 --- /dev/null +++ b/drivers/media/platform/verisilicon/rockchip_av1_filmgrain.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _ROCKCHIP_AV1_FILMGRAIN_H_ +#define _ROCKCHIP_AV1_FILMGRAIN_H_ + +#include + +void rockchip_av1_generate_luma_grain_block(s32 (*luma_grain_block)[73][82], + s32 bitdepth, + u8 num_y_points, + s32 grain_scale_shift, + s32 ar_coeff_lag, + s32 (*ar_coeffs_y)[24], + s32 ar_coeff_shift, + s32 grain_min, + s32 grain_max, + u16 random_seed); + +void rockchip_av1_generate_chroma_grain_block(s32 (*luma_grain_block)[73][82], + s32 (*cb_grain_block)[38][44], + s32 (*cr_grain_block)[38][44], + s32 bitdepth, + u8 num_y_points, + u8 num_cb_points, + u8 num_cr_points, + s32 grain_scale_shift, + s32 ar_coeff_lag, + s32 (*ar_coeffs_cb)[25], + s32 (*ar_coeffs_cr)[25], + s32 ar_coeff_shift, + s32 grain_min, + s32 grain_max, + u8 chroma_scaling_from_luma, + u16 random_seed); + +#endif diff --git a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c index bf175072a07b..cc4483857489 100644 --- a/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c +++ b/drivers/media/platform/verisilicon/rockchip_vpu981_hw_av1_dec.c @@ -334,6 +334,12 @@ void rockchip_vpu981_av1_dec_exit(struct hantro_ctx *ctx) av1_dec->tile_info.dma); av1_dec->tile_info.cpu = NULL; + if (av1_dec->film_grain.cpu) + dma_free_coherent(vpu->dev, av1_dec->film_grain.size, + av1_dec->film_grain.cpu, + av1_dec->film_grain.dma); + av1_dec->film_grain.cpu = NULL; + if (av1_dec->prob_tbl.cpu) dma_free_coherent(vpu->dev, av1_dec->prob_tbl.size, av1_dec->prob_tbl.cpu, av1_dec->prob_tbl.dma); @@ -374,6 +380,14 @@ int rockchip_vpu981_av1_dec_init(struct hantro_ctx *ctx) return -ENOMEM; av1_dec->tile_info.size = AV1_MAX_TILES; + av1_dec->film_grain.cpu = dma_alloc_coherent(vpu->dev, + ALIGN(sizeof(struct rockchip_av1_film_grain), 2048), + &av1_dec->film_grain.dma, + GFP_KERNEL); + if (!av1_dec->film_grain.cpu) + return -ENOMEM; + av1_dec->film_grain.size = ALIGN(sizeof(struct rockchip_av1_film_grain), 2048); + av1_dec->prob_tbl.cpu = dma_alloc_coherent(vpu->dev, ALIGN(sizeof(struct av1cdfs), 2048), &av1_dec->prob_tbl.dma, @@ -1178,6 +1192,201 @@ static void rockchip_vpu981_av1_dec_set_prob(struct hantro_ctx *ctx) hantro_write_addr(vpu, AV1_PROP_TABLE, av1_dec->prob_tbl.dma); } +static void +rockchip_vpu981_av1_dec_init_scaling_function(const u8 *values, const u8 *scaling, + u8 num_points, u8 *scaling_lut) +{ + int i, point; + + if (num_points == 0) { + memset(scaling_lut, 0, 256); + return; + } + + for (point = 0; point < num_points - 1; point++) { + int x; + s32 delta_y = scaling[point + 1] - scaling[point]; + s32 delta_x = values[point + 1] - values[point]; + s64 delta = + delta_x ? delta_y * ((65536 + (delta_x >> 1)) / + delta_x) : 0; + + for (x = 0; x < delta_x; x++) { + scaling_lut[values[point] + x] = + scaling[point] + + (s32)((x * delta + 32768) >> 16); + } + } + + for (i = values[num_points - 1]; i < 256; i++) + scaling_lut[i] = scaling[num_points - 1]; +} + +static void rockchip_vpu981_av1_dec_set_fgs(struct hantro_ctx *ctx) +{ + struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; + struct hantro_av1_dec_ctrls *ctrls = &av1_dec->ctrls; + const struct v4l2_ctrl_av1_film_grain *film_grain = ctrls->film_grain; + struct rockchip_av1_film_grain *fgmem = av1_dec->film_grain.cpu; + struct hantro_dev *vpu = ctx->dev; + bool scaling_from_luma = + !!(film_grain->flags & V4L2_AV1_FILM_GRAIN_FLAG_CHROMA_SCALING_FROM_LUMA); + s32 (*ar_coeffs_y)[24]; + s32 (*ar_coeffs_cb)[25]; + s32 (*ar_coeffs_cr)[25]; + s32 (*luma_grain_block)[73][82]; + s32 (*cb_grain_block)[38][44]; + s32 (*cr_grain_block)[38][44]; + s32 ar_coeff_lag, ar_coeff_shift; + s32 grain_scale_shift, bitdepth; + s32 grain_center, grain_min, grain_max; + int i, j; + + hantro_reg_write(vpu, &av1_apply_grain, 0); + + if (!(film_grain->flags & V4L2_AV1_FILM_GRAIN_FLAG_APPLY_GRAIN)) { + hantro_reg_write(vpu, &av1_num_y_points_b, 0); + hantro_reg_write(vpu, &av1_num_cb_points_b, 0); + hantro_reg_write(vpu, &av1_num_cr_points_b, 0); + hantro_reg_write(vpu, &av1_scaling_shift, 0); + hantro_reg_write(vpu, &av1_cb_mult, 0); + hantro_reg_write(vpu, &av1_cb_luma_mult, 0); + hantro_reg_write(vpu, &av1_cb_offset, 0); + hantro_reg_write(vpu, &av1_cr_mult, 0); + hantro_reg_write(vpu, &av1_cr_luma_mult, 0); + hantro_reg_write(vpu, &av1_cr_offset, 0); + hantro_reg_write(vpu, &av1_overlap_flag, 0); + hantro_reg_write(vpu, &av1_clip_to_restricted_range, 0); + hantro_reg_write(vpu, &av1_chroma_scaling_from_luma, 0); + hantro_reg_write(vpu, &av1_random_seed, 0); + hantro_write_addr(vpu, AV1_FILM_GRAIN, 0); + return; + } + + ar_coeffs_y = kzalloc(sizeof(int32_t) * 24, GFP_KERNEL); + ar_coeffs_cb = kzalloc(sizeof(int32_t) * 25, GFP_KERNEL); + ar_coeffs_cr = kzalloc(sizeof(int32_t) * 25, GFP_KERNEL); + luma_grain_block = kzalloc(sizeof(int32_t) * 73 * 82, GFP_KERNEL); + cb_grain_block = kzalloc(sizeof(int32_t) * 38 * 44, GFP_KERNEL); + cr_grain_block = kzalloc(sizeof(int32_t) * 38 * 44, GFP_KERNEL); + + if (!ar_coeffs_y || !ar_coeffs_cb || !ar_coeffs_cr || + !luma_grain_block || !cb_grain_block || !cr_grain_block) { + pr_warn("Fail allocating memory for film grain parameters\n"); + goto alloc_fail; + } + + hantro_reg_write(vpu, &av1_apply_grain, 1); + + hantro_reg_write(vpu, &av1_num_y_points_b, + film_grain->num_y_points > 0); + hantro_reg_write(vpu, &av1_num_cb_points_b, + film_grain->num_cb_points > 0); + hantro_reg_write(vpu, &av1_num_cr_points_b, + film_grain->num_cr_points > 0); + hantro_reg_write(vpu, &av1_scaling_shift, + film_grain->grain_scaling_minus_8 + 8); + + if (!scaling_from_luma) { + hantro_reg_write(vpu, &av1_cb_mult, film_grain->cb_mult - 128); + hantro_reg_write(vpu, &av1_cb_luma_mult, film_grain->cb_luma_mult - 128); + hantro_reg_write(vpu, &av1_cb_offset, film_grain->cb_offset - 256); + hantro_reg_write(vpu, &av1_cr_mult, film_grain->cr_mult - 128); + hantro_reg_write(vpu, &av1_cr_luma_mult, film_grain->cr_luma_mult - 128); + hantro_reg_write(vpu, &av1_cr_offset, film_grain->cr_offset - 256); + } else { + hantro_reg_write(vpu, &av1_cb_mult, 0); + hantro_reg_write(vpu, &av1_cb_luma_mult, 0); + hantro_reg_write(vpu, &av1_cb_offset, 0); + hantro_reg_write(vpu, &av1_cr_mult, 0); + hantro_reg_write(vpu, &av1_cr_luma_mult, 0); + hantro_reg_write(vpu, &av1_cr_offset, 0); + } + + hantro_reg_write(vpu, &av1_overlap_flag, + !!(film_grain->flags & V4L2_AV1_FILM_GRAIN_FLAG_OVERLAP)); + hantro_reg_write(vpu, &av1_clip_to_restricted_range, + !!(film_grain->flags & V4L2_AV1_FILM_GRAIN_FLAG_CLIP_TO_RESTRICTED_RANGE)); + hantro_reg_write(vpu, &av1_chroma_scaling_from_luma, scaling_from_luma); + hantro_reg_write(vpu, &av1_random_seed, film_grain->grain_seed); + + rockchip_vpu981_av1_dec_init_scaling_function(film_grain->point_y_value, + film_grain->point_y_scaling, + film_grain->num_y_points, + fgmem->scaling_lut_y); + + if (film_grain->flags & + V4L2_AV1_FILM_GRAIN_FLAG_CHROMA_SCALING_FROM_LUMA) { + memcpy(fgmem->scaling_lut_cb, fgmem->scaling_lut_y, + sizeof(*fgmem->scaling_lut_y) * 256); + memcpy(fgmem->scaling_lut_cr, fgmem->scaling_lut_y, + sizeof(*fgmem->scaling_lut_y) * 256); + } else { + rockchip_vpu981_av1_dec_init_scaling_function + (film_grain->point_cb_value, film_grain->point_cb_scaling, + film_grain->num_cb_points, fgmem->scaling_lut_cb); + rockchip_vpu981_av1_dec_init_scaling_function + (film_grain->point_cr_value, film_grain->point_cr_scaling, + film_grain->num_cr_points, fgmem->scaling_lut_cr); + } + + for (i = 0; i < V4L2_AV1_AR_COEFFS_SIZE; i++) { + if (i < 24) + (*ar_coeffs_y)[i] = film_grain->ar_coeffs_y_plus_128[i] - 128; + (*ar_coeffs_cb)[i] = film_grain->ar_coeffs_cb_plus_128[i] - 128; + (*ar_coeffs_cr)[i] = film_grain->ar_coeffs_cr_plus_128[i] - 128; + } + + ar_coeff_lag = film_grain->ar_coeff_lag; + ar_coeff_shift = film_grain->ar_coeff_shift_minus_6 + 6; + grain_scale_shift = film_grain->grain_scale_shift; + bitdepth = ctx->bit_depth; + grain_center = 128 << (bitdepth - 8); + grain_min = 0 - grain_center; + grain_max = (256 << (bitdepth - 8)) - 1 - grain_center; + + rockchip_av1_generate_luma_grain_block(luma_grain_block, bitdepth, + film_grain->num_y_points, grain_scale_shift, + ar_coeff_lag, ar_coeffs_y, ar_coeff_shift, + grain_min, grain_max, film_grain->grain_seed); + + rockchip_av1_generate_chroma_grain_block(luma_grain_block, cb_grain_block, + cr_grain_block, bitdepth, + film_grain->num_y_points, + film_grain->num_cb_points, + film_grain->num_cr_points, + grain_scale_shift, ar_coeff_lag, ar_coeffs_cb, + ar_coeffs_cr, ar_coeff_shift, grain_min, + grain_max, + scaling_from_luma, + film_grain->grain_seed); + + for (i = 0; i < 64; i++) { + for (j = 0; j < 64; j++) + fgmem->cropped_luma_grain_block[i * 64 + j] = + (*luma_grain_block)[i + 9][j + 9]; + } + + for (i = 0; i < 32; i++) { + for (j = 0; j < 32; j++) { + fgmem->cropped_chroma_grain_block[i * 64 + 2 * j] = + (*cb_grain_block)[i + 6][j + 6]; + fgmem->cropped_chroma_grain_block[i * 64 + 2 * j + 1] = + (*cr_grain_block)[i + 6][j + 6]; + } + } + + hantro_write_addr(vpu, AV1_FILM_GRAIN, av1_dec->film_grain.dma); + +alloc_fail: + kfree(ar_coeffs_y); + kfree(ar_coeffs_cb); + kfree(ar_coeffs_cr); + kfree(luma_grain_block); + kfree(cb_grain_block); + kfree(cr_grain_block); +} + static void rockchip_vpu981_av1_dec_set_cdef(struct hantro_ctx *ctx) { struct hantro_av1_dec_hw_ctx *av1_dec = &ctx->av1_dec; @@ -1915,6 +2124,7 @@ int rockchip_vpu981_av1_dec_run(struct hantro_ctx *ctx) rockchip_vpu981_av1_dec_set_picture_dimensions(ctx); rockchip_vpu981_av1_dec_set_cdef(ctx); rockchip_vpu981_av1_dec_set_lr(ctx); + rockchip_vpu981_av1_dec_set_fgs(ctx); rockchip_vpu981_av1_dec_set_prob(ctx); hantro_reg_write(vpu, &av1_dec_mode, AV1_DEC_MODE); From 003afda97c6510f33d1ebcd96ca39661f3bf922f Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 3 May 2023 09:34:37 +0100 Subject: [PATCH 238/253] media: verisilicon: Enable AV1 decoder on rk3588 Add rk3588 AV1 decoder to Hantro variant. The hardware support image from 64x64 up to 7680x4320 by steps of 16 pixels. Signed-off-by: Benjamin Gaignard Reviewed-by: Nicolas Dufresne Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/verisilicon/hantro_drv.c | 1 + .../media/platform/verisilicon/hantro_hw.h | 2 + .../platform/verisilicon/rockchip_vpu_hw.c | 134 ++++++++++++++++++ 3 files changed, 137 insertions(+) diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c index be1f06c21910..dd41a6de1a0c 100644 --- a/drivers/media/platform/verisilicon/hantro_drv.c +++ b/drivers/media/platform/verisilicon/hantro_drv.c @@ -713,6 +713,7 @@ static const struct of_device_id of_hantro_match[] = { { .compatible = "rockchip,rk3399-vpu", .data = &rk3399_vpu_variant, }, { .compatible = "rockchip,rk3568-vepu", .data = &rk3568_vepu_variant, }, { .compatible = "rockchip,rk3568-vpu", .data = &rk3568_vpu_variant, }, + { .compatible = "rockchip,rk3588-av1-vpu", .data = &rk3588_vpu981_variant, }, #endif #ifdef CONFIG_VIDEO_HANTRO_IMX8M { .compatible = "nxp,imx8mm-vpu-g1", .data = &imx8mm_vpu_g1_variant, }, diff --git a/drivers/media/platform/verisilicon/hantro_hw.h b/drivers/media/platform/verisilicon/hantro_hw.h index 021fad15d66f..7f33f7b07ce4 100644 --- a/drivers/media/platform/verisilicon/hantro_hw.h +++ b/drivers/media/platform/verisilicon/hantro_hw.h @@ -403,11 +403,13 @@ extern const struct hantro_variant rk3328_vpu_variant; extern const struct hantro_variant rk3399_vpu_variant; extern const struct hantro_variant rk3568_vepu_variant; extern const struct hantro_variant rk3568_vpu_variant; +extern const struct hantro_variant rk3588_vpu981_variant; extern const struct hantro_variant sama5d4_vdec_variant; extern const struct hantro_variant sunxi_vpu_variant; extern const struct hantro_postproc_ops hantro_g1_postproc_ops; extern const struct hantro_postproc_ops hantro_g2_postproc_ops; +extern const struct hantro_postproc_ops rockchip_vpu981_postproc_ops; extern const u32 hantro_vp8_dec_mc_filter[8][6]; diff --git a/drivers/media/platform/verisilicon/rockchip_vpu_hw.c b/drivers/media/platform/verisilicon/rockchip_vpu_hw.c index 8de6fd2e8eef..816ffa905a4b 100644 --- a/drivers/media/platform/verisilicon/rockchip_vpu_hw.c +++ b/drivers/media/platform/verisilicon/rockchip_vpu_hw.c @@ -13,9 +13,13 @@ #include "hantro_g1_regs.h" #include "hantro_h1_regs.h" #include "rockchip_vpu2_regs.h" +#include "rockchip_vpu981_regs.h" #define RK3066_ACLK_MAX_FREQ (300 * 1000 * 1000) #define RK3288_ACLK_MAX_FREQ (400 * 1000 * 1000) +#define RK3588_ACLK_MAX_FREQ (300 * 1000 * 1000) + +#define ROCKCHIP_VPU981_MIN_SIZE 64 /* * Supported formats. @@ -74,6 +78,37 @@ static const struct hantro_fmt rockchip_vpu1_postproc_fmts[] = { }, }; +static const struct hantro_fmt rockchip_vpu981_postproc_fmts[] = { + { + .fourcc = V4L2_PIX_FMT_NV12, + .codec_mode = HANTRO_MODE_NONE, + .match_depth = true, + .postprocessed = true, + .frmsize = { + .min_width = ROCKCHIP_VPU981_MIN_SIZE, + .max_width = FMT_UHD_WIDTH, + .step_width = MB_DIM, + .min_height = ROCKCHIP_VPU981_MIN_SIZE, + .max_height = FMT_UHD_HEIGHT, + .step_height = MB_DIM, + }, + }, + { + .fourcc = V4L2_PIX_FMT_P010, + .codec_mode = HANTRO_MODE_NONE, + .match_depth = true, + .postprocessed = true, + .frmsize = { + .min_width = ROCKCHIP_VPU981_MIN_SIZE, + .max_width = FMT_UHD_WIDTH, + .step_width = MB_DIM, + .min_height = ROCKCHIP_VPU981_MIN_SIZE, + .max_height = FMT_UHD_HEIGHT, + .step_height = MB_DIM, + }, + }, +}; + static const struct hantro_fmt rk3066_vpu_dec_fmts[] = { { .fourcc = V4L2_PIX_FMT_NV12, @@ -277,6 +312,48 @@ static const struct hantro_fmt rk3399_vpu_dec_fmts[] = { }, }; +static const struct hantro_fmt rockchip_vpu981_dec_fmts[] = { + { + .fourcc = V4L2_PIX_FMT_NV12_4L4, + .codec_mode = HANTRO_MODE_NONE, + .match_depth = true, + .frmsize = { + .min_width = ROCKCHIP_VPU981_MIN_SIZE, + .max_width = FMT_UHD_WIDTH, + .step_width = MB_DIM, + .min_height = ROCKCHIP_VPU981_MIN_SIZE, + .max_height = FMT_UHD_HEIGHT, + .step_height = MB_DIM, + }, + }, + { + .fourcc = V4L2_PIX_FMT_NV15_4L4, + .codec_mode = HANTRO_MODE_NONE, + .match_depth = true, + .frmsize = { + .min_width = ROCKCHIP_VPU981_MIN_SIZE, + .max_width = FMT_UHD_WIDTH, + .step_width = MB_DIM, + .min_height = ROCKCHIP_VPU981_MIN_SIZE, + .max_height = FMT_UHD_HEIGHT, + .step_height = MB_DIM, + }, + }, + { + .fourcc = V4L2_PIX_FMT_AV1_FRAME, + .codec_mode = HANTRO_MODE_AV1_DEC, + .max_depth = 2, + .frmsize = { + .min_width = ROCKCHIP_VPU981_MIN_SIZE, + .max_width = FMT_UHD_WIDTH, + .step_width = MB_DIM, + .min_height = ROCKCHIP_VPU981_MIN_SIZE, + .max_height = FMT_UHD_HEIGHT, + .step_height = MB_DIM, + }, + }, +}; + static irqreturn_t rockchip_vpu1_vepu_irq(int irq, void *dev_id) { struct hantro_dev *vpu = dev_id; @@ -331,6 +408,24 @@ static irqreturn_t rockchip_vpu2_vepu_irq(int irq, void *dev_id) return IRQ_HANDLED; } +static irqreturn_t rk3588_vpu981_irq(int irq, void *dev_id) +{ + struct hantro_dev *vpu = dev_id; + enum vb2_buffer_state state; + u32 status; + + status = vdpu_read(vpu, AV1_REG_INTERRUPT); + state = (status & AV1_REG_INTERRUPT_DEC_RDY_INT) ? + VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR; + + vdpu_write(vpu, 0, AV1_REG_INTERRUPT); + vdpu_write(vpu, AV1_REG_CONFIG_DEC_CLK_GATE_E, AV1_REG_CONFIG); + + hantro_irq_done(vpu, state); + + return IRQ_HANDLED; +} + static int rk3036_vpu_hw_init(struct hantro_dev *vpu) { /* Bump ACLK to max. possible freq. to improve performance. */ @@ -346,6 +441,13 @@ static int rk3066_vpu_hw_init(struct hantro_dev *vpu) return 0; } +static int rk3588_vpu981_hw_init(struct hantro_dev *vpu) +{ + /* Bump ACLKs to max. possible freq. to improve performance. */ + clk_set_rate(vpu->clocks[0].clk, RK3588_ACLK_MAX_FREQ); + return 0; +} + static int rockchip_vpu_hw_init(struct hantro_dev *vpu) { /* Bump ACLK to max. possible freq. to improve performance. */ @@ -498,6 +600,14 @@ static const struct hantro_codec_ops rk3568_vepu_codec_ops[] = { }, }; +static const struct hantro_codec_ops rk3588_vpu981_codec_ops[] = { + [HANTRO_MODE_AV1_DEC] = { + .run = rockchip_vpu981_av1_dec_run, + .init = rockchip_vpu981_av1_dec_init, + .exit = rockchip_vpu981_av1_dec_exit, + .done = rockchip_vpu981_av1_dec_done, + }, +}; /* * VPU variant. */ @@ -529,10 +639,18 @@ static const char * const rk3066_vpu_clk_names[] = { "aclk_vepu", "hclk_vepu" }; +static const struct hantro_irq rk3588_vpu981_irqs[] = { + { "vdpu", rk3588_vpu981_irq }, +}; + static const char * const rockchip_vpu_clk_names[] = { "aclk", "hclk" }; +static const char * const rk3588_vpu981_vpu_clk_names[] = { + "aclk", "hclk", "aclk_vdpu_root", "hclk_vdpu_root" +}; + /* VDPU1/VEPU1 */ const struct hantro_variant rk3036_vpu_variant = { @@ -678,3 +796,19 @@ const struct hantro_variant px30_vpu_variant = { .clk_names = rockchip_vpu_clk_names, .num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names) }; + +const struct hantro_variant rk3588_vpu981_variant = { + .dec_offset = 0x0, + .dec_fmts = rockchip_vpu981_dec_fmts, + .num_dec_fmts = ARRAY_SIZE(rockchip_vpu981_dec_fmts), + .postproc_fmts = rockchip_vpu981_postproc_fmts, + .num_postproc_fmts = ARRAY_SIZE(rockchip_vpu981_postproc_fmts), + .postproc_ops = &rockchip_vpu981_postproc_ops, + .codec = HANTRO_AV1_DECODER, + .codec_ops = rk3588_vpu981_codec_ops, + .irqs = rk3588_vpu981_irqs, + .num_irqs = ARRAY_SIZE(rk3588_vpu981_irqs), + .init = rk3588_vpu981_hw_init, + .clk_names = rk3588_vpu981_vpu_clk_names, + .num_clocks = ARRAY_SIZE(rk3588_vpu981_vpu_clk_names) +}; From 80c7373a456e71a41e40f0cfb32e32b9572262ce Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 3 May 2023 09:34:38 +0100 Subject: [PATCH 239/253] media: verisilicon: Conditionally ignore native formats AV1 film grain feature requires to use the postprocessor to produce valid frames. In such case the driver shouldn't propose native pixels format but only post-processed pixels format. Additionally if when setting a control a value could change capture queue pixels formats it is needed to call hantro_reset_raw_fmt(). Signed-off-by: Benjamin Gaignard Reviewed-by: Nicolas Dufresne Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/verisilicon/hantro.h | 3 + .../media/platform/verisilicon/hantro_drv.c | 14 +++-- .../platform/verisilicon/hantro_postproc.c | 6 +- .../media/platform/verisilicon/hantro_v4l2.c | 57 +++++++++++++------ .../media/platform/verisilicon/hantro_v4l2.h | 8 ++- 5 files changed, 63 insertions(+), 25 deletions(-) diff --git a/drivers/media/platform/verisilicon/hantro.h b/drivers/media/platform/verisilicon/hantro.h index a98cb40a8d3b..6523ffb74881 100644 --- a/drivers/media/platform/verisilicon/hantro.h +++ b/drivers/media/platform/verisilicon/hantro.h @@ -231,6 +231,8 @@ struct hantro_dev { * @ctrl_handler: Control handler used to register controls. * @jpeg_quality: User-specified JPEG compression quality. * @bit_depth: Bit depth of current frame + * @need_postproc: Set to true if the bitstream features require to + * use the post-processor. * * @codec_ops: Set of operations related to codec mode. * @postproc: Post-processing context. @@ -261,6 +263,7 @@ struct hantro_ctx { const struct hantro_codec_ops *codec_ops; struct hantro_postproc_ctx postproc; + bool need_postproc; /* Specific for particular codec modes. */ union { diff --git a/drivers/media/platform/verisilicon/hantro_drv.c b/drivers/media/platform/verisilicon/hantro_drv.c index dd41a6de1a0c..c0a368bacf88 100644 --- a/drivers/media/platform/verisilicon/hantro_drv.c +++ b/drivers/media/platform/verisilicon/hantro_drv.c @@ -319,7 +319,7 @@ static int hantro_vp9_s_ctrl(struct v4l2_ctrl *ctrl) if (ctx->bit_depth == bit_depth) return 0; - return hantro_reset_raw_fmt(ctx, bit_depth); + return hantro_reset_raw_fmt(ctx, bit_depth, HANTRO_AUTO_POSTPROC); } default: return -EINVAL; @@ -343,7 +343,7 @@ static int hantro_hevc_s_ctrl(struct v4l2_ctrl *ctrl) if (ctx->bit_depth == bit_depth) return 0; - return hantro_reset_raw_fmt(ctx, bit_depth); + return hantro_reset_raw_fmt(ctx, bit_depth, HANTRO_AUTO_POSTPROC); } default: return -EINVAL; @@ -363,11 +363,17 @@ static int hantro_av1_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_STATELESS_AV1_SEQUENCE: { int bit_depth = ctrl->p_new.p_av1_sequence->bit_depth; + bool need_postproc = HANTRO_AUTO_POSTPROC; - if (ctx->bit_depth == bit_depth) + if (ctrl->p_new.p_av1_sequence->flags + & V4L2_AV1_SEQUENCE_FLAG_FILM_GRAIN_PARAMS_PRESENT) + need_postproc = HANTRO_FORCE_POSTPROC; + + if (ctx->bit_depth == bit_depth && + ctx->need_postproc == need_postproc) return 0; - return hantro_reset_raw_fmt(ctx, bit_depth); + return hantro_reset_raw_fmt(ctx, bit_depth, need_postproc); } default: return -EINVAL; diff --git a/drivers/media/platform/verisilicon/hantro_postproc.c b/drivers/media/platform/verisilicon/hantro_postproc.c index bb16af50719d..c977d64105b1 100644 --- a/drivers/media/platform/verisilicon/hantro_postproc.c +++ b/drivers/media/platform/verisilicon/hantro_postproc.c @@ -57,6 +57,10 @@ bool hantro_needs_postproc(const struct hantro_ctx *ctx, { if (ctx->is_encoder) return false; + + if (ctx->need_postproc) + return true; + return fmt->postprocessed; } @@ -197,7 +201,7 @@ int hantro_postproc_alloc(struct hantro_ctx *ctx) unsigned int i, buf_size; /* this should always pick native format */ - fmt = hantro_get_default_fmt(ctx, false, ctx->bit_depth); + fmt = hantro_get_default_fmt(ctx, false, ctx->bit_depth, HANTRO_AUTO_POSTPROC); if (!fmt) return -EINVAL; v4l2_fill_pixfmt_mp(&pix_mp, fmt->fourcc, ctx->src_fmt.width, diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c index 3367aa956ba3..e871c078dd59 100644 --- a/drivers/media/platform/verisilicon/hantro_v4l2.c +++ b/drivers/media/platform/verisilicon/hantro_v4l2.c @@ -31,15 +31,21 @@ #define HANTRO_DEFAULT_BIT_DEPTH 8 static int hantro_set_fmt_out(struct hantro_ctx *ctx, - struct v4l2_pix_format_mplane *pix_mp); + struct v4l2_pix_format_mplane *pix_mp, + bool need_postproc); static int hantro_set_fmt_cap(struct hantro_ctx *ctx, struct v4l2_pix_format_mplane *pix_mp); static const struct hantro_fmt * -hantro_get_formats(const struct hantro_ctx *ctx, unsigned int *num_fmts) +hantro_get_formats(const struct hantro_ctx *ctx, unsigned int *num_fmts, bool need_postproc) { const struct hantro_fmt *formats; + if (need_postproc) { + *num_fmts = 0; + return NULL; + } + if (ctx->is_encoder) { formats = ctx->dev->variant->enc_fmts; *num_fmts = ctx->dev->variant->num_enc_fmts; @@ -108,7 +114,7 @@ hantro_find_format(const struct hantro_ctx *ctx, u32 fourcc) const struct hantro_fmt *formats; unsigned int i, num_fmts; - formats = hantro_get_formats(ctx, &num_fmts); + formats = hantro_get_formats(ctx, &num_fmts, HANTRO_AUTO_POSTPROC); for (i = 0; i < num_fmts; i++) if (formats[i].fourcc == fourcc) return &formats[i]; @@ -121,18 +127,28 @@ hantro_find_format(const struct hantro_ctx *ctx, u32 fourcc) } const struct hantro_fmt * -hantro_get_default_fmt(const struct hantro_ctx *ctx, bool bitstream, int bit_depth) +hantro_get_default_fmt(const struct hantro_ctx *ctx, bool bitstream, + int bit_depth, bool need_postproc) { const struct hantro_fmt *formats; unsigned int i, num_fmts; - formats = hantro_get_formats(ctx, &num_fmts); + formats = hantro_get_formats(ctx, &num_fmts, need_postproc); for (i = 0; i < num_fmts; i++) { if (bitstream == (formats[i].codec_mode != HANTRO_MODE_NONE) && hantro_check_depth_match(&formats[i], bit_depth)) return &formats[i]; } + + formats = hantro_get_postproc_formats(ctx, &num_fmts); + for (i = 0; i < num_fmts; i++) { + if (bitstream == (formats[i].codec_mode != + HANTRO_MODE_NONE) && + hantro_check_depth_match(&formats[i], bit_depth)) + return &formats[i]; + } + return NULL; } @@ -199,7 +215,7 @@ static int vidioc_enum_fmt(struct file *file, void *priv, */ skip_mode_none = capture == ctx->is_encoder; - formats = hantro_get_formats(ctx, &num_fmts); + formats = hantro_get_formats(ctx, &num_fmts, HANTRO_AUTO_POSTPROC); for (i = 0; i < num_fmts; i++) { bool mode_none = formats[i].codec_mode == HANTRO_MODE_NONE; fmt = &formats[i]; @@ -294,7 +310,7 @@ static int hantro_try_fmt(const struct hantro_ctx *ctx, fmt = hantro_find_format(ctx, pix_mp->pixelformat); if (!fmt) { - fmt = hantro_get_default_fmt(ctx, coded, HANTRO_DEFAULT_BIT_DEPTH); + fmt = hantro_get_default_fmt(ctx, coded, HANTRO_DEFAULT_BIT_DEPTH, HANTRO_AUTO_POSTPROC); pix_mp->pixelformat = fmt->fourcc; } @@ -383,7 +399,7 @@ hantro_reset_encoded_fmt(struct hantro_ctx *ctx) const struct hantro_fmt *vpu_fmt; struct v4l2_pix_format_mplane fmt; - vpu_fmt = hantro_get_default_fmt(ctx, true, HANTRO_DEFAULT_BIT_DEPTH); + vpu_fmt = hantro_get_default_fmt(ctx, true, HANTRO_DEFAULT_BIT_DEPTH, HANTRO_AUTO_POSTPROC); if (!vpu_fmt) return; @@ -393,17 +409,17 @@ hantro_reset_encoded_fmt(struct hantro_ctx *ctx) if (ctx->is_encoder) hantro_set_fmt_cap(ctx, &fmt); else - hantro_set_fmt_out(ctx, &fmt); + hantro_set_fmt_out(ctx, &fmt, HANTRO_AUTO_POSTPROC); } int -hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth) +hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth, bool need_postproc) { const struct hantro_fmt *raw_vpu_fmt; struct v4l2_pix_format_mplane raw_fmt, *encoded_fmt; int ret; - raw_vpu_fmt = hantro_get_default_fmt(ctx, false, bit_depth); + raw_vpu_fmt = hantro_get_default_fmt(ctx, false, bit_depth, need_postproc); if (!raw_vpu_fmt) return -EINVAL; @@ -418,12 +434,14 @@ hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth) raw_fmt.width = encoded_fmt->width; raw_fmt.height = encoded_fmt->height; if (ctx->is_encoder) - ret = hantro_set_fmt_out(ctx, &raw_fmt); + ret = hantro_set_fmt_out(ctx, &raw_fmt, need_postproc); else ret = hantro_set_fmt_cap(ctx, &raw_fmt); - if (!ret) + if (!ret) { ctx->bit_depth = bit_depth; + ctx->need_postproc = need_postproc; + } return ret; } @@ -431,7 +449,7 @@ hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth) void hantro_reset_fmts(struct hantro_ctx *ctx) { hantro_reset_encoded_fmt(ctx); - hantro_reset_raw_fmt(ctx, HANTRO_DEFAULT_BIT_DEPTH); + hantro_reset_raw_fmt(ctx, HANTRO_DEFAULT_BIT_DEPTH, HANTRO_AUTO_POSTPROC); } static void @@ -478,7 +496,8 @@ hantro_update_requires_hold_capture_buf(struct hantro_ctx *ctx, u32 fourcc) } static int hantro_set_fmt_out(struct hantro_ctx *ctx, - struct v4l2_pix_format_mplane *pix_mp) + struct v4l2_pix_format_mplane *pix_mp, + bool need_postproc) { struct vb2_queue *vq; int ret; @@ -531,7 +550,9 @@ static int hantro_set_fmt_out(struct hantro_ctx *ctx, * changes to the raw format. */ if (!ctx->is_encoder) - hantro_reset_raw_fmt(ctx, hantro_get_format_depth(pix_mp->pixelformat)); + hantro_reset_raw_fmt(ctx, + hantro_get_format_depth(pix_mp->pixelformat), + need_postproc); /* Colorimetry information are always propagated. */ ctx->dst_fmt.colorspace = pix_mp->colorspace; @@ -594,7 +615,7 @@ static int hantro_set_fmt_cap(struct hantro_ctx *ctx, * changes to the raw format. */ if (ctx->is_encoder) - hantro_reset_raw_fmt(ctx, HANTRO_DEFAULT_BIT_DEPTH); + hantro_reset_raw_fmt(ctx, HANTRO_DEFAULT_BIT_DEPTH, HANTRO_AUTO_POSTPROC); /* Colorimetry information are always propagated. */ ctx->src_fmt.colorspace = pix_mp->colorspace; @@ -614,7 +635,7 @@ static int hantro_set_fmt_cap(struct hantro_ctx *ctx, static int vidioc_s_fmt_out_mplane(struct file *file, void *priv, struct v4l2_format *f) { - return hantro_set_fmt_out(fh_to_ctx(priv), &f->fmt.pix_mp); + return hantro_set_fmt_out(fh_to_ctx(priv), &f->fmt.pix_mp, HANTRO_AUTO_POSTPROC); } static int diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.h b/drivers/media/platform/verisilicon/hantro_v4l2.h index 9ea2fef57dcd..fca7e3a690e5 100644 --- a/drivers/media/platform/verisilicon/hantro_v4l2.h +++ b/drivers/media/platform/verisilicon/hantro_v4l2.h @@ -18,13 +18,17 @@ #include "hantro.h" +#define HANTRO_FORCE_POSTPROC true +#define HANTRO_AUTO_POSTPROC false + extern const struct v4l2_ioctl_ops hantro_ioctl_ops; extern const struct vb2_ops hantro_queue_ops; -int hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth); +int hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth, bool need_postproc); void hantro_reset_fmts(struct hantro_ctx *ctx); int hantro_get_format_depth(u32 fourcc); const struct hantro_fmt * -hantro_get_default_fmt(const struct hantro_ctx *ctx, bool bitstream, int bit_depth); +hantro_get_default_fmt(const struct hantro_ctx *ctx, bool bitstream, + int bit_depth, bool need_postproc); #endif /* HANTRO_V4L2_H_ */ From 2f5d0aef37c64c30da17a74a82cb782a4a943545 Mon Sep 17 00:00:00 2001 From: Xiaoyong Lu Date: Tue, 30 May 2023 08:55:00 +0100 Subject: [PATCH 240/253] media: mediatek: vcodec: support stateless AV1 decoder Add mediatek av1 decoder linux driver which use the stateless API in MT8195. Signed-off-by: Xiaoyong Lu Tested-by: Nicolas Dufresne Reviewed-by: Nicolas Dufresne Tested-by: AngeloGioacchino Del Regno Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/mediatek/vcodec/Makefile | 1 + .../vcodec/mtk_vcodec_dec_stateless.c | 47 +- .../platform/mediatek/vcodec/mtk_vcodec_drv.h | 1 + .../vcodec/vdec/vdec_av1_req_lat_if.c | 2207 +++++++++++++++++ .../platform/mediatek/vcodec/vdec_drv_if.c | 4 + .../platform/mediatek/vcodec/vdec_drv_if.h | 1 + .../platform/mediatek/vcodec/vdec_msg_queue.c | 27 + .../platform/mediatek/vcodec/vdec_msg_queue.h | 4 + 8 files changed, 2291 insertions(+), 1 deletion(-) create mode 100644 drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c diff --git a/drivers/media/platform/mediatek/vcodec/Makefile b/drivers/media/platform/mediatek/vcodec/Makefile index d24b452d0fb3..d719cfaf83ad 100644 --- a/drivers/media/platform/mediatek/vcodec/Makefile +++ b/drivers/media/platform/mediatek/vcodec/Makefile @@ -10,6 +10,7 @@ mtk-vcodec-dec-y := vdec/vdec_h264_if.o \ vdec/vdec_vp8_req_if.o \ vdec/vdec_vp9_if.o \ vdec/vdec_vp9_req_lat_if.o \ + vdec/vdec_av1_req_lat_if.o \ vdec/vdec_h264_req_if.o \ vdec/vdec_h264_req_common.o \ vdec/vdec_h264_req_multi_if.o \ diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c index 7b3eb0ccb522..db1e14a1bd6c 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c @@ -159,11 +159,51 @@ static const struct mtk_stateless_control mtk_stateless_controls[] = { }, .codec_type = V4L2_PIX_FMT_HEVC_SLICE, }, + { + .cfg = { + .id = V4L2_CID_STATELESS_AV1_SEQUENCE, + + }, + .codec_type = V4L2_PIX_FMT_AV1_FRAME, + }, + { + .cfg = { + .id = V4L2_CID_STATELESS_AV1_FRAME, + + }, + .codec_type = V4L2_PIX_FMT_AV1_FRAME, + }, + { + .cfg = { + .id = V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY, + .dims = { V4L2_AV1_MAX_TILE_COUNT }, + + }, + .codec_type = V4L2_PIX_FMT_AV1_FRAME, + }, + { + .cfg = { + .id = V4L2_CID_MPEG_VIDEO_AV1_PROFILE, + .min = V4L2_MPEG_VIDEO_AV1_PROFILE_MAIN, + .def = V4L2_MPEG_VIDEO_AV1_PROFILE_MAIN, + .max = V4L2_MPEG_VIDEO_AV1_PROFILE_MAIN, + }, + .codec_type = V4L2_PIX_FMT_AV1_FRAME, + }, + { + .cfg = { + .id = V4L2_CID_MPEG_VIDEO_AV1_LEVEL, + .min = V4L2_MPEG_VIDEO_AV1_LEVEL_2_0, + .def = V4L2_MPEG_VIDEO_AV1_LEVEL_4_0, + .max = V4L2_MPEG_VIDEO_AV1_LEVEL_5_1, + }, + .codec_type = V4L2_PIX_FMT_AV1_FRAME, + }, }; #define NUM_CTRLS ARRAY_SIZE(mtk_stateless_controls) -static struct mtk_video_fmt mtk_video_formats[6]; +static struct mtk_video_fmt mtk_video_formats[7]; static struct mtk_video_fmt default_out_format; static struct mtk_video_fmt default_cap_format; @@ -409,6 +449,7 @@ static void mtk_vcodec_add_formats(unsigned int fourcc, case V4L2_PIX_FMT_VP8_FRAME: case V4L2_PIX_FMT_VP9_FRAME: case V4L2_PIX_FMT_HEVC_SLICE: + case V4L2_PIX_FMT_AV1_FRAME: mtk_video_formats[count_formats].fourcc = fourcc; mtk_video_formats[count_formats].type = MTK_FMT_DEC; mtk_video_formats[count_formats].num_planes = 1; @@ -469,6 +510,10 @@ static void mtk_vcodec_get_supported_formats(struct mtk_vcodec_ctx *ctx) mtk_vcodec_add_formats(V4L2_PIX_FMT_HEVC_SLICE, ctx); out_format_count++; } + if (ctx->dev->dec_capability & MTK_VDEC_FORMAT_AV1_FRAME) { + mtk_vcodec_add_formats(V4L2_PIX_FMT_AV1_FRAME, ctx); + out_format_count++; + } if (cap_format_count) default_cap_format = mtk_video_formats[cap_format_count - 1]; diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h index 1f4c5774ec47..94404624970a 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h @@ -347,6 +347,7 @@ enum mtk_vdec_format_types { MTK_VDEC_FORMAT_H264_SLICE = 0x100, MTK_VDEC_FORMAT_VP8_FRAME = 0x200, MTK_VDEC_FORMAT_VP9_FRAME = 0x400, + MTK_VDEC_FORMAT_AV1_FRAME = 0x800, MTK_VDEC_FORMAT_HEVC_FRAME = 0x1000, MTK_VCODEC_INNER_RACING = 0x20000, }; diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c new file mode 100644 index 000000000000..404a1a23fd40 --- /dev/null +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c @@ -0,0 +1,2207 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 MediaTek Inc. + * Author: Xiaoyong Lu + */ + +#include +#include +#include + +#include "../mtk_vcodec_util.h" +#include "../mtk_vcodec_dec.h" +#include "../mtk_vcodec_intr.h" +#include "../vdec_drv_base.h" +#include "../vdec_drv_if.h" +#include "../vdec_vpu_if.h" + +#define AV1_MAX_FRAME_BUF_COUNT (V4L2_AV1_TOTAL_REFS_PER_FRAME + 1) +#define AV1_TILE_BUF_SIZE 64 +#define AV1_SCALE_SUBPEL_BITS 10 +#define AV1_REF_SCALE_SHIFT 14 +#define AV1_REF_NO_SCALE BIT(AV1_REF_SCALE_SHIFT) +#define AV1_REF_INVALID_SCALE -1 +#define AV1_CDF_TABLE_BUFFER_SIZE 16384 +#define AV1_PRIMARY_REF_NONE 7 + +#define AV1_INVALID_IDX -1 + +#define AV1_DIV_ROUND_UP_POW2(value, n) \ +({ \ + typeof(n) _n = n; \ + typeof(value) _value = value; \ + (_value + (BIT(_n) >> 1)) >> _n; \ +}) + +#define AV1_DIV_ROUND_UP_POW2_SIGNED(value, n) \ +({ \ + typeof(n) _n_ = n; \ + typeof(value) _value_ = value; \ + (((_value_) < 0) ? -AV1_DIV_ROUND_UP_POW2(-(_value_), (_n_)) \ + : AV1_DIV_ROUND_UP_POW2((_value_), (_n_))); \ +}) + +#define BIT_FLAG(x, bit) (!!((x)->flags & (bit))) +#define SEGMENTATION_FLAG(x, name) (!!((x)->flags & V4L2_AV1_SEGMENTATION_FLAG_##name)) +#define QUANT_FLAG(x, name) (!!((x)->flags & V4L2_AV1_QUANTIZATION_FLAG_##name)) +#define SEQUENCE_FLAG(x, name) (!!((x)->flags & V4L2_AV1_SEQUENCE_FLAG_##name)) +#define FH_FLAG(x, name) (!!((x)->flags & V4L2_AV1_FRAME_FLAG_##name)) + +#define MINQ 0 +#define MAXQ 255 + +#define DIV_LUT_PREC_BITS 14 +#define DIV_LUT_BITS 8 +#define DIV_LUT_NUM BIT(DIV_LUT_BITS) +#define WARP_PARAM_REDUCE_BITS 6 +#define WARPEDMODEL_PREC_BITS 16 + +#define SEG_LVL_ALT_Q 0 +#define SECONDARY_FILTER_STRENGTH_NUM_BITS 2 + +static const short div_lut[DIV_LUT_NUM + 1] = { + 16384, 16320, 16257, 16194, 16132, 16070, 16009, 15948, 15888, 15828, 15768, + 15709, 15650, 15592, 15534, 15477, 15420, 15364, 15308, 15252, 15197, 15142, + 15087, 15033, 14980, 14926, 14873, 14821, 14769, 14717, 14665, 14614, 14564, + 14513, 14463, 14413, 14364, 14315, 14266, 14218, 14170, 14122, 14075, 14028, + 13981, 13935, 13888, 13843, 13797, 13752, 13707, 13662, 13618, 13574, 13530, + 13487, 13443, 13400, 13358, 13315, 13273, 13231, 13190, 13148, 13107, 13066, + 13026, 12985, 12945, 12906, 12866, 12827, 12788, 12749, 12710, 12672, 12633, + 12596, 12558, 12520, 12483, 12446, 12409, 12373, 12336, 12300, 12264, 12228, + 12193, 12157, 12122, 12087, 12053, 12018, 11984, 11950, 11916, 11882, 11848, + 11815, 11782, 11749, 11716, 11683, 11651, 11619, 11586, 11555, 11523, 11491, + 11460, 11429, 11398, 11367, 11336, 11305, 11275, 11245, 11215, 11185, 11155, + 11125, 11096, 11067, 11038, 11009, 10980, 10951, 10923, 10894, 10866, 10838, + 10810, 10782, 10755, 10727, 10700, 10673, 10645, 10618, 10592, 10565, 10538, + 10512, 10486, 10460, 10434, 10408, 10382, 10356, 10331, 10305, 10280, 10255, + 10230, 10205, 10180, 10156, 10131, 10107, 10082, 10058, 10034, 10010, 9986, + 9963, 9939, 9916, 9892, 9869, 9846, 9823, 9800, 9777, 9754, 9732, + 9709, 9687, 9664, 9642, 9620, 9598, 9576, 9554, 9533, 9511, 9489, + 9468, 9447, 9425, 9404, 9383, 9362, 9341, 9321, 9300, 9279, 9259, + 9239, 9218, 9198, 9178, 9158, 9138, 9118, 9098, 9079, 9059, 9039, + 9020, 9001, 8981, 8962, 8943, 8924, 8905, 8886, 8867, 8849, 8830, + 8812, 8793, 8775, 8756, 8738, 8720, 8702, 8684, 8666, 8648, 8630, + 8613, 8595, 8577, 8560, 8542, 8525, 8508, 8490, 8473, 8456, 8439, + 8422, 8405, 8389, 8372, 8355, 8339, 8322, 8306, 8289, 8273, 8257, + 8240, 8224, 8208, 8192, +}; + +/** + * struct vdec_av1_slice_init_vsi - VSI used to initialize instance + * @architecture: architecture type + * @reserved: reserved + * @core_vsi: for core vsi + * @cdf_table_addr: cdf table addr + * @cdf_table_size: cdf table size + * @iq_table_addr: iq table addr + * @iq_table_size: iq table size + * @vsi_size: share vsi structure size + */ +struct vdec_av1_slice_init_vsi { + u32 architecture; + u32 reserved; + u64 core_vsi; + u64 cdf_table_addr; + u32 cdf_table_size; + u64 iq_table_addr; + u32 iq_table_size; + u32 vsi_size; +}; + +/** + * struct vdec_av1_slice_mem - memory address and size + * @buf: dma_addr padding + * @dma_addr: buffer address + * @size: buffer size + * @dma_addr_end: buffer end address + * @padding: for padding + */ +struct vdec_av1_slice_mem { + union { + u64 buf; + dma_addr_t dma_addr; + }; + union { + size_t size; + dma_addr_t dma_addr_end; + u64 padding; + }; +}; + +/** + * struct vdec_av1_slice_state - decoding state + * @err : err type for decode + * @full : transcoded buffer is full or not + * @timeout : decode timeout or not + * @perf : performance enable + * @crc : hw checksum + * @out_size : hw output size + */ +struct vdec_av1_slice_state { + int err; + u32 full; + u32 timeout; + u32 perf; + u32 crc[16]; + u32 out_size; +}; + +/* + * enum vdec_av1_slice_resolution_level - resolution level + */ +enum vdec_av1_slice_resolution_level { + AV1_RES_NONE, + AV1_RES_FHD, + AV1_RES_4K, + AV1_RES_8K, +}; + +/* + * enum vdec_av1_slice_frame_type - av1 frame type + */ +enum vdec_av1_slice_frame_type { + AV1_KEY_FRAME = 0, + AV1_INTER_FRAME, + AV1_INTRA_ONLY_FRAME, + AV1_SWITCH_FRAME, + AV1_FRAME_TYPES, +}; + +/* + * enum vdec_av1_slice_reference_mode - reference mode type + */ +enum vdec_av1_slice_reference_mode { + AV1_SINGLE_REFERENCE = 0, + AV1_COMPOUND_REFERENCE, + AV1_REFERENCE_MODE_SELECT, + AV1_REFERENCE_MODES, +}; + +/** + * struct vdec_av1_slice_tile_group - info for each tile + * @num_tiles: tile number + * @tile_size: input size for each tile + * @tile_start_offset: tile offset to input buffer + */ +struct vdec_av1_slice_tile_group { + u32 num_tiles; + u32 tile_size[V4L2_AV1_MAX_TILE_COUNT]; + u32 tile_start_offset[V4L2_AV1_MAX_TILE_COUNT]; +}; + +/** + * struct vdec_av1_slice_scale_factors - scale info for each ref frame + * @is_scaled: frame is scaled or not + * @x_scale: frame width scale coefficient + * @y_scale: frame height scale coefficient + * @x_step: width step for x_scale + * @y_step: height step for y_scale + */ +struct vdec_av1_slice_scale_factors { + u8 is_scaled; + int x_scale; + int y_scale; + int x_step; + int y_step; +}; + +/** + * struct vdec_av1_slice_frame_refs - ref frame info + * @ref_fb_idx: ref slot index + * @ref_map_idx: ref frame index + * @scale_factors: scale factors for each ref frame + */ +struct vdec_av1_slice_frame_refs { + int ref_fb_idx; + int ref_map_idx; + struct vdec_av1_slice_scale_factors scale_factors; +}; + +/** + * struct vdec_av1_slice_gm - AV1 Global Motion parameters + * @wmtype: The type of global motion transform used + * @wmmat: gm_params + * @alpha: alpha info + * @beta: beta info + * @gamma: gamma info + * @delta: delta info + * @invalid: is invalid or not + */ +struct vdec_av1_slice_gm { + int wmtype; + int wmmat[8]; + short alpha; + short beta; + short gamma; + short delta; + char invalid; +}; + +/** + * struct vdec_av1_slice_sm - AV1 Skip Mode parameters + * @skip_mode_allowed: Skip Mode is allowed or not + * @skip_mode_present: specified that the skip_mode will be present or not + * @skip_mode_frame: specifies the frames to use for compound prediction + */ +struct vdec_av1_slice_sm { + u8 skip_mode_allowed; + u8 skip_mode_present; + int skip_mode_frame[2]; +}; + +/** + * struct vdec_av1_slice_seg - AV1 Segmentation params + * @segmentation_enabled: this frame makes use of the segmentation tool or not + * @segmentation_update_map: segmentation map are updated during the decoding frame + * @segmentation_temporal_update:segmentation map are coded relative the existing segmentaion map + * @segmentation_update_data: new parameters are about to be specified for each segment + * @feature_data: specifies the feature data for a segment feature + * @feature_enabled_mask: the corresponding feature value is coded or not. + * @segid_preskip: segment id will be read before the skip syntax element. + * @last_active_segid: the highest numbered segment id that has some enabled feature + */ +struct vdec_av1_slice_seg { + u8 segmentation_enabled; + u8 segmentation_update_map; + u8 segmentation_temporal_update; + u8 segmentation_update_data; + int feature_data[V4L2_AV1_MAX_SEGMENTS][V4L2_AV1_SEG_LVL_MAX]; + u16 feature_enabled_mask[V4L2_AV1_MAX_SEGMENTS]; + int segid_preskip; + int last_active_segid; +}; + +/** + * struct vdec_av1_slice_delta_q_lf - AV1 Loop Filter delta parameters + * @delta_q_present: specified whether quantizer index delta values are present + * @delta_q_res: specifies the left shift which should be applied to decoded quantizer index + * @delta_lf_present: specifies whether loop filter delta values are present + * @delta_lf_res: specifies the left shift which should be applied to decoded + * loop filter delta values + * @delta_lf_multi: specifies that separate loop filter deltas are sent for horizontal + * luma edges,vertical luma edges,the u edges, and the v edges. + */ +struct vdec_av1_slice_delta_q_lf { + u8 delta_q_present; + u8 delta_q_res; + u8 delta_lf_present; + u8 delta_lf_res; + u8 delta_lf_multi; +}; + +/** + * struct vdec_av1_slice_quantization - AV1 Quantization params + * @base_q_idx: indicates the base frame qindex. This is used for Y AC + * coefficients and as the base value for the other quantizers. + * @qindex: qindex + * @delta_qydc: indicates the Y DC quantizer relative to base_q_idx + * @delta_qudc: indicates the U DC quantizer relative to base_q_idx. + * @delta_quac: indicates the U AC quantizer relative to base_q_idx + * @delta_qvdc: indicates the V DC quantizer relative to base_q_idx + * @delta_qvac: indicates the V AC quantizer relative to base_q_idx + * @using_qmatrix: specifies that the quantizer matrix will be used to + * compute quantizers + * @qm_y: specifies the level in the quantizer matrix that should + * be used for luma plane decoding + * @qm_u: specifies the level in the quantizer matrix that should + * be used for chroma U plane decoding. + * @qm_v: specifies the level in the quantizer matrix that should be + * used for chroma V plane decoding + */ +struct vdec_av1_slice_quantization { + int base_q_idx; + int qindex[V4L2_AV1_MAX_SEGMENTS]; + int delta_qydc; + int delta_qudc; + int delta_quac; + int delta_qvdc; + int delta_qvac; + u8 using_qmatrix; + u8 qm_y; + u8 qm_u; + u8 qm_v; +}; + +/** + * struct vdec_av1_slice_lr - AV1 Loop Restauration parameters + * @use_lr: whether to use loop restoration + * @use_chroma_lr: whether to use chroma loop restoration + * @frame_restoration_type: specifies the type of restoration used for each plane + * @loop_restoration_size: pecifies the size of loop restoration units in units + * of samples in the current plane + */ +struct vdec_av1_slice_lr { + u8 use_lr; + u8 use_chroma_lr; + u8 frame_restoration_type[V4L2_AV1_NUM_PLANES_MAX]; + u32 loop_restoration_size[V4L2_AV1_NUM_PLANES_MAX]; +}; + +/** + * struct vdec_av1_slice_loop_filter - AV1 Loop filter parameters + * @loop_filter_level: an array containing loop filter strength values. + * @loop_filter_ref_deltas: contains the adjustment needed for the filter + * level based on the chosen reference frame + * @loop_filter_mode_deltas: contains the adjustment needed for the filter + * level based on the chosen mode + * @loop_filter_sharpness: indicates the sharpness level. The loop_filter_level + * and loop_filter_sharpness together determine when + * a block edge is filtered, and by how much the + * filtering can change the sample values + * @loop_filter_delta_enabled: filetr level depends on the mode and reference + * frame used to predict a block + */ +struct vdec_av1_slice_loop_filter { + u8 loop_filter_level[4]; + int loop_filter_ref_deltas[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + int loop_filter_mode_deltas[2]; + u8 loop_filter_sharpness; + u8 loop_filter_delta_enabled; +}; + +/** + * struct vdec_av1_slice_cdef - AV1 CDEF parameters + * @cdef_damping: controls the amount of damping in the deringing filter + * @cdef_y_strength: specifies the strength of the primary filter and secondary filter + * @cdef_uv_strength: specifies the strength of the primary filter and secondary filter + * @cdef_bits: specifies the number of bits needed to specify which + * CDEF filter to apply + */ +struct vdec_av1_slice_cdef { + u8 cdef_damping; + u8 cdef_y_strength[8]; + u8 cdef_uv_strength[8]; + u8 cdef_bits; +}; + +/** + * struct vdec_av1_slice_mfmv - AV1 mfmv parameters + * @mfmv_valid_ref: mfmv_valid_ref + * @mfmv_dir: mfmv_dir + * @mfmv_ref_to_cur: mfmv_ref_to_cur + * @mfmv_ref_frame_idx: mfmv_ref_frame_idx + * @mfmv_count: mfmv_count + */ +struct vdec_av1_slice_mfmv { + u32 mfmv_valid_ref[3]; + u32 mfmv_dir[3]; + int mfmv_ref_to_cur[3]; + int mfmv_ref_frame_idx[3]; + int mfmv_count; +}; + +/** + * struct vdec_av1_slice_tile - AV1 Tile info + * @tile_cols: specifies the number of tiles across the frame + * @tile_rows: pecifies the number of tiles down the frame + * @mi_col_starts: an array specifying the start column + * @mi_row_starts: an array specifying the start row + * @context_update_tile_id: specifies which tile to use for the CDF update + * @uniform_tile_spacing_flag: tiles are uniformly spaced across the frame + * or the tile sizes are coded + */ +struct vdec_av1_slice_tile { + u8 tile_cols; + u8 tile_rows; + int mi_col_starts[V4L2_AV1_MAX_TILE_COLS + 1]; + int mi_row_starts[V4L2_AV1_MAX_TILE_ROWS + 1]; + u8 context_update_tile_id; + u8 uniform_tile_spacing_flag; +}; + +/** + * struct vdec_av1_slice_uncompressed_header - Represents an AV1 Frame Header OBU + * @use_ref_frame_mvs: use_ref_frame_mvs flag + * @order_hint: specifies OrderHintBits least significant bits of the expected + * @gm: global motion param + * @upscaled_width: the upscaled width + * @frame_width: frame's width + * @frame_height: frame's height + * @reduced_tx_set: frame is restricted to a reduced subset of the full + * set of transform types + * @tx_mode: specifies how the transform size is determined + * @uniform_tile_spacing_flag: tiles are uniformly spaced across the frame + * or the tile sizes are coded + * @interpolation_filter: specifies the filter selection used for performing inter prediction + * @allow_warped_motion: motion_mode may be present or not + * @is_motion_mode_switchable : euqlt to 0 specifies that only the SIMPLE motion mode will be used + * @reference_mode : frame reference mode selected + * @allow_high_precision_mv: specifies that motion vectors are specified to + * quarter pel precision or to eighth pel precision + * @allow_intra_bc: ubducates that intra block copy may be used in this frame + * @force_integer_mv: specifies motion vectors will always be integers or + * can contain fractional bits + * @allow_screen_content_tools: intra blocks may use palette encoding + * @error_resilient_mode: error resislent mode is enable/disable + * @frame_type: specifies the AV1 frame type + * @primary_ref_frame: specifies which reference frame contains the CDF values + * and other state that should be loaded at the start of the frame + * slots will be updated with the current frame after it is decoded + * @disable_frame_end_update_cdf:indicates the end of frame CDF update is disable or enable + * @disable_cdf_update: specified whether the CDF update in the symbol + * decoding process should be disables + * @skip_mode: av1 skip mode parameters + * @seg: av1 segmentaon parameters + * @delta_q_lf: av1 delta loop fileter + * @quant: av1 Quantization params + * @lr: av1 Loop Restauration parameters + * @superres_denom: the denominator for the upscaling ratio + * @loop_filter: av1 Loop filter parameters + * @cdef: av1 CDEF parameters + * @mfmv: av1 mfmv parameters + * @tile: av1 Tile info + * @frame_is_intra: intra frame + * @loss_less_array: loss less array + * @coded_loss_less: coded lsss less + * @mi_rows: size of mi unit in rows + * @mi_cols: size of mi unit in cols + */ +struct vdec_av1_slice_uncompressed_header { + u8 use_ref_frame_mvs; + int order_hint; + struct vdec_av1_slice_gm gm[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + u32 upscaled_width; + u32 frame_width; + u32 frame_height; + u8 reduced_tx_set; + u8 tx_mode; + u8 uniform_tile_spacing_flag; + u8 interpolation_filter; + u8 allow_warped_motion; + u8 is_motion_mode_switchable; + u8 reference_mode; + u8 allow_high_precision_mv; + u8 allow_intra_bc; + u8 force_integer_mv; + u8 allow_screen_content_tools; + u8 error_resilient_mode; + u8 frame_type; + u8 primary_ref_frame; + u8 disable_frame_end_update_cdf; + u32 disable_cdf_update; + struct vdec_av1_slice_sm skip_mode; + struct vdec_av1_slice_seg seg; + struct vdec_av1_slice_delta_q_lf delta_q_lf; + struct vdec_av1_slice_quantization quant; + struct vdec_av1_slice_lr lr; + u32 superres_denom; + struct vdec_av1_slice_loop_filter loop_filter; + struct vdec_av1_slice_cdef cdef; + struct vdec_av1_slice_mfmv mfmv; + struct vdec_av1_slice_tile tile; + u8 frame_is_intra; + u8 loss_less_array[V4L2_AV1_MAX_SEGMENTS]; + u8 coded_loss_less; + u32 mi_rows; + u32 mi_cols; +}; + +/** + * struct vdec_av1_slice_seq_header - Represents an AV1 Sequence OBU + * @bitdepth: the bitdepth to use for the sequence + * @enable_superres: specifies whether the use_superres syntax element may be present + * @enable_filter_intra: specifies the use_filter_intra syntax element may be present + * @enable_intra_edge_filter: whether the intra edge filtering process should be enabled + * @enable_interintra_compound: specifies the mode info fo rinter blocks may + * contain the syntax element interintra + * @enable_masked_compound: specifies the mode info fo rinter blocks may + * contain the syntax element compound_type + * @enable_dual_filter: the inter prediction filter type may be specified independently + * @enable_jnt_comp: distance weights process may be used for inter prediction + * @mono_chrome: indicates the video does not contain U and V color planes + * @enable_order_hint: tools based on the values of order hints may be used + * @order_hint_bits: the number of bits used for the order_hint field at each frame + * @use_128x128_superblock: indicates superblocks contain 128*128 luma samples + * @subsampling_x: the chroma subsamling format + * @subsampling_y: the chroma subsamling format + * @max_frame_width: the maximum frame width for the frames represented by sequence + * @max_frame_height: the maximum frame height for the frames represented by sequence + */ +struct vdec_av1_slice_seq_header { + u8 bitdepth; + u8 enable_superres; + u8 enable_filter_intra; + u8 enable_intra_edge_filter; + u8 enable_interintra_compound; + u8 enable_masked_compound; + u8 enable_dual_filter; + u8 enable_jnt_comp; + u8 mono_chrome; + u8 enable_order_hint; + u8 order_hint_bits; + u8 use_128x128_superblock; + u8 subsampling_x; + u8 subsampling_y; + u32 max_frame_width; + u32 max_frame_height; +}; + +/** + * struct vdec_av1_slice_frame - Represents current Frame info + * @uh: uncompressed header info + * @seq: sequence header info + * @large_scale_tile: is large scale mode + * @cur_ts: current frame timestamp + * @prev_fb_idx: prev slot id + * @ref_frame_sign_bias: arrays for ref_frame sign bias + * @order_hints: arrays for ref_frame order hint + * @ref_frame_valid: arrays for valid ref_frame + * @ref_frame_map: map to slot frame info + * @frame_refs: ref_frame info + */ +struct vdec_av1_slice_frame { + struct vdec_av1_slice_uncompressed_header uh; + struct vdec_av1_slice_seq_header seq; + u8 large_scale_tile; + u64 cur_ts; + int prev_fb_idx; + u8 ref_frame_sign_bias[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + u32 order_hints[V4L2_AV1_REFS_PER_FRAME]; + u32 ref_frame_valid[V4L2_AV1_REFS_PER_FRAME]; + int ref_frame_map[V4L2_AV1_TOTAL_REFS_PER_FRAME]; + struct vdec_av1_slice_frame_refs frame_refs[V4L2_AV1_REFS_PER_FRAME]; +}; + +/** + * struct vdec_av1_slice_work_buffer - work buffer for lat + * @mv_addr: mv buffer memory info + * @cdf_addr: cdf buffer memory info + * @segid_addr: segid buffer memory info + */ +struct vdec_av1_slice_work_buffer { + struct vdec_av1_slice_mem mv_addr; + struct vdec_av1_slice_mem cdf_addr; + struct vdec_av1_slice_mem segid_addr; +}; + +/** + * struct vdec_av1_slice_frame_info - frame info for each slot + * @frame_type: frame type + * @frame_is_intra: is intra frame + * @order_hint: order hint + * @order_hints: referece frame order hint + * @upscaled_width: upscale width + * @pic_pitch: buffer pitch + * @frame_width: frane width + * @frame_height: frame height + * @mi_rows: rows in mode info + * @mi_cols: cols in mode info + * @ref_count: mark to reference frame counts + */ +struct vdec_av1_slice_frame_info { + u8 frame_type; + u8 frame_is_intra; + int order_hint; + u32 order_hints[V4L2_AV1_REFS_PER_FRAME]; + u32 upscaled_width; + u32 pic_pitch; + u32 frame_width; + u32 frame_height; + u32 mi_rows; + u32 mi_cols; + int ref_count; +}; + +/** + * struct vdec_av1_slice_slot - slot info that needs to be saved in the global instance + * @frame_info: frame info for each slot + * @timestamp: time stamp info + */ +struct vdec_av1_slice_slot { + struct vdec_av1_slice_frame_info frame_info[AV1_MAX_FRAME_BUF_COUNT]; + u64 timestamp[AV1_MAX_FRAME_BUF_COUNT]; +}; + +/** + * struct vdec_av1_slice_fb - frame buffer for decoding + * @y: current y buffer address info + * @c: current c buffer address info + */ +struct vdec_av1_slice_fb { + struct vdec_av1_slice_mem y; + struct vdec_av1_slice_mem c; +}; + +/** + * struct vdec_av1_slice_vsi - exchange frame information between Main CPU and MicroP + * @bs: input buffer info + * @work_buffer: working buffe for hw + * @cdf_table: cdf_table buffer + * @cdf_tmp: cdf temp buffer + * @rd_mv: mv buffer for lat output , core input + * @ube: ube buffer + * @trans: transcoded buffer + * @err_map: err map buffer + * @row_info: row info buffer + * @fb: current y/c buffer + * @ref: ref y/c buffer + * @iq_table: iq table buffer + * @tile: tile buffer + * @slots: slots info for each frame + * @slot_id: current frame slot id + * @frame: current frame info + * @state: status after decode done + * @cur_lst_tile_id: tile id for large scale + */ +struct vdec_av1_slice_vsi { + /* lat */ + struct vdec_av1_slice_mem bs; + struct vdec_av1_slice_work_buffer work_buffer[AV1_MAX_FRAME_BUF_COUNT]; + struct vdec_av1_slice_mem cdf_table; + struct vdec_av1_slice_mem cdf_tmp; + /* LAT stage's output, Core stage's input */ + struct vdec_av1_slice_mem rd_mv; + struct vdec_av1_slice_mem ube; + struct vdec_av1_slice_mem trans; + struct vdec_av1_slice_mem err_map; + struct vdec_av1_slice_mem row_info; + /* core */ + struct vdec_av1_slice_fb fb; + struct vdec_av1_slice_fb ref[V4L2_AV1_REFS_PER_FRAME]; + struct vdec_av1_slice_mem iq_table; + /* lat and core share*/ + struct vdec_av1_slice_mem tile; + struct vdec_av1_slice_slot slots; + s8 slot_id; + struct vdec_av1_slice_frame frame; + struct vdec_av1_slice_state state; + u32 cur_lst_tile_id; +}; + +/** + * struct vdec_av1_slice_pfc - per-frame context that contains a local vsi. + * pass it from lat to core + * @vsi: local vsi. copy to/from remote vsi before/after decoding + * @ref_idx: reference buffer timestamp + * @seq: picture sequence + */ +struct vdec_av1_slice_pfc { + struct vdec_av1_slice_vsi vsi; + u64 ref_idx[V4L2_AV1_REFS_PER_FRAME]; + int seq; +}; + +/** + * struct vdec_av1_slice_instance - represent one av1 instance + * @ctx: pointer to codec's context + * @vpu: VPU instance + * @iq_table: iq table buffer + * @cdf_table: cdf table buffer + * @mv: mv working buffer + * @cdf: cdf working buffer + * @seg: segmentation working buffer + * @cdf_temp: cdf temp buffer + * @tile: tile buffer + * @slots: slots info + * @tile_group: tile_group entry + * @level: level of current resolution + * @width: width of last picture + * @height: height of last picture + * @frame_type: frame_type of last picture + * @irq_enabled: irq to Main CPU or MicroP + * @inneracing_mode: is inneracing mode + * @init_vsi: vsi used for initialized AV1 instance + * @vsi: vsi used for decoding/flush ... + * @core_vsi: vsi used for Core stage + * @seq: global picture sequence + */ +struct vdec_av1_slice_instance { + struct mtk_vcodec_ctx *ctx; + struct vdec_vpu_inst vpu; + + struct mtk_vcodec_mem iq_table; + struct mtk_vcodec_mem cdf_table; + + struct mtk_vcodec_mem mv[AV1_MAX_FRAME_BUF_COUNT]; + struct mtk_vcodec_mem cdf[AV1_MAX_FRAME_BUF_COUNT]; + struct mtk_vcodec_mem seg[AV1_MAX_FRAME_BUF_COUNT]; + struct mtk_vcodec_mem cdf_temp; + struct mtk_vcodec_mem tile; + struct vdec_av1_slice_slot slots; + struct vdec_av1_slice_tile_group tile_group; + + /* for resolution change and get_pic_info */ + enum vdec_av1_slice_resolution_level level; + u32 width; + u32 height; + + u32 frame_type; + u32 irq_enabled; + u32 inneracing_mode; + + /* MicroP vsi */ + union { + struct vdec_av1_slice_init_vsi *init_vsi; + struct vdec_av1_slice_vsi *vsi; + }; + struct vdec_av1_slice_vsi *core_vsi; + int seq; +}; + +static int vdec_av1_slice_core_decode(struct vdec_lat_buf *lat_buf); + +static inline int vdec_av1_slice_get_msb(u32 n) +{ + if (n == 0) + return 0; + return 31 ^ __builtin_clz(n); +} + +static inline bool vdec_av1_slice_need_scale(u32 ref_width, u32 ref_height, + u32 this_width, u32 this_height) +{ + return ((this_width << 1) >= ref_width) && + ((this_height << 1) >= ref_height) && + (this_width <= (ref_width << 4)) && + (this_height <= (ref_height << 4)); +} + +static void *vdec_av1_get_ctrl_ptr(struct mtk_vcodec_ctx *ctx, int id) +{ + struct v4l2_ctrl *ctrl = v4l2_ctrl_find(&ctx->ctrl_hdl, id); + + if (!ctrl) + return ERR_PTR(-EINVAL); + + return ctrl->p_cur.p; +} + +static int vdec_av1_slice_init_cdf_table(struct vdec_av1_slice_instance *instance) +{ + u8 *remote_cdf_table; + struct mtk_vcodec_ctx *ctx; + struct vdec_av1_slice_init_vsi *vsi; + int ret; + + ctx = instance->ctx; + vsi = instance->vpu.vsi; + remote_cdf_table = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler, + (u32)vsi->cdf_table_addr); + if (IS_ERR(remote_cdf_table)) { + mtk_vcodec_err(instance, "failed to map cdf table\n"); + return PTR_ERR(remote_cdf_table); + } + + mtk_vcodec_debug(instance, "map cdf table to 0x%p\n", + remote_cdf_table); + + if (instance->cdf_table.va) + mtk_vcodec_mem_free(ctx, &instance->cdf_table); + instance->cdf_table.size = vsi->cdf_table_size; + + ret = mtk_vcodec_mem_alloc(ctx, &instance->cdf_table); + if (ret) + return ret; + + memcpy(instance->cdf_table.va, remote_cdf_table, vsi->cdf_table_size); + + return 0; +} + +static int vdec_av1_slice_init_iq_table(struct vdec_av1_slice_instance *instance) +{ + u8 *remote_iq_table; + struct mtk_vcodec_ctx *ctx; + struct vdec_av1_slice_init_vsi *vsi; + int ret; + + ctx = instance->ctx; + vsi = instance->vpu.vsi; + remote_iq_table = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler, + (u32)vsi->iq_table_addr); + if (IS_ERR(remote_iq_table)) { + mtk_vcodec_err(instance, "failed to map iq table\n"); + return PTR_ERR(remote_iq_table); + } + + mtk_vcodec_debug(instance, "map iq table to 0x%p\n", remote_iq_table); + + if (instance->iq_table.va) + mtk_vcodec_mem_free(ctx, &instance->iq_table); + instance->iq_table.size = vsi->iq_table_size; + + ret = mtk_vcodec_mem_alloc(ctx, &instance->iq_table); + if (ret) + return ret; + + memcpy(instance->iq_table.va, remote_iq_table, vsi->iq_table_size); + + return 0; +} + +static int vdec_av1_slice_get_new_slot(struct vdec_av1_slice_vsi *vsi) +{ + struct vdec_av1_slice_slot *slots = &vsi->slots; + int new_slot_idx = AV1_INVALID_IDX; + int i; + + for (i = 0; i < AV1_MAX_FRAME_BUF_COUNT; i++) { + if (slots->frame_info[i].ref_count == 0) { + new_slot_idx = i; + break; + } + } + + if (new_slot_idx != AV1_INVALID_IDX) { + slots->frame_info[new_slot_idx].ref_count++; + slots->timestamp[new_slot_idx] = vsi->frame.cur_ts; + } + + return new_slot_idx; +} + +static inline void vdec_av1_slice_clear_fb(struct vdec_av1_slice_frame_info *frame_info) +{ + memset((void *)frame_info, 0, sizeof(struct vdec_av1_slice_frame_info)); +} + +static void vdec_av1_slice_decrease_ref_count(struct vdec_av1_slice_slot *slots, int fb_idx) +{ + struct vdec_av1_slice_frame_info *frame_info = slots->frame_info; + + frame_info[fb_idx].ref_count--; + if (frame_info[fb_idx].ref_count < 0) { + frame_info[fb_idx].ref_count = 0; + mtk_v4l2_err("av1_error: %s() fb_idx %d decrease ref_count error\n", + __func__, fb_idx); + } + + vdec_av1_slice_clear_fb(&frame_info[fb_idx]); +} + +static void vdec_av1_slice_cleanup_slots(struct vdec_av1_slice_slot *slots, + struct vdec_av1_slice_frame *frame, + struct v4l2_ctrl_av1_frame *ctrl_fh) +{ + int slot_id, ref_id; + + for (ref_id = 0; ref_id < V4L2_AV1_TOTAL_REFS_PER_FRAME; ref_id++) + frame->ref_frame_map[ref_id] = AV1_INVALID_IDX; + + for (slot_id = 0; slot_id < AV1_MAX_FRAME_BUF_COUNT; slot_id++) { + u64 timestamp = slots->timestamp[slot_id]; + bool ref_used = false; + + /* ignored unused slots */ + if (slots->frame_info[slot_id].ref_count == 0) + continue; + + for (ref_id = 0; ref_id < V4L2_AV1_TOTAL_REFS_PER_FRAME; ref_id++) { + if (ctrl_fh->reference_frame_ts[ref_id] == timestamp) { + frame->ref_frame_map[ref_id] = slot_id; + ref_used = true; + } + } + + if (!ref_used) + vdec_av1_slice_decrease_ref_count(slots, slot_id); + } +} + +static void vdec_av1_slice_setup_slot(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_vsi *vsi, + struct v4l2_ctrl_av1_frame *ctrl_fh) +{ + struct vdec_av1_slice_frame_info *cur_frame_info; + struct vdec_av1_slice_uncompressed_header *uh = &vsi->frame.uh; + int ref_id; + + memcpy(&vsi->slots, &instance->slots, sizeof(instance->slots)); + vdec_av1_slice_cleanup_slots(&vsi->slots, &vsi->frame, ctrl_fh); + vsi->slot_id = vdec_av1_slice_get_new_slot(vsi); + + if (vsi->slot_id == AV1_INVALID_IDX) { + mtk_v4l2_err("warning:av1 get invalid index slot\n"); + vsi->slot_id = 0; + } + cur_frame_info = &vsi->slots.frame_info[vsi->slot_id]; + cur_frame_info->frame_type = uh->frame_type; + cur_frame_info->frame_is_intra = ((uh->frame_type == AV1_INTRA_ONLY_FRAME) || + (uh->frame_type == AV1_KEY_FRAME)); + cur_frame_info->order_hint = uh->order_hint; + cur_frame_info->upscaled_width = uh->upscaled_width; + cur_frame_info->pic_pitch = 0; + cur_frame_info->frame_width = uh->frame_width; + cur_frame_info->frame_height = uh->frame_height; + cur_frame_info->mi_cols = ((uh->frame_width + 7) >> 3) << 1; + cur_frame_info->mi_rows = ((uh->frame_height + 7) >> 3) << 1; + + /* ensure current frame is properly mapped if referenced */ + for (ref_id = 0; ref_id < V4L2_AV1_TOTAL_REFS_PER_FRAME; ref_id++) { + u64 timestamp = vsi->slots.timestamp[vsi->slot_id]; + + if (ctrl_fh->reference_frame_ts[ref_id] == timestamp) + vsi->frame.ref_frame_map[ref_id] = vsi->slot_id; + } +} + +static int vdec_av1_slice_alloc_working_buffer(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_vsi *vsi) +{ + struct mtk_vcodec_ctx *ctx = instance->ctx; + enum vdec_av1_slice_resolution_level level; + u32 max_sb_w, max_sb_h, max_w, max_h, w, h; + int i, ret; + + w = vsi->frame.uh.frame_width; + h = vsi->frame.uh.frame_height; + + if (w > VCODEC_DEC_4K_CODED_WIDTH || h > VCODEC_DEC_4K_CODED_HEIGHT) + /* 8K */ + return -EINVAL; + + if (w > MTK_VDEC_MAX_W || h > MTK_VDEC_MAX_H) { + /* 4K */ + level = AV1_RES_4K; + max_w = VCODEC_DEC_4K_CODED_WIDTH; + max_h = VCODEC_DEC_4K_CODED_HEIGHT; + } else { + /* FHD */ + level = AV1_RES_FHD; + max_w = MTK_VDEC_MAX_W; + max_h = MTK_VDEC_MAX_H; + } + + if (level == instance->level) + return 0; + + mtk_vcodec_debug(instance, "resolution level changed from %u to %u, %ux%u", + instance->level, level, w, h); + + max_sb_w = DIV_ROUND_UP(max_w, 128); + max_sb_h = DIV_ROUND_UP(max_h, 128); + + for (i = 0; i < AV1_MAX_FRAME_BUF_COUNT; i++) { + if (instance->mv[i].va) + mtk_vcodec_mem_free(ctx, &instance->mv[i]); + instance->mv[i].size = max_sb_w * max_sb_h * SZ_1K; + ret = mtk_vcodec_mem_alloc(ctx, &instance->mv[i]); + if (ret) + goto err; + + if (instance->seg[i].va) + mtk_vcodec_mem_free(ctx, &instance->seg[i]); + instance->seg[i].size = max_sb_w * max_sb_h * 512; + ret = mtk_vcodec_mem_alloc(ctx, &instance->seg[i]); + if (ret) + goto err; + + if (instance->cdf[i].va) + mtk_vcodec_mem_free(ctx, &instance->cdf[i]); + instance->cdf[i].size = AV1_CDF_TABLE_BUFFER_SIZE; + ret = mtk_vcodec_mem_alloc(ctx, &instance->cdf[i]); + if (ret) + goto err; + } + + if (!instance->cdf_temp.va) { + instance->cdf_temp.size = (SZ_1K * 16 * 100); + ret = mtk_vcodec_mem_alloc(ctx, &instance->cdf_temp); + if (ret) + goto err; + vsi->cdf_tmp.buf = instance->cdf_temp.dma_addr; + vsi->cdf_tmp.size = instance->cdf_temp.size; + } + + if (instance->tile.va) + mtk_vcodec_mem_free(ctx, &instance->tile); + + instance->tile.size = AV1_TILE_BUF_SIZE * V4L2_AV1_MAX_TILE_COUNT; + ret = mtk_vcodec_mem_alloc(ctx, &instance->tile); + if (ret) + goto err; + + instance->level = level; + return 0; + +err: + instance->level = AV1_RES_NONE; + return ret; +} + +static void vdec_av1_slice_free_working_buffer(struct vdec_av1_slice_instance *instance) +{ + struct mtk_vcodec_ctx *ctx = instance->ctx; + int i; + + for (i = 0; i < ARRAY_SIZE(instance->mv); i++) + mtk_vcodec_mem_free(ctx, &instance->mv[i]); + + for (i = 0; i < ARRAY_SIZE(instance->seg); i++) + mtk_vcodec_mem_free(ctx, &instance->seg[i]); + + for (i = 0; i < ARRAY_SIZE(instance->cdf); i++) + mtk_vcodec_mem_free(ctx, &instance->cdf[i]); + + mtk_vcodec_mem_free(ctx, &instance->tile); + mtk_vcodec_mem_free(ctx, &instance->cdf_temp); + mtk_vcodec_mem_free(ctx, &instance->cdf_table); + mtk_vcodec_mem_free(ctx, &instance->iq_table); + + instance->level = AV1_RES_NONE; +} + +static inline void vdec_av1_slice_vsi_from_remote(struct vdec_av1_slice_vsi *vsi, + struct vdec_av1_slice_vsi *remote_vsi) +{ + memcpy(&vsi->trans, &remote_vsi->trans, sizeof(vsi->trans)); + memcpy(&vsi->state, &remote_vsi->state, sizeof(vsi->state)); +} + +static inline void vdec_av1_slice_vsi_to_remote(struct vdec_av1_slice_vsi *vsi, + struct vdec_av1_slice_vsi *remote_vsi) +{ + memcpy(remote_vsi, vsi, sizeof(*vsi)); +} + +static int vdec_av1_slice_setup_lat_from_src_buf(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_vsi *vsi, + struct vdec_lat_buf *lat_buf) +{ + struct vb2_v4l2_buffer *src; + struct vb2_v4l2_buffer *dst; + + src = v4l2_m2m_next_src_buf(instance->ctx->m2m_ctx); + if (!src) + return -EINVAL; + + lat_buf->src_buf_req = src->vb2_buf.req_obj.req; + dst = &lat_buf->ts_info; + v4l2_m2m_buf_copy_metadata(src, dst, true); + vsi->frame.cur_ts = dst->vb2_buf.timestamp; + + return 0; +} + +static short vdec_av1_slice_resolve_divisor_32(u32 D, short *shift) +{ + int f; + int e; + + *shift = vdec_av1_slice_get_msb(D); + /* e is obtained from D after resetting the most significant 1 bit. */ + e = D - ((u32)1 << *shift); + /* Get the most significant DIV_LUT_BITS (8) bits of e into f */ + if (*shift > DIV_LUT_BITS) + f = AV1_DIV_ROUND_UP_POW2(e, *shift - DIV_LUT_BITS); + else + f = e << (DIV_LUT_BITS - *shift); + if (f > DIV_LUT_NUM) + return -1; + *shift += DIV_LUT_PREC_BITS; + /* Use f as lookup into the precomputed table of multipliers */ + return div_lut[f]; +} + +static void vdec_av1_slice_get_shear_params(struct vdec_av1_slice_gm *gm_params) +{ + const int *mat = gm_params->wmmat; + short shift; + short y; + long long gv, dv; + + if (gm_params->wmmat[2] <= 0) + return; + + gm_params->alpha = clamp_val(mat[2] - (1 << WARPEDMODEL_PREC_BITS), S16_MIN, S16_MAX); + gm_params->beta = clamp_val(mat[3], S16_MIN, S16_MAX); + + y = vdec_av1_slice_resolve_divisor_32(abs(mat[2]), &shift) * (mat[2] < 0 ? -1 : 1); + + gv = ((long long)mat[4] * (1 << WARPEDMODEL_PREC_BITS)) * y; + gm_params->gamma = clamp_val((int)AV1_DIV_ROUND_UP_POW2_SIGNED(gv, shift), + S16_MIN, S16_MAX); + + dv = ((long long)mat[3] * mat[4]) * y; + gm_params->delta = clamp_val(mat[5] - (int)AV1_DIV_ROUND_UP_POW2_SIGNED(dv, shift) - + (1 << WARPEDMODEL_PREC_BITS), S16_MIN, S16_MAX); + + gm_params->alpha = AV1_DIV_ROUND_UP_POW2_SIGNED(gm_params->alpha, WARP_PARAM_REDUCE_BITS) * + (1 << WARP_PARAM_REDUCE_BITS); + gm_params->beta = AV1_DIV_ROUND_UP_POW2_SIGNED(gm_params->beta, WARP_PARAM_REDUCE_BITS) * + (1 << WARP_PARAM_REDUCE_BITS); + gm_params->gamma = AV1_DIV_ROUND_UP_POW2_SIGNED(gm_params->gamma, WARP_PARAM_REDUCE_BITS) * + (1 << WARP_PARAM_REDUCE_BITS); + gm_params->delta = AV1_DIV_ROUND_UP_POW2_SIGNED(gm_params->delta, WARP_PARAM_REDUCE_BITS) * + (1 << WARP_PARAM_REDUCE_BITS); +} + +static void vdec_av1_slice_setup_gm(struct vdec_av1_slice_gm *gm, + struct v4l2_av1_global_motion *ctrl_gm) +{ + u32 i, j; + + for (i = 0; i < V4L2_AV1_TOTAL_REFS_PER_FRAME; i++) { + gm[i].wmtype = ctrl_gm->type[i]; + for (j = 0; j < 6; j++) + gm[i].wmmat[j] = ctrl_gm->params[i][j]; + + gm[i].invalid = !!(ctrl_gm->invalid & BIT(i)); + gm[i].alpha = 0; + gm[i].beta = 0; + gm[i].gamma = 0; + gm[i].delta = 0; + if (gm[i].wmtype <= V4L2_AV1_WARP_MODEL_AFFINE) + vdec_av1_slice_get_shear_params(&gm[i]); + } +} + +static void vdec_av1_slice_setup_seg(struct vdec_av1_slice_seg *seg, + struct v4l2_av1_segmentation *ctrl_seg) +{ + u32 i, j; + + seg->segmentation_enabled = SEGMENTATION_FLAG(ctrl_seg, ENABLED); + seg->segmentation_update_map = SEGMENTATION_FLAG(ctrl_seg, UPDATE_MAP); + seg->segmentation_temporal_update = SEGMENTATION_FLAG(ctrl_seg, TEMPORAL_UPDATE); + seg->segmentation_update_data = SEGMENTATION_FLAG(ctrl_seg, UPDATE_DATA); + seg->segid_preskip = SEGMENTATION_FLAG(ctrl_seg, SEG_ID_PRE_SKIP); + seg->last_active_segid = ctrl_seg->last_active_seg_id; + + for (i = 0; i < V4L2_AV1_MAX_SEGMENTS; i++) { + seg->feature_enabled_mask[i] = ctrl_seg->feature_enabled[i]; + for (j = 0; j < V4L2_AV1_SEG_LVL_MAX; j++) + seg->feature_data[i][j] = ctrl_seg->feature_data[i][j]; + } +} + +static void vdec_av1_slice_setup_quant(struct vdec_av1_slice_quantization *quant, + struct v4l2_av1_quantization *ctrl_quant) +{ + quant->base_q_idx = ctrl_quant->base_q_idx; + quant->delta_qydc = ctrl_quant->delta_q_y_dc; + quant->delta_qudc = ctrl_quant->delta_q_u_dc; + quant->delta_quac = ctrl_quant->delta_q_u_ac; + quant->delta_qvdc = ctrl_quant->delta_q_v_dc; + quant->delta_qvac = ctrl_quant->delta_q_v_ac; + quant->qm_y = ctrl_quant->qm_y; + quant->qm_u = ctrl_quant->qm_u; + quant->qm_v = ctrl_quant->qm_v; + quant->using_qmatrix = QUANT_FLAG(ctrl_quant, USING_QMATRIX); +} + +static int vdec_av1_slice_get_qindex(struct vdec_av1_slice_uncompressed_header *uh, + int segmentation_id) +{ + struct vdec_av1_slice_seg *seg = &uh->seg; + struct vdec_av1_slice_quantization *quant = &uh->quant; + int data = 0, qindex = 0; + + if (seg->segmentation_enabled && + (seg->feature_enabled_mask[segmentation_id] & BIT(SEG_LVL_ALT_Q))) { + data = seg->feature_data[segmentation_id][SEG_LVL_ALT_Q]; + qindex = quant->base_q_idx + data; + return clamp_val(qindex, 0, MAXQ); + } + + return quant->base_q_idx; +} + +static void vdec_av1_slice_setup_lr(struct vdec_av1_slice_lr *lr, + struct v4l2_av1_loop_restoration *ctrl_lr) +{ + int i; + + lr->use_lr = 0; + lr->use_chroma_lr = 0; + for (i = 0; i < V4L2_AV1_NUM_PLANES_MAX; i++) { + lr->frame_restoration_type[i] = ctrl_lr->frame_restoration_type[i]; + lr->loop_restoration_size[i] = ctrl_lr->loop_restoration_size[i]; + if (lr->frame_restoration_type[i]) { + lr->use_lr = 1; + if (i > 0) + lr->use_chroma_lr = 1; + } + } +} + +static void vdec_av1_slice_setup_lf(struct vdec_av1_slice_loop_filter *lf, + struct v4l2_av1_loop_filter *ctrl_lf) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(lf->loop_filter_level); i++) + lf->loop_filter_level[i] = ctrl_lf->level[i]; + + for (i = 0; i < V4L2_AV1_TOTAL_REFS_PER_FRAME; i++) + lf->loop_filter_ref_deltas[i] = ctrl_lf->ref_deltas[i]; + + for (i = 0; i < ARRAY_SIZE(lf->loop_filter_mode_deltas); i++) + lf->loop_filter_mode_deltas[i] = ctrl_lf->mode_deltas[i]; + + lf->loop_filter_sharpness = ctrl_lf->sharpness; + lf->loop_filter_delta_enabled = + BIT_FLAG(ctrl_lf, V4L2_AV1_LOOP_FILTER_FLAG_DELTA_ENABLED); +} + +static void vdec_av1_slice_setup_cdef(struct vdec_av1_slice_cdef *cdef, + struct v4l2_av1_cdef *ctrl_cdef) +{ + int i; + + cdef->cdef_damping = ctrl_cdef->damping_minus_3 + 3; + cdef->cdef_bits = ctrl_cdef->bits; + + for (i = 0; i < V4L2_AV1_CDEF_MAX; i++) { + if (ctrl_cdef->y_sec_strength[i] == 4) + ctrl_cdef->y_sec_strength[i] -= 1; + + if (ctrl_cdef->uv_sec_strength[i] == 4) + ctrl_cdef->uv_sec_strength[i] -= 1; + + cdef->cdef_y_strength[i] = + ctrl_cdef->y_pri_strength[i] << SECONDARY_FILTER_STRENGTH_NUM_BITS | + ctrl_cdef->y_sec_strength[i]; + cdef->cdef_uv_strength[i] = + ctrl_cdef->uv_pri_strength[i] << SECONDARY_FILTER_STRENGTH_NUM_BITS | + ctrl_cdef->uv_sec_strength[i]; + } +} + +static void vdec_av1_slice_setup_seq(struct vdec_av1_slice_seq_header *seq, + struct v4l2_ctrl_av1_sequence *ctrl_seq) +{ + seq->bitdepth = ctrl_seq->bit_depth; + seq->max_frame_width = ctrl_seq->max_frame_width_minus_1 + 1; + seq->max_frame_height = ctrl_seq->max_frame_height_minus_1 + 1; + seq->enable_superres = SEQUENCE_FLAG(ctrl_seq, ENABLE_SUPERRES); + seq->enable_filter_intra = SEQUENCE_FLAG(ctrl_seq, ENABLE_FILTER_INTRA); + seq->enable_intra_edge_filter = SEQUENCE_FLAG(ctrl_seq, ENABLE_INTRA_EDGE_FILTER); + seq->enable_interintra_compound = SEQUENCE_FLAG(ctrl_seq, ENABLE_INTERINTRA_COMPOUND); + seq->enable_masked_compound = SEQUENCE_FLAG(ctrl_seq, ENABLE_MASKED_COMPOUND); + seq->enable_dual_filter = SEQUENCE_FLAG(ctrl_seq, ENABLE_DUAL_FILTER); + seq->enable_jnt_comp = SEQUENCE_FLAG(ctrl_seq, ENABLE_JNT_COMP); + seq->mono_chrome = SEQUENCE_FLAG(ctrl_seq, MONO_CHROME); + seq->enable_order_hint = SEQUENCE_FLAG(ctrl_seq, ENABLE_ORDER_HINT); + seq->order_hint_bits = ctrl_seq->order_hint_bits; + seq->use_128x128_superblock = SEQUENCE_FLAG(ctrl_seq, USE_128X128_SUPERBLOCK); + seq->subsampling_x = SEQUENCE_FLAG(ctrl_seq, SUBSAMPLING_X); + seq->subsampling_y = SEQUENCE_FLAG(ctrl_seq, SUBSAMPLING_Y); +} + +static void vdec_av1_slice_setup_tile(struct vdec_av1_slice_frame *frame, + struct v4l2_av1_tile_info *ctrl_tile) +{ + struct vdec_av1_slice_seq_header *seq = &frame->seq; + struct vdec_av1_slice_tile *tile = &frame->uh.tile; + u32 mib_size_log2 = seq->use_128x128_superblock ? 5 : 4; + int i; + + tile->tile_cols = ctrl_tile->tile_cols; + tile->tile_rows = ctrl_tile->tile_rows; + tile->context_update_tile_id = ctrl_tile->context_update_tile_id; + tile->uniform_tile_spacing_flag = + BIT_FLAG(ctrl_tile, V4L2_AV1_TILE_INFO_FLAG_UNIFORM_TILE_SPACING); + + for (i = 0; i < tile->tile_cols + 1; i++) + tile->mi_col_starts[i] = + ALIGN(ctrl_tile->mi_col_starts[i], BIT(mib_size_log2)) >> mib_size_log2; + + for (i = 0; i < tile->tile_rows + 1; i++) + tile->mi_row_starts[i] = + ALIGN(ctrl_tile->mi_row_starts[i], BIT(mib_size_log2)) >> mib_size_log2; +} + +static void vdec_av1_slice_setup_uh(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_frame *frame, + struct v4l2_ctrl_av1_frame *ctrl_fh) +{ + struct vdec_av1_slice_uncompressed_header *uh = &frame->uh; + int i; + + uh->use_ref_frame_mvs = FH_FLAG(ctrl_fh, USE_REF_FRAME_MVS); + uh->order_hint = ctrl_fh->order_hint; + vdec_av1_slice_setup_gm(uh->gm, &ctrl_fh->global_motion); + uh->upscaled_width = ctrl_fh->upscaled_width; + uh->frame_width = ctrl_fh->frame_width_minus_1 + 1; + uh->frame_height = ctrl_fh->frame_height_minus_1 + 1; + uh->mi_cols = ((uh->frame_width + 7) >> 3) << 1; + uh->mi_rows = ((uh->frame_height + 7) >> 3) << 1; + uh->reduced_tx_set = FH_FLAG(ctrl_fh, REDUCED_TX_SET); + uh->tx_mode = ctrl_fh->tx_mode; + uh->uniform_tile_spacing_flag = + BIT_FLAG(&ctrl_fh->tile_info, V4L2_AV1_TILE_INFO_FLAG_UNIFORM_TILE_SPACING); + uh->interpolation_filter = ctrl_fh->interpolation_filter; + uh->allow_warped_motion = FH_FLAG(ctrl_fh, ALLOW_WARPED_MOTION); + uh->is_motion_mode_switchable = FH_FLAG(ctrl_fh, IS_MOTION_MODE_SWITCHABLE); + uh->frame_type = ctrl_fh->frame_type; + uh->frame_is_intra = (uh->frame_type == V4L2_AV1_INTRA_ONLY_FRAME || + uh->frame_type == V4L2_AV1_KEY_FRAME); + + if (!uh->frame_is_intra && FH_FLAG(ctrl_fh, REFERENCE_SELECT)) + uh->reference_mode = AV1_REFERENCE_MODE_SELECT; + else + uh->reference_mode = AV1_SINGLE_REFERENCE; + + uh->allow_high_precision_mv = FH_FLAG(ctrl_fh, ALLOW_HIGH_PRECISION_MV); + uh->allow_intra_bc = FH_FLAG(ctrl_fh, ALLOW_INTRABC); + uh->force_integer_mv = FH_FLAG(ctrl_fh, FORCE_INTEGER_MV); + uh->allow_screen_content_tools = FH_FLAG(ctrl_fh, ALLOW_SCREEN_CONTENT_TOOLS); + uh->error_resilient_mode = FH_FLAG(ctrl_fh, ERROR_RESILIENT_MODE); + uh->primary_ref_frame = ctrl_fh->primary_ref_frame; + uh->disable_frame_end_update_cdf = + FH_FLAG(ctrl_fh, DISABLE_FRAME_END_UPDATE_CDF); + uh->disable_cdf_update = FH_FLAG(ctrl_fh, DISABLE_CDF_UPDATE); + uh->skip_mode.skip_mode_present = FH_FLAG(ctrl_fh, SKIP_MODE_PRESENT); + uh->skip_mode.skip_mode_frame[0] = + ctrl_fh->skip_mode_frame[0] - V4L2_AV1_REF_LAST_FRAME; + uh->skip_mode.skip_mode_frame[1] = + ctrl_fh->skip_mode_frame[1] - V4L2_AV1_REF_LAST_FRAME; + uh->skip_mode.skip_mode_allowed = ctrl_fh->skip_mode_frame[0] ? 1 : 0; + + vdec_av1_slice_setup_seg(&uh->seg, &ctrl_fh->segmentation); + uh->delta_q_lf.delta_q_present = QUANT_FLAG(&ctrl_fh->quantization, DELTA_Q_PRESENT); + uh->delta_q_lf.delta_q_res = 1 << ctrl_fh->quantization.delta_q_res; + uh->delta_q_lf.delta_lf_present = + BIT_FLAG(&ctrl_fh->loop_filter, V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_PRESENT); + uh->delta_q_lf.delta_lf_res = ctrl_fh->loop_filter.delta_lf_res; + uh->delta_q_lf.delta_lf_multi = + BIT_FLAG(&ctrl_fh->loop_filter, V4L2_AV1_LOOP_FILTER_FLAG_DELTA_LF_MULTI); + vdec_av1_slice_setup_quant(&uh->quant, &ctrl_fh->quantization); + + uh->coded_loss_less = 1; + for (i = 0; i < V4L2_AV1_MAX_SEGMENTS; i++) { + uh->quant.qindex[i] = vdec_av1_slice_get_qindex(uh, i); + uh->loss_less_array[i] = + (uh->quant.qindex[i] == 0 && uh->quant.delta_qydc == 0 && + uh->quant.delta_quac == 0 && uh->quant.delta_qudc == 0 && + uh->quant.delta_qvac == 0 && uh->quant.delta_qvdc == 0); + + if (!uh->loss_less_array[i]) + uh->coded_loss_less = 0; + } + + vdec_av1_slice_setup_lr(&uh->lr, &ctrl_fh->loop_restoration); + uh->superres_denom = ctrl_fh->superres_denom; + vdec_av1_slice_setup_lf(&uh->loop_filter, &ctrl_fh->loop_filter); + vdec_av1_slice_setup_cdef(&uh->cdef, &ctrl_fh->cdef); + vdec_av1_slice_setup_tile(frame, &ctrl_fh->tile_info); +} + +static int vdec_av1_slice_setup_tile_group(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_vsi *vsi) +{ + struct v4l2_ctrl_av1_tile_group_entry *ctrl_tge; + struct vdec_av1_slice_tile_group *tile_group = &instance->tile_group; + struct vdec_av1_slice_uncompressed_header *uh = &vsi->frame.uh; + struct vdec_av1_slice_tile *tile = &uh->tile; + struct v4l2_ctrl *ctrl; + u32 tge_size; + int i; + + ctrl = v4l2_ctrl_find(&instance->ctx->ctrl_hdl, V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY); + if (!ctrl) + return -EINVAL; + + tge_size = ctrl->elems; + ctrl_tge = (struct v4l2_ctrl_av1_tile_group_entry *)ctrl->p_cur.p; + + tile_group->num_tiles = tile->tile_cols * tile->tile_rows; + + if (tile_group->num_tiles != tge_size || + tile_group->num_tiles > V4L2_AV1_MAX_TILE_COUNT) { + mtk_vcodec_err(instance, "invalid tge_size %d, tile_num:%d\n", + tge_size, tile_group->num_tiles); + return -EINVAL; + } + + for (i = 0; i < tge_size; i++) { + if (i != ctrl_tge[i].tile_row * vsi->frame.uh.tile.tile_cols + + ctrl_tge[i].tile_col) { + mtk_vcodec_err(instance, "invalid tge info %d, %d %d %d\n", + i, ctrl_tge[i].tile_row, ctrl_tge[i].tile_col, + vsi->frame.uh.tile.tile_rows); + return -EINVAL; + } + tile_group->tile_size[i] = ctrl_tge[i].tile_size; + tile_group->tile_start_offset[i] = ctrl_tge[i].tile_offset; + } + + return 0; +} + +static inline void vdec_av1_slice_setup_state(struct vdec_av1_slice_vsi *vsi) +{ + memset(&vsi->state, 0, sizeof(vsi->state)); +} + +static void vdec_av1_slice_setup_scale_factors(struct vdec_av1_slice_frame_refs *frame_ref, + struct vdec_av1_slice_frame_info *ref_frame_info, + struct vdec_av1_slice_uncompressed_header *uh) +{ + struct vdec_av1_slice_scale_factors *scale_factors = &frame_ref->scale_factors; + u32 ref_upscaled_width = ref_frame_info->upscaled_width; + u32 ref_frame_height = ref_frame_info->frame_height; + u32 frame_width = uh->frame_width; + u32 frame_height = uh->frame_height; + + if (!vdec_av1_slice_need_scale(ref_upscaled_width, ref_frame_height, + frame_width, frame_height)) { + scale_factors->x_scale = -1; + scale_factors->y_scale = -1; + scale_factors->is_scaled = 0; + return; + } + + scale_factors->x_scale = + ((ref_upscaled_width << AV1_REF_SCALE_SHIFT) + (frame_width >> 1)) / frame_width; + scale_factors->y_scale = + ((ref_frame_height << AV1_REF_SCALE_SHIFT) + (frame_height >> 1)) / frame_height; + scale_factors->is_scaled = + (scale_factors->x_scale != AV1_REF_INVALID_SCALE) && + (scale_factors->y_scale != AV1_REF_INVALID_SCALE) && + (scale_factors->x_scale != AV1_REF_NO_SCALE || + scale_factors->y_scale != AV1_REF_NO_SCALE); + scale_factors->x_step = + AV1_DIV_ROUND_UP_POW2(scale_factors->x_scale, + AV1_REF_SCALE_SHIFT - AV1_SCALE_SUBPEL_BITS); + scale_factors->y_step = + AV1_DIV_ROUND_UP_POW2(scale_factors->y_scale, + AV1_REF_SCALE_SHIFT - AV1_SCALE_SUBPEL_BITS); +} + +static unsigned char vdec_av1_slice_get_sign_bias(int a, + int b, + u8 enable_order_hint, + u8 order_hint_bits) +{ + int diff = 0; + int m = 0; + unsigned char result = 0; + + if (!enable_order_hint) + return 0; + + diff = a - b; + m = 1 << (order_hint_bits - 1); + diff = (diff & (m - 1)) - (diff & m); + + if (diff > 0) + result = 1; + + return result; +} + +static void vdec_av1_slice_setup_ref(struct vdec_av1_slice_pfc *pfc, + struct v4l2_ctrl_av1_frame *ctrl_fh) +{ + struct vdec_av1_slice_vsi *vsi = &pfc->vsi; + struct vdec_av1_slice_frame *frame = &vsi->frame; + struct vdec_av1_slice_slot *slots = &vsi->slots; + struct vdec_av1_slice_uncompressed_header *uh = &frame->uh; + struct vdec_av1_slice_seq_header *seq = &frame->seq; + struct vdec_av1_slice_frame_info *cur_frame_info = + &slots->frame_info[vsi->slot_id]; + struct vdec_av1_slice_frame_info *frame_info; + int i, slot_id; + + if (uh->frame_is_intra) + return; + + for (i = 0; i < V4L2_AV1_REFS_PER_FRAME; i++) { + int ref_idx = ctrl_fh->ref_frame_idx[i]; + + pfc->ref_idx[i] = ctrl_fh->reference_frame_ts[ref_idx]; + slot_id = frame->ref_frame_map[ref_idx]; + frame_info = &slots->frame_info[slot_id]; + if (slot_id == AV1_INVALID_IDX) { + mtk_v4l2_err("cannot match reference[%d] 0x%llx\n", i, + ctrl_fh->reference_frame_ts[ref_idx]); + frame->order_hints[i] = 0; + frame->ref_frame_valid[i] = 0; + continue; + } + + frame->frame_refs[i].ref_fb_idx = slot_id; + vdec_av1_slice_setup_scale_factors(&frame->frame_refs[i], + frame_info, uh); + if (!seq->enable_order_hint) + frame->ref_frame_sign_bias[i + 1] = 0; + else + frame->ref_frame_sign_bias[i + 1] = + vdec_av1_slice_get_sign_bias(frame_info->order_hint, + uh->order_hint, + seq->enable_order_hint, + seq->order_hint_bits); + + frame->order_hints[i] = ctrl_fh->order_hints[i + 1]; + cur_frame_info->order_hints[i] = frame->order_hints[i]; + frame->ref_frame_valid[i] = 1; + } +} + +static void vdec_av1_slice_get_previous(struct vdec_av1_slice_vsi *vsi) +{ + struct vdec_av1_slice_frame *frame = &vsi->frame; + + if (frame->uh.primary_ref_frame == AV1_PRIMARY_REF_NONE) + frame->prev_fb_idx = AV1_INVALID_IDX; + else + frame->prev_fb_idx = frame->frame_refs[frame->uh.primary_ref_frame].ref_fb_idx; +} + +static inline void vdec_av1_slice_setup_operating_mode(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_frame *frame) +{ + frame->large_scale_tile = 0; +} + +static int vdec_av1_slice_setup_pfc(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_pfc *pfc) +{ + struct v4l2_ctrl_av1_frame *ctrl_fh; + struct v4l2_ctrl_av1_sequence *ctrl_seq; + struct vdec_av1_slice_vsi *vsi = &pfc->vsi; + int ret = 0; + + /* frame header */ + ctrl_fh = (struct v4l2_ctrl_av1_frame *) + vdec_av1_get_ctrl_ptr(instance->ctx, + V4L2_CID_STATELESS_AV1_FRAME); + if (IS_ERR(ctrl_fh)) + return PTR_ERR(ctrl_fh); + + ctrl_seq = (struct v4l2_ctrl_av1_sequence *) + vdec_av1_get_ctrl_ptr(instance->ctx, + V4L2_CID_STATELESS_AV1_SEQUENCE); + if (IS_ERR(ctrl_seq)) + return PTR_ERR(ctrl_seq); + + /* setup vsi information */ + vdec_av1_slice_setup_seq(&vsi->frame.seq, ctrl_seq); + vdec_av1_slice_setup_uh(instance, &vsi->frame, ctrl_fh); + vdec_av1_slice_setup_operating_mode(instance, &vsi->frame); + + vdec_av1_slice_setup_state(vsi); + vdec_av1_slice_setup_slot(instance, vsi, ctrl_fh); + vdec_av1_slice_setup_ref(pfc, ctrl_fh); + vdec_av1_slice_get_previous(vsi); + + pfc->seq = instance->seq; + instance->seq++; + + return ret; +} + +static void vdec_av1_slice_setup_lat_buffer(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_vsi *vsi, + struct mtk_vcodec_mem *bs, + struct vdec_lat_buf *lat_buf) +{ + struct vdec_av1_slice_work_buffer *work_buffer; + int i; + + vsi->bs.dma_addr = bs->dma_addr; + vsi->bs.size = bs->size; + + vsi->ube.dma_addr = lat_buf->ctx->msg_queue.wdma_addr.dma_addr; + vsi->ube.size = lat_buf->ctx->msg_queue.wdma_addr.size; + vsi->trans.dma_addr = lat_buf->ctx->msg_queue.wdma_wptr_addr; + /* used to store trans end */ + vsi->trans.dma_addr_end = lat_buf->ctx->msg_queue.wdma_rptr_addr; + vsi->err_map.dma_addr = lat_buf->wdma_err_addr.dma_addr; + vsi->err_map.size = lat_buf->wdma_err_addr.size; + vsi->rd_mv.dma_addr = lat_buf->rd_mv_addr.dma_addr; + vsi->rd_mv.size = lat_buf->rd_mv_addr.size; + + vsi->row_info.buf = 0; + vsi->row_info.size = 0; + + work_buffer = vsi->work_buffer; + + for (i = 0; i < AV1_MAX_FRAME_BUF_COUNT; i++) { + work_buffer[i].mv_addr.buf = instance->mv[i].dma_addr; + work_buffer[i].mv_addr.size = instance->mv[i].size; + work_buffer[i].segid_addr.buf = instance->seg[i].dma_addr; + work_buffer[i].segid_addr.size = instance->seg[i].size; + work_buffer[i].cdf_addr.buf = instance->cdf[i].dma_addr; + work_buffer[i].cdf_addr.size = instance->cdf[i].size; + } + + vsi->cdf_tmp.buf = instance->cdf_temp.dma_addr; + vsi->cdf_tmp.size = instance->cdf_temp.size; + + vsi->tile.buf = instance->tile.dma_addr; + vsi->tile.size = instance->tile.size; + memcpy(lat_buf->tile_addr.va, instance->tile.va, 64 * instance->tile_group.num_tiles); + + vsi->cdf_table.buf = instance->cdf_table.dma_addr; + vsi->cdf_table.size = instance->cdf_table.size; + vsi->iq_table.buf = instance->iq_table.dma_addr; + vsi->iq_table.size = instance->iq_table.size; +} + +static void vdec_av1_slice_setup_seg_buffer(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_vsi *vsi) +{ + struct vdec_av1_slice_uncompressed_header *uh = &vsi->frame.uh; + struct mtk_vcodec_mem *buf; + + /* reset segment buffer */ + if (uh->primary_ref_frame == AV1_PRIMARY_REF_NONE || !uh->seg.segmentation_enabled) { + mtk_vcodec_debug(instance, "reset seg %d\n", vsi->slot_id); + if (vsi->slot_id != AV1_INVALID_IDX) { + buf = &instance->seg[vsi->slot_id]; + memset(buf->va, 0, buf->size); + } + } +} + +static void vdec_av1_slice_setup_tile_buffer(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_vsi *vsi, + struct mtk_vcodec_mem *bs) +{ + struct vdec_av1_slice_tile_group *tile_group = &instance->tile_group; + struct vdec_av1_slice_uncompressed_header *uh = &vsi->frame.uh; + struct vdec_av1_slice_tile *tile = &uh->tile; + u32 tile_num, tile_row, tile_col; + u32 allow_update_cdf = 0; + u32 sb_boundary_x_m1 = 0, sb_boundary_y_m1 = 0; + int tile_info_base; + u32 tile_buf_pa; + u32 *tile_info_buf = instance->tile.va; + u32 pa = (u32)bs->dma_addr; + + if (uh->disable_cdf_update == 0) + allow_update_cdf = 1; + + for (tile_num = 0; tile_num < tile_group->num_tiles; tile_num++) { + /* each uint32 takes place of 4 bytes */ + tile_info_base = (AV1_TILE_BUF_SIZE * tile_num) >> 2; + tile_row = tile_num / tile->tile_cols; + tile_col = tile_num % tile->tile_cols; + tile_info_buf[tile_info_base + 0] = (tile_group->tile_size[tile_num] << 3); + tile_buf_pa = pa + tile_group->tile_start_offset[tile_num]; + + tile_info_buf[tile_info_base + 1] = (tile_buf_pa >> 4) << 4; + tile_info_buf[tile_info_base + 2] = (tile_buf_pa % 16) << 3; + + sb_boundary_x_m1 = + (tile->mi_col_starts[tile_col + 1] - tile->mi_col_starts[tile_col] - 1) & + 0x3f; + sb_boundary_y_m1 = + (tile->mi_row_starts[tile_row + 1] - tile->mi_row_starts[tile_row] - 1) & + 0x1ff; + + tile_info_buf[tile_info_base + 3] = (sb_boundary_y_m1 << 7) | sb_boundary_x_m1; + tile_info_buf[tile_info_base + 4] = ((allow_update_cdf << 18) | (1 << 16)); + + if (tile_num == tile->context_update_tile_id && + uh->disable_frame_end_update_cdf == 0) + tile_info_buf[tile_info_base + 4] |= (1 << 17); + + mtk_vcodec_debug(instance, "// tile buf %d pos(%dx%d) offset 0x%x\n", + tile_num, tile_row, tile_col, tile_info_base); + mtk_vcodec_debug(instance, "// %08x %08x %08x %08x\n", + tile_info_buf[tile_info_base + 0], + tile_info_buf[tile_info_base + 1], + tile_info_buf[tile_info_base + 2], + tile_info_buf[tile_info_base + 3]); + mtk_vcodec_debug(instance, "// %08x %08x %08x %08x\n", + tile_info_buf[tile_info_base + 4], + tile_info_buf[tile_info_base + 5], + tile_info_buf[tile_info_base + 6], + tile_info_buf[tile_info_base + 7]); + } +} + +static int vdec_av1_slice_setup_lat(struct vdec_av1_slice_instance *instance, + struct mtk_vcodec_mem *bs, + struct vdec_lat_buf *lat_buf, + struct vdec_av1_slice_pfc *pfc) +{ + struct vdec_av1_slice_vsi *vsi = &pfc->vsi; + int ret; + + ret = vdec_av1_slice_setup_lat_from_src_buf(instance, vsi, lat_buf); + if (ret) + return ret; + + ret = vdec_av1_slice_setup_pfc(instance, pfc); + if (ret) + return ret; + + ret = vdec_av1_slice_setup_tile_group(instance, vsi); + if (ret) + return ret; + + ret = vdec_av1_slice_alloc_working_buffer(instance, vsi); + if (ret) + return ret; + + vdec_av1_slice_setup_seg_buffer(instance, vsi); + vdec_av1_slice_setup_tile_buffer(instance, vsi, bs); + vdec_av1_slice_setup_lat_buffer(instance, vsi, bs, lat_buf); + + return 0; +} + +static int vdec_av1_slice_update_lat(struct vdec_av1_slice_instance *instance, + struct vdec_lat_buf *lat_buf, + struct vdec_av1_slice_pfc *pfc) +{ + struct vdec_av1_slice_vsi *vsi; + + vsi = &pfc->vsi; + mtk_vcodec_debug(instance, "frame %u LAT CRC 0x%08x, output size is %d\n", + pfc->seq, vsi->state.crc[0], vsi->state.out_size); + + /* buffer full, need to re-decode */ + if (vsi->state.full) { + /* buffer not enough */ + if (vsi->trans.dma_addr_end - vsi->trans.dma_addr == vsi->ube.size) + return -ENOMEM; + return -EAGAIN; + } + + instance->width = vsi->frame.uh.upscaled_width; + instance->height = vsi->frame.uh.frame_height; + instance->frame_type = vsi->frame.uh.frame_type; + + return 0; +} + +static int vdec_av1_slice_setup_core_to_dst_buf(struct vdec_av1_slice_instance *instance, + struct vdec_lat_buf *lat_buf) +{ + struct vb2_v4l2_buffer *dst; + + dst = v4l2_m2m_next_dst_buf(instance->ctx->m2m_ctx); + if (!dst) + return -EINVAL; + + v4l2_m2m_buf_copy_metadata(&lat_buf->ts_info, dst, true); + + return 0; +} + +static int vdec_av1_slice_setup_core_buffer(struct vdec_av1_slice_instance *instance, + struct vdec_av1_slice_pfc *pfc, + struct vdec_av1_slice_vsi *vsi, + struct vdec_fb *fb, + struct vdec_lat_buf *lat_buf) +{ + struct vb2_buffer *vb; + struct vb2_queue *vq; + int w, h, plane, size; + int i; + + plane = instance->ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes; + w = vsi->frame.uh.upscaled_width; + h = vsi->frame.uh.frame_height; + size = ALIGN(w, VCODEC_DEC_ALIGNED_64) * ALIGN(h, VCODEC_DEC_ALIGNED_64); + + /* frame buffer */ + vsi->fb.y.dma_addr = fb->base_y.dma_addr; + if (plane == 1) + vsi->fb.c.dma_addr = fb->base_y.dma_addr + size; + else + vsi->fb.c.dma_addr = fb->base_c.dma_addr; + + /* reference buffers */ + vq = v4l2_m2m_get_vq(instance->ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); + if (!vq) + return -EINVAL; + + /* get current output buffer */ + vb = &v4l2_m2m_next_dst_buf(instance->ctx->m2m_ctx)->vb2_buf; + if (!vb) + return -EINVAL; + + /* get buffer address from vb2buf */ + for (i = 0; i < V4L2_AV1_REFS_PER_FRAME; i++) { + struct vdec_av1_slice_fb *vref = &vsi->ref[i]; + + vb = vb2_find_buffer(vq, pfc->ref_idx[i]); + if (!vb) { + memset(vref, 0, sizeof(*vref)); + continue; + } + + vref->y.dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0); + if (plane == 1) + vref->c.dma_addr = vref->y.dma_addr + size; + else + vref->c.dma_addr = vb2_dma_contig_plane_dma_addr(vb, 1); + } + vsi->tile.dma_addr = lat_buf->tile_addr.dma_addr; + vsi->tile.size = lat_buf->tile_addr.size; + + return 0; +} + +static int vdec_av1_slice_setup_core(struct vdec_av1_slice_instance *instance, + struct vdec_fb *fb, + struct vdec_lat_buf *lat_buf, + struct vdec_av1_slice_pfc *pfc) +{ + struct vdec_av1_slice_vsi *vsi = &pfc->vsi; + int ret; + + ret = vdec_av1_slice_setup_core_to_dst_buf(instance, lat_buf); + if (ret) + return ret; + + ret = vdec_av1_slice_setup_core_buffer(instance, pfc, vsi, fb, lat_buf); + if (ret) + return ret; + + return 0; +} + +static int vdec_av1_slice_update_core(struct vdec_av1_slice_instance *instance, + struct vdec_lat_buf *lat_buf, + struct vdec_av1_slice_pfc *pfc) +{ + struct vdec_av1_slice_vsi *vsi = instance->core_vsi; + + mtk_vcodec_debug(instance, "frame %u Y_CRC %08x %08x %08x %08x\n", + pfc->seq, vsi->state.crc[0], vsi->state.crc[1], + vsi->state.crc[2], vsi->state.crc[3]); + mtk_vcodec_debug(instance, "frame %u C_CRC %08x %08x %08x %08x\n", + pfc->seq, vsi->state.crc[8], vsi->state.crc[9], + vsi->state.crc[10], vsi->state.crc[11]); + + return 0; +} + +static int vdec_av1_slice_init(struct mtk_vcodec_ctx *ctx) +{ + struct vdec_av1_slice_instance *instance; + struct vdec_av1_slice_init_vsi *vsi; + int ret; + + instance = kzalloc(sizeof(*instance), GFP_KERNEL); + if (!instance) + return -ENOMEM; + + instance->ctx = ctx; + instance->vpu.id = SCP_IPI_VDEC_LAT; + instance->vpu.core_id = SCP_IPI_VDEC_CORE; + instance->vpu.ctx = ctx; + instance->vpu.codec_type = ctx->current_codec; + + ret = vpu_dec_init(&instance->vpu); + if (ret) { + mtk_vcodec_err(instance, "failed to init vpu dec, ret %d\n", ret); + goto error_vpu_init; + } + + /* init vsi and global flags */ + vsi = instance->vpu.vsi; + if (!vsi) { + mtk_vcodec_err(instance, "failed to get AV1 vsi\n"); + ret = -EINVAL; + goto error_vsi; + } + instance->init_vsi = vsi; + instance->core_vsi = mtk_vcodec_fw_map_dm_addr(ctx->dev->fw_handler, (u32)vsi->core_vsi); + + if (!instance->core_vsi) { + mtk_vcodec_err(instance, "failed to get AV1 core vsi\n"); + ret = -EINVAL; + goto error_vsi; + } + + if (vsi->vsi_size != sizeof(struct vdec_av1_slice_vsi)) + mtk_vcodec_err(instance, "remote vsi size 0x%x mismatch! expected: 0x%zx\n", + vsi->vsi_size, sizeof(struct vdec_av1_slice_vsi)); + + instance->irq_enabled = 1; + instance->inneracing_mode = IS_VDEC_INNER_RACING(instance->ctx->dev->dec_capability); + + mtk_vcodec_debug(instance, "vsi 0x%p core_vsi 0x%llx 0x%p, inneracing_mode %d\n", + vsi, vsi->core_vsi, instance->core_vsi, instance->inneracing_mode); + + ret = vdec_av1_slice_init_cdf_table(instance); + if (ret) + goto error_vsi; + + ret = vdec_av1_slice_init_iq_table(instance); + if (ret) + goto error_vsi; + + ctx->drv_handle = instance; + + return 0; +error_vsi: + vpu_dec_deinit(&instance->vpu); +error_vpu_init: + kfree(instance); + + return ret; +} + +static void vdec_av1_slice_deinit(void *h_vdec) +{ + struct vdec_av1_slice_instance *instance = h_vdec; + + if (!instance) + return; + mtk_vcodec_debug(instance, "h_vdec 0x%p\n", h_vdec); + vpu_dec_deinit(&instance->vpu); + vdec_av1_slice_free_working_buffer(instance); + vdec_msg_queue_deinit(&instance->ctx->msg_queue, instance->ctx); + kfree(instance); +} + +static int vdec_av1_slice_flush(void *h_vdec, struct mtk_vcodec_mem *bs, + struct vdec_fb *fb, bool *res_chg) +{ + struct vdec_av1_slice_instance *instance = h_vdec; + int i; + + mtk_vcodec_debug(instance, "flush ...\n"); + + vdec_msg_queue_wait_lat_buf_full(&instance->ctx->msg_queue); + + for (i = 0; i < AV1_MAX_FRAME_BUF_COUNT; i++) + vdec_av1_slice_clear_fb(&instance->slots.frame_info[i]); + + return vpu_dec_reset(&instance->vpu); +} + +static void vdec_av1_slice_get_pic_info(struct vdec_av1_slice_instance *instance) +{ + struct mtk_vcodec_ctx *ctx = instance->ctx; + u32 data[3]; + + mtk_vcodec_debug(instance, "w %u h %u\n", ctx->picinfo.pic_w, ctx->picinfo.pic_h); + + data[0] = ctx->picinfo.pic_w; + data[1] = ctx->picinfo.pic_h; + data[2] = ctx->capture_fourcc; + vpu_dec_get_param(&instance->vpu, data, 3, GET_PARAM_PIC_INFO); + + ctx->picinfo.buf_w = ALIGN(ctx->picinfo.pic_w, VCODEC_DEC_ALIGNED_64); + ctx->picinfo.buf_h = ALIGN(ctx->picinfo.pic_h, VCODEC_DEC_ALIGNED_64); + ctx->picinfo.fb_sz[0] = instance->vpu.fb_sz[0]; + ctx->picinfo.fb_sz[1] = instance->vpu.fb_sz[1]; +} + +static inline void vdec_av1_slice_get_dpb_size(struct vdec_av1_slice_instance *instance, + u32 *dpb_sz) +{ + /* refer av1 specification */ + *dpb_sz = V4L2_AV1_TOTAL_REFS_PER_FRAME + 1; +} + +static void vdec_av1_slice_get_crop_info(struct vdec_av1_slice_instance *instance, + struct v4l2_rect *cr) +{ + struct mtk_vcodec_ctx *ctx = instance->ctx; + + cr->left = 0; + cr->top = 0; + cr->width = ctx->picinfo.pic_w; + cr->height = ctx->picinfo.pic_h; + + mtk_vcodec_debug(instance, "l=%d, t=%d, w=%d, h=%d\n", + cr->left, cr->top, cr->width, cr->height); +} + +static int vdec_av1_slice_get_param(void *h_vdec, enum vdec_get_param_type type, void *out) +{ + struct vdec_av1_slice_instance *instance = h_vdec; + + switch (type) { + case GET_PARAM_PIC_INFO: + vdec_av1_slice_get_pic_info(instance); + break; + case GET_PARAM_DPB_SIZE: + vdec_av1_slice_get_dpb_size(instance, out); + break; + case GET_PARAM_CROP_INFO: + vdec_av1_slice_get_crop_info(instance, out); + break; + default: + mtk_vcodec_err(instance, "invalid get parameter type=%d\n", type); + return -EINVAL; + } + + return 0; +} + +static int vdec_av1_slice_lat_decode(void *h_vdec, struct mtk_vcodec_mem *bs, + struct vdec_fb *fb, bool *res_chg) +{ + struct vdec_av1_slice_instance *instance = h_vdec; + struct vdec_lat_buf *lat_buf; + struct vdec_av1_slice_pfc *pfc; + struct vdec_av1_slice_vsi *vsi; + struct mtk_vcodec_ctx *ctx; + int ret; + + if (!instance || !instance->ctx) + return -EINVAL; + + ctx = instance->ctx; + /* init msgQ for the first time */ + if (vdec_msg_queue_init(&ctx->msg_queue, ctx, + vdec_av1_slice_core_decode, sizeof(*pfc))) { + mtk_vcodec_err(instance, "failed to init AV1 msg queue\n"); + return -ENOMEM; + } + + /* bs NULL means flush decoder */ + if (!bs) + return vdec_av1_slice_flush(h_vdec, bs, fb, res_chg); + + lat_buf = vdec_msg_queue_dqbuf(&ctx->msg_queue.lat_ctx); + if (!lat_buf) { + mtk_vcodec_err(instance, "failed to get AV1 lat buf\n"); + return -EAGAIN; + } + pfc = (struct vdec_av1_slice_pfc *)lat_buf->private_data; + if (!pfc) { + ret = -EINVAL; + goto err_free_fb_out; + } + vsi = &pfc->vsi; + + ret = vdec_av1_slice_setup_lat(instance, bs, lat_buf, pfc); + if (ret) { + mtk_vcodec_err(instance, "failed to setup AV1 lat ret %d\n", ret); + goto err_free_fb_out; + } + + vdec_av1_slice_vsi_to_remote(vsi, instance->vsi); + ret = vpu_dec_start(&instance->vpu, NULL, 0); + if (ret) { + mtk_vcodec_err(instance, "failed to dec AV1 ret %d\n", ret); + goto err_free_fb_out; + } + if (instance->inneracing_mode) + vdec_msg_queue_qbuf(&ctx->msg_queue.core_ctx, lat_buf); + + if (instance->irq_enabled) { + ret = mtk_vcodec_wait_for_done_ctx(ctx, MTK_INST_IRQ_RECEIVED, + WAIT_INTR_TIMEOUT_MS, + MTK_VDEC_LAT0); + /* update remote vsi if decode timeout */ + if (ret) { + mtk_vcodec_err(instance, "AV1 Frame %d decode timeout %d\n", pfc->seq, ret); + WRITE_ONCE(instance->vsi->state.timeout, 1); + } + vpu_dec_end(&instance->vpu); + } + + vdec_av1_slice_vsi_from_remote(vsi, instance->vsi); + ret = vdec_av1_slice_update_lat(instance, lat_buf, pfc); + + /* LAT trans full, re-decode */ + if (ret == -EAGAIN) { + mtk_vcodec_err(instance, "AV1 Frame %d trans full\n", pfc->seq); + if (!instance->inneracing_mode) + vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf); + return 0; + } + + /* LAT trans full, no more UBE or decode timeout */ + if (ret == -ENOMEM || vsi->state.timeout) { + mtk_vcodec_err(instance, "AV1 Frame %d insufficient buffer or timeout\n", pfc->seq); + if (!instance->inneracing_mode) + vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf); + return -EBUSY; + } + vsi->trans.dma_addr_end += ctx->msg_queue.wdma_addr.dma_addr; + mtk_vcodec_debug(instance, "lat dma 1 0x%pad 0x%pad\n", + &pfc->vsi.trans.dma_addr, &pfc->vsi.trans.dma_addr_end); + + vdec_msg_queue_update_ube_wptr(&ctx->msg_queue, vsi->trans.dma_addr_end); + + if (!instance->inneracing_mode) + vdec_msg_queue_qbuf(&ctx->msg_queue.core_ctx, lat_buf); + memcpy(&instance->slots, &vsi->slots, sizeof(instance->slots)); + + return 0; + +err_free_fb_out: + vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf); + + if (pfc) + mtk_vcodec_err(instance, "slice dec number: %d err: %d", pfc->seq, ret); + + return ret; +} + +static int vdec_av1_slice_core_decode(struct vdec_lat_buf *lat_buf) +{ + struct vdec_av1_slice_instance *instance; + struct vdec_av1_slice_pfc *pfc; + struct mtk_vcodec_ctx *ctx = NULL; + struct vdec_fb *fb = NULL; + int ret = -EINVAL; + + if (!lat_buf) + return -EINVAL; + + pfc = lat_buf->private_data; + ctx = lat_buf->ctx; + if (!pfc || !ctx) + return -EINVAL; + + instance = ctx->drv_handle; + if (!instance) + goto err; + + fb = ctx->dev->vdec_pdata->get_cap_buffer(ctx); + if (!fb) { + ret = -EBUSY; + goto err; + } + + ret = vdec_av1_slice_setup_core(instance, fb, lat_buf, pfc); + if (ret) { + mtk_vcodec_err(instance, "vdec_av1_slice_setup_core\n"); + goto err; + } + vdec_av1_slice_vsi_to_remote(&pfc->vsi, instance->core_vsi); + ret = vpu_dec_core(&instance->vpu); + if (ret) { + mtk_vcodec_err(instance, "vpu_dec_core\n"); + goto err; + } + + if (instance->irq_enabled) { + ret = mtk_vcodec_wait_for_done_ctx(ctx, MTK_INST_IRQ_RECEIVED, + WAIT_INTR_TIMEOUT_MS, + MTK_VDEC_CORE); + /* update remote vsi if decode timeout */ + if (ret) { + mtk_vcodec_err(instance, "AV1 frame %d core timeout\n", pfc->seq); + WRITE_ONCE(instance->vsi->state.timeout, 1); + } + vpu_dec_core_end(&instance->vpu); + } + + ret = vdec_av1_slice_update_core(instance, lat_buf, pfc); + if (ret) { + mtk_vcodec_err(instance, "vdec_av1_slice_update_core\n"); + goto err; + } + + mtk_vcodec_debug(instance, "core dma_addr_end 0x%pad\n", + &instance->core_vsi->trans.dma_addr_end); + vdec_msg_queue_update_ube_rptr(&ctx->msg_queue, instance->core_vsi->trans.dma_addr_end); + + ctx->dev->vdec_pdata->cap_to_disp(ctx, 0, lat_buf->src_buf_req); + + return 0; + +err: + /* always update read pointer */ + vdec_msg_queue_update_ube_rptr(&ctx->msg_queue, pfc->vsi.trans.dma_addr_end); + + if (fb) + ctx->dev->vdec_pdata->cap_to_disp(ctx, 1, lat_buf->src_buf_req); + + return ret; +} + +const struct vdec_common_if vdec_av1_slice_lat_if = { + .init = vdec_av1_slice_init, + .decode = vdec_av1_slice_lat_decode, + .get_param = vdec_av1_slice_get_param, + .deinit = vdec_av1_slice_deinit, +}; diff --git a/drivers/media/platform/mediatek/vcodec/vdec_drv_if.c b/drivers/media/platform/mediatek/vcodec/vdec_drv_if.c index 0bde1eb04015..06d393174cc2 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec_drv_if.c +++ b/drivers/media/platform/mediatek/vcodec/vdec_drv_if.c @@ -53,6 +53,10 @@ int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc) ctx->dec_if = &vdec_hevc_slice_multi_if; ctx->hw_id = MTK_VDEC_LAT0; break; + case V4L2_PIX_FMT_AV1_FRAME: + ctx->dec_if = &vdec_av1_slice_lat_if; + ctx->hw_id = MTK_VDEC_LAT0; + break; default: return -EINVAL; } diff --git a/drivers/media/platform/mediatek/vcodec/vdec_drv_if.h b/drivers/media/platform/mediatek/vcodec/vdec_drv_if.h index ef3a0762fdc8..a8da6a59a6a5 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec_drv_if.h +++ b/drivers/media/platform/mediatek/vcodec/vdec_drv_if.h @@ -62,6 +62,7 @@ extern const struct vdec_common_if vdec_vp8_slice_if; extern const struct vdec_common_if vdec_vp9_if; extern const struct vdec_common_if vdec_vp9_slice_lat_if; extern const struct vdec_common_if vdec_hevc_slice_multi_if; +extern const struct vdec_common_if vdec_av1_slice_lat_if; /** * vdec_if_init() - initialize decode driver diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c index 66b4175601e3..f555341ae708 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c +++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c @@ -20,6 +20,9 @@ /* the size used to store avc error information */ #define VDEC_ERR_MAP_SZ_AVC (17 * SZ_1K) +#define VDEC_RD_MV_BUFFER_SZ (((SZ_4K * 2304 >> 4) + SZ_1K) << 1) +#define VDEC_LAT_TILE_SZ (64 * V4L2_AV1_MAX_TILE_COUNT) + /* core will read the trans buffer which decoded by lat to decode again. * The trans buffer size of FHD and 4K bitstreams are different. */ @@ -219,6 +222,14 @@ void vdec_msg_queue_deinit(struct vdec_msg_queue *msg_queue, if (mem->va) mtk_vcodec_mem_free(ctx, mem); + mem = &lat_buf->rd_mv_addr; + if (mem->va) + mtk_vcodec_mem_free(ctx, mem); + + mem = &lat_buf->tile_addr; + if (mem->va) + mtk_vcodec_mem_free(ctx, mem); + kfree(lat_buf->private_data); } @@ -321,6 +332,22 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue, goto mem_alloc_err; } + if (ctx->current_codec == V4L2_PIX_FMT_AV1_FRAME) { + lat_buf->rd_mv_addr.size = VDEC_RD_MV_BUFFER_SZ; + err = mtk_vcodec_mem_alloc(ctx, &lat_buf->rd_mv_addr); + if (err) { + mtk_v4l2_err("failed to allocate rd_mv_addr buf[%d]", i); + return -ENOMEM; + } + + lat_buf->tile_addr.size = VDEC_LAT_TILE_SZ; + err = mtk_vcodec_mem_alloc(ctx, &lat_buf->tile_addr); + if (err) { + mtk_v4l2_err("failed to allocate tile_addr buf[%d]", i); + return -ENOMEM; + } + } + lat_buf->private_data = kzalloc(private_size, GFP_KERNEL); if (!lat_buf->private_data) { err = -ENOMEM; diff --git a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h index 8f771874f8e6..2a745e902ad1 100644 --- a/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h +++ b/drivers/media/platform/mediatek/vcodec/vdec_msg_queue.h @@ -54,6 +54,8 @@ struct vdec_msg_queue_ctx { * struct vdec_lat_buf - lat buffer message used to store lat info for core decode * @wdma_err_addr: wdma error address used for lat hardware * @slice_bc_addr: slice bc address used for lat hardware + * @rd_mv_addr: mv addr for av1 lat hardware output, core hardware input + * @tile_addr: tile buffer for av1 core input * @ts_info: need to set timestamp from output to capture * @src_buf_req: output buffer media request object * @@ -68,6 +70,8 @@ struct vdec_msg_queue_ctx { struct vdec_lat_buf { struct mtk_vcodec_mem wdma_err_addr; struct mtk_vcodec_mem slice_bc_addr; + struct mtk_vcodec_mem rd_mv_addr; + struct mtk_vcodec_mem tile_addr; struct vb2_v4l2_buffer ts_info; struct media_request *src_buf_req; From 7866e124394d2c0e8e57b29d8c62ef362896c705 Mon Sep 17 00:00:00 2001 From: Yunfei Dong Date: Tue, 30 May 2023 20:29:01 +0800 Subject: [PATCH 241/253] media: mediatek: vcodec: Add debugfs interface to get debug information This will be useful when debugging specific issues related to kernel in running status. Signed-off-by: Yunfei Dong Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/mediatek/vcodec/Makefile | 6 ++++ .../mediatek/vcodec/mtk_vcodec_dbgfs.c | 33 +++++++++++++++++++ .../mediatek/vcodec/mtk_vcodec_dbgfs.h | 32 ++++++++++++++++++ .../mediatek/vcodec/mtk_vcodec_dec_drv.c | 2 ++ .../platform/mediatek/vcodec/mtk_vcodec_drv.h | 4 +++ 5 files changed, 77 insertions(+) create mode 100644 drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c create mode 100644 drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h diff --git a/drivers/media/platform/mediatek/vcodec/Makefile b/drivers/media/platform/mediatek/vcodec/Makefile index d719cfaf83ad..5f4c30fec85a 100644 --- a/drivers/media/platform/mediatek/vcodec/Makefile +++ b/drivers/media/platform/mediatek/vcodec/Makefile @@ -46,3 +46,9 @@ endif ifneq ($(CONFIG_VIDEO_MEDIATEK_VCODEC_SCP),) mtk-vcodec-common-y += mtk_vcodec_fw_scp.o endif + +ifneq ($(CONFIG_DEBUG_FS),) +obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-dbgfs.o + +mtk-vcodec-dbgfs-y := mtk_vcodec_dbgfs.o +endif \ No newline at end of file diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c new file mode 100644 index 000000000000..fb9edd379af5 --- /dev/null +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 MediaTek Inc. + * Author: Yunfei Dong + */ + +#include + +#include "mtk_vcodec_dbgfs.h" +#include "mtk_vcodec_drv.h" +#include "mtk_vcodec_util.h" + +void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev) +{ + struct dentry *vcodec_root; + + vcodec_dev->dbgfs.vcodec_root = debugfs_create_dir("vcodec-dec", NULL); + if (IS_ERR(vcodec_dev->dbgfs.vcodec_root)) + dev_err(&vcodec_dev->plat_dev->dev, "create vcodec dir err:%d\n", + IS_ERR(vcodec_dev->dbgfs.vcodec_root)); + + vcodec_root = vcodec_dev->dbgfs.vcodec_root; +} +EXPORT_SYMBOL_GPL(mtk_vcodec_dbgfs_init); + +void mtk_vcodec_dbgfs_deinit(struct mtk_vcodec_dev *vcodec_dev) +{ + debugfs_remove_recursive(vcodec_dev->dbgfs.vcodec_root); +} +EXPORT_SYMBOL_GPL(mtk_vcodec_dbgfs_deinit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Mediatek video codec driver"); diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h new file mode 100644 index 000000000000..5eec2211cbbe --- /dev/null +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023 MediaTek Inc. + * Author: Yunfei Dong + */ + +#ifndef __MTK_VCODEC_DBGFS_H__ +#define __MTK_VCODEC_DBGFS_H__ + +struct mtk_vcodec_dev; + +/** + * struct mtk_vcodec_dbgfs - dbgfs information + * @vcodec_root: vcodec dbgfs entry + */ +struct mtk_vcodec_dbgfs { + struct dentry *vcodec_root; +}; + +#if defined(CONFIG_DEBUG_FS) +void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev); +void mtk_vcodec_dbgfs_deinit(struct mtk_vcodec_dev *vcodec_dev); +#else +static inline void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev) +{ +} + +static inline void mtk_vcodec_dbgfs_deinit(struct mtk_vcodec_dev *vcodec_dev) +{ +} +#endif +#endif diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c index 7bd300341cf0..51a9af193f92 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c @@ -422,6 +422,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev) mtk_v4l2_debug(0, "media registered as /dev/media%d", vfd_dec->minor); } + mtk_vcodec_dbgfs_init(dev); mtk_v4l2_debug(0, "decoder registered as /dev/video%d", vfd_dec->minor); return 0; @@ -497,6 +498,7 @@ static void mtk_vcodec_dec_remove(struct platform_device *pdev) if (dev->vfd_dec) video_unregister_device(dev->vfd_dec); + mtk_vcodec_dbgfs_deinit(dev); v4l2_device_unregister(&dev->v4l2_dev); if (!dev->vdec_pdata->is_subdev_supported) pm_runtime_disable(dev->pm.dev); diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h index 94404624970a..f17d67e781c9 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_drv.h @@ -16,6 +16,7 @@ #include #include +#include "mtk_vcodec_dbgfs.h" #include "mtk_vcodec_util.h" #include "vdec_msg_queue.h" @@ -471,6 +472,7 @@ struct mtk_vcodec_enc_pdata { * @dec_active_cnt: used to mark whether need to record register value * @vdec_racing_info: record register value * @dec_racing_info_mutex: mutex lock used for inner racing mode + * @dbgfs: debug log related information */ struct mtk_vcodec_dev { struct v4l2_device v4l2_dev; @@ -520,6 +522,8 @@ struct mtk_vcodec_dev { u32 vdec_racing_info[132]; /* Protects access to vdec_racing_info data */ struct mutex dec_racing_info_mutex; + + struct mtk_vcodec_dbgfs dbgfs; }; static inline struct mtk_vcodec_ctx *fh_to_ctx(struct v4l2_fh *fh) From 404500ba8009ae8fa29edbb871b9bc2591b39c76 Mon Sep 17 00:00:00 2001 From: Yunfei Dong Date: Tue, 30 May 2023 20:29:02 +0800 Subject: [PATCH 242/253] media: mediatek: vcodec: Add debug params to control different log level Add parameter mtk_vcodec_dbg to open each codec log. Add parameter mtk_v4l2_dbg_level to open each instance log according to the parameter value. Signed-off-by: Yunfei Dong Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Hans Verkuil [hverkuil: add () around 'level' in macro] Signed-off-by: Mauro Carvalho Chehab --- .../mediatek/vcodec/mtk_vcodec_dbgfs.c | 2 ++ .../mediatek/vcodec/mtk_vcodec_util.c | 8 ++++++ .../mediatek/vcodec/mtk_vcodec_util.h | 26 ++++++++++++++++--- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c index fb9edd379af5..b5093e4e4aa2 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c @@ -20,6 +20,8 @@ void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev) IS_ERR(vcodec_dev->dbgfs.vcodec_root)); vcodec_root = vcodec_dev->dbgfs.vcodec_root; + debugfs_create_x32("mtk_v4l2_dbg_level", 0644, vcodec_root, &mtk_v4l2_dbg_level); + debugfs_create_x32("mtk_vcodec_dbg", 0644, vcodec_root, &mtk_vcodec_dbg); } EXPORT_SYMBOL_GPL(mtk_vcodec_dbgfs_init); diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.c index ace78c4b5b9e..f214e6f67005 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.c @@ -13,6 +13,14 @@ #include "mtk_vcodec_drv.h" #include "mtk_vcodec_util.h" +#if defined(CONFIG_DEBUG_FS) +int mtk_vcodec_dbg; +EXPORT_SYMBOL(mtk_vcodec_dbg); + +int mtk_v4l2_dbg_level; +EXPORT_SYMBOL(mtk_v4l2_dbg_level); +#endif + void __iomem *mtk_vcodec_get_reg_addr(struct mtk_vcodec_ctx *data, unsigned int reg_idx) { diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.h b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.h index 71956627a0e2..88d389b65f13 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.h +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_util.h @@ -35,15 +35,35 @@ struct mtk_vcodec_dev; pr_err("[MTK_VCODEC][ERROR][%d]: " fmt "\n", \ ((struct mtk_vcodec_ctx *)(h)->ctx)->id, ##args) +#if defined(CONFIG_DEBUG_FS) +extern int mtk_v4l2_dbg_level; +extern int mtk_vcodec_dbg; +#define mtk_v4l2_debug(level, fmt, args...) \ + do { \ + if (mtk_v4l2_dbg_level >= (level)) \ + pr_debug("[MTK_V4L2] %s, %d: " fmt "\n", \ + __func__, __LINE__, ##args); \ + } while (0) + +#define mtk_vcodec_debug(h, fmt, args...) \ + do { \ + if (mtk_vcodec_dbg) \ + dev_dbg(&(((struct mtk_vcodec_ctx *)(h)->ctx)->dev->plat_dev->dev), \ + "[MTK_VCODEC][%d]: %s, %d " fmt "\n", \ + ((struct mtk_vcodec_ctx *)(h)->ctx)->id, \ + __func__, __LINE__, ##args); \ + } while (0) +#else #define mtk_v4l2_debug(level, fmt, args...) pr_debug(fmt, ##args) -#define mtk_v4l2_debug_enter() mtk_v4l2_debug(3, "+") -#define mtk_v4l2_debug_leave() mtk_v4l2_debug(3, "-") - #define mtk_vcodec_debug(h, fmt, args...) \ pr_debug("[MTK_VCODEC][%d]: " fmt "\n", \ ((struct mtk_vcodec_ctx *)(h)->ctx)->id, ##args) +#endif + +#define mtk_v4l2_debug_enter() mtk_v4l2_debug(3, "+") +#define mtk_v4l2_debug_leave() mtk_v4l2_debug(3, "-") #define mtk_vcodec_debug_enter(h) mtk_vcodec_debug(h, "+") #define mtk_vcodec_debug_leave(h) mtk_vcodec_debug(h, "-") From 5e488a4fd8595817e74b255d33868e03f57ad16f Mon Sep 17 00:00:00 2001 From: Yunfei Dong Date: Tue, 30 May 2023 20:29:03 +0800 Subject: [PATCH 243/253] media: mediatek: vcodec: Add a debugfs file to get different useful information In oder to get each instance information according to test command, adding one file node "vdec". Can use echo command to set different string value as 'echo -picinfo > vdec'. Signed-off-by: Yunfei Dong Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Hans Verkuil [hverkuil: drop unwanted dbgfs_inst NULL ptr check in mtk_vcodec_dbgfs_remove] Signed-off-by: Mauro Carvalho Chehab --- .../mediatek/vcodec/mtk_vcodec_dbgfs.c | 63 +++++++++++++++++++ .../mediatek/vcodec/mtk_vcodec_dbgfs.h | 33 ++++++++++ .../mediatek/vcodec/mtk_vcodec_dec_drv.c | 2 + 3 files changed, 98 insertions(+) diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c index b5093e4e4aa2..b0ce117378b0 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c @@ -10,6 +10,63 @@ #include "mtk_vcodec_drv.h" #include "mtk_vcodec_util.h" +static ssize_t mtk_vdec_dbgfs_write(struct file *filp, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct mtk_vcodec_dev *vcodec_dev = filp->private_data; + struct mtk_vcodec_dbgfs *dbgfs = &vcodec_dev->dbgfs; + + mutex_lock(&dbgfs->dbgfs_lock); + dbgfs->buf_size = simple_write_to_buffer(dbgfs->dbgfs_buf, sizeof(dbgfs->dbgfs_buf), + ppos, ubuf, count); + mutex_unlock(&dbgfs->dbgfs_lock); + if (dbgfs->buf_size > 0) + return count; + + return dbgfs->buf_size; +} + +static const struct file_operations vdec_fops = { + .open = simple_open, + .write = mtk_vdec_dbgfs_write, +}; + +void mtk_vcodec_dbgfs_create(struct mtk_vcodec_ctx *ctx) +{ + struct mtk_vcodec_dbgfs_inst *dbgfs_inst; + struct mtk_vcodec_dev *vcodec_dev = ctx->dev; + + dbgfs_inst = kzalloc(sizeof(*dbgfs_inst), GFP_KERNEL); + if (!dbgfs_inst) + return; + + list_add_tail(&dbgfs_inst->node, &vcodec_dev->dbgfs.dbgfs_head); + + vcodec_dev->dbgfs.inst_count++; + + dbgfs_inst->inst_id = ctx->id; + dbgfs_inst->vcodec_ctx = ctx; +} +EXPORT_SYMBOL_GPL(mtk_vcodec_dbgfs_create); + +void mtk_vcodec_dbgfs_remove(struct mtk_vcodec_dev *vcodec_dev, int ctx_id) +{ + struct mtk_vcodec_dbgfs_inst *dbgfs_inst; + + list_for_each_entry(dbgfs_inst, &vcodec_dev->dbgfs.dbgfs_head, node) { + if (dbgfs_inst->inst_id == ctx_id) { + vcodec_dev->dbgfs.inst_count--; + break; + } + } + + if (dbgfs_inst) { + list_del(&dbgfs_inst->node); + kfree(dbgfs_inst); + } +} +EXPORT_SYMBOL_GPL(mtk_vcodec_dbgfs_remove); + void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev) { struct dentry *vcodec_root; @@ -22,6 +79,12 @@ void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev) vcodec_root = vcodec_dev->dbgfs.vcodec_root; debugfs_create_x32("mtk_v4l2_dbg_level", 0644, vcodec_root, &mtk_v4l2_dbg_level); debugfs_create_x32("mtk_vcodec_dbg", 0644, vcodec_root, &mtk_vcodec_dbg); + + vcodec_dev->dbgfs.inst_count = 0; + + INIT_LIST_HEAD(&vcodec_dev->dbgfs.dbgfs_head); + debugfs_create_file("vdec", 0200, vcodec_root, vcodec_dev, &vdec_fops); + mutex_init(&vcodec_dev->dbgfs.dbgfs_lock); } EXPORT_SYMBOL_GPL(mtk_vcodec_dbgfs_init); diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h index 5eec2211cbbe..a563e656f42e 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h @@ -8,19 +8,52 @@ #define __MTK_VCODEC_DBGFS_H__ struct mtk_vcodec_dev; +struct mtk_vcodec_ctx; + +/** + * struct mtk_vcodec_dbgfs_inst - debugfs information for each inst + * @node: list node for each inst + * @vcodec_ctx: struct mtk_vcodec_ctx + * @inst_id: index of the context that the same with ctx->id + */ +struct mtk_vcodec_dbgfs_inst { + struct list_head node; + struct mtk_vcodec_ctx *vcodec_ctx; + int inst_id; +}; /** * struct mtk_vcodec_dbgfs - dbgfs information + * @dbgfs_head: list head used to link each instance * @vcodec_root: vcodec dbgfs entry + * @dbgfs_lock: dbgfs lock used to protect dbgfs_buf + * @dbgfs_buf: dbgfs buf used to store dbgfs cmd + * @buf_size: buffer size of dbgfs + * @inst_count: the count of total instance */ struct mtk_vcodec_dbgfs { + struct list_head dbgfs_head; struct dentry *vcodec_root; + struct mutex dbgfs_lock; + char dbgfs_buf[1024]; + int buf_size; + int inst_count; }; #if defined(CONFIG_DEBUG_FS) +void mtk_vcodec_dbgfs_create(struct mtk_vcodec_ctx *ctx); +void mtk_vcodec_dbgfs_remove(struct mtk_vcodec_dev *vcodec_dev, int ctx_id); void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev); void mtk_vcodec_dbgfs_deinit(struct mtk_vcodec_dev *vcodec_dev); #else +static inline void mtk_vcodec_dbgfs_create(struct mtk_vcodec_ctx *ctx) +{ +} + +static inline void mtk_vcodec_dbgfs_remove(struct mtk_vcodec_dev *vcodec_dev, int ctx_id) +{ +} + static inline void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev) { } diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c index 51a9af193f92..b25943ac3909 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c @@ -215,6 +215,7 @@ static int fops_vcodec_open(struct file *file) ctx->dev->vdec_pdata->init_vdec_params(ctx); list_add(&ctx->list, &dev->ctx_list); + mtk_vcodec_dbgfs_create(ctx); mutex_unlock(&dev->dev_mutex); mtk_v4l2_debug(0, "%s decoder [%d]", dev_name(&dev->plat_dev->dev), @@ -256,6 +257,7 @@ static int fops_vcodec_release(struct file *file) v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->ctrl_hdl); + mtk_vcodec_dbgfs_remove(dev, ctx->id); list_del_init(&ctx->list); kfree(ctx); mutex_unlock(&dev->dev_mutex); From 07b7e505ff13f6c8493291bc0b24c6303a6b224f Mon Sep 17 00:00:00 2001 From: Yunfei Dong Date: Tue, 30 May 2023 20:29:04 +0800 Subject: [PATCH 244/253] media: mediatek: vcodec: Get each context resolution information Will store the string to temp buffer like "echo -picinfo > vdec" when user want to get needed information. Then getting debug information using command 'cat vdec' calling mtk_vdec_dbgfs_read to analysis the temp buffer. Signed-off-by: Yunfei Dong Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../mediatek/vcodec/mtk_vcodec_dbgfs.c | 42 +++++++++++++++++++ .../mediatek/vcodec/mtk_vcodec_dbgfs.h | 8 ++++ 2 files changed, 50 insertions(+) diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c index b0ce117378b0..4191a4032f25 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c @@ -26,9 +26,51 @@ static ssize_t mtk_vdec_dbgfs_write(struct file *filp, const char __user *ubuf, return dbgfs->buf_size; } +static ssize_t mtk_vdec_dbgfs_read(struct file *filp, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct mtk_vcodec_dev *vcodec_dev = filp->private_data; + struct mtk_vcodec_dbgfs *dbgfs = &vcodec_dev->dbgfs; + struct mtk_vcodec_dbgfs_inst *dbgfs_inst; + struct mtk_vcodec_ctx *ctx; + int total_len = 200 * (dbgfs->inst_count == 0 ? 1 : dbgfs->inst_count); + int used_len = 0, curr_len, ret; + bool dbgfs_index[MTK_VDEC_DBGFS_MAX] = {0}; + char *buf = kmalloc(total_len, GFP_KERNEL); + + if (!buf) + return -ENOMEM; + + if (strstr(dbgfs->dbgfs_buf, "-picinfo")) + dbgfs_index[MTK_VDEC_DBGFS_PICINFO] = true; + + mutex_lock(&dbgfs->dbgfs_lock); + list_for_each_entry(dbgfs_inst, &dbgfs->dbgfs_head, node) { + ctx = dbgfs_inst->vcodec_ctx; + + curr_len = snprintf(buf + used_len, total_len - used_len, + "inst[%d]:\n ", ctx->id); + used_len += curr_len; + + if (dbgfs_index[MTK_VDEC_DBGFS_PICINFO]) { + curr_len = snprintf(buf + used_len, total_len - used_len, + "\treal(%dx%d)=>align(%dx%d)\n", + ctx->picinfo.pic_w, ctx->picinfo.pic_h, + ctx->picinfo.buf_w, ctx->picinfo.buf_h); + used_len += curr_len; + } + } + mutex_unlock(&dbgfs->dbgfs_lock); + + ret = simple_read_from_buffer(ubuf, count, ppos, buf, used_len); + kfree(buf); + return ret; +} + static const struct file_operations vdec_fops = { .open = simple_open, .write = mtk_vdec_dbgfs_write, + .read = mtk_vdec_dbgfs_read, }; void mtk_vcodec_dbgfs_create(struct mtk_vcodec_ctx *ctx) diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h index a563e656f42e..30d956b7227f 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h @@ -10,6 +10,14 @@ struct mtk_vcodec_dev; struct mtk_vcodec_ctx; +/* + * enum mtk_vdec_dbgfs_log_index - used to get different debug information + */ +enum mtk_vdec_dbgfs_log_index { + MTK_VDEC_DBGFS_PICINFO, + MTK_VDEC_DBGFS_MAX, +}; + /** * struct mtk_vcodec_dbgfs_inst - debugfs information for each inst * @node: list node for each inst From 6d5aea131f4d99ec0de79d3bd8e8e15ee05563e4 Mon Sep 17 00:00:00 2001 From: Yunfei Dong Date: Tue, 30 May 2023 20:29:05 +0800 Subject: [PATCH 245/253] media: mediatek: vcodec: Get each instance format type Adding echo command to get capture and output queue format type of each instance:"echo '-format' > vdec", not current hardware supported. Signed-off-by: Yunfei Dong Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../mediatek/vcodec/mtk_vcodec_dbgfs.c | 48 +++++++++++++++++++ .../mediatek/vcodec/mtk_vcodec_dbgfs.h | 1 + 2 files changed, 49 insertions(+) diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c index 4191a4032f25..9ca04eb2a7cb 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c @@ -10,6 +10,48 @@ #include "mtk_vcodec_drv.h" #include "mtk_vcodec_util.h" +static void mtk_vdec_dbgfs_get_format_type(struct mtk_vcodec_ctx *ctx, char *buf, + int *used, int total) +{ + int curr_len; + + switch (ctx->current_codec) { + case V4L2_PIX_FMT_H264_SLICE: + curr_len = snprintf(buf + *used, total - *used, + "\toutput format: h264 slice\n"); + break; + case V4L2_PIX_FMT_VP8_FRAME: + curr_len = snprintf(buf + *used, total - *used, + "\toutput format: vp8 slice\n"); + break; + case V4L2_PIX_FMT_VP9_FRAME: + curr_len = snprintf(buf + *used, total - *used, + "\toutput format: vp9 slice\n"); + break; + default: + curr_len = snprintf(buf + *used, total - *used, + "\tunsupported output format: 0x%x\n", + ctx->current_codec); + } + *used += curr_len; + + switch (ctx->capture_fourcc) { + case V4L2_PIX_FMT_MM21: + curr_len = snprintf(buf + *used, total - *used, + "\tcapture format: MM21\n"); + break; + case V4L2_PIX_FMT_MT21C: + curr_len = snprintf(buf + *used, total - *used, + "\tcapture format: MT21C\n"); + break; + default: + curr_len = snprintf(buf + *used, total - *used, + "\tunsupported capture format: 0x%x\n", + ctx->capture_fourcc); + } + *used += curr_len; +} + static ssize_t mtk_vdec_dbgfs_write(struct file *filp, const char __user *ubuf, size_t count, loff_t *ppos) { @@ -44,6 +86,9 @@ static ssize_t mtk_vdec_dbgfs_read(struct file *filp, char __user *ubuf, if (strstr(dbgfs->dbgfs_buf, "-picinfo")) dbgfs_index[MTK_VDEC_DBGFS_PICINFO] = true; + if (strstr(dbgfs->dbgfs_buf, "-format")) + dbgfs_index[MTK_VDEC_DBGFS_FORMAT] = true; + mutex_lock(&dbgfs->dbgfs_lock); list_for_each_entry(dbgfs_inst, &dbgfs->dbgfs_head, node) { ctx = dbgfs_inst->vcodec_ctx; @@ -59,6 +104,9 @@ static ssize_t mtk_vdec_dbgfs_read(struct file *filp, char __user *ubuf, ctx->picinfo.buf_w, ctx->picinfo.buf_h); used_len += curr_len; } + + if (dbgfs_index[MTK_VDEC_DBGFS_FORMAT]) + mtk_vdec_dbgfs_get_format_type(ctx, buf, &used_len, total_len); } mutex_unlock(&dbgfs->dbgfs_lock); diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h index 30d956b7227f..6fcb20cfcd91 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h @@ -15,6 +15,7 @@ struct mtk_vcodec_ctx; */ enum mtk_vdec_dbgfs_log_index { MTK_VDEC_DBGFS_PICINFO, + MTK_VDEC_DBGFS_FORMAT, MTK_VDEC_DBGFS_MAX, }; From 5910584b560b7db374d00d65ba608eb0b156eb11 Mon Sep 17 00:00:00 2001 From: Yunfei Dong Date: Tue, 30 May 2023 20:29:06 +0800 Subject: [PATCH 246/253] media: mediatek: vcodec: Change dbgfs interface to support encode Extend dbgfs init interface to support encode and create encode dbgfs file. Signed-off-by: Yunfei Dong Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c | 9 +++++++-- .../media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h | 4 ++-- .../media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c index 9ca04eb2a7cb..eee82ebeeabd 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c @@ -157,11 +157,14 @@ void mtk_vcodec_dbgfs_remove(struct mtk_vcodec_dev *vcodec_dev, int ctx_id) } EXPORT_SYMBOL_GPL(mtk_vcodec_dbgfs_remove); -void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev) +void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev, bool is_encode) { struct dentry *vcodec_root; - vcodec_dev->dbgfs.vcodec_root = debugfs_create_dir("vcodec-dec", NULL); + if (is_encode) + vcodec_dev->dbgfs.vcodec_root = debugfs_create_dir("vcodec-enc", NULL); + else + vcodec_dev->dbgfs.vcodec_root = debugfs_create_dir("vcodec-dec", NULL); if (IS_ERR(vcodec_dev->dbgfs.vcodec_root)) dev_err(&vcodec_dev->plat_dev->dev, "create vcodec dir err:%d\n", IS_ERR(vcodec_dev->dbgfs.vcodec_root)); @@ -171,6 +174,8 @@ void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev) debugfs_create_x32("mtk_vcodec_dbg", 0644, vcodec_root, &mtk_vcodec_dbg); vcodec_dev->dbgfs.inst_count = 0; + if (is_encode) + return; INIT_LIST_HEAD(&vcodec_dev->dbgfs.dbgfs_head); debugfs_create_file("vdec", 0200, vcodec_root, vcodec_dev, &vdec_fops); diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h index 6fcb20cfcd91..241ff8197e73 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.h @@ -52,7 +52,7 @@ struct mtk_vcodec_dbgfs { #if defined(CONFIG_DEBUG_FS) void mtk_vcodec_dbgfs_create(struct mtk_vcodec_ctx *ctx); void mtk_vcodec_dbgfs_remove(struct mtk_vcodec_dev *vcodec_dev, int ctx_id); -void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev); +void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev, bool is_encode); void mtk_vcodec_dbgfs_deinit(struct mtk_vcodec_dev *vcodec_dev); #else static inline void mtk_vcodec_dbgfs_create(struct mtk_vcodec_ctx *ctx) @@ -63,7 +63,7 @@ static inline void mtk_vcodec_dbgfs_remove(struct mtk_vcodec_dev *vcodec_dev, in { } -static inline void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev) +static inline void mtk_vcodec_dbgfs_init(struct mtk_vcodec_dev *vcodec_dev, bool is_encode) { } diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c index b25943ac3909..d41f2121b94f 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_drv.c @@ -424,7 +424,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev) mtk_v4l2_debug(0, "media registered as /dev/media%d", vfd_dec->minor); } - mtk_vcodec_dbgfs_init(dev); + mtk_vcodec_dbgfs_init(dev, false); mtk_v4l2_debug(0, "decoder registered as /dev/video%d", vfd_dec->minor); return 0; From cc770218226534d921d2adb0819e00014ce471c5 Mon Sep 17 00:00:00 2001 From: Yunfei Dong Date: Tue, 30 May 2023 20:29:07 +0800 Subject: [PATCH 247/253] media: mediatek: vcodec: Add encode to support dbgfs Add encode to support dbgfs. Signed-off-by: Yunfei Dong Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_drv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_drv.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_drv.c index 168004a08888..5df0a22ff3b5 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_drv.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc_drv.c @@ -358,6 +358,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev) goto err_enc_reg; } + mtk_vcodec_dbgfs_init(dev, true); mtk_v4l2_debug(0, "encoder %d registered as /dev/video%d", dev->venc_pdata->core_id, vfd_enc->num); @@ -468,6 +469,7 @@ static void mtk_vcodec_enc_remove(struct platform_device *pdev) if (dev->vfd_enc) video_unregister_device(dev->vfd_enc); + mtk_vcodec_dbgfs_deinit(dev); v4l2_device_unregister(&dev->v4l2_dev); pm_runtime_disable(dev->pm.dev); mtk_vcodec_fw_release(dev->fw_handler); From d78b9d6671decdaedb539635b1d0a34f8f5934f8 Mon Sep 17 00:00:00 2001 From: Yunfei Dong Date: Tue, 30 May 2023 20:29:08 +0800 Subject: [PATCH 248/253] media: mediatek: vcodec: Add dbgfs help function Getting dbgfs help information with command "echo -help > vdec" or "echo > vdec". Signed-off-by: Yunfei Dong Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../mediatek/vcodec/mtk_vcodec_dbgfs.c | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c index eee82ebeeabd..b5cdbbfcc388 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dbgfs.c @@ -52,6 +52,23 @@ static void mtk_vdec_dbgfs_get_format_type(struct mtk_vcodec_ctx *ctx, char *buf *used += curr_len; } +static void mtk_vdec_dbgfs_get_help(char *buf, int *used, int total) +{ + int curr_len; + + curr_len = snprintf(buf + *used, total - *used, + "help: (1: echo -'info' > vdec 2: cat vdec)\n"); + *used += curr_len; + + curr_len = snprintf(buf + *used, total - *used, + "\t-picinfo: get resolution\n"); + *used += curr_len; + + curr_len = snprintf(buf + *used, total - *used, + "\t-format: get output & capture queue format\n"); + *used += curr_len; +} + static ssize_t mtk_vdec_dbgfs_write(struct file *filp, const char __user *ubuf, size_t count, loff_t *ppos) { @@ -83,6 +100,11 @@ static ssize_t mtk_vdec_dbgfs_read(struct file *filp, char __user *ubuf, if (!buf) return -ENOMEM; + if (strstr(dbgfs->dbgfs_buf, "-help") || dbgfs->buf_size == 1) { + mtk_vdec_dbgfs_get_help(buf, &used_len, total_len); + goto read_buffer; + } + if (strstr(dbgfs->dbgfs_buf, "-picinfo")) dbgfs_index[MTK_VDEC_DBGFS_PICINFO] = true; @@ -109,7 +131,7 @@ static ssize_t mtk_vdec_dbgfs_read(struct file *filp, char __user *ubuf, mtk_vdec_dbgfs_get_format_type(ctx, buf, &used_len, total_len); } mutex_unlock(&dbgfs->dbgfs_lock); - +read_buffer: ret = simple_read_from_buffer(ubuf, count, ppos, buf, used_len); kfree(buf); return ret; From 582d4ad468cbc6ef2db4689ff3bd5868d95402c9 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 23 Jun 2023 17:23:09 +0200 Subject: [PATCH 249/253] media: tc358746: select CONFIG_GENERIC_PHY The tc358746 driver selects CONFIG_GENERIC_PHY_MIPI_DPHY and links to that, but this fails when CONFIG_GENERIC_PHY is disabled, because Kbuild then never enters the drivers/phy directory for building object files: ERROR: modpost: "phy_mipi_dphy_get_default_config_for_hsclk" [drivers/media/i2c/tc358746.ko] undefined! Add an explicit 'select GENERIC_PHY' here to ensure that the directory is entered, and add another dependency on that symbol so make it more obvious what is going on if another driver has the same problem, as this will produce a Kconfig warning. Link: https://lore.kernel.org/linux-media/20230623152318.2276816-1-arnd@kernel.org Fixes: 80a21da360516 ("media: tc358746: add Toshiba TC358746 Parallel to CSI-2 bridge driver") Signed-off-by: Arnd Bergmann Reviewed-by: Marco Felsch Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/Kconfig | 1 + drivers/phy/Kconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index cf675ac4b132..226454b6a90d 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -1305,6 +1305,7 @@ config VIDEO_TC358746 select VIDEO_V4L2_SUBDEV_API select MEDIA_CONTROLLER select V4L2_FWNODE + select GENERIC_PHY select GENERIC_PHY_MIPI_DPHY select REGMAP_I2C help diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index f46e3148d286..8dba9596408f 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -18,6 +18,7 @@ config GENERIC_PHY config GENERIC_PHY_MIPI_DPHY bool + depends on GENERIC_PHY help Generic MIPI D-PHY support. From 7997604bc90bbb367396dd406ecb50645ab406ef Mon Sep 17 00:00:00 2001 From: Niklas Schnelle Date: Mon, 22 May 2023 12:50:23 +0200 Subject: [PATCH 250/253] media: add HAS_IOPORT dependencies In a future patch HAS_IOPORT=n will result in inb()/outb() and friends not being declared. We thus need to add HAS_IOPORT as dependency for those drivers using them. Link: https://lore.kernel.org/linux-media/20230522105049.1467313-19-schnelle@linux.ibm.com Reviewed-by: Sean Young # media/rc Co-developed-by: Arnd Bergmann Signed-off-by: Arnd Bergmann Signed-off-by: Niklas Schnelle Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/dm1105/Kconfig | 2 +- drivers/media/radio/Kconfig | 14 +++++++++++++- drivers/media/rc/Kconfig | 6 ++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/dm1105/Kconfig b/drivers/media/pci/dm1105/Kconfig index e0e3af67c99c..4498c37f4990 100644 --- a/drivers/media/pci/dm1105/Kconfig +++ b/drivers/media/pci/dm1105/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only config DVB_DM1105 tristate "SDMC DM1105 based PCI cards" - depends on DVB_CORE && PCI && I2C && I2C_ALGOBIT + depends on DVB_CORE && PCI && I2C && I2C_ALGOBIT && HAS_IOPORT select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 616a38feb641..d52eccdc7eb9 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -15,7 +15,7 @@ if RADIO_ADAPTERS config RADIO_MAXIRADIO tristate "Guillemot MAXI Radio FM 2000 radio" - depends on PCI + depends on PCI && HAS_IOPORT select RADIO_TEA575X help Choose Y here if you have this radio card. This card may also be @@ -232,6 +232,7 @@ source "drivers/media/radio/wl128x/Kconfig" menuconfig V4L_RADIO_ISA_DRIVERS bool "ISA radio devices" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT help Say Y here to enable support for these ISA drivers. @@ -240,6 +241,7 @@ if V4L_RADIO_ISA_DRIVERS config RADIO_AZTECH tristate "Aztech/Packard Bell Radio" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT select RADIO_ISA help Choose Y here if you have one of these FM radio cards, and then fill @@ -260,6 +262,7 @@ config RADIO_AZTECH_PORT config RADIO_CADET tristate "ADS Cadet AM/FM Tuner" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT help Choose Y here if you have one of these AM/FM radio cards, and then fill in the port address below. @@ -270,6 +273,7 @@ config RADIO_CADET config RADIO_GEMTEK tristate "GemTek Radio card (or compatible) support" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT select RADIO_ISA help Choose Y here if you have this FM radio card, and then fill in the @@ -309,6 +313,7 @@ config RADIO_GEMTEK_PROBE config RADIO_ISA depends on ISA || COMPILE_TEST + depends on HAS_IOPORT tristate config RADIO_MIROPCM20 @@ -329,6 +334,7 @@ config RADIO_MIROPCM20 config RADIO_RTRACK tristate "AIMSlab RadioTrack (aka RadioReveal) support" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT select RADIO_ISA help Choose Y here if you have one of these FM radio cards, and then fill @@ -383,6 +389,7 @@ config RADIO_RTRACK_PORT config RADIO_SF16FMI tristate "SF16-FMI/SF16-FMP/SF16-FMD Radio" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT help Choose Y here if you have one of these FM radio cards. @@ -392,6 +399,7 @@ config RADIO_SF16FMI config RADIO_SF16FMR2 tristate "SF16-FMR2/SF16-FMD2 Radio" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT select RADIO_TEA575X help Choose Y here if you have one of these FM radio cards. @@ -402,6 +410,7 @@ config RADIO_SF16FMR2 config RADIO_TERRATEC tristate "TerraTec ActiveRadio ISA Standalone" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT select RADIO_ISA help Choose Y here if you have this FM radio card. @@ -416,6 +425,7 @@ config RADIO_TERRATEC config RADIO_TRUST tristate "Trust FM radio card" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT select RADIO_ISA help This is a driver for the Trust FM radio cards. Say Y if you have @@ -439,6 +449,7 @@ config RADIO_TRUST_PORT config RADIO_TYPHOON tristate "Typhoon Radio (a.k.a. EcoRadio)" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT select RADIO_ISA help Choose Y here if you have one of these FM radio cards, and then fill @@ -473,6 +484,7 @@ config RADIO_TYPHOON_PORT config RADIO_ZOLTRIX tristate "Zoltrix Radio" depends on ISA || COMPILE_TEST + depends on HAS_IOPORT select RADIO_ISA help Choose Y here if you have one of these FM radio cards, and then fill diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index ac4172feb6f9..922c790b577e 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -148,6 +148,7 @@ if RC_DEVICES config IR_ENE tristate "ENE eHome Receiver/Transceiver (pnp id: ENE0100/ENE02xxx)" depends on PNP || COMPILE_TEST + depends on HAS_IOPORT help Say Y here to enable support for integrated infrared receiver /transceiver made by ENE. @@ -161,6 +162,7 @@ config IR_ENE config IR_FINTEK tristate "Fintek Consumer Infrared Transceiver" depends on PNP || COMPILE_TEST + depends on HAS_IOPORT help Say Y here to enable support for integrated infrared receiver /transceiver made by Fintek. This chip is found on assorted @@ -249,6 +251,7 @@ config IR_IMON_RAW config IR_ITE_CIR tristate "ITE Tech Inc. IT8712/IT8512 Consumer Infrared Transceiver" depends on PNP || COMPILE_TEST + depends on HAS_IOPORT help Say Y here to enable support for integrated infrared receivers /transceivers made by ITE Tech Inc. These are found in @@ -301,6 +304,7 @@ config IR_MTK config IR_NUVOTON tristate "Nuvoton w836x7hg Consumer Infrared Transceiver" depends on PNP || COMPILE_TEST + depends on HAS_IOPORT help Say Y here to enable support for integrated infrared receiver /transceiver made by Nuvoton (formerly Winbond). This chip is @@ -345,6 +349,7 @@ config IR_RX51 config IR_SERIAL tristate "Homebrew Serial Port Receiver" + depends on HAS_IOPORT help Say Y if you want to use Homebrew Serial Port Receivers and Transceivers. @@ -412,6 +417,7 @@ config IR_TTUSBIR config IR_WINBOND_CIR tristate "Winbond IR remote control" depends on (X86 && PNP) || COMPILE_TEST + depends on HAS_IOPORT select NEW_LEDS select LEDS_CLASS select BITREVERSE From 29f96ac23648b2259f42d40703c47dd18fd172ca Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 8 Jun 2023 04:54:35 +0200 Subject: [PATCH 251/253] media: cec: i2c: ch7322: also select REGMAP Selecting only REGMAP_I2C can leave REGMAP unset, causing build errors, so also select REGMAP to prevent the build errors. ../drivers/media/cec/i2c/ch7322.c:158:21: error: variable 'ch7322_regmap' has initializer but incomplete type 158 | static const struct regmap_config ch7322_regmap = { ../drivers/media/cec/i2c/ch7322.c:159:10: error: 'const struct regmap_config' has no member named 'reg_bits' 159 | .reg_bits = 8, ../drivers/media/cec/i2c/ch7322.c:159:21: warning: excess elements in struct initializer 159 | .reg_bits = 8, ../drivers/media/cec/i2c/ch7322.c:160:10: error: 'const struct regmap_config' has no member named 'val_bits' 160 | .val_bits = 8, ../drivers/media/cec/i2c/ch7322.c:160:21: warning: excess elements in struct initializer 160 | .val_bits = 8, ../drivers/media/cec/i2c/ch7322.c:161:10: error: 'const struct regmap_config' has no member named 'max_register' 161 | .max_register = 0x7f, ../drivers/media/cec/i2c/ch7322.c:161:25: warning: excess elements in struct initializer 161 | .max_register = 0x7f, ../drivers/media/cec/i2c/ch7322.c:162:10: error: 'const struct regmap_config' has no member named 'disable_locking' 162 | .disable_locking = true, ../drivers/media/cec/i2c/ch7322.c:162:28: warning: excess elements in struct initializer 162 | .disable_locking = true, ../drivers/media/cec/i2c/ch7322.c: In function 'ch7322_probe': ../drivers/media/cec/i2c/ch7322.c:468:26: error: implicit declaration of function 'devm_regmap_init_i2c' [-Werror=implicit-function-declaration] 468 | ch7322->regmap = devm_regmap_init_i2c(client, &ch7322_regmap); ../drivers/media/cec/i2c/ch7322.c:468:24: warning: assignment to 'struct regmap *' from 'int' makes pointer from integer without a cast [-Wint-conversion] 468 | ch7322->regmap = devm_regmap_init_i2c(client, &ch7322_regmap); ../drivers/media/cec/i2c/ch7322.c: At top level: ../drivers/media/cec/i2c/ch7322.c:158:35: error: storage size of 'ch7322_regmap' isn't known 158 | static const struct regmap_config ch7322_regmap = { Link: https://lore.kernel.org/linux-media/20230608025435.29249-1-rdunlap@infradead.org Fixes: 21b9a47e0ec7 ("media: cec: i2c: ch7322: Add ch7322 CEC controller driver") Signed-off-by: Randy Dunlap Cc: Jeff Chase Cc: Hans Verkuil Cc: Joe Tessler Cc: Arnd Bergmann Cc: Mark Brown Cc: Masahiro Yamada Signed-off-by: Mauro Carvalho Chehab --- drivers/media/cec/i2c/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/cec/i2c/Kconfig b/drivers/media/cec/i2c/Kconfig index 70432a1d6918..d912d143fb31 100644 --- a/drivers/media/cec/i2c/Kconfig +++ b/drivers/media/cec/i2c/Kconfig @@ -5,6 +5,7 @@ config CEC_CH7322 tristate "Chrontel CH7322 CEC controller" depends on I2C + select REGMAP select REGMAP_I2C select CEC_CORE help From 190e2e1177010ab9ffccd5f968500099c247e8e5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 28 Jun 2023 15:03:39 +0200 Subject: [PATCH 252/253] media: dvb: mb86a20s: get rid of a clang-15 warning When building with clang-15: this warning is produced: ../drivers/media/dvb-frontends/mb86a20s.c:1572:6: error: variable 'active_layers' set but not used [-Werror,-Wunused-but-set-variable] int active_layers = 0, pre_ber_layers = 0, post_ber_layers = 0; ^ 1 error generated. Link: https://lore.kernel.org/linux-media/20230628130339.206261-1-mchehab@kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/mb86a20s.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c index b74b9afed9a2..125fed4891ba 100644 --- a/drivers/media/dvb-frontends/mb86a20s.c +++ b/drivers/media/dvb-frontends/mb86a20s.c @@ -1569,7 +1569,7 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe, int status_nr) u32 t_post_bit_error = 0, t_post_bit_count = 0; u32 block_error = 0, block_count = 0; u32 t_block_error = 0, t_block_count = 0; - int active_layers = 0, pre_ber_layers = 0, post_ber_layers = 0; + int pre_ber_layers = 0, post_ber_layers = 0; int per_layers = 0; dev_dbg(&state->i2c->dev, "%s called.\n", __func__); @@ -1589,9 +1589,6 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe, int status_nr) for (layer = 0; layer < NUM_LAYERS; layer++) { if (c->isdbt_layer_enabled & (1 << layer)) { - /* Layer is active and has rc segments */ - active_layers++; - /* Handle BER before vterbi */ rc = mb86a20s_get_pre_ber(fe, layer, &bit_error, &bit_count); From c61480a2ea5e5b997d10dfda556d3a63e31f87cd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 28 Jun 2023 21:48:53 +0200 Subject: [PATCH 253/253] media: wl128x: fix a clang warning Clang-16 produces this warning, which is fatal with CONFIG_WERROR: ../drivers/media/radio/wl128x/fmdrv_common.c:1237:19: error: variable 'cmd_cnt' set but not used [-Werror,-Wunused-but-set-variable] int ret, fw_len, cmd_cnt; ^ 1 error generated. What happens is that cmd_cnt tracks the amount of firmware data packets were transfered, which is printed only when debug is used. Switch to use the firmware count, as the message is all about reporting a partial firmware transfer. Link: https://lore.kernel.org/linux-media/6badd27ebfa718d5737f517f18b29a3e0f6e43f8.1687981726.git.mchehab@kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/wl128x/fmdrv_common.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c index cbd49dff6d74..b31b7ed60bbe 100644 --- a/drivers/media/radio/wl128x/fmdrv_common.c +++ b/drivers/media/radio/wl128x/fmdrv_common.c @@ -1234,9 +1234,8 @@ static int fm_download_firmware(struct fmdev *fmdev, const u8 *fw_name) struct bts_action *action; struct bts_action_delay *delay; u8 *fw_data; - int ret, fw_len, cmd_cnt; + int ret, fw_len; - cmd_cnt = 0; set_bit(FM_FW_DW_INPROGRESS, &fmdev->flag); ret = request_firmware(&fw_entry, fw_name, @@ -1272,7 +1271,6 @@ static int fm_download_firmware(struct fmdev *fmdev, const u8 *fw_name) if (ret) goto rel_fw; - cmd_cnt++; break; case ACTION_DELAY: /* Delay */ @@ -1284,7 +1282,7 @@ static int fm_download_firmware(struct fmdev *fmdev, const u8 *fw_name) fw_data += (sizeof(struct bts_action) + (action->size)); fw_len -= (sizeof(struct bts_action) + (action->size)); } - fmdbg("Firmware commands(%d) loaded to chip\n", cmd_cnt); + fmdbg("Transfered only %d of %d bytes of the firmware to chip\n", fw_entry->size - fw_len, fw_entry->size); rel_fw: release_firmware(fw_entry); clear_bit(FM_FW_DW_INPROGRESS, &fmdev->flag);