diff --git a/arch/arm64/configs/vendor/pro1x-perf_defconfig b/arch/arm64/configs/vendor/pro1x-perf_defconfig index 547aae82152f..7dd54b2071bd 100644 --- a/arch/arm64/configs/vendor/pro1x-perf_defconfig +++ b/arch/arm64/configs/vendor/pro1x-perf_defconfig @@ -647,7 +647,6 @@ CONFIG_SQUASHFS_LZ4=y # CONFIG_NETWORK_FILESYSTEMS is not set CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y -CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y CONFIG_SECURITY=y CONFIG_HARDENED_USERCOPY=y CONFIG_HARDENED_USERCOPY_PAGESPAN=y diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 116d4914a799..7ba0d4b5571f 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -1030,7 +1030,7 @@ static int geni_i2c_probe(struct platform_device *pdev) if (of_property_read_u32(pdev->dev.of_node, "qcom,clk-freq-out", &gi2c->i2c_rsc.clk_freq_out)) { - gi2c->i2c_rsc.clk_freq_out = KHz(400); + gi2c->i2c_rsc.clk_freq_out = KHz(100); } dev_info(&pdev->dev, "Bus frequency is set to %dHz\n", gi2c->i2c_rsc.clk_freq_out); diff --git a/drivers/input/fingerprint/madev.c b/drivers/input/fingerprint/madev.c index f5c1f374acdf..b1863d5c7c06 100755 --- a/drivers/input/fingerprint/madev.c +++ b/drivers/input/fingerprint/madev.c @@ -22,16 +22,18 @@ static DECLARE_WAIT_QUEUE_HEAD(screenwaitq); static DECLARE_WAIT_QUEUE_HEAD(gWaitq); static DECLARE_WAIT_QUEUE_HEAD(U1_Waitq); static DECLARE_WAIT_QUEUE_HEAD(U2_Waitq); + #ifdef CONFIG_PM_WAKELOCKS struct wakeup_source *gIntWakeLock = NULL; struct wakeup_source *gProcessWakeLock = NULL; #else struct wake_lock gIntWakeLock; struct wake_lock gProcessWakeLock; -#endif +#endif //CONFIG_PM_WAKELOCKS + struct work_struct gWork; struct workqueue_struct *gWorkq; -// + static LIST_HEAD(dev_list); static DEFINE_MUTEX(dev_lock); static DEFINE_MUTEX(drv_lock); @@ -55,17 +57,17 @@ static void mas_work(struct work_struct *pws) { smas->f_irq = 1; wake_up(&gWaitq); #ifdef COMPATIBLE_VERSION3 - wake_up(&drv_waitq); + wake_up(&drv_waitq); #endif } static irqreturn_t mas_interrupt(int irq, void *dev_id) { #ifdef DOUBLE_EDGE_IRQ - if(mas_get_interrupt_gpio(0)==1){ - //TODO IRQF_TRIGGER_RISING - }else{ - //TODO IRQF_TRIGGER_FALLING - } + if(mas_get_interrupt_gpio(0)==1){ + //TODO IRQF_TRIGGER_RISING + }else{ + //TODO IRQF_TRIGGER_FALLING + } #else printk("mas_interrupt.\n"); #ifdef CONFIG_PM_WAKELOCKS @@ -126,27 +128,6 @@ struct spi_transfer t = { -/* 读数据 - * @return 成功:count, -1count太大,-2通讯失败, -3拷贝失败 - */ -static ssize_t mas_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { - int val, ret = 0; - // MALOGD("start"); - ret = mas_sync(stxb, srxb, count); - if(ret) { - MALOGW("mas_sync failed."); - return -2; - } - ret = copy_to_user(buf, srxb, count); - if(!ret) val = count; - else { - val = -3; - MALOGW("copy_to_user failed."); - } - // MALOGD("end."); - return val; -} - static void mas_set_input(void) { struct input_dev *input = NULL; @@ -200,12 +181,14 @@ static long mas_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { smas->f_irq = 1; wake_up(&gWaitq); break; +#ifndef USE_PLATFORM_DRIVE case ENABLE_CLK: mas_enable_spi_clock(smas->spi); //if the spi clock is not opening always, do this methods break; case DISABLE_CLK: mas_disable_spi_clock(smas->spi); //disable the spi clock break; +#endif case ENABLE_INTERRUPT: enable_irq(irq); //enable the irq,in fact, you can make irq enable always break; @@ -362,10 +345,12 @@ int version3_ioctl(int cmd, int arg){ break; case IOCTL_IRQ_ENABLE: break; + #ifndef USE_PLATFORM_DRIVE case IOCTL_SPI_SPEED: smas->spi->max_speed_hz = (u32) arg; spi_setup(smas->spi); break; + #endif //USE_PLATFORM_DRIVE case IOCTL_COVER_NUM: ret = COVER_NUM; break; @@ -444,13 +429,14 @@ int version3_ioctl(int cmd, int arg){ } #endif +#ifndef USE_PLATFORM_DRIVE /* 写数据 * @return 成功:count, -1count太大,-2拷贝失败 */ static ssize_t mas_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { int val = 0; - // MALOGD("start"); - if(count==6) { //cmd ioctl, old version used the write interface to do ioctl, this is only for the old version + // MALOGD("start"); + if(count==6) { //cmd ioctl, old version used the write interface to do ioctl, this is only for the old version int cmd, arg; u8 tmp[6]; ret = copy_from_user(tmp, buf, count); @@ -464,10 +450,10 @@ static ssize_t mas_write(struct file *filp, const char __user *buf, size_t count arg += tmp[4]; arg <<= 8; arg += tmp[5]; -#ifdef COMPATIBLE_VERSION3 + #ifdef COMPATIBLE_VERSION3 val = (int)version3_ioctl(NULL, (unsigned int)cmd, (unsigned long)arg); -#endif - } else { + #endif + } else { memset(stxb, 0, FBUF); ret = copy_from_user(stxb, buf, count); if(ret) { @@ -477,9 +463,32 @@ static ssize_t mas_write(struct file *filp, const char __user *buf, size_t count val = count; } } - // MALOGD("end"); + // MALOGD("end"); return val; } + +/* 读数据 + * @return 成功:count, -1count太大,-2通讯失败, -3拷贝失败 + */ +static ssize_t mas_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { + int val, ret = 0; + // MALOGD("start"); + ret = mas_sync(stxb, srxb, count); + if(ret) { + MALOGW("mas_sync failed."); + return -2; + } + ret = copy_to_user(buf, srxb, count); + if(!ret) val = count; + else { + val = -3; + MALOGW("copy_to_user failed."); + } + // MALOGD("end."); + return val; +} +#endif + void * kernel_memaddr = NULL; unsigned long kernel_memesize = 0; @@ -526,8 +535,10 @@ static unsigned int mas_poll(struct file *filp, struct poll_table_struct *wait) /*---------------------------------- fops ------------------------------------*/ static const struct file_operations sfops = { .owner = THIS_MODULE, +#ifndef USE_PLATFORM_DRIVE .write = mas_write, .read = mas_read, +#endif .unlocked_ioctl = mas_ioctl, .mmap = mas_mmap, //.ioctl = mas_ioctl, @@ -543,56 +554,64 @@ static const struct file_operations sfops = { static int init_file_node(void) { - int ret; - //MALOGF("start"); - ret = alloc_chrdev_region(&sdev->idd, 0, 1, MA_CHR_DEV_NAME); - if(ret < 0) - { - MALOGW("alloc_chrdev_region error!"); - return -1; - } - sdev->chd = cdev_alloc(); - if (!sdev->chd) - { - MALOGW("cdev_alloc error!"); - return -1; - } - sdev->chd->owner = THIS_MODULE; - sdev->chd->ops = &sfops; - cdev_add(sdev->chd, sdev->idd, 1); - sdev->cls = class_create(THIS_MODULE, MA_CHR_DEV_NAME); - if (IS_ERR(sdev->cls)) { - MALOGE("class_create"); - return -1; - } - sdev->dev = device_create(sdev->cls, NULL, sdev->idd, NULL, MA_CHR_FILE_NAME); - ret = IS_ERR(sdev->dev) ? PTR_ERR(sdev->dev) : 0; - if(ret){ - MALOGE("device_create"); - } - //MALOGF("end"); - return 0; + int ret; + //MALOGF("start"); + ret = alloc_chrdev_region(&sdev->idd, 0, 1, MA_CHR_DEV_NAME); + if(ret < 0) + { + MALOGW("alloc_chrdev_region error!"); + return -1; + } + + sdev->chd = cdev_alloc(); + if (!sdev->chd) + { + MALOGW("cdev_alloc error!"); + return -1; + } + + sdev->chd->owner = THIS_MODULE; + sdev->chd->ops = &sfops; + + cdev_add(sdev->chd, sdev->idd, 1); + + sdev->cls = class_create(THIS_MODULE, MA_CHR_DEV_NAME); + if (IS_ERR(sdev->cls)) { + MALOGE("class_create"); + return -1; + } + + sdev->dev = device_create(sdev->cls, NULL, sdev->idd, NULL, MA_CHR_FILE_NAME); + ret = IS_ERR(sdev->dev) ? PTR_ERR(sdev->dev) : 0; + if(ret){ + MALOGE("device_create"); + } + //MALOGF("end"); + return 0; } static int deinit_file_node(void) { - cdev_del(sdev->chd); - sdev->chd = NULL; - kfree(sdev->chd); - device_destroy(sdev->cls, sdev->idd); - unregister_chrdev_region(sdev->idd, 1); - class_destroy(sdev->cls); + cdev_del(sdev->chd); + sdev->chd = NULL; + kfree(sdev->chd); + device_destroy(sdev->cls, sdev->idd); + unregister_chrdev_region(sdev->idd, 1); + class_destroy(sdev->cls); return 0; } static int init_interrupt(void) { const char*tname = MA_EINT_NAME; + int ret = 0; + irq = mas_get_irq(); if(irq<=0){ ret = irq; MALOGE("mas_get_irq"); } + #ifdef DOUBLE_EDGE_IRQ ret = request_irq(irq, mas_interrupt, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, tname, NULL); #else @@ -601,23 +620,25 @@ static int init_interrupt(void) if(ret<0){ MALOGE("request_irq"); } + return ret; } + + static int deinit_interrupt(void) { - if(irq) + if(irq) {disable_irq(irq); - free_irq(irq, NULL); + free_irq(irq, NULL); } return 0; } + static int init_vars(void) { sdev = kmalloc(sizeof(struct fprint_dev), GFP_KERNEL); smas = kmalloc(sizeof(struct fprint_spi), GFP_KERNEL); - stxb = kmalloc(FBUF, GFP_KERNEL); - srxb = kmalloc(FBUF, GFP_KERNEL); if (sdev==NULL || smas==NULL ) { MALOGW("smas kmalloc failed."); if(sdev!=NULL) kfree(sdev); @@ -625,10 +646,15 @@ static int init_vars(void) return -ENOMEM; } - printk("[%s][%d]smas %p \r\n",__func__,__LINE__, smas); - printk("[%s][%d]sdev %p \r\n",__func__,__LINE__, sdev); - printk("[%s][%d]stxb %p \r\n",__func__,__LINE__, stxb); - printk("[%s][%d]srxb %p \r\n",__func__,__LINE__, srxb); + stxb = kmalloc(FBUF, GFP_KERNEL); + srxb = kmalloc(FBUF, GFP_KERNEL); + if (stxb==NULL || srxb==NULL ) { + MALOGW("stxb srxb kmalloc failed."); + if(stxb!=NULL) kfree(stxb); + if(srxb!=NULL) kfree(srxb); + return -ENOMEM; + } + #ifdef CONFIG_PM_WAKELOCKS gIntWakeLock = wakeup_source_register(NULL, "microarray_int_wakelock"); @@ -655,13 +681,23 @@ static int deinit_vars(void) wake_lock_destroy(&gIntWakeLock); wake_lock_destroy(&gProcessWakeLock); #endif - if(sdev!=NULL) kfree(sdev); - if(smas!=NULL) kfree(smas); - // if(stxb!=NULL) kfree(stxb); - // if(srxb!=NULL) kfree(srxb); + if(sdev!=NULL) + kfree(sdev); + + if(smas!=NULL) + kfree(smas); + + if(stxb!=NULL) + kfree(stxb); + + if(srxb!=NULL) + kfree(srxb); + return 0; } + +#ifndef USE_PLATFORM_DRIVE static int init_spi(struct spi_device *spi){ msleep(50); smas->spi = spi; @@ -673,16 +709,21 @@ static int init_spi(struct spi_device *spi){ return 0; } + static int deinit_spi(struct spi_device *spi){ smas->spi = NULL; mas_disable_spi_clock(spi); return 0; } +#endif + + /* * init_connect function to check whether the chip is microarray's * @return 0 not 1 yes * param void */ +#ifdef REE int init_connect(void){ int i; int res = 0; @@ -721,6 +762,7 @@ int init_connect(void){ int deinit_connect(void){ return 0; } +#endif static int mas_fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data){ struct fb_event *evdata = data; @@ -748,72 +790,96 @@ static int init_notifier_call(void); static int deinit_notifier_call(void); static int init_notifier_call(){ - notifier.notifier_call = mas_fb_notifier_callback; - fb_register_client(¬ifier); - is_screen_on = 1; - return 0; + notifier.notifier_call = mas_fb_notifier_callback; + fb_register_client(¬ifier); + is_screen_on = 1; + return 0; } static int deinit_notifier_call(){ fb_unregister_client(¬ifier); return 0; } +#ifdef USE_PLATFORM_DRIVE +int mas_probe(struct platform_device *spi){ +#else int mas_probe(struct spi_device *spi) { - int ret; +#endif + int ret; + pr_err("mas_probe,by eric.wang\n"); ret= mas_qcm_platform_init(spi); + pr_err("mas_qcm_platform_init:ret=%d,by eric.wang\n",ret); if(ret) - goto err0; + goto err0; ret = init_vars(); + pr_err("init_vars:ret=%d,by eric.wang\n",ret); if(ret){ goto err1; } ret = init_interrupt(); + pr_err("init_interrupt:ret=%d,by eric.wang\n",ret); if(ret){ goto err2; } ret = init_file_node(); + pr_err("init_file_node:ret=%d,by eric.wang\n",ret); if(ret){ goto err3; } +#ifndef USE_PLATFORM_DRIVE ret = init_spi(spi); + pr_err("init_spi:ret=%d,by eric.wang\n",ret); if(ret){ goto err4; } +#endif + #ifdef REE ret = init_connect(); #elif defined TEE - ret = 1; + ret = 1; #endif if(ret == 0){//not chip compatible = 0; - pr_info("%s:init_connect failed.\n", __func__); + pr_info("%s:init_connect failed.\n", __func__); +#ifdef USE_PLATFORM_DRIVE + goto err3; +#else goto err5; +#endif } else - pr_info("%s:init_connect successfully.\n", __func__); + pr_err("%s:init_connect successfully.\n", __func__); + mas_set_input(); MALOGF("end"); + ret = init_notifier_call(); if(ret != 0){ - ret = -ENODEV; - goto err6; - } + ret = -ENODEV; + goto err6; + } + mas_set_wakeup(spi); //Fingerprint_name="Microarray_A121N"; - pr_info("%s:completed.\n", __func__); + pr_err("%s:completed.\n", __func__); return ret; err6: deinit_notifier_call(); +#ifdef REE err5: deinit_connect(); +#endif +#ifndef USE_PLATFORM_DRIVE err4: deinit_spi(spi); +#endif err3: deinit_file_node(); err2: @@ -825,7 +891,11 @@ int mas_probe(struct spi_device *spi) { return -EINVAL; } +#ifdef USE_PLATFORM_DRIVE +int mas_remove(struct platform_device *spi) { +#else int mas_remove(struct spi_device *spi) { +#endif deinit_file_node(); deinit_interrupt(); deinit_vars(); diff --git a/drivers/input/fingerprint/madev.h b/drivers/input/fingerprint/madev.h index d7ce8975e72a..0639abd25452 100755 --- a/drivers/input/fingerprint/madev.h +++ b/drivers/input/fingerprint/madev.h @@ -1,24 +1,26 @@ /* Copyright (C) MicroArray * MicroArray Fprint Driver Code * madev.h * Date: 2017-3-9 - * Version: v4.0.05 + * Version: v4.0.05 * Author: guq * Contact: guq@microarray.com.cn */ #ifndef __MADEV_H_ #define __MADEV_H_ - + //settings macro #define QUALCOMM //[MTK|QUALCOMM|SPRD] -#define REE //[TEE|REE] //select platform +#define TEE //[TEE|REE] //select platform #define MALOGD_LEVEL KERN_EMERG //[KERN_DEBUG|KERN_EMERG] usually, the debug level is used for the release version -#define MA_CHR_FILE_NAME "madev0" //do not neeed modify usually -#define MA_CHR_DEV_NAME "madev" //do not neeed modify usually +#define MA_CHR_FILE_NAME "madev0" //do not neeed modify usually +#define MA_CHR_DEV_NAME "madev" //do not neeed modify usually + +#define USE_PLATFORM_DRIVE #define MA_EINT_NAME "afs121_irq" @@ -120,12 +122,12 @@ //fprint_spi struct use to save the value struct fprint_spi { u8 do_what; //工作内容 - u8 f_wake; //唤醒标志 - int value; + u8 f_wake; //唤醒标志 + int value; volatile u8 f_irq; //中断标志 volatile u8 u1_flag; //reserve for ours thread interrupt volatile u8 u2_flag; //reserve for ours thread interrupt - volatile u8 f_repo; //上报开关 + volatile u8 f_repo; //上报开关 spinlock_t spi_lock; struct spi_device *spi; struct list_head dev_entry; @@ -146,8 +148,8 @@ struct fprint_spi { //end struct fprint_dev { - dev_t idd; - int major; + dev_t idd; + int major; int minor; struct cdev *chd; struct class *cls; @@ -157,21 +159,27 @@ struct fprint_dev { //function define -//extern the settings.h function +//extern the settings.h function +#ifdef USE_PLATFORM_DRIVE +extern int mas_qcm_platform_init(struct platform_device *spi); +extern int mas_qcm_platform_uninit(struct platform_device *spi); +extern void mas_set_wakeup(struct platform_device *spi); +#else extern int mas_qcm_platform_init(struct spi_device *spi); extern int mas_qcm_platform_uninit(struct spi_device *spi); -extern int mas_fingerprint_power(bool flags); - extern void mas_select_transfer(struct spi_device *spi, int len); -extern int mas_finger_get_gpio_info(struct platform_device *pdev); -extern int mas_finger_set_gpio_info(int cmd); extern void mas_enable_spi_clock(struct spi_device *spi); extern void mas_disable_spi_clock(struct spi_device *spi); -extern unsigned int mas_get_irq(void); -extern int mas_get_platform(void); -extern int mas_remove_platform(void); extern void ma_spi_change(struct spi_device *spi, unsigned int speed, int flag); extern void mas_set_wakeup(struct spi_device *spi); +#endif + +extern int mas_fingerprint_power(bool flags); +extern int mas_finger_get_gpio_info(struct platform_device *pdev); +extern int mas_finger_set_gpio_info(int cmd); +extern unsigned int mas_get_irq(void); +extern int mas_get_platform(void); +extern int mas_remove_platform(void);\ extern int mas_get_interrupt_gpio(unsigned int index); //end @@ -185,7 +193,7 @@ extern int mas_get_interrupt_gpio(unsigned int index); /** - * the old ioctl command, compatible for the old version + * the old ioctl command, compatible for the old version */ //ioctl cmd #ifdef COMPATIBLE_VERSION3 diff --git a/drivers/input/fingerprint/qcom-settings.c b/drivers/input/fingerprint/qcom-settings.c index 8b0364027cf4..aada1af5d145 100755 --- a/drivers/input/fingerprint/qcom-settings.c +++ b/drivers/input/fingerprint/qcom-settings.c @@ -22,13 +22,15 @@ struct mas_platform_data { //kingsun/zlc: int clk_enabled; struct clk *core_clk; - struct clk *iface_clk; + struct clk *iface_clk; unsigned int int_irq; //end }; struct mas_platform_data *mas_pdata; int first_int_after_suspend=0; //kingsun/zlc: + + #ifdef CONFIG_OF /* -------------------------------------------------------------------- */ #ifdef CONFIG_HAS_EARLYSUSPEND @@ -36,10 +38,12 @@ int mas_suspend(struct spi_device *spi, pm_message_t mesg) { printk("%s start\n",__func__); if (device_may_wakeup(&spi->dev)) - enable_irq_wake(mas_pdata->int_irq); + enable_irq_wake(mas_pdata->int_irq); +#ifndef USE_PLATFORM_DRIVE printk("mas_ioctl_clk_disable\n"); mas_disable_spi_clock(spi); +#endif //USE_PLATFORM_DRIVE first_int_after_suspend=1; printk("%s end\n",__func__); return 0; @@ -49,18 +53,27 @@ int mas_suspend(struct spi_device *spi, pm_message_t mesg) /* -------------------------------------------------------------------- */ int mas_resume(struct spi_device *spi) { - printk("%s start\n",__func__); - if (device_may_wakeup(&spi->dev)) - disable_irq_wake(mas_pdata->int_irq); + printk("%s start\n",__func__); + if (device_may_wakeup(&spi->dev)) + disable_irq_wake(mas_pdata->int_irq); +#ifndef USE_PLATFORM_DRIVE printk("mas_enable_spi_clock\n"); mas_enable_spi_clock(spi); +#endif //USE_PLATFORM_DRIVE printk("%s end\n",__func__); return 0; } + + #else + + int mas_suspend(struct device *dev) { +#ifdef USE_PLATFORM_DRIVE + printk("%s start\n",__func__); +#else struct spi_device *spi = NULL; printk("%s start\n",__func__); @@ -69,20 +82,28 @@ int mas_suspend(struct device *dev) printk("%s get spi device failed\n",__func__); return -1; } +#endif //USE_PLATFORM_DRIVE if (device_may_wakeup(dev)) - enable_irq_wake(mas_pdata->int_irq); + enable_irq_wake(mas_pdata->int_irq); +#ifndef USE_PLATFORM_DRIVE printk("mas_ioctl_clk_disable\n"); mas_disable_spi_clock(spi); +#endif //USE_PLATFORM_DRIVE first_int_after_suspend=1; printk("%s end\n",__func__); return 0; } + int mas_resume(struct device *dev) { +#ifdef USE_PLATFORM_DRIVE + printk("%s start\n",__func__); +#else struct spi_device *spi = NULL; + printk("%s start\n",__func__); spi = to_spi_device(dev); @@ -90,61 +111,76 @@ int mas_resume(struct device *dev) printk("%s get spi device failed\n",__func__); return -1; } +#endif //USE_PLATFORM_DRIVE - if (device_may_wakeup(dev)) - disable_irq_wake(mas_pdata->int_irq); + if (device_may_wakeup(dev)) + disable_irq_wake(mas_pdata->int_irq); +#ifndef USE_PLATFORM_DRIVE printk("mas_enable_spi_clock\n"); mas_enable_spi_clock(spi); +#endif //USE_PLATFORM_DRIVE + printk("%s end\n",__func__); return 0; } -#endif +#endif //CONFIG_HAS_EARLYSUSPEND static struct of_device_id mas_of_match[] = { - {.compatible = "microarray,fingerprint",}, - {} + {.compatible = "microarray,fingerprint",}, + {} }; MODULE_DEVICE_TABLE(of, mas_of_match); #ifndef CONFIG_HAS_EARLYSUSPEND const struct dev_pm_ops mas_pm_ops = { - .suspend = mas_suspend, - .resume = mas_resume, + .suspend = mas_suspend, + .resume = mas_resume, }; -#endif -#endif +#endif //CONFIG_HAS_EARLYSUSPEND +#endif//CONFIG_OF + + +#ifndef USE_PLATFORM_DRIVE struct spi_device_id sdev_id = {MA_DRV_NAME, 0}; +#endif //USE_PLATFORM_DRIVE + +#ifdef USE_PLATFORM_DRIVE +struct platform_driver sdrv = { +#else struct spi_driver sdrv = { - .driver = { - .name = MA_DRV_NAME, - //.bus = &spi_bus_type, - .owner = THIS_MODULE, +#endif //USE_PLATFORM_DRIVE + .driver = { + .name = MA_DRV_NAME, + //.bus = &spi_bus_type, + .owner = THIS_MODULE, #ifndef CONFIG_HAS_EARLYSUSPEND - .pm = &mas_pm_ops, -#endif + .pm = &mas_pm_ops, +#endif //CONFIG_HAS_EARLYSUSPEND #ifdef CONFIG_OF - .of_match_table = mas_of_match, -#endif - }, - .id_table = &sdev_id, - .probe = mas_probe, - .remove = mas_remove, + .of_match_table = mas_of_match, +#endif //CONFIG_OF + }, +#ifndef USE_PLATFORM_DRIVE + .id_table = &sdev_id, +#endif //USE_PLATFORM_DRIVE + .probe = mas_probe, + .remove = mas_remove, #ifdef CONFIG_HAS_EARLYSUSPEND - .suspend = mas_suspend, - .resume = mas_resume, -#endif + .suspend = mas_suspend, + .resume = mas_resume, +#endif //CONFIG_HAS_EARLYSUSPEND }; //driver end +#ifndef USE_PLATFORM_DRIVE /** * the spi struct date start,for getting the spi_device to set the spi clock enable end */ - void mas_select_transfer(struct spi_device *spi, int len) { return ; } @@ -246,7 +282,8 @@ static int mas_ioctl_clk_init(struct spi_device *spi, struct mas_platform_data * } static int mas_ioctl_clk_uninit(struct mas_platform_data *data) -{ return 0; //kingsun/zlc: bypass the operation of spi clock +{ + return 0; //kingsun/zlc: bypass the operation of spi clock pr_info("%s: enter\n", __func__); if (!IS_ERR_OR_NULL(data->core_clk)) { @@ -290,7 +327,8 @@ static int mas_ioctl_clk_enable(struct mas_platform_data *data) } static int mas_ioctl_clk_disable(struct mas_platform_data *data) -{ return 0; //kingsun/zlc: bypass the operation of spi clock +{ + return 0; //kingsun/zlc: bypass the operation of spi clock if (!data->clk_enabled) return 0; @@ -300,11 +338,15 @@ static int mas_ioctl_clk_disable(struct mas_platform_data *data) return 0; } - +#endif //USE_PLATFORM_DRIVE int mas_get_platform(void) { int ret; +#ifdef USE_PLATFORM_DRIVE + ret = platform_driver_register(&sdrv); +#else ret = spi_register_driver(&sdrv); +#endif pr_err("MAFP_ spi_register_driver ret = %d",ret); if(ret) { @@ -314,7 +356,11 @@ int mas_get_platform(void) { } int mas_remove_platform(void){ - spi_unregister_driver(&sdrv); +#ifdef USE_PLATFORM_DRIVE + platform_driver_unregister(&sdrv); +#else + spi_unregister_driver(&sdrv); +#endif return 0; } @@ -447,34 +493,44 @@ static int mas_gpio_configure(bool on) return rc; } - +#ifdef USE_PLATFORM_DRIVE +int mas_qcm_platform_uninit(struct platform_device *spi) +#else int mas_qcm_platform_uninit(struct spi_device *spi) -{ int ret=0; +#endif +{ + int ret=0; + #ifndef USE_PLATFORM_DRIVE mas_ioctl_clk_uninit(mas_pdata); + #endif mas_fingerprint_power(false); + #if 0 - if(mas_pdata->vcc_io_l6) - regulator_put(mas_pdata->vcc_io_l6); - #endif - mas_gpio_configure(false); - mas_pdata->int_irq=0; - kfree(mas_pdata); - return ret; + if(mas_pdata->vcc_io_l6) + regulator_put(mas_pdata->vcc_io_l6); + #endif + mas_gpio_configure(false); + mas_pdata->int_irq=0; + kfree(mas_pdata); + return ret; } - +#ifdef USE_PLATFORM_DRIVE +int mas_qcm_platform_init(struct platform_device *spi) +#else int mas_qcm_platform_init(struct spi_device *spi) +#endif { int ret=0; mas_pdata = kmalloc(sizeof(struct mas_platform_data), GFP_KERNEL); if (mas_pdata == NULL) { pr_info("%s:Failed to allocate buffer\n", __func__); ret=-ENOMEM; - goto err_devm_kzalloc; + goto fingeriprnt_err_devm_kzalloc; } ret = mas_get_of_pdata(&spi->dev); if(ret<0) - goto get_of_pdata_err; + goto fingeriprnt_get_of_pdata_err; ret = mas_gpio_configure(true); if(ret<0) @@ -484,26 +540,32 @@ int mas_qcm_platform_init(struct spi_device *spi) if(ret<0) goto fingeriprnt_power_err; + #ifndef USE_PLATFORM_DRIVE if (mas_ioctl_clk_init(spi, mas_pdata)) goto fingeriprnt_power_err; if (mas_ioctl_clk_enable(mas_pdata)) goto fingeriprnt_clk_enable_failed; spi_clock_set(mas_pdata, 9600000); + #endif + return ret; +#ifndef USE_PLATFORM_DRIVE fingeriprnt_clk_enable_failed: mas_ioctl_clk_uninit(mas_pdata); +#endif fingeriprnt_power_err: //if(mas_pdata->vcc_io_l6) //regulator_put(mas_pdata->vcc_io_l6); fingeriprnt_gpio_configure_err: -get_of_pdata_err: +fingeriprnt_get_of_pdata_err: kfree(mas_pdata); -err_devm_kzalloc: +fingeriprnt_err_devm_kzalloc: return ret; } +#ifndef USE_PLATFORM_DRIVE void mas_enable_spi_clock(struct spi_device *spi) { mas_ioctl_clk_enable(mas_pdata); @@ -513,19 +575,22 @@ void mas_disable_spi_clock(struct spi_device *spi) { mas_ioctl_clk_disable(mas_pdata); } - +#endif unsigned int mas_get_irq(void){ - unsigned int irq=0; - irq = gpio_to_irq(mas_pdata->irq_gpio); - if(irq) - printk("mas_get_irq: %d\n",irq); - mas_pdata->int_irq=irq; - return irq; + unsigned int irq=0; + irq = gpio_to_irq(mas_pdata->irq_gpio); + if(irq) + printk("mas_get_irq: %d\n",irq); + mas_pdata->int_irq=irq; + return irq; } - +#ifdef USE_PLATFORM_DRIVE +void mas_set_wakeup(struct platform_device *spi) +#else void mas_set_wakeup(struct spi_device *spi) +#endif { device_init_wakeup(&spi->dev, 1); } diff --git a/drivers/input/fingerprint/qcom-settings.h b/drivers/input/fingerprint/qcom-settings.h index 18c14ed737f6..e733f1767022 100755 --- a/drivers/input/fingerprint/qcom-settings.h +++ b/drivers/input/fingerprint/qcom-settings.h @@ -46,6 +46,7 @@ #include #include +#include "madev.h" //macro settings #define MA_DRV_NAME "madev" @@ -53,10 +54,18 @@ #define MA_DTS_NAME "mediatek,hct_finger" #define MA_EINT_DTS_NAME "mediatek,hct_finger" + + //macro settings end +#ifdef USE_PLATFORM_DRIVE +extern int mas_probe(struct platform_device *spi); +extern int mas_remove(struct platform_device *spi); +#else extern int mas_probe(struct spi_device *spi); extern int mas_remove(struct spi_device *spi); +#endif + /* add for spi cls ctl start */ struct mt_spi_t { diff --git a/drivers/input/keyboard/aw9523/aw9523b.c b/drivers/input/keyboard/aw9523/aw9523b.c index 284822984ab4..a8af243c93c1 100755 --- a/drivers/input/keyboard/aw9523/aw9523b.c +++ b/drivers/input/keyboard/aw9523/aw9523b.c @@ -143,14 +143,14 @@ static struct input_dev *aw9523b_input_dev = NULL; static struct i2c_client *g_client = NULL; static const unsigned short key_array[Y_NUM][X_NUM] = { - { 0xFFFF, KEY_H, KEY_B, KEY_7, KEY_UP, KEY_ENTER, KEY_Y, KEY_COMMA }, - { KEY_3, KEY_S, KEY_Z, KEY_M, KEY_I, KEY_9, KEY_W, KEY_J }, - { KEY_LEFT, KEY_G, KEY_V, KEY_6, KEY_RIGHT, KEY_DELETE, KEY_T, KEY_DOT }, - { KEY_SYM, KEY_A, KEY_RIGHTBRACE, KEY_HOMEPAGE, KEY_P, KEY_MINUS, KEY_Q, KEY_L }, - { KEY_BACKSPACE, KEY_D, KEY_X, KEY_K, KEY_SEMICOLON, KEY_EQUAL, KEY_E, KEY_APOSTROPHE }, - { KEY_CAPSLOCK, KEY_BACKSLASH, KEY_LEFTBRACE, KEY_DOWN, KEY_O, KEY_0, KEY_GRAVE, KEY_K }, - { KEY_SPACE, KEY_F, KEY_C, KEY_N, KEY_U, KEY_8, KEY_R, KEY_5 }, - { KEY_ESC, KEY_1, 0xFFFF, 0xFFFF, KEY_2, KEY_4, KEY_TAB, 0xFFFF } + { 0xFFFF, KEY_J, KEY_N, KEY_7, KEY_UP, KEY_ENTER, KEY_U, KEY_DOT }, + { KEY_3, KEY_D, KEY_X, KEY_COMMA, KEY_O, KEY_9, KEY_E, KEY_K }, + { KEY_LEFT, KEY_H, KEY_B, KEY_6, KEY_RIGHT, KEY_DELETE, KEY_Y, KEY_SLASH }, + { KEY_SYM, KEY_S, KEY_Z, KEY_HOMEPAGE, KEY_LEFTBRACE, KEY_MINUS, KEY_W, KEY_SEMICOLON }, + { KEY_BACKSPACE, KEY_F, KEY_C, 0xFFFF, KEY_RIGHTBRACE,KEY_EQUAL, KEY_R, KEY_APOSTROPHE }, + { KEY_CAPSLOCK, KEY_A, KEY_GRAVE, KEY_DOWN, KEY_P, KEY_0, KEY_Q, KEY_L }, + { KEY_SPACE, KEY_G, KEY_V, KEY_M, KEY_I, KEY_8, KEY_T, KEY_5 }, + { KEY_ESC, KEY_1, 0xFFFF, 0xFFFF, KEY_2, KEY_4, KEY_TAB, 0xFFFF } }; // This macro sets the interval between polls of the key matrix for ghosted keys (in milliseconds). @@ -1034,12 +1034,9 @@ static int aw9523b_check_dt(struct device_node *np) { int i; int count; - - struct device_node *node; struct drm_panel *panel; - //需要在屏dts初始化后才能找到panel的字段 count = of_count_phandle_with_args(np, "panel", NULL); diff --git a/drivers/input/keyboard/aw9523/aw9523b.h b/drivers/input/keyboard/aw9523/aw9523b.h index 26dd3dfcc03d..8f694fed5163 100755 --- a/drivers/input/keyboard/aw9523/aw9523b.h +++ b/drivers/input/keyboard/aw9523/aw9523b.h @@ -42,12 +42,12 @@ -//IIC的写地址,={1011,0,AD1,AD0,0},AD0,AD1接低则为0xB0 ,接高则是0xB6 +//IICдַ={10110AD1AD00}AD0,AD1ӵΪ0xB0 Ӹ0xB6 #define IIC_ADDRESS_WRITE (0xB0) //0x58 #define IIC_ADDRESS_READ (0xB1) -#define X_NUM (8) //列 -#define Y_NUM (8) //行 +#define X_NUM (8) // +#define Y_NUM (8) // //i2c tranfer ,repeat try times #define AW9523_I2C_MAX_LOOP (50) diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index be5c1e8095aa..1a25bf1dfe1b 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -77,3 +77,4 @@ obj-$(CONFIG_QTI_MAXIM_FAN_CONTROLLER) += max31760.o obj-$(CONFIG_QTI_XR_SMRTVWR_MISC) += qxr-stdalonevwr.o obj-$(CONFIG_FPR_FPC) += fpr_FingerprintCard/ obj-y += qrc/ +obj-$(CONFIG_AW862XX_HAPTIC) += aw862xx_haptic/ diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 1cc9db100d59..d91f8fcab152 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -5366,8 +5366,8 @@ int qseecom_process_listener_from_smcinvoke(struct scm_desc *desc) pr_err("Failed on cmd %d for lsnr %d session %d, ret = %d\n", (int)desc->ret[0], (int)desc->ret[2], (int)desc->ret[1], ret); - desc->ret[0] = resp.resp_type; - desc->ret[1] = resp.result; + desc->ret[0] = resp.result; + desc->ret[1] = resp.resp_type; desc->ret[2] = resp.data; return ret; } diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c index a63ce0b4c826..c1b0799963e6 100644 --- a/drivers/power/reset/msm-poweroff.c +++ b/drivers/power/reset/msm-poweroff.c @@ -62,7 +62,7 @@ static void scm_disable_sdi(void); * There is no API from TZ to re-enable the registers. * So the SDI cannot be re-enabled when it already by-passed. */ -static int download_mode = 0; +static int download_mode = 1; static struct kobject dload_kobj; static int in_panic; diff --git a/drivers/power/supply/qcom/qg-util.c b/drivers/power/supply/qcom/qg-util.c index cee6285fce4a..36b5fefa42aa 100644 --- a/drivers/power/supply/qcom/qg-util.c +++ b/drivers/power/supply/qcom/qg-util.c @@ -374,8 +374,7 @@ int qg_get_battery_temp(struct qpnp_qg *chip, int *temp) pr_err("Failed reading BAT_TEMP over ADC rc=%d\n", rc); return rc; } - //pr_err("batt_temp = %d,by eric.wang\n", *temp);//by eric.wang - //*temp = 250; + pr_debug("batt_temp = %d\n", *temp); return 0; } diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index 494cab5fb721..71aa200ad0fd 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -3699,12 +3699,6 @@ static int smblib_get_prop_ufp_mode(struct smb_charger *chg) } smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_1 = 0x%02x\n", stat); - /* config 0x154A to 0x17 */ - if (stat & (SNK_RP_STD_DAM_BIT | SNK_RP_1P5_DAM_BIT | SNK_RP_3P0_DAM_BIT)){ - smblib_masked_write(chg, TYPE_C_DEBUG_ACCESS_SINK_REG, - TYPEC_DEBUG_ACCESS_SINK_MASK, 0x17); - } - switch (stat & DETECTED_SRC_TYPE_MASK) { case SNK_RP_STD_BIT: case SNK_RP_STD_DAM_BIT: @@ -5628,10 +5622,6 @@ void smblib_usb_plugin_locked(struct smb_charger *chg) smblib_err(chg, "Couldn't disable DPDM rc=%d\n", rc); smblib_update_usb_type(chg); - - if(chg->use_extcon) - smblib_notify_device_mode(chg,false); - vote(chg->usb_icl_votable, USB_PSY_VOTER,false, 0);//remove USB_PSY voting when plugin detach } if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB) @@ -5779,7 +5769,6 @@ static void update_sw_icl_max(struct smb_charger *chg, int pst) /* TypeC rp med or high, use rp value */ typec_mode = smblib_get_prop_typec_mode(chg); - if (typec_rp_med_high(chg, typec_mode)) { rp_ua = get_rp_based_dcp_current(chg, typec_mode); vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, rp_ua); @@ -5834,6 +5823,7 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising) return; apsd_result = smblib_update_usb_type(chg); + update_sw_icl_max(chg, apsd_result->pst); switch (apsd_result->bit) { @@ -6400,6 +6390,7 @@ static void smblib_handle_rp_change(struct smb_charger *chg, int typec_mode) == FORCE_FLOAT_SDP_CFG_BIT) return; } + update_sw_icl_max(chg, apsd->pst); smblib_dbg(chg, PR_MISC, "CC change old_mode=%d new_mode=%d\n", diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index f18ad3ce24e8..742877f67704 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -3589,6 +3589,13 @@ static int msm_geni_serial_probe(struct platform_device *pdev) if (!uart_console(uport)) spin_lock_init(&dev_port->rx_lock); + /* + * Earlyconsole to kernel console will switch happen after + * uart_add_one_port. Hence marking is_earlycon to false here. + */ + if (is_console) + is_earlycon = false; + IPC_LOG_MSG(dev_port->ipc_log_misc, "%s: port:%s irq:%d\n", __func__, uport->name, uport->irq); diff --git a/lib/vsprintf.c b/lib/vsprintf.c index a6e36a2260e0..a35601667dff 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1958,8 +1958,11 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, return buf; } case 'K': + /* if (!kptr_restrict || IS_ENABLED(CONFIG_DEBUG_CONSOLE_UNHASHED_POINTERS)) + */ + if (!kptr_restrict) break; return restricted_pointer(buf, end, ptr, spec); case 'N': diff --git a/techpack/camera/Makefile b/techpack/camera/Makefile index 9e0b13785b58..c32d9b5b8726 100644 --- a/techpack/camera/Makefile +++ b/techpack/camera/Makefile @@ -13,6 +13,10 @@ ifeq ($(CONFIG_ARCH_BENGAL), y) include $(srctree)/techpack/camera/config/bengalcamera.conf endif +ifeq ($(CONFIG_ARCH_KHAJE), y) +include $(srctree)/techpack/camera/config/khajecamera.conf +endif + ifeq ($(CONFIG_ARCH_KONA), y) LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/konacameraconf.h @@ -28,6 +32,11 @@ LINUXINCLUDE += \ -include $(srctree)/techpack/camera/config/bengalcameraconf.h endif +ifeq ($(CONFIG_ARCH_KHAJE), y) +LINUXINCLUDE += \ + -include $(srctree)/techpack/camera/config/khajecameraconf.h +endif + ifdef CONFIG_SPECTRA_CAMERA # Use USERINCLUDE when you must reference the UAPI directories only. USERINCLUDE += \ diff --git a/techpack/camera/config/khajecamera.conf b/techpack/camera/config/khajecamera.conf new file mode 100644 index 000000000000..d84667d275dd --- /dev/null +++ b/techpack/camera/config/khajecamera.conf @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2021, The Linux Foundation. All rights reserved. + +export CONFIG_SPECTRA_CAMERA_OPE=y +export CONFIG_SPECTRA_CAMERA_TFE=y +export CONFIG_SPECTRA_CAMERA_SENSOR=y diff --git a/techpack/camera/config/khajecameraconf.h b/techpack/camera/config/khajecameraconf.h new file mode 100644 index 000000000000..583e5ec8b1d2 --- /dev/null +++ b/techpack/camera/config/khajecameraconf.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#define CONFIG_SPECTRA_CAMERA 1 +#define CONFIG_SPECTRA_CAMERA_OPE 1 +#define CONFIG_SPECTRA_CAMERA_TFE 1 diff --git a/techpack/camera/drivers/cam_cdm/cam_cdm.h b/techpack/camera/drivers/cam_cdm/cam_cdm.h index 1814bcddda97..8c8e6a4bd2d6 100644 --- a/techpack/camera/drivers/cam_cdm/cam_cdm.h +++ b/techpack/camera/drivers/cam_cdm/cam_cdm.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CDM_H_ @@ -83,6 +83,7 @@ #define CAM_CDM_RESET_HW_STATUS 0x4 #define CAM_CDM_ERROR_HW_STATUS 0x5 #define CAM_CDM_FLUSH_HW_STATUS 0x6 +#define CAM_CDM_RESET_ERR_STATUS 0x7 /* Curent BL command masks and shifts */ #define CAM_CDM_CURRENT_BL_LEN 0xFFFFF @@ -276,6 +277,7 @@ struct cam_cdm_common_reg_data { * wait, etc. * @core_en: offset to pause/enable CDM * @fe_cfg: offset to configure CDM fetch engine + * @irq_context_status offset to read back irq context status * @bl_fifo_rb: offset to set BL_FIFO read back * @bl_fifo_base_rb: offset to read back base address on offset set by * bl_fifo_rb @@ -319,6 +321,7 @@ struct cam_cdm_common_regs { uint32_t core_cfg; uint32_t core_en; uint32_t fe_cfg; + uint32_t irq_context_status; uint32_t bl_fifo_rb; uint32_t bl_fifo_base_rb; uint32_t bl_fifo_len_rb; @@ -374,6 +377,7 @@ enum cam_cdm_hw_process_intf_cmd { CAM_CDM_HW_INTF_CMD_FLUSH_HW, CAM_CDM_HW_INTF_CMD_HANDLE_ERROR, CAM_CDM_HW_INTF_CMD_HANG_DETECT, + CAM_CDM_HW_INTF_DUMP_DBG_REGS, CAM_CDM_HW_INTF_CMD_INVALID, }; @@ -415,6 +419,7 @@ enum cam_cdm_hw_version { CAM_CDM_VERSION_1_1 = 0x10010000, CAM_CDM_VERSION_1_2 = 0x10020000, CAM_CDM_VERSION_2_0 = 0x20000000, + CAM_CDM_VERSION_2_1 = 0x20010000, CAM_CDM_VERSION_MAX, }; diff --git a/techpack/camera/drivers/cam_cdm/cam_cdm_core_common.c b/techpack/camera/drivers/cam_cdm/cam_cdm_core_common.c index 8859fa833546..fd84b8d6866b 100644 --- a/techpack/camera/drivers/cam_cdm/cam_cdm_core_common.c +++ b/techpack/camera/drivers/cam_cdm/cam_cdm_core_common.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -49,6 +49,7 @@ bool cam_cdm_set_cam_hw_version( case CAM_CDM110_VERSION: case CAM_CDM120_VERSION: case CAM_CDM200_VERSION: + case CAM_CDM210_VERSION: cam_version->major = (ver & 0xF0000000); cam_version->minor = (ver & 0xFFF0000); cam_version->incr = (ver & 0xFFFF); @@ -81,6 +82,7 @@ struct cam_cdm_utils_ops *cam_cdm_get_ops( case CAM_CDM110_VERSION: case CAM_CDM120_VERSION: case CAM_CDM200_VERSION: + case CAM_CDM210_VERSION: return &CDM170_ops; default: CAM_ERR(CAM_CDM, "CDM Version=%x not supported in util", @@ -178,10 +180,12 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, (struct cam_cdm_bl_cb_request_entry *)data; client_idx = CAM_CDM_GET_CLIENT_IDX(node->client_hdl); + mutex_lock(&cdm_hw->hw_mutex); client = core->clients[client_idx]; if ((!client) || (client->handle != node->client_hdl)) { CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client, node->client_hdl); + mutex_unlock(&cdm_hw->hw_mutex); return; } cam_cdm_get_client_refcount(client); @@ -200,6 +204,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, } mutex_unlock(&client->lock); cam_cdm_put_client_refcount(client); + mutex_unlock(&cdm_hw->hw_mutex); return; } else if (status == CAM_CDM_CB_STATUS_HW_RESET_DONE || status == CAM_CDM_CB_STATUS_HW_FLUSH || @@ -215,7 +220,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, if ((!client) || (client->handle != node->client_hdl)) { CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client, node->client_hdl); - return; + return; } cam_cdm_get_client_refcount(client); mutex_lock(&client->lock); @@ -237,6 +242,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, for (i = 0; i < CAM_PER_CDM_MAX_REGISTERED_CLIENTS; i++) { if (core->clients[i] != NULL) { + mutex_lock(&cdm_hw->hw_mutex); client = core->clients[i]; cam_cdm_get_client_refcount(client); mutex_lock(&client->lock); @@ -259,6 +265,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, } mutex_unlock(&client->lock); cam_cdm_put_client_refcount(client); + mutex_unlock(&cdm_hw->hw_mutex); } } } @@ -318,35 +325,34 @@ int cam_cdm_stream_ops_internal(void *hw_priv, return -EINVAL; core = (struct cam_cdm *)cdm_hw->core_info; + mutex_lock(&cdm_hw->hw_mutex); client_idx = CAM_CDM_GET_CLIENT_IDX(*handle); client = core->clients[client_idx]; if (!client) { CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client, *handle); + mutex_unlock(&cdm_hw->hw_mutex); return -EINVAL; } cam_cdm_get_client_refcount(client); if (*handle != client->handle) { CAM_ERR(CAM_CDM, "client id given handle=%x invalid", *handle); - cam_cdm_put_client_refcount(client); - return -EINVAL; + rc = -EINVAL; + goto end; } if (operation == true) { if (true == client->stream_on) { CAM_ERR(CAM_CDM, "Invalid CDM client is already streamed ON"); - cam_cdm_put_client_refcount(client); - return rc; + goto end; } } else { if (client->stream_on == false) { CAM_ERR(CAM_CDM, "Invalid CDM client is already streamed Off"); - cam_cdm_put_client_refcount(client); - return rc; + goto end; } } - mutex_lock(&cdm_hw->hw_mutex); if (operation == true) { if (!cdm_hw->open_count) { struct cam_ahb_vote ahb_vote; @@ -817,6 +823,22 @@ int cam_cdm_process_cmd(void *hw_priv, rc = cam_hw_cdm_hang_detect(cdm_hw, *handle); break; } + case CAM_CDM_HW_INTF_DUMP_DBG_REGS: + { + uint32_t *handle = cmd_args; + + if (sizeof(uint32_t) != arg_size) { + CAM_ERR(CAM_CDM, + "Invalid CDM cmd %d size=%x for handle=0x%x", + cmd, arg_size, *handle); + return -EINVAL; + } + + mutex_lock(&cdm_hw->hw_mutex); + cam_hw_cdm_dump_core_debug_registers(cdm_hw, true); + mutex_unlock(&cdm_hw->hw_mutex); + break; + } default: CAM_ERR(CAM_CDM, "CDM HW intf command not valid =%d", cmd); break; diff --git a/techpack/camera/drivers/cam_cdm/cam_cdm_core_common.h b/techpack/camera/drivers/cam_cdm/cam_cdm_core_common.h index 5545f15903e0..96fd8b36d037 100644 --- a/techpack/camera/drivers/cam_cdm/cam_cdm_core_common.h +++ b/techpack/camera/drivers/cam_cdm/cam_cdm_core_common.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CDM_CORE_COMMON_H_ @@ -12,6 +12,7 @@ #define CAM_CDM110_VERSION 0x10010000 #define CAM_CDM120_VERSION 0x10020000 #define CAM_CDM200_VERSION 0x20000000 +#define CAM_CDM210_VERSION 0x20010000 #define CAM_CDM_AHB_BURST_LEN_1 (BIT(1) - 1) #define CAM_CDM_AHB_BURST_LEN_4 (BIT(2) - 1) @@ -55,5 +56,7 @@ struct cam_cdm_bl_cb_request_entry *cam_cdm_find_request_by_bl_tag( uint32_t tag, struct list_head *bl_list); void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, enum cam_cdm_cb_status status, void *data); +void cam_hw_cdm_dump_core_debug_registers( + struct cam_hw_info *cdm_hw, bool pause_core); #endif /* _CAM_CDM_CORE_COMMON_H_ */ diff --git a/techpack/camera/drivers/cam_cdm/cam_cdm_hw_core.c b/techpack/camera/drivers/cam_cdm/cam_cdm_hw_core.c index 55209a62f859..22dbcf59251a 100644 --- a/techpack/camera/drivers/cam_cdm/cam_cdm_hw_core.c +++ b/techpack/camera/drivers/cam_cdm/cam_cdm_hw_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -22,6 +22,7 @@ #include "cam_cdm_hw_reg_1_1.h" #include "cam_cdm_hw_reg_1_2.h" #include "cam_cdm_hw_reg_2_0.h" +#include "cam_cdm_hw_reg_2_1.h" #include "cam_trace.h" #include "cam_req_mgr_workq.h" @@ -60,6 +61,19 @@ static const struct of_device_id msm_cam_hw_cdm_dt_match[] = { .compatible = CAM_HW_CDM_OPE_NAME_2_0, .data = &cam_cdm_2_0_reg_offset, }, + { + .compatible = CAM_HW_CDM_CPAS_NAME_2_1, + .data = &cam_cdm_2_1_reg_offset, + }, + { + .compatible = CAM_HW_CDM_OPE_NAME_2_1, + .data = &cam_cdm_2_1_reg_offset, + }, + { + .compatible = CAM_HW_CDM_IFE_NAME_2_1, + .data = &cam_cdm_2_1_reg_offset, + }, + {}, }; static enum cam_cdm_id cam_hw_cdm_get_id_by_name(char *name) @@ -85,6 +99,15 @@ static enum cam_cdm_id cam_hw_cdm_get_id_by_name(char *name) if (strnstr(name, CAM_HW_CDM_OPE_NAME_2_0, strlen(CAM_HW_CDM_CPAS_NAME_2_0))) return CAM_CDM_OPE; + if (strnstr(name, CAM_HW_CDM_CPAS_NAME_2_1, + strlen(CAM_HW_CDM_CPAS_NAME_2_1))) + return CAM_CDM_CPAS; + if (strnstr(name, CAM_HW_CDM_OPE_NAME_2_1, + strlen(CAM_HW_CDM_OPE_NAME_2_1))) + return CAM_CDM_OPE; + if (strnstr(name, CAM_HW_CDM_IFE_NAME_2_1, + strlen(CAM_HW_CDM_IFE_NAME_2_1))) + return CAM_CDM_IFE; return CAM_CDM_MAX; } @@ -147,14 +170,14 @@ static int cam_hw_cdm_pause_core(struct cam_hw_info *cdm_hw, bool pause) return rc; } -int cam_hw_cdm_enable_core_dbg(struct cam_hw_info *cdm_hw) +int cam_hw_cdm_enable_core_dbg(struct cam_hw_info *cdm_hw, uint32_t value) { int rc = 0; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; if (cam_cdm_write_hw_reg(cdm_hw, core->offsets->cmn_reg->core_debug, - 0x10100)) { + value)) { CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug"); rc = -EIO; } @@ -241,24 +264,7 @@ int cam_hw_cdm_bl_fifo_pending_bl_rb_in_fifo( return rc; } -int cam_hw_cdm_enable_core_dbg_per_fifo( - struct cam_hw_info *cdm_hw, - uint32_t fifo_idx) -{ - int rc = 0; - struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; - - if (cam_cdm_write_hw_reg(cdm_hw, - core->offsets->cmn_reg->core_debug, - (0x10100 | fifo_idx << 20))) { - CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug"); - rc = -EIO; - } - - return rc; -} - -void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw) +static void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw) { struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; int i, j; @@ -267,13 +273,7 @@ void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw) for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) { cam_hw_cdm_bl_fifo_pending_bl_rb_in_fifo(cdm_hw, i, &num_pending_req); - - if (cam_hw_cdm_enable_core_dbg_per_fifo(cdm_hw, i)) { - CAM_ERR(CAM_CDM, - "Problem in selecting the fifo for readback"); - continue; - } - for (j = 0 ; j < num_pending_req ; j++) { + for (j = 0; j < num_pending_req ; j++) { cam_cdm_write_hw_reg(cdm_hw, core->offsets->cmn_reg->bl_fifo_rb, j); cam_cdm_read_hw_reg(cdm_hw, @@ -294,89 +294,152 @@ void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw) } } -void cam_hw_cdm_dump_core_debug_registers( - struct cam_hw_info *cdm_hw) +void cam_hw_cdm_dump_core_debug_registers(struct cam_hw_info *cdm_hw, + bool pause_core) { - uint32_t dump_reg, core_dbg; + uint32_t dump_reg[4], core_dbg = 0x100; int i; + bool is_core_paused_already; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; + const struct cam_cdm_icl_regs *inv_cmd_log = + core->offsets->cmn_reg->icl_reg; - cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW core status=%x", dump_reg); + cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en, + &dump_reg[0]); + + if (pause_core) { + cam_hw_cdm_pause_core(cdm_hw, true); + usleep_range(1000, 1010); + } + cam_hw_cdm_enable_core_dbg(cdm_hw, core_dbg); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->usr_data, - &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW core userdata=0x%x", dump_reg); - - usleep_range(1000, 1010); + &dump_reg[1]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->debug_status, - &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW Debug status reg=%x", dump_reg); - cam_cdm_read_hw_reg(cdm_hw, - core->offsets->cmn_reg->core_debug, - &core_dbg); + &dump_reg[2]); + + CAM_INFO(CAM_CDM, "Core stat 0x%x udata 0x%x dbg_stat 0x%x", + dump_reg[0], dump_reg[1], dump_reg[2]); + if (core_dbg & 0x100) { cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->last_ahb_addr, - &dump_reg); - CAM_INFO(CAM_CDM, "AHB dump reglastaddr=%x", dump_reg); + &dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->last_ahb_data, - &dump_reg); - CAM_INFO(CAM_CDM, "AHB dump reglastdata=%x", dump_reg); + &dump_reg[1]); + CAM_INFO(CAM_CDM, "AHB dump lastaddr=0x%x lastdata=0x%x", + dump_reg[0], dump_reg[1]); } else { CAM_INFO(CAM_CDM, "CDM HW AHB dump not enable"); } - cam_hw_cdm_dump_bl_fifo_data(cdm_hw); + if (inv_cmd_log) { + if (inv_cmd_log->misc_regs) { + cam_cdm_read_hw_reg(cdm_hw, + inv_cmd_log->misc_regs->icl_status, + &dump_reg[0]); + cam_cdm_read_hw_reg(cdm_hw, + inv_cmd_log->misc_regs->icl_inv_bl_addr, + &dump_reg[1]); + CAM_INFO(CAM_CDM, + "Last Inv Cmd Log(ICL)Status: 0x%x bl_addr: 0x%x", + dump_reg[0], dump_reg[1]); + } + if (inv_cmd_log->data_regs) { + cam_cdm_read_hw_reg(cdm_hw, + inv_cmd_log->data_regs->icl_inv_data, + &dump_reg[0]); + CAM_INFO(CAM_CDM, "First word of Last Inv cmd: 0x%x", + dump_reg[0]); + + cam_cdm_read_hw_reg(cdm_hw, + inv_cmd_log->data_regs->icl_last_data_0, + &dump_reg[0]); + cam_cdm_read_hw_reg(cdm_hw, + inv_cmd_log->data_regs->icl_last_data_1, + &dump_reg[1]); + cam_cdm_read_hw_reg(cdm_hw, + inv_cmd_log->data_regs->icl_last_data_2, + &dump_reg[2]); + + + CAM_INFO(CAM_CDM, "Last good cmd word 0x%x 0x%x 0x%x", + dump_reg[0], dump_reg[1], dump_reg[2]); + } + } + + if (core_dbg & 0x10000) { + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->core_en, &dump_reg[0]); + is_core_paused_already = (bool)(dump_reg[0] & 0x20); + if (!is_core_paused_already) { + cam_hw_cdm_pause_core(cdm_hw, true); + usleep_range(1000, 1010); + } + + cam_hw_cdm_dump_bl_fifo_data(cdm_hw); + + if (!is_core_paused_already) + cam_hw_cdm_pause_core(cdm_hw, false); + } - CAM_INFO(CAM_CDM, "CDM HW default dump"); cam_cdm_read_hw_reg(cdm_hw, - core->offsets->cmn_reg->core_cfg, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW core cfg=%x", dump_reg); + core->offsets->cmn_reg->core_cfg, &dump_reg[0]); + CAM_INFO(CAM_CDM, "CDM HW core cfg=0x%x", dump_reg[0]); for (i = 0; i < core->offsets->reg_data->num_bl_fifo_irq; i++) { cam_cdm_read_hw_reg(cdm_hw, - core->offsets->irq_reg[i]->irq_status, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW irq status%d=%x", i, dump_reg); - + core->offsets->irq_reg[i]->irq_status, &dump_reg[0]); cam_cdm_read_hw_reg(cdm_hw, - core->offsets->irq_reg[i]->irq_set, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW irq set%d=%x", i, dump_reg); - + core->offsets->irq_reg[i]->irq_set, &dump_reg[1]); cam_cdm_read_hw_reg(cdm_hw, - core->offsets->irq_reg[i]->irq_mask, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW irq mask%d=%x", i, dump_reg); - + core->offsets->irq_reg[i]->irq_mask, &dump_reg[2]); cam_cdm_read_hw_reg(cdm_hw, - core->offsets->irq_reg[i]->irq_clear, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW irq clear%d=%x", i, dump_reg); + core->offsets->irq_reg[i]->irq_clear, &dump_reg[3]); + + CAM_INFO(CAM_CDM, + "cnt %d irq status 0x%x set 0x%x mask 0x%x clear 0x%x", + i, dump_reg[0], dump_reg[1], dump_reg[2], dump_reg[3]); } cam_cdm_read_hw_reg(cdm_hw, - core->offsets->cmn_reg->current_bl_base, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW current BL base=%x", dump_reg); + core->offsets->cmn_reg->current_bl_base, &dump_reg[0]); + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->current_used_ahb_base, &dump_reg[1]); + CAM_INFO(CAM_CDM, "curr BL base 0x%x AHB base 0x%x", + dump_reg[0], dump_reg[1]); cam_cdm_read_hw_reg(cdm_hw, - core->offsets->cmn_reg->current_bl_len, &dump_reg); + core->offsets->cmn_reg->wait_status, &dump_reg[0]); + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->comp_wait[0]->comp_wait_status, + &dump_reg[1]); + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->comp_wait[1]->comp_wait_status, + &dump_reg[2]); + CAM_INFO(CAM_CDM, "wait status 0x%x comp wait status 0x%x: 0x%x", + dump_reg[0], dump_reg[1], dump_reg[2]); + + cam_cdm_read_hw_reg(cdm_hw, + core->offsets->cmn_reg->current_bl_len, &dump_reg[0]); CAM_INFO(CAM_CDM, "CDM HW current BL len=%d ARB %d FIFO %d tag=%d, ", - (dump_reg & CAM_CDM_CURRENT_BL_LEN), - (dump_reg & CAM_CDM_CURRENT_BL_ARB) >> + (dump_reg[0] & CAM_CDM_CURRENT_BL_LEN), + (dump_reg[0] & CAM_CDM_CURRENT_BL_ARB) >> CAM_CDM_CURRENT_BL_ARB_SHIFT, - (dump_reg & CAM_CDM_CURRENT_BL_FIFO) >> + (dump_reg[0] & CAM_CDM_CURRENT_BL_FIFO) >> CAM_CDM_CURRENT_BL_FIFO_SHIFT, - (dump_reg & CAM_CDM_CURRENT_BL_TAG) >> + (dump_reg[0] & CAM_CDM_CURRENT_BL_TAG) >> CAM_CDM_CURRENT_BL_TAG_SHIFT); - cam_cdm_read_hw_reg(cdm_hw, - core->offsets->cmn_reg->current_used_ahb_base, &dump_reg); - CAM_INFO(CAM_CDM, "CDM HW current AHB base=%x", dump_reg); - + cam_hw_cdm_disable_core_dbg(cdm_hw); + if (pause_core) + cam_hw_cdm_pause_core(cdm_hw, false); } enum cam_cdm_arbitration cam_cdm_get_arbitration_type( @@ -1084,11 +1147,15 @@ static void cam_hw_cdm_reset_cleanup( int i; struct cam_cdm_bl_cb_request_entry *node, *tnode; bool flush_hw = false; + bool reset_err = false; if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status) || test_bit(CAM_CDM_FLUSH_HW_STATUS, &core->cdm_status)) flush_hw = true; + if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status)) + reset_err = true; + for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) { list_for_each_entry_safe(node, tnode, &core->bl_fifo[i].bl_request_list, entry) { @@ -1097,12 +1164,19 @@ static void cam_hw_cdm_reset_cleanup( CAM_DBG(CAM_CDM, "Notifying client %d for tag %d", node->client_hdl, node->bl_tag); - if (flush_hw) + if (flush_hw) { + enum cam_cdm_cb_status status; + + status = reset_err ? + CAM_CDM_CB_STATUS_HW_ERROR : + CAM_CDM_CB_STATUS_HW_RESUBMIT; + cam_cdm_notify_clients(cdm_hw, (node->client_hdl == handle) ? CAM_CDM_CB_STATUS_HW_FLUSH : - CAM_CDM_CB_STATUS_HW_RESUBMIT, + status, (void *)node); + } else cam_cdm_notify_clients(cdm_hw, CAM_CDM_CB_STATUS_HW_RESET_DONE, @@ -1245,7 +1319,7 @@ static void cam_hw_cdm_work(struct work_struct *work) * to dump debug info */ cam_hw_cdm_pause_core(cdm_hw, true); - cam_hw_cdm_dump_core_debug_registers(cdm_hw); + cam_hw_cdm_dump_core_debug_registers(cdm_hw, true); if (payload->irq_status & CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK) { @@ -1284,6 +1358,8 @@ static void cam_hw_cdm_work(struct work_struct *work) CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK)) clear_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status); + } else { + CAM_ERR(CAM_CDM, "NULL payload"); } kfree(payload); payload = NULL; @@ -1306,16 +1382,8 @@ static void cam_hw_cdm_iommu_fault_handler(struct iommu_domain *domain, for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) mutex_lock(&core->bl_fifo[i].fifo_lock); if (cdm_hw->hw_state == CAM_HW_STATE_POWER_UP) { - /* - * First pause CDM, If it fails still proceed - * to dump debug info - */ - cam_hw_cdm_pause_core(cdm_hw, true); - cam_hw_cdm_dump_core_debug_registers(cdm_hw); - /* Resume CDM back */ - cam_hw_cdm_pause_core(cdm_hw, false); - } - else + cam_hw_cdm_dump_core_debug_registers(cdm_hw, true); + } else CAM_INFO(CAM_CDM, "CDM hw is power in off state"); for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) mutex_unlock(&core->bl_fifo[i].fifo_lock); @@ -1338,17 +1406,28 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data) struct cam_cdm_work_payload *payload[CAM_CDM_BL_FIFO_MAX] = {0}; uint32_t user_data = 0; uint32_t irq_status[CAM_CDM_BL_FIFO_MAX] = {0}; + uint32_t irq_context_summary = 0xF; bool work_status; int i; - CAM_DBG(CAM_CDM, "Got irq"); + CAM_DBG(CAM_CDM, "Got irq hw_version 0x%x", cdm_core->hw_version); spin_lock(&cdm_hw->hw_lock); if (cdm_hw->hw_state == CAM_HW_STATE_POWER_DOWN) { CAM_DBG(CAM_CDM, "CDM is in power down state"); spin_unlock(&cdm_hw->hw_lock); return IRQ_HANDLED; } + if (cdm_core->hw_version >= CAM_CDM_VERSION_2_1) { + if (cam_cdm_read_hw_reg(cdm_hw, + cdm_core->offsets->cmn_reg->irq_context_status, + &irq_context_summary)) { + CAM_ERR(CAM_CDM, "Failed to read CDM HW IRQ status"); + } + } for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo_irq; i++) { + if (!(BIT(i) & irq_context_summary)) + continue; + if (cam_cdm_read_hw_reg(cdm_hw, cdm_core->offsets->irq_reg[i]->irq_status, &irq_status[i])) { @@ -1613,7 +1692,7 @@ int cam_hw_cdm_handle_error_info( current_fifo, current_tag); /* dump cdm registers for further debug */ - cam_hw_cdm_dump_core_debug_registers(cdm_hw); + cam_hw_cdm_dump_core_debug_registers(cdm_hw, false); for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) { reset_val = reset_val | @@ -1639,7 +1718,7 @@ int cam_hw_cdm_handle_error_info( if (time_left <= 0) { rc = -ETIMEDOUT; CAM_ERR(CAM_CDM, "CDM HW reset Wait failed rc=%d", rc); - goto end; + set_bit(CAM_CDM_RESET_ERR_STATUS, &cdm_core->cdm_status); } rc = cam_hw_cdm_set_cdm_core_cfg(cdm_hw); @@ -1678,6 +1757,7 @@ int cam_hw_cdm_handle_error_info( end: clear_bit(CAM_CDM_FLUSH_HW_STATUS, &cdm_core->cdm_status); clear_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status); + clear_bit(CAM_CDM_RESET_ERR_STATUS, &cdm_core->cdm_status); for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) mutex_unlock(&cdm_core->bl_fifo[i].fifo_lock); diff --git a/techpack/camera/drivers/cam_cdm/cam_cdm_hw_reg_2_1.h b/techpack/camera/drivers/cam_cdm/cam_cdm_hw_reg_2_1.h new file mode 100644 index 000000000000..a12be17a3c4a --- /dev/null +++ b/techpack/camera/drivers/cam_cdm/cam_cdm_hw_reg_2_1.h @@ -0,0 +1,253 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#include "cam_cdm.h" + +struct cam_cdm_bl_pending_req_reg_params cdm_hw_2_1_bl_pending_req0 = { + .rb_offset = 0x6c, + .rb_mask = 0x1ff, + .rb_num_fifo = 0x2, + .rb_next_fifo_shift = 0x10, +}; + +struct cam_cdm_bl_pending_req_reg_params cdm_hw_2_1_bl_pending_req1 = { + .rb_offset = 0x70, + .rb_mask = 0x1ff, + .rb_num_fifo = 0x2, + .rb_next_fifo_shift = 0x10, +}; + +static struct cam_cdm_irq_regs cdm_hw_2_1_irq0 = { + .irq_mask = 0x30, + .irq_clear = 0x34, + .irq_clear_cmd = 0x38, + .irq_set = 0x3c, + .irq_set_cmd = 0x40, + .irq_status = 0x44, +}; + +static struct cam_cdm_irq_regs cdm_hw_2_1_irq1 = { + .irq_mask = 0x130, + .irq_clear = 0x134, + .irq_clear_cmd = 0x138, + .irq_set = 0x13c, + .irq_set_cmd = 0x140, + .irq_status = 0x144, +}; + +static struct cam_cdm_irq_regs cdm_hw_2_1_irq2 = { + .irq_mask = 0x230, + .irq_clear = 0x234, + .irq_clear_cmd = 0x238, + .irq_set = 0x23c, + .irq_set_cmd = 0x240, + .irq_status = 0x244, +}; + +static struct cam_cdm_irq_regs cdm_hw_2_1_irq3 = { + .irq_mask = 0x330, + .irq_clear = 0x334, + .irq_clear_cmd = 0x338, + .irq_set = 0x33c, + .irq_set_cmd = 0x340, + .irq_status = 0x344, +}; + +static struct cam_cdm_bl_fifo_regs cdm_hw_2_1_bl_fifo0 = { + .bl_fifo_base = 0x50, + .bl_fifo_len = 0x54, + .bl_fifo_store = 0x58, + .bl_fifo_cfg = 0x5c, +}; + +static struct cam_cdm_bl_fifo_regs cdm_hw_2_1_bl_fifo1 = { + .bl_fifo_base = 0x150, + .bl_fifo_len = 0x154, + .bl_fifo_store = 0x158, + .bl_fifo_cfg = 0x15c, +}; + +static struct cam_cdm_bl_fifo_regs cdm_hw_2_1_bl_fifo2 = { + .bl_fifo_base = 0x250, + .bl_fifo_len = 0x254, + .bl_fifo_store = 0x258, + .bl_fifo_cfg = 0x25c, +}; + +static struct cam_cdm_bl_fifo_regs cdm_hw_2_1_bl_fifo3 = { + .bl_fifo_base = 0x350, + .bl_fifo_len = 0x354, + .bl_fifo_store = 0x358, + .bl_fifo_cfg = 0x35c, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg0 = { + .scratch_reg = 0x90, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg1 = { + .scratch_reg = 0x94, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg2 = { + .scratch_reg = 0x98, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg3 = { + .scratch_reg = 0x9c, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg4 = { + .scratch_reg = 0xa0, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg5 = { + .scratch_reg = 0xa4, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg6 = { + .scratch_reg = 0xa8, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg7 = { + .scratch_reg = 0xac, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg8 = { + .scratch_reg = 0xb0, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg9 = { + .scratch_reg = 0xb4, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg10 = { + .scratch_reg = 0xb8, +}; + +static struct cam_cdm_scratch_reg cdm_2_1_scratch_reg11 = { + .scratch_reg = 0xbc, +}; + +static struct cam_cdm_perf_mon_regs cdm_2_1_perf_mon0 = { + .perf_mon_ctrl = 0x110, + .perf_mon_0 = 0x114, + .perf_mon_1 = 0x118, + .perf_mon_2 = 0x11c, +}; + +static struct cam_cdm_perf_mon_regs cdm_2_1_perf_mon1 = { + .perf_mon_ctrl = 0x120, + .perf_mon_0 = 0x124, + .perf_mon_1 = 0x128, + .perf_mon_2 = 0x12c, +}; + +static struct cam_cdm_comp_wait_status cdm_2_1_comp_wait_status0 = { + .comp_wait_status = 0x88, +}; + +static struct cam_cdm_comp_wait_status cdm_2_1_comp_wait_status1 = { + .comp_wait_status = 0x8c, +}; + +static struct cam_cdm_icl_data_regs cdm_2_1_icl_data = { + .icl_last_data_0 = 0x1c0, + .icl_last_data_1 = 0x1c4, + .icl_last_data_2 = 0x1c8, + .icl_inv_data = 0x1cc, +}; + +static struct cam_cdm_icl_misc_regs cdm_2_1_icl_misc = { + .icl_inv_bl_addr = 0x1d0, + .icl_status = 0x1d8, +}; + +static struct cam_cdm_icl_regs cdm_2_1_icl = { + .data_regs = &cdm_2_1_icl_data, + .misc_regs = &cdm_2_1_icl_misc, +}; + +static struct cam_cdm_common_regs cdm_hw_2_1_cmn_reg_offset = { + .cdm_hw_version = 0x0, + .cam_version = NULL, + .rst_cmd = 0x10, + .cgc_cfg = 0x14, + .core_cfg = 0x18, + .core_en = 0x1c, + .fe_cfg = 0x20, + .irq_context_status = 0x2c, + .bl_fifo_rb = 0x60, + .bl_fifo_base_rb = 0x64, + .bl_fifo_len_rb = 0x68, + .usr_data = 0x80, + .wait_status = 0x84, + .last_ahb_addr = 0xd0, + .last_ahb_data = 0xd4, + .core_debug = 0xd8, + .last_ahb_err_addr = 0xe0, + .last_ahb_err_data = 0xe4, + .current_bl_base = 0xe8, + .current_bl_len = 0xec, + .current_used_ahb_base = 0xf0, + .debug_status = 0xf4, + .bus_misr_cfg0 = 0x100, + .bus_misr_cfg1 = 0x104, + .bus_misr_rd_val = 0x108, + .pending_req = { + &cdm_hw_2_1_bl_pending_req0, + &cdm_hw_2_1_bl_pending_req1, + }, + .comp_wait = { + &cdm_2_1_comp_wait_status0, + &cdm_2_1_comp_wait_status1, + }, + .perf_mon = { + &cdm_2_1_perf_mon0, + &cdm_2_1_perf_mon1, + }, + .scratch = { + &cdm_2_1_scratch_reg0, + &cdm_2_1_scratch_reg1, + &cdm_2_1_scratch_reg2, + &cdm_2_1_scratch_reg3, + &cdm_2_1_scratch_reg4, + &cdm_2_1_scratch_reg5, + &cdm_2_1_scratch_reg6, + &cdm_2_1_scratch_reg7, + &cdm_2_1_scratch_reg8, + &cdm_2_1_scratch_reg9, + &cdm_2_1_scratch_reg10, + &cdm_2_1_scratch_reg11, + }, + .perf_reg = NULL, + .icl_reg = &cdm_2_1_icl, + .spare = 0x3fc, +}; + +static struct cam_cdm_common_reg_data cdm_hw_2_1_cmn_reg_data = { + .num_bl_fifo = 0x4, + .num_bl_fifo_irq = 0x4, + .num_bl_pending_req_reg = 0x2, + .num_scratch_reg = 0xc, +}; + +struct cam_cdm_hw_reg_offset cam_cdm_2_1_reg_offset = { + .cmn_reg = &cdm_hw_2_1_cmn_reg_offset, + .bl_fifo_reg = { + &cdm_hw_2_1_bl_fifo0, + &cdm_hw_2_1_bl_fifo1, + &cdm_hw_2_1_bl_fifo2, + &cdm_hw_2_1_bl_fifo3, + }, + .irq_reg = { + &cdm_hw_2_1_irq0, + &cdm_hw_2_1_irq1, + &cdm_hw_2_1_irq2, + &cdm_hw_2_1_irq3, + }, + .reg_data = &cdm_hw_2_1_cmn_reg_data, +}; + diff --git a/techpack/camera/drivers/cam_cdm/cam_cdm_intf.c b/techpack/camera/drivers/cam_cdm/cam_cdm_intf.c index 3d50beb4cf43..4beeb71d2181 100644 --- a/techpack/camera/drivers/cam_cdm/cam_cdm_intf.c +++ b/techpack/camera/drivers/cam_cdm/cam_cdm_intf.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -506,6 +506,32 @@ int cam_cdm_detect_hang_error(uint32_t handle) } EXPORT_SYMBOL(cam_cdm_detect_hang_error); +int cam_cdm_dump_debug_registers(uint32_t handle) +{ + uint32_t hw_index; + int rc = -EINVAL; + struct cam_hw_intf *hw; + + if (get_cdm_mgr_refcount()) { + CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed"); + rc = -EPERM; + return rc; + } + + hw_index = CAM_CDM_GET_HW_IDX(handle); + if (hw_index < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM) { + hw = cdm_mgr.nodes[hw_index].device; + if (hw && hw->hw_ops.process_cmd) + rc = hw->hw_ops.process_cmd(hw->hw_priv, + CAM_CDM_HW_INTF_DUMP_DBG_REGS, + &handle, + sizeof(handle)); + } + put_cdm_mgr_refcount(); + + return rc; +} + int cam_cdm_intf_register_hw_cdm(struct cam_hw_intf *hw, struct cam_cdm_private_dt_data *data, enum cam_cdm_type type, uint32_t *index) diff --git a/techpack/camera/drivers/cam_cdm/cam_cdm_intf_api.h b/techpack/camera/drivers/cam_cdm/cam_cdm_intf_api.h index 25d0a5db88ed..1e9cc3455a0f 100644 --- a/techpack/camera/drivers/cam_cdm/cam_cdm_intf_api.h +++ b/techpack/camera/drivers/cam_cdm/cam_cdm_intf_api.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CDM_API_H_ @@ -296,4 +296,13 @@ struct cam_cdm_utils_ops *cam_cdm_publish_ops(void); * @return 0 on success */ int cam_cdm_detect_hang_error(uint32_t handle); + +/** + * @brief : API to dump the CDM Debug registers + * + * @handle : Input handle of the CDM to dump the registers + * + * @return 0 on success + */ +int cam_cdm_dump_debug_registers(uint32_t handle); #endif /* _CAM_CDM_API_H_ */ diff --git a/techpack/camera/drivers/cam_cdm/cam_cdm_soc.h b/techpack/camera/drivers/cam_cdm/cam_cdm_soc.h index 137922e1bd35..320c406feac3 100644 --- a/techpack/camera/drivers/cam_cdm/cam_cdm_soc.h +++ b/techpack/camera/drivers/cam_cdm/cam_cdm_soc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CDM_SOC_H_ @@ -13,6 +13,9 @@ #define CAM_HW_CDM_IFE_NAME_1_2 "qcom,cam-ife-cdm1_2" #define CAM_HW_CDM_CPAS_NAME_2_0 "qcom,cam-cpas-cdm2_0" #define CAM_HW_CDM_OPE_NAME_2_0 "qcom,cam-ope-cdm2_0" +#define CAM_HW_CDM_CPAS_NAME_2_1 "qcom,cam-cpas-cdm2_1" +#define CAM_HW_CDM_OPE_NAME_2_1 "qcom,cam-ope-cdm2_1" +#define CAM_HW_CDM_IFE_NAME_2_1 "qcom,cam-ife-cdm2_1" int cam_hw_cdm_soc_get_dt_properties(struct cam_hw_info *cdm_hw, const struct of_device_id *table); diff --git a/techpack/camera/drivers/cam_cpas/cam_cpas_soc.c b/techpack/camera/drivers/cam_cpas/cam_cpas_soc.c index f6906025f368..2694c5ebaa1d 100644 --- a/techpack/camera/drivers/cam_cpas/cam_cpas_soc.c +++ b/techpack/camera/drivers/cam_cpas/cam_cpas_soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. */ #include @@ -529,6 +529,10 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw, (u32 *)&soc_private->camnoc_axi_min_ib_bw); } + soc_private->custom_id = 0; + rc = of_property_read_u32(of_node, + "custom-id", + &soc_private->custom_id); if (rc) { CAM_DBG(CAM_CPAS, "failed to read camnoc-axi-min-ib-bw rc:%d", rc); diff --git a/techpack/camera/drivers/cam_cpas/cam_cpas_soc.h b/techpack/camera/drivers/cam_cpas/cam_cpas_soc.h index 46c748fbb12f..c1e65803aff8 100644 --- a/techpack/camera/drivers/cam_cpas/cam_cpas_soc.h +++ b/techpack/camera/drivers/cam_cpas/cam_cpas_soc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. */ #ifndef _CAM_CPAS_SOC_H_ @@ -109,6 +109,8 @@ struct cam_cpas_feature_info { * @feature_info: fuse based feature info for hw supported features * @cx_ipeak_gpu_limit: Flag for Cx Ipeak GPU mitigation * @gpu_pwr_limit: Handle for Cx Ipeak GPU Mitigation + * @custom_id: Custom id to differentiate between target if + * cpas version is same * */ struct cam_cpas_private_soc { @@ -129,6 +131,7 @@ struct cam_cpas_private_soc { struct cam_cpas_feature_info feature_info[CAM_CPAS_MAX_FUSE_FEATURE]; uint32_t cx_ipeak_gpu_limit; struct kgsl_pwr_limit *gpu_pwr_limit; + uint32_t custom_id; }; void cam_cpas_util_debug_parse_data(struct cam_cpas_private_soc *soc_private); diff --git a/techpack/camera/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/techpack/camera/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index f6af26fc579d..c8d96bd3672e 100644 --- a/techpack/camera/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/techpack/camera/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -24,6 +24,7 @@ #include "cpastop_v480_100.h" #include "cpastop_v540_100.h" #include "cpastop_v520_100.h" +#include "cpastop_v545_110_518.h" #include "cam_req_mgr_workq.h" struct cam_camnoc_info *camnoc_info; @@ -133,6 +134,14 @@ static int cam_cpastop_get_hw_info(struct cam_hw_info *cpas_hw, (hw_caps->camera_version.minor == 2) && (hw_caps->camera_version.incr == 0)) { soc_info->hw_version = CAM_CPAS_TITAN_520_V100; + } else if ((hw_caps->camera_version.major == 5) && + (hw_caps->camera_version.minor == 4) && + (hw_caps->camera_version.incr == 5)) { + if ((hw_caps->cpas_version.major == 1) && + (hw_caps->cpas_version.minor == 1) && + (hw_caps->cpas_version.incr == 0)) { + soc_info->hw_version = CAM_CPAS_TITAN_545_V110; + } } CAM_DBG(CAM_CPAS, "CPAS HW VERSION %x", soc_info->hw_version); @@ -605,6 +614,7 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, { int rc = 0; struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; + struct cam_cpas_private_soc *soc_private; CAM_DBG(CAM_CPAS, "hw_version=0x%x Camera Version %d.%d.%d, cpas version %d.%d.%d", @@ -647,6 +657,12 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, case CAM_CPAS_TITAN_520_V100: camnoc_info = &cam520_cpas100_camnoc_info; break; + case CAM_CPAS_TITAN_545_V110: + soc_private = (struct cam_cpas_private_soc *) + soc_info->soc_private; + if (soc_private->custom_id == CAM_CPAS_TITAN_SOC_ID_518) + camnoc_info = &cam545_cpas110_socid518_camnoc_info; + break; default: CAM_ERR(CAM_CPAS, "Camera Version not supported %d.%d.%d", hw_caps->camera_version.major, diff --git a/techpack/camera/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h b/techpack/camera/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h index 597f988f7de9..6a13d35b3e39 100644 --- a/techpack/camera/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h +++ b/techpack/camera/drivers/cam_cpas/cpas_top/cam_cpastop_hw.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CPASTOP_HW_H_ @@ -107,6 +107,8 @@ enum cam_camnoc_hw_irq_type { * @CAM_CAMNOC_FD: Indicates FD HW connection to camnoc * @CAM_CAMNOC_ICP: Indicates ICP HW connection to camnoc * @CAM_CAMNOC_TFE: Indicates TFE HW connection to camnoc + * @CAM_CAMNOC_TFE_1 : Indicates TFE1 HW connection to camnoc + * @CAM_CAMNOC_TFE_2 : Indicates TFE2 HW connection to camnoc * @CAM_CAMNOC_OPE: Indicates OPE HW connection to camnoc */ enum cam_camnoc_port_type { @@ -131,6 +133,8 @@ enum cam_camnoc_port_type { CAM_CAMNOC_FD, CAM_CAMNOC_ICP, CAM_CAMNOC_TFE, + CAM_CAMNOC_TFE_1, + CAM_CAMNOC_TFE_2, CAM_CAMNOC_OPE, }; diff --git a/techpack/camera/drivers/cam_cpas/cpas_top/cpastop_v545_110_518.h b/techpack/camera/drivers/cam_cpas/cpas_top/cpastop_v545_110_518.h new file mode 100644 index 000000000000..2948f4217878 --- /dev/null +++ b/techpack/camera/drivers/cam_cpas/cpas_top/cpastop_v545_110_518.h @@ -0,0 +1,320 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#ifndef _CPASTOP_V545_110_518_H_ +#define _CPASTOP_V545_110_518_H_ + +#define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas_v545_110_socid518_irq_sbm = { + .sbm_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0xA40, /* SBM_FAULTINEN0_LOW */ + .value = 0x1 | /* SBM_FAULTINEN0_LOW_PORT0_MASK*/ + (TEST_IRQ_ENABLE ? + 0x2 : /* SBM_FAULTINEN0_LOW_PORT6_MASK */ + 0x0) /* SBM_FAULTINEN0_LOW_PORT1_MASK */, + }, + .sbm_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xA48, /* SBM_FAULTINSTATUS0_LOW */ + }, + .sbm_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0xA80, /* SBM_FLAGOUTCLR0_LOW */ + .value = TEST_IRQ_ENABLE ? 0x3 : 0x1, + } +}; + +static struct cam_camnoc_irq_err + cam_cpas_v545_110_socid518_irq_err[] = { + { + .irq_type = CAM_CAMNOC_HW_IRQ_SLAVE_ERROR, + .enable = true, + .sbm_port = 0x1, /* SBM_FAULTINSTATUS0_LOW_PORT0_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0xD08, /* ERRORLOGGER_MAINCTL_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xD10, /* ERRORLOGGER_ERRVLD_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0xD18, /* ERRORLOGGER_ERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_CAMNOC_TEST, + .enable = TEST_IRQ_ENABLE ? true : false, + .sbm_port = 0x2, /* SBM_FAULTINSTATUS0_LOW_PORT6_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0xA88, /* SBM_FLAGOUTSET0_LOW */ + .value = 0x1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xA90, /* SBM_FLAGOUTSTATUS0_LOW */ + }, + .err_clear = { + .enable = false, + }, + }, +}; + + +static struct cam_camnoc_specific + cam_cpas_v545_110_socid518_camnoc_specific[] = { + { + .port_type = CAM_CAMNOC_CDM, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE30, /* CDM_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE34, /* CDM_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE38, /* CDM_URGENCY_LOW */ + .value = 0x00000003, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE40, /* CDM_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xE48, /* CDM_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_TFE, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_LOW */ + .offset = 0x30, + .value = 0x44443333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_HIGH */ + .offset = 0x34, + .value = 0x66665555, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x38, /* TFE_URGENCY_LOW */ + .value = 0x00001030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x40, /* TFE_DANGERLUT_LOW */ + .value = 0xFFFF0000, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x48, /* TFE_SAFELUT_LOW */ + .value = 0x00000003, + }, + .ubwc_ctl = { + /* + * Do not explicitly set ubwc config register. + * Power on default values are taking care of required + * register settings. + */ + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_TFE_1, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_LOW */ + .offset = 0x4030, + .value = 0x44443333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_HIGH */ + .offset = 0x4034, + .value = 0x66665555, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x4038, /* TFE_URGENCY_LOW */ + .value = 0x00001030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x4040, /* TFE_DANGERLUT_LOW */ + .value = 0xFFFF0000, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x4048, /* TFE_SAFELUT_LOW */ + .value = 0x00000003, + }, + }, + { + .port_type = CAM_CAMNOC_TFE_2, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_LOW */ + .offset = 0x5030, + .value = 0x44443333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + /* TFE_PRIORITYLUT_HIGH */ + .offset = 0x5034, + .value = 0x66665555, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x5038, /* TFE_URGENCY_LOW */ + .value = 0x00001030, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x5040, /* TFE_DANGERLUT_LOW */ + .value = 0xFFFF0000, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x5048, /* TFE_SAFELUT_LOW */ + .value = 0x00000003, + }, + }, + { + .port_type = CAM_CAMNOC_OPE, + .enable = true, + .priority_lut_low = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x430, /* OPE_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x434, /* OPE_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x438, /* OPE_URGENCY_LOW */ + .value = 0x00000033, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x440, /* OPE_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x448, /* OPE_SAFELUT_LOW */ + .value = 0xF, + }, + .ubwc_ctl = { + /* + * Do not explicitly set ubwc config register. + * Power on default values are taking care of required + * register settings. + */ + .enable = false, + }, + }, +}; + +static struct cam_camnoc_err_logger_info + cam545_cpas110_socid518_err_logger_offsets = { + .mainctrl = 0xD08, /* ERRLOGGER_MAINCTL_LOW */ + .errvld = 0xD10, /* ERRLOGGER_ERRVLD_LOW */ + .errlog0_low = 0xD20, /* ERRLOGGER_ERRLOG0_LOW */ + .errlog0_high = 0xD24, /* ERRLOGGER_ERRLOG0_HIGH */ + .errlog1_low = 0xD28, /* ERRLOGGER_ERRLOG1_LOW */ + .errlog1_high = 0xD2C, /* ERRLOGGER_ERRLOG1_HIGH */ + .errlog2_low = 0xD30, /* ERRLOGGER_ERRLOG2_LOW */ + .errlog2_high = 0xD34, /* ERRLOGGER_ERRLOG2_HIGH */ + .errlog3_low = 0xD38, /* ERRLOGGER_ERRLOG3_LOW */ + .errlog3_high = 0xD3C, /* ERRLOGGER_ERRLOG3_HIGH */ +}; + +static struct cam_camnoc_info cam545_cpas110_socid518_camnoc_info = { + .specific = &cam_cpas_v545_110_socid518_camnoc_specific[0], + .specific_size = + ARRAY_SIZE(cam_cpas_v545_110_socid518_camnoc_specific), + .irq_sbm = &cam_cpas_v545_110_socid518_irq_sbm, + .irq_err = &cam_cpas_v545_110_socid518_irq_err[0], + .irq_err_size = ARRAY_SIZE(cam_cpas_v545_110_socid518_irq_err), + .err_logger = &cam545_cpas110_socid518_err_logger_offsets, + .errata_wa_list = NULL, +}; + +#endif /* _CPASTOP_V545_110_518_H_ */ diff --git a/techpack/camera/drivers/cam_cpas/include/cam_cpas_api.h b/techpack/camera/drivers/cam_cpas/include/cam_cpas_api.h index 9dd3be1ff0d6..4c1a51119693 100644 --- a/techpack/camera/drivers/cam_cpas/include/cam_cpas_api.h +++ b/techpack/camera/drivers/cam_cpas/include/cam_cpas_api.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CPAS_API_H_ @@ -48,9 +48,19 @@ enum cam_cpas_hw_version { CAM_CPAS_TITAN_480_V100 = 0x480100, CAM_CPAS_TITAN_540_V100 = 0x540100, CAM_CPAS_TITAN_520_V100 = 0x520100, + CAM_CPAS_TITAN_545_V110 = 0x545110, CAM_CPAS_TITAN_MAX }; +/** + * enum cam_cpas_hw_soc_id - Enum for Titan soc id + */ +enum cam_cpas_hw_soc_id { + CAM_CPAS_TITAN_SOC_ID_507 = 507, + CAM_CPAS_TITAN_SOC_ID_518 = 518, + CAM_CPAS_TITAN_SOC_ID_MAX +}; + /** * enum cam_camnoc_irq_type - Enum for camnoc irq types * diff --git a/techpack/camera/drivers/cam_isp/cam_isp_context.c b/techpack/camera/drivers/cam_isp/cam_isp_context.c index 1e772dedc24f..f3da6ad1c7e2 100644 --- a/techpack/camera/drivers/cam_isp/cam_isp_context.c +++ b/techpack/camera/drivers/cam_isp/cam_isp_context.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -3066,6 +3066,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied( ctx_isp->frame_id, ctx->ctx_id); ctx->ctx_crm_intf->notify_err(¬ify); + atomic_set(&ctx_isp->process_bubble, 1); } else { req_isp->bubble_report = 0; } @@ -3123,6 +3124,44 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( ctx_isp->boot_timestamp = sof_event_data->boot_time; CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx", ctx_isp->frame_id, ctx_isp->sof_timestamp_val); + + + if (atomic_read(&ctx_isp->process_bubble)) { + if (list_empty(&ctx->active_req_list)) { + CAM_ERR(CAM_ISP, "No available active req in bubble"); + atomic_set(&ctx_isp->process_bubble, 0); + return -EINVAL; + } + + if (ctx_isp->last_sof_timestamp == + ctx_isp->sof_timestamp_val) { + CAM_DBG(CAM_ISP, + "Tasklet delay detected! Bubble frame: %lld check skipped, sof_timestamp: %lld, ctx_id: %d", + ctx_isp->frame_id, + ctx_isp->sof_timestamp_val, + ctx->ctx_id); + goto end; + } + + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + + if (req_isp->bubble_detected) { + req_isp->num_acked = 0; + req_isp->bubble_detected = false; + list_del_init(&req->list); + list_add(&req->list, &ctx->pending_req_list); + atomic_set(&ctx_isp->process_bubble, 0); + ctx_isp->active_req_cnt--; + CAM_DBG(CAM_REQ, + "Move active req: %lld to pending list(cnt = %d) [bubble re-apply],ctx %u", + req->request_id, + ctx_isp->active_req_cnt, ctx->ctx_id); + goto end; + } + } + /* * Signal all active requests with error and move the all the active * requests to free list @@ -3144,6 +3183,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( ctx_isp->active_req_cnt--; } +end: /* notify reqmgr with sof signal */ if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) { notify.link_hdl = ctx->link_hdl; @@ -3174,6 +3214,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( __cam_isp_ctx_substate_val_to_type( ctx_isp->substate_activated)); + ctx_isp->last_sof_timestamp = ctx_isp->sof_timestamp_val; return 0; } @@ -3426,6 +3467,7 @@ static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx, ctx_isp->hw_acquired = false; ctx_isp->init_received = false; ctx_isp->req_info.last_bufdone_req_id = 0; + ctx_isp->last_sof_timestamp = 0; atomic64_set(&ctx_isp->state_monitor_head, -1); @@ -3490,6 +3532,7 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx, ctx_isp->init_received = false; ctx_isp->rdi_only_context = false; ctx_isp->req_info.last_bufdone_req_id = 0; + ctx_isp->last_sof_timestamp = 0; atomic64_set(&ctx_isp->state_monitor_head, -1); for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) @@ -3830,6 +3873,7 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx, ctx_isp->hw_acquired = true; ctx_isp->split_acquire = false; ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; + ctx_isp->last_sof_timestamp = 0; atomic64_set(&ctx_isp->state_monitor_head, -1); for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) @@ -3987,6 +4031,7 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx, ctx_isp->hw_ctx = param.ctxt_to_hw_map; ctx_isp->hw_acquired = true; ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; + ctx_isp->last_sof_timestamp = 0; atomic64_set(&ctx_isp->state_monitor_head, -1); @@ -4132,6 +4177,7 @@ static int __cam_isp_ctx_acquire_hw_v2(struct cam_context *ctx, ctx_isp->hw_ctx = param.ctxt_to_hw_map; ctx_isp->hw_acquired = true; ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; + ctx_isp->last_sof_timestamp = 0; trace_cam_context_state("ISP", ctx); CAM_DBG(CAM_ISP, @@ -4390,9 +4436,11 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx, /* HW failure. user need to clean up the resource */ CAM_ERR(CAM_ISP, "Start HW failed"); ctx->state = CAM_CTX_READY; - trace_cam_context_state("ISP", ctx); - if (rc == -ETIMEDOUT) + if ((rc == -ETIMEDOUT) && + (isp_ctx_debug.enable_cdm_cmd_buff_dump)) rc = cam_isp_ctx_dump_req(req_isp, 0, 0, NULL, false); + + trace_cam_context_state("ISP", ctx); list_del_init(&req->list); list_add(&req->list, &ctx->pending_req_list); goto end; @@ -4953,8 +5001,15 @@ static int cam_isp_context_debug_register(void) goto err; } - return 0; + if (!debugfs_create_u32("enable_cdm_cmd_buffer_dump", + 0644, + isp_ctx_debug.dentry, + &isp_ctx_debug.enable_cdm_cmd_buff_dump)) { + CAM_ERR(CAM_ISP, "failed to create enable_cdm_cmd_buffer_dump"); + goto err; + } + return 0; err: debugfs_remove_recursive(isp_ctx_debug.dentry); return -ENOMEM; diff --git a/techpack/camera/drivers/cam_isp/cam_isp_context.h b/techpack/camera/drivers/cam_isp/cam_isp_context.h index a98f1d874d5a..72d35cb7e9f9 100644 --- a/techpack/camera/drivers/cam_isp/cam_isp_context.h +++ b/techpack/camera/drivers/cam_isp/cam_isp_context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_ISP_CONTEXT_H_ @@ -110,13 +110,15 @@ enum cam_isp_state_change_trigger { /** * struct cam_isp_ctx_debug - Contains debug parameters * - * @dentry: Debugfs entry - * @enable_state_monitor_dump: Enable isp state monitor dump + * @dentry: Debugfs entry + * @enable_state_monitor_dump: Enable isp state monitor dump + * @enable_cdm_cmd_buff_dump: Enable CDM Command buffer dump * */ struct cam_isp_ctx_debug { struct dentry *dentry; uint32_t enable_state_monitor_dump; + uint32_t enable_cdm_cmd_buff_dump; }; /** @@ -232,6 +234,7 @@ struct cam_isp_context_event_record { * @req_isp: ISP private request object storage * @hw_ctx: HW object returned by the acquire device command * @sof_timestamp_val: Captured time stamp value at sof hw event + * @last_sof_timestamp: Time stamp value for last SOF event * @boot_timestamp: Boot time stamp for a given req_id * @active_req_cnt: Counter for the active request * @reported_req_id: Last reported request id @@ -268,6 +271,7 @@ struct cam_isp_context { void *hw_ctx; uint64_t sof_timestamp_val; + uint64_t last_sof_timestamp; uint64_t boot_timestamp; int32_t active_req_cnt; int64_t reported_req_id; diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c b/techpack/camera/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c index 298a2b0c1933..8a783915e4c9 100644 --- a/techpack/camera/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include @@ -2971,6 +2971,17 @@ static int cam_tfe_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args) sizeof(g_tfe_hw_mgr.debug_cfg.csid_debug)); } + /* set tpg debug information for top tpg */ + for (i = 0; i < CAM_TOP_TPG_HW_NUM_MAX; i++) { + if (g_tfe_hw_mgr.tpg_devices[i]) { + rc = g_tfe_hw_mgr.tpg_devices[i]->hw_ops.process_cmd( + g_tfe_hw_mgr.tpg_devices[i]->hw_priv, + CAM_ISP_HW_CMD_TPG_SET_PATTERN, + &g_tfe_hw_mgr.debug_cfg.set_tpg_pattern, + sizeof(g_tfe_hw_mgr.debug_cfg.set_tpg_pattern)); + } + } + camif_debug = g_tfe_hw_mgr.debug_cfg.camif_debug; list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { @@ -5450,6 +5461,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(cam_tfe_camif_debug, static int cam_tfe_hw_mgr_debug_register(void) { + g_tfe_hw_mgr.debug_cfg.set_tpg_pattern = CAM_TOP_TPG_DEFAULT_PATTERN; g_tfe_hw_mgr.debug_cfg.dentry = debugfs_create_dir("camera_tfe", NULL); @@ -5482,6 +5494,14 @@ static int cam_tfe_hw_mgr_debug_register(void) goto err; } + if (!debugfs_create_u32("set_tpg_pattern", + 0644, + g_tfe_hw_mgr.debug_cfg.dentry, + &g_tfe_hw_mgr.debug_cfg.set_tpg_pattern)) { + CAM_ERR(CAM_ISP, "failed to create set_tpg_pattern"); + goto err; + } + if (!debugfs_create_u32("enable_reg_dump", 0644, g_tfe_hw_mgr.debug_cfg.dentry, diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h b/techpack/camera/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h index 7b3d62b92c6a..f66ea4052bd5 100644 --- a/techpack/camera/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_TFE_HW_MGR_H_ @@ -30,6 +30,7 @@ * @enable_recovery: enable recovery * @enable_csid_recovery: enable csid recovery * @camif_debug: enable sensor diagnosis status + * @set_tpg_pattern: tpg pattern information * @enable_reg_dump: enable reg dump on error; * @per_req_reg_dump: Enable per request reg dump * @@ -40,6 +41,7 @@ struct cam_tfe_hw_mgr_debug { uint32_t enable_recovery; uint32_t enable_csid_recovery; uint32_t camif_debug; + uint32_t set_tpg_pattern; uint32_t enable_reg_dump; uint32_t per_req_reg_dump; }; diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index e0c2f55ef704..c5666158bd19 100644 --- a/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -140,6 +140,14 @@ static int cam_isp_update_dual_config( } hw_mgr_res = &res_list_isp_out[i]; + if (!hw_mgr_res) { + CAM_ERR(CAM_ISP, + "Invalid isp out resource i %d num_out_res %d", + i, dual_config->num_ports); + rc = -EINVAL; + goto end; + } + for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) { if (!hw_mgr_res->hw_res[j]) continue; diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/Makefile b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/Makefile index 67cf169a3569..e5158b69f19b 100644 --- a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/Makefile +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_SPECTRA_CAMERA) += top_tpg/ ifdef CONFIG_SPECTRA_CAMERA_TFE +obj-$(CONFIG_SPECTRA_CAMERA) += ppi_hw/ obj-$(CONFIG_SPECTRA_CAMERA) += tfe_csid_hw/ tfe_hw/ endif diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index e5610b98d528..4603b20b6a68 100644 --- a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_ISP_HW_H_ @@ -114,6 +114,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_TPG_PHY_CLOCK_UPDATE, CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP, CAM_ISP_HW_CMD_DUMP_HW, + CAM_ISP_HW_CMD_TPG_SET_PATTERN, CAM_ISP_HW_CMD_MAX, }; diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h index a773a23dfda4..224d4bbfb7b7 100644 --- a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_top_tpg_hw_intf.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_TOP_TPG_HW_INTF_H_ @@ -13,7 +13,8 @@ #define CAM_TOP_TPG_HW_NUM_MAX 2 /* Max supported number of DT for TPG */ #define CAM_TOP_TPG_MAX_SUPPORTED_DT 4 - +/* TPG default pattern should be color bar */ +#define CAM_TOP_TPG_DEFAULT_PATTERN 0x8 /** * enum cam_top_tpg_id - top tpg hw instance id */ diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/Makefile b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/Makefile new file mode 100644 index 000000000000..9c21987f7e70 --- /dev/null +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/Makefile @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_utils +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cdm/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_cpas/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ + +obj-$(CONFIG_SPECTRA_CAMERA) += cam_csid_ppi_dev.o cam_csid_ppi_core.o cam_csid_ppi100.o diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi100.c b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi100.c new file mode 100644 index 000000000000..7b2f449f277f --- /dev/null +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi100.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, 2021, The Linux Foundation. All rights reserved. + */ + +#include +#include "cam_csid_ppi_core.h" +#include "cam_csid_ppi100.h" +#include "cam_csid_ppi_dev.h" + +#define CAM_PPI_DRV_NAME "ppi_100" +#define CAM_PPI_VERSION_V100 0x10000000 + +static struct cam_csid_ppi_hw_info cam_csid_ppi100_hw_info = { + .ppi_reg = &cam_csid_ppi_100_reg_offset, +}; + +static const struct of_device_id cam_csid_ppi100_dt_match[] = { + { + .compatible = "qcom,ppi100", + .data = &cam_csid_ppi100_hw_info, + }, + {} +}; + +MODULE_DEVICE_TABLE(of, cam_csid_ppi100_dt_match); + +static struct platform_driver cam_csid_ppi100_driver = { + .probe = cam_csid_ppi_probe, + .remove = cam_csid_ppi_remove, + .driver = { + .name = CAM_PPI_DRV_NAME, + .of_match_table = cam_csid_ppi100_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_csid_ppi100_init_module(void) +{ + return platform_driver_register(&cam_csid_ppi100_driver); +} + +static void __exit cam_csid_ppi100_exit_module(void) +{ + platform_driver_unregister(&cam_csid_ppi100_driver); +} + +module_init(cam_csid_ppi100_init_module); +MODULE_DESCRIPTION("CAM CSID_PPI100 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi100.h b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi100.h new file mode 100644 index 000000000000..8aee24c13aef --- /dev/null +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi100.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, 2021, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CSID_PPI_100_H_ +#define _CAM_CSID_PPI_100_H_ + +#include "cam_csid_ppi_core.h" + +static struct cam_csid_ppi_reg_offset cam_csid_ppi_100_reg_offset = { + .ppi_hw_version_addr = 0, + .ppi_module_cfg_addr = 0x60, + .ppi_irq_status_addr = 0x68, + .ppi_irq_mask_addr = 0x6c, + .ppi_irq_set_addr = 0x70, + .ppi_irq_clear_addr = 0x74, + .ppi_irq_cmd_addr = 0x78, + .ppi_rst_cmd_addr = 0x7c, + .ppi_test_bus_ctrl_addr = 0x1f4, + .ppi_debug_addr = 0x1f8, + .ppi_spare_addr = 0x1fc, +}; + +#endif /*_CAM_CSID_PPI_100_H_ */ diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.c b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.c new file mode 100644 index 000000000000..63bd4e9a9b6f --- /dev/null +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.c @@ -0,0 +1,374 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, 2021, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include + +#include "cam_csid_ppi_core.h" +#include "cam_csid_ppi_dev.h" +#include "cam_soc_util.h" +#include "cam_debug_util.h" +#include "cam_io_util.h" + +static int cam_csid_ppi_reset(struct cam_csid_ppi_hw *ppi_hw) +{ + struct cam_hw_soc_info *soc_info; + const struct cam_csid_ppi_reg_offset *ppi_reg; + int rc = 0; + uint32_t status; + + soc_info = &ppi_hw->hw_info->soc_info; + ppi_reg = ppi_hw->ppi_info->ppi_reg; + + CAM_DBG(CAM_ISP, "PPI:%d reset", ppi_hw->hw_intf->hw_idx); + + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_mask_addr); + cam_io_w_mb(PPI_RST_CONTROL, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_set_addr); + cam_io_w_mb(PPI_RST_CONTROL, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_rst_cmd_addr); + cam_io_w_mb(PPI_IRQ_CMD_SET, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_cmd_addr); + + rc = readl_poll_timeout(soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_status_addr, status, + (status & 0x1) == 0x1, 1000, 500000); + CAM_DBG(CAM_ISP, "PPI:%d reset status %d", ppi_hw->hw_intf->hw_idx, + status); + if (rc < 0) { + CAM_ERR(CAM_ISP, "PPI:%d ppi_reset fail rc = %d status = %d", + ppi_hw->hw_intf->hw_idx, rc, status); + return rc; + } + cam_io_w_mb(PPI_RST_CONTROL, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_clear_addr); + cam_io_w_mb(PPI_IRQ_CMD_CLEAR, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_cmd_addr); + + return 0; +} + +static int cam_csid_ppi_enable_hw(struct cam_csid_ppi_hw *ppi_hw) +{ + int rc = 0; + int32_t i; + uint64_t val; + const struct cam_csid_ppi_reg_offset *ppi_reg; + struct cam_hw_soc_info *soc_info; + uint32_t err_irq_mask; + + ppi_reg = ppi_hw->ppi_info->ppi_reg; + soc_info = &ppi_hw->hw_info->soc_info; + + CAM_DBG(CAM_ISP, "PPI:%d init PPI HW", ppi_hw->hw_intf->hw_idx); + + ppi_hw->hw_info->open_count++; + if (ppi_hw->hw_info->open_count > 1) { + CAM_DBG(CAM_ISP, "PPI:%d dual vfe already enabled", + ppi_hw->hw_intf->hw_idx); + return 0; + } + + for (i = 0; i < soc_info->num_clk; i++) { + rc = cam_soc_util_clk_enable(soc_info->clk[i], + soc_info->clk_name[i], 0); + if (rc) + goto clk_disable; + } + + rc = cam_csid_ppi_reset(ppi_hw); + if (rc) + goto clk_disable; + + err_irq_mask = PPI_IRQ_FIFO0_OVERFLOW | PPI_IRQ_FIFO1_OVERFLOW | + PPI_IRQ_FIFO2_OVERFLOW; + cam_io_w_mb(err_irq_mask, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_mask_addr); + rc = cam_soc_util_irq_enable(soc_info); + if (rc) + goto clk_disable; + + cam_io_w_mb(PPI_RST_CONTROL, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_clear_addr); + cam_io_w_mb(PPI_IRQ_CMD_CLEAR, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_cmd_addr); + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + ppi_reg->ppi_hw_version_addr); + CAM_DBG(CAM_ISP, "PPI:%d PPI HW version: 0x%x", + ppi_hw->hw_intf->hw_idx, val); + ppi_hw->device_enabled = 1; + + return 0; +clk_disable: + for (--i; i >= 0; i--) + cam_soc_util_clk_disable(soc_info->clk[i], + soc_info->clk_name[i]); + ppi_hw->hw_info->open_count--; + return rc; +} + +static int cam_csid_ppi_disable_hw(struct cam_csid_ppi_hw *ppi_hw) +{ + int rc = 0; + int i; + struct cam_hw_soc_info *soc_info; + const struct cam_csid_ppi_reg_offset *ppi_reg; + uint64_t ppi_cfg_val = 0; + + CAM_DBG(CAM_ISP, "PPI:%d De-init PPI HW", + ppi_hw->hw_intf->hw_idx); + + if (!ppi_hw->hw_info->open_count) { + CAM_WARN(CAM_ISP, "ppi[%d] unbalanced disable hw", + ppi_hw->hw_intf->hw_idx); + return -EINVAL; + } + ppi_hw->hw_info->open_count--; + + if (ppi_hw->hw_info->open_count) + return rc; + + soc_info = &ppi_hw->hw_info->soc_info; + ppi_reg = ppi_hw->ppi_info->ppi_reg; + + CAM_DBG(CAM_ISP, "Calling PPI Reset"); + cam_csid_ppi_reset(ppi_hw); + CAM_DBG(CAM_ISP, "PPI Reset Done"); + + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_mask_addr); + cam_soc_util_irq_disable(soc_info); + + for (i = 0; i < CAM_CSID_PPI_LANES_MAX; i++) + ppi_cfg_val &= ~PPI_CFG_CPHY_DLX_EN(i); + + cam_io_w_mb(ppi_cfg_val, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_module_cfg_addr); + + ppi_hw->device_enabled = 0; + + for (i = 0; i < soc_info->num_clk; i++) + cam_soc_util_clk_disable(soc_info->clk[i], + soc_info->clk_name[i]); + + return rc; +} + +static int cam_csid_ppi_init_hw(void *hw_priv, void *init_args, + uint32_t arg_size) +{ + int i, rc = 0; + uint32_t num_lanes; + uint32_t cphy; + uint32_t ppi_cfg_val = 0; + struct cam_csid_ppi_hw *ppi_hw; + struct cam_hw_info *ppi_hw_info; + const struct cam_csid_ppi_reg_offset *ppi_reg; + struct cam_hw_soc_info *soc_info; + struct cam_csid_ppi_cfg ppi_cfg; + + if (!hw_priv || !init_args || + (arg_size != sizeof(struct cam_csid_ppi_cfg))) { + CAM_ERR(CAM_ISP, "PPI: Invalid args"); + rc = -EINVAL; + goto end; + } + + ppi_hw_info = (struct cam_hw_info *)hw_priv; + ppi_hw = (struct cam_csid_ppi_hw *)ppi_hw_info->core_info; + ppi_reg = ppi_hw->ppi_info->ppi_reg; + ppi_cfg = *((struct cam_csid_ppi_cfg *)init_args); + + rc = cam_csid_ppi_enable_hw(ppi_hw); + if (rc) + goto end; + + num_lanes = ppi_cfg.lane_num; + cphy = ppi_cfg.lane_type; + CAM_DBG(CAM_ISP, "lane_cfg 0x%x | num_lanes 0x%x | lane_type 0x%x", + ppi_cfg.lane_cfg, num_lanes, cphy); + + if (cphy) { + ppi_cfg_val |= PPI_CFG_CPHY_DLX_SEL(0); + ppi_cfg_val |= PPI_CFG_CPHY_DLX_SEL(1); + } else { + ppi_cfg_val = 0; + } + + for (i = 0; i < CAM_CSID_PPI_LANES_MAX; i++) + ppi_cfg_val |= PPI_CFG_CPHY_DLX_EN(i); + + CAM_DBG(CAM_ISP, "ppi_cfg_val 0x%x", ppi_cfg_val); + soc_info = &ppi_hw->hw_info->soc_info; + cam_io_w_mb(ppi_cfg_val, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_module_cfg_addr); + + CAM_DBG(CAM_ISP, "ppi cfg 0x%x", + cam_io_r_mb(soc_info->reg_map[0].mem_base + + ppi_reg->ppi_module_cfg_addr)); +end: + return rc; +} + +static int cam_csid_ppi_deinit_hw(void *hw_priv, void *deinit_args, + uint32_t arg_size) +{ + int rc = 0; + struct cam_csid_ppi_hw *ppi_hw; + struct cam_hw_info *ppi_hw_info; + + CAM_DBG(CAM_ISP, "Enter"); + + if (!hw_priv) { + CAM_ERR(CAM_ISP, "PPI:Invalid arguments"); + rc = -EINVAL; + goto end; + } + + ppi_hw_info = (struct cam_hw_info *)hw_priv; + ppi_hw = (struct cam_csid_ppi_hw *)ppi_hw_info->core_info; + + CAM_DBG(CAM_ISP, "Disabling PPI Hw"); + rc = cam_csid_ppi_disable_hw(ppi_hw); + if (rc < 0) + CAM_DBG(CAM_ISP, "Exit with %d", rc); +end: + return rc; +} + +int cam_csid_ppi_hw_probe_init(struct cam_hw_intf *ppi_hw_intf, + uint32_t ppi_idx) +{ + int rc = -EINVAL; + struct cam_hw_info *ppi_hw_info; + struct cam_csid_ppi_hw *csid_ppi_hw = NULL; + + if (ppi_idx >= CAM_CSID_PPI_HW_MAX) { + CAM_ERR(CAM_ISP, "Invalid ppi index:%d", ppi_idx); + goto err; + } + + ppi_hw_info = (struct cam_hw_info *) ppi_hw_intf->hw_priv; + csid_ppi_hw = (struct cam_csid_ppi_hw *) ppi_hw_info->core_info; + + csid_ppi_hw->hw_intf = ppi_hw_intf; + csid_ppi_hw->hw_info = ppi_hw_info; + + CAM_DBG(CAM_ISP, "type %d index %d", + csid_ppi_hw->hw_intf->hw_type, ppi_idx); + + rc = cam_csid_ppi_init_soc_resources(&csid_ppi_hw->hw_info->soc_info, + cam_csid_ppi_irq, csid_ppi_hw); + if (rc < 0) { + CAM_ERR(CAM_ISP, "PPI:%d Failed to init_soc", ppi_idx); + goto err; + } + + csid_ppi_hw->hw_intf->hw_ops.init = cam_csid_ppi_init_hw; + csid_ppi_hw->hw_intf->hw_ops.deinit = cam_csid_ppi_deinit_hw; + return 0; +err: + return rc; +} + +int cam_csid_ppi_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t ppi_irq_handler, void *irq_data) +{ + int rc = 0; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc) { + CAM_ERR(CAM_ISP, "PPI: Failed to get dt properties"); + goto end; + } + + rc = cam_soc_util_request_platform_resource(soc_info, ppi_irq_handler, + irq_data); + if (rc) { + CAM_ERR(CAM_ISP, + "PPI: Error Request platform resources failed rc=%d", + rc); + goto err; + } +end: + return rc; +err: + cam_soc_util_release_platform_resource(soc_info); + return rc; +} + +irqreturn_t cam_csid_ppi_irq(int irq_num, void *data) +{ + uint32_t irq_status = 0; + uint32_t i, ppi_cfg_val = 0; + bool fatal_err_detected = false; + + struct cam_csid_ppi_hw *ppi_hw; + struct cam_hw_soc_info *soc_info; + const struct cam_csid_ppi_reg_offset *ppi_reg; + + if (!data) { + CAM_ERR(CAM_ISP, "PPI: Invalid arguments"); + return IRQ_HANDLED; + } + + ppi_hw = (struct cam_csid_ppi_hw *)data; + ppi_reg = ppi_hw->ppi_info->ppi_reg; + soc_info = &ppi_hw->hw_info->soc_info; + + if (ppi_hw->device_enabled != 1) + goto ret; + + irq_status = cam_io_r_mb(soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_status_addr); + + cam_io_w_mb(irq_status, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_clear_addr); + + cam_io_w_mb(PPI_IRQ_CMD_CLEAR, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_cmd_addr); + + CAM_DBG(CAM_ISP, "PPI %d irq status 0x%x", ppi_hw->hw_intf->hw_idx, + irq_status); + + if (irq_status & PPI_IRQ_RST_DONE) { + CAM_DBG(CAM_ISP, "PPI Reset Done"); + goto ret; + } + if ((irq_status & PPI_IRQ_FIFO0_OVERFLOW) || + (irq_status & PPI_IRQ_FIFO1_OVERFLOW) || + (irq_status & PPI_IRQ_FIFO2_OVERFLOW)) { + fatal_err_detected = true; + goto handle_fatal_error; + } + +handle_fatal_error: + if (fatal_err_detected) { + CAM_ERR(CAM_ISP, "PPI: %d irq_status:0x%x", + ppi_hw->hw_intf->hw_idx, irq_status); + for (i = 0; i < CAM_CSID_PPI_LANES_MAX; i++) + ppi_cfg_val &= ~PPI_CFG_CPHY_DLX_EN(i); + + cam_io_w_mb(ppi_cfg_val, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_module_cfg_addr); + } +ret: + CAM_DBG(CAM_ISP, "IRQ Handling exit"); + return IRQ_HANDLED; +} + +int cam_csid_ppi_hw_deinit(struct cam_csid_ppi_hw *csid_ppi_hw) +{ + if (!csid_ppi_hw) { + CAM_ERR(CAM_ISP, "Invalid param"); + return -EINVAL; + } + return cam_soc_util_release_platform_resource( + &csid_ppi_hw->hw_info->soc_info); +} + + diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.h b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.h new file mode 100644 index 000000000000..777c4e3fb573 --- /dev/null +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, 2021, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CSID_PPI_HW_H_ +#define _CAM_CSID_PPI_HW_H_ + +#include "cam_hw.h" +#include "cam_hw_intf.h" + +#define CAM_CSID_PPI_HW_MAX 4 +#define CAM_CSID_PPI_LANES_MAX 3 + +#define PPI_IRQ_RST_DONE BIT(0) +#define PPI_IRQ_FIFO0_OVERFLOW BIT(1) +#define PPI_IRQ_FIFO1_OVERFLOW BIT(2) +#define PPI_IRQ_FIFO2_OVERFLOW BIT(3) + +#define PPI_IRQ_CMD_SET BIT(1) + +#define PPI_IRQ_CMD_CLEAR BIT(0) + +#define PPI_RST_CONTROL BIT(0) +/* + * Select the PHY (CPHY set '1' or DPHY set '0') + */ +#define PPI_CFG_CPHY_DLX_SEL(X) BIT(X) + +#define PPI_CFG_CPHY_DLX_EN(X) BIT(4+X) + +struct cam_csid_ppi_reg_offset { + uint32_t ppi_hw_version_addr; + uint32_t ppi_module_cfg_addr; + + uint32_t ppi_irq_status_addr; + uint32_t ppi_irq_mask_addr; + uint32_t ppi_irq_set_addr; + uint32_t ppi_irq_clear_addr; + uint32_t ppi_irq_cmd_addr; + uint32_t ppi_rst_cmd_addr; + uint32_t ppi_test_bus_ctrl_addr; + uint32_t ppi_debug_addr; + uint32_t ppi_spare_addr; +}; + +/** + * struct cam_csid_ppi_hw_info- ppi HW info + * + * @ppi_reg: ppi register offsets + * + */ +struct cam_csid_ppi_hw_info { + const struct cam_csid_ppi_reg_offset *ppi_reg; +}; + +/** + * struct cam_csid_ppi_hw- ppi hw device resources data + * + * @hw_intf: contain the ppi hw interface information + * @hw_info: ppi hw device information + * @ppi_info: ppi hw specific information + * @device_enabled Device enabled will set once ppi powered on and + * initial configuration are done. + * + */ +struct cam_csid_ppi_hw { + struct cam_hw_intf *hw_intf; + struct cam_hw_info *hw_info; + struct cam_csid_ppi_hw_info *ppi_info; + uint32_t device_enabled; +}; + +/** + * struct cam_csid_ppi_cfg - ppi lane configuration data + * @lane_type: lane type: c-phy or d-phy + * @lane_num : active lane number + * @lane_cfg: lane configurations: 4 bits per lane + * + */ +struct cam_csid_ppi_cfg { + uint32_t lane_type; + uint32_t lane_num; + uint32_t lane_cfg; +}; + +int cam_csid_ppi_hw_probe_init(struct cam_hw_intf *ppi_hw_intf, + uint32_t ppi_idx); +int cam_csid_ppi_hw_deinit(struct cam_csid_ppi_hw *csid_ppi_hw); +int cam_csid_ppi_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t ppi_irq_handler, void *irq_data); +int cam_csid_ppi_deinit_soc_resources(struct cam_hw_soc_info *soc_info); +int cam_csid_ppi_hw_init(struct cam_hw_intf **csid_ppi_hw, + uint32_t hw_idx); +#endif /* _CAM_CSID_PPI_HW_H_ */ diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_dev.c b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_dev.c new file mode 100644 index 000000000000..1467815d5e65 --- /dev/null +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_dev.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, 2021, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include + +#include "cam_isp_hw.h" +#include "cam_hw_intf.h" +#include "cam_csid_ppi_core.h" +#include "cam_csid_ppi_dev.h" +#include "cam_debug_util.h" + +static struct cam_hw_intf *cam_csid_ppi_hw_list[CAM_CSID_PPI_HW_MAX] = { + NULL, NULL, NULL, NULL}; +static char ppi_dev_name[8]; + +int cam_csid_ppi_probe(struct platform_device *pdev) +{ + struct cam_hw_intf *ppi_hw_intf; + struct cam_hw_info *ppi_hw_info; + struct cam_csid_ppi_hw *ppi_dev = NULL; + const struct of_device_id *match_dev = NULL; + struct cam_csid_ppi_hw_info *ppi_hw_data = NULL; + uint32_t ppi_dev_idx; + int rc = 0; + + CAM_DBG(CAM_ISP, "PPI probe called"); + + ppi_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); + if (!ppi_hw_intf) { + rc = -ENOMEM; + goto err; + } + + ppi_hw_info = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!ppi_hw_info) { + rc = -ENOMEM; + goto free_hw_intf; + } + + ppi_dev = kzalloc(sizeof(struct cam_csid_ppi_hw), GFP_KERNEL); + if (!ppi_dev) { + rc = -ENOMEM; + goto free_hw_info; + } + + of_property_read_u32(pdev->dev.of_node, "cell-index", &ppi_dev_idx); + + match_dev = of_match_device(pdev->dev.driver->of_match_table, + &pdev->dev); + if (!match_dev) { + CAM_ERR(CAM_ISP, "No matching table for the CSID PPI HW!"); + rc = -EINVAL; + goto free_dev; + } + + memset(ppi_dev_name, 0, sizeof(ppi_dev_name)); + snprintf(ppi_dev_name, sizeof(ppi_dev_name), "ppi%1u", ppi_dev_idx); + + ppi_hw_intf->hw_idx = ppi_dev_idx; + ppi_hw_intf->hw_priv = ppi_hw_info; + + if (ppi_hw_intf->hw_idx < CAM_CSID_PPI_HW_MAX) + cam_csid_ppi_hw_list[ppi_hw_intf->hw_idx] = ppi_hw_intf; + else { + rc = -EINVAL; + goto free_dev; + } + + ppi_hw_info->core_info = ppi_dev; + ppi_hw_info->soc_info.pdev = pdev; + ppi_hw_info->soc_info.dev = &pdev->dev; + ppi_hw_info->soc_info.dev_name = ppi_dev_name; + ppi_hw_info->soc_info.index = ppi_dev_idx; + + ppi_hw_data = (struct cam_csid_ppi_hw_info *)match_dev->data; + ppi_dev->ppi_info = ppi_hw_data; + + rc = cam_csid_ppi_hw_probe_init(ppi_hw_intf, ppi_dev_idx); + if (rc) { + CAM_ERR(CAM_ISP, "PPI: Probe init failed!"); + goto free_dev; + } + + platform_set_drvdata(pdev, ppi_dev); + CAM_DBG(CAM_ISP, "PPI:%d probe successful", + ppi_hw_intf->hw_idx); + + return 0; +free_dev: + kfree(ppi_dev); +free_hw_info: + kfree(ppi_hw_info); +free_hw_intf: + kfree(ppi_hw_intf); +err: + return rc; +} + +int cam_csid_ppi_remove(struct platform_device *pdev) +{ + struct cam_csid_ppi_hw *ppi_dev = NULL; + struct cam_hw_intf *ppi_hw_intf; + struct cam_hw_info *ppi_hw_info; + + ppi_dev = (struct cam_csid_ppi_hw *)platform_get_drvdata(pdev); + ppi_hw_intf = ppi_dev->hw_intf; + ppi_hw_info = ppi_dev->hw_info; + + CAM_DBG(CAM_ISP, "PPI:%d remove", ppi_dev->hw_intf->hw_idx); + + cam_csid_ppi_hw_deinit(ppi_dev); + + kfree(ppi_dev); + kfree(ppi_hw_info); + kfree(ppi_hw_intf); + + return 0; +} + +int cam_csid_ppi_hw_init(struct cam_hw_intf **csid_ppi_hw, + uint32_t hw_idx) +{ + int rc = 0; + + if (cam_csid_ppi_hw_list[hw_idx]) { + *csid_ppi_hw = cam_csid_ppi_hw_list[hw_idx]; + } else { + *csid_ppi_hw = NULL; + rc = -1; + } + + return rc; +} +EXPORT_SYMBOL(cam_csid_ppi_hw_init); diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_dev.h b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_dev.h new file mode 100644 index 000000000000..2992c2243732 --- /dev/null +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_dev.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, 2021, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_CSID_PPI_DEV_H_ +#define _CAM_CSID_PPI_DEV_H_ + +#include "cam_isp_hw.h" + +irqreturn_t cam_csid_ppi_irq(int irq_num, void *data); +int cam_csid_ppi_probe(struct platform_device *pdev); +int cam_csid_ppi_remove(struct platform_device *pdev); + +#endif /*_CAM_CSID_PPI_DEV_H_ */ diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/Makefile b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/Makefile index dcb41c82af58..956d9ca20bb5 100644 --- a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/Makefile +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/Makefile @@ -8,6 +8,7 @@ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/include ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/hw_utils/irq_controller ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include +ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h index 7486a35af33e..634c35917396 100644 --- a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid530.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_TFE_CSID_530_H_ @@ -134,6 +134,7 @@ static struct cam_tfe_csid_csi2_rx_reg_offset .csid_csi2_rx_irq_set_addr = 0x2c, /*CSI2 rx control */ + .phy_sel_base = 1, .csid_csi2_rx_cfg0_addr = 0x100, .csid_csi2_rx_cfg1_addr = 0x104, .csid_csi2_rx_capture_ctrl_addr = 0x108, diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c index 8a90958c2065..510ba0f382fb 100644 --- a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include @@ -10,6 +10,7 @@ #include #include "cam_tfe_csid_core.h" +#include "cam_csid_ppi_core.h" #include "cam_isp_hw.h" #include "cam_soc_util.h" #include "cam_io_util.h" @@ -738,6 +739,8 @@ static int cam_tfe_csid_enable_csi2( { const struct cam_tfe_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; + struct cam_csid_ppi_cfg ppi_lane_cfg; + uint32_t ppi_index = 0, rc; uint32_t val = 0; csid_reg = csid_hw->csid_info->csid_reg; @@ -801,6 +804,30 @@ static int cam_tfe_csid_enable_csi2( cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + /* + * There is one to one mapping for ppi index with phy index + * we do not always update phy sel equal to phy number,for some + * targets "phy_sel = phy_num + 1", and for some targets it is + * "phy_sel = phy_num", ppi_index should be updated accordingly + */ + ppi_index = csid_hw->csi2_rx_cfg.phy_sel - + csid_reg->csi2_reg->phy_sel_base; + + if (csid_hw->ppi_hw_intf[ppi_index] && csid_hw->ppi_enable) { + ppi_lane_cfg.lane_type = csid_hw->csi2_rx_cfg.lane_type; + ppi_lane_cfg.lane_num = csid_hw->csi2_rx_cfg.lane_num; + ppi_lane_cfg.lane_cfg = csid_hw->csi2_rx_cfg.lane_cfg; + + CAM_DBG(CAM_ISP, "ppi_index to init %d", ppi_index); + rc = csid_hw->ppi_hw_intf[ppi_index]->hw_ops.init( + csid_hw->ppi_hw_intf[ppi_index]->hw_priv, + &ppi_lane_cfg, + sizeof(struct cam_csid_ppi_cfg)); + if (rc < 0) { + CAM_ERR(CAM_ISP, "PPI:%d Init Failed", ppi_index); + return rc; + } + } return 0; } @@ -810,6 +837,7 @@ static int cam_tfe_csid_disable_csi2( { const struct cam_tfe_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; + uint32_t ppi_index = 0, rc; csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; @@ -826,6 +854,20 @@ static int cam_tfe_csid_disable_csi2( cam_io_w_mb(0, soc_info->reg_map[0].mem_base + csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr); + ppi_index = csid_hw->csi2_rx_cfg.phy_sel - + csid_reg->csi2_reg->phy_sel_base; + if (csid_hw->ppi_hw_intf[ppi_index] && csid_hw->ppi_enable) { + /* De-Initialize the PPI bridge */ + CAM_DBG(CAM_ISP, "ppi_index to de-init %d\n", ppi_index); + rc = csid_hw->ppi_hw_intf[ppi_index]->hw_ops.deinit( + csid_hw->ppi_hw_intf[ppi_index]->hw_priv, + NULL, 0); + if (rc < 0) { + CAM_ERR(CAM_ISP, "PPI:%d De-Init Failed", ppi_index); + return rc; + } + } + return 0; } @@ -2700,13 +2742,15 @@ irqreturn_t cam_tfe_csid_irq(int irq_num, void *data) unsigned long flags; uint32_t i, val; - csid_hw = (struct cam_tfe_csid_hw *)data; if (!data) { CAM_ERR(CAM_ISP, "CSID: Invalid arguments"); return IRQ_HANDLED; } + csid_hw = (struct cam_tfe_csid_hw *)data; + CAM_DBG(CAM_ISP, "CSID %d IRQ Handling", csid_hw->hw_intf->hw_idx); + csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; csi2_reg = csid_reg->csi2_reg; @@ -3207,6 +3251,24 @@ int cam_tfe_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, tfe_csid_hw->error_irq_count = 0; tfe_csid_hw->prev_boot_timestamp = 0; + /* Check if ppi bridge is present or not? */ + tfe_csid_hw->ppi_enable = of_property_read_bool( + csid_hw_info->soc_info.pdev->dev.of_node, + "ppi-enable"); + + if (!tfe_csid_hw->ppi_enable) + return 0; + + /* Initialize the PPI bridge */ + for (i = 0; i < CAM_CSID_PPI_HW_MAX; i++) { + rc = cam_csid_ppi_hw_init(&tfe_csid_hw->ppi_hw_intf[i], i); + if (rc < 0) { + CAM_INFO(CAM_ISP, "PPI init failed for PPI %d", i); + rc = 0; + break; + } + } + return 0; err: if (rc) { diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h index 4b50eeb4bbd6..d0935689fd01 100644 --- a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_csid_hw/cam_tfe_csid_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_TFE_CSID_HW_H_ @@ -9,6 +9,7 @@ #include "cam_hw.h" #include "cam_tfe_csid_hw_intf.h" #include "cam_tfe_csid_soc.h" +#include "cam_csid_ppi_core.h" #define CAM_TFE_CSID_CID_MAX 4 @@ -184,6 +185,7 @@ struct cam_tfe_csid_csi2_rx_reg_offset { uint32_t csid_csi2_rx_total_crc_err_addr; /*configurations */ + uint32_t phy_sel_base; uint32_t csi2_rst_srb_all; uint32_t csi2_rst_done_shift_val; uint32_t csi2_irq_mask_all; @@ -407,6 +409,9 @@ struct cam_csid_evt_payload { * @event_cb_priv: Context data * @prev_boot_timestamp previous frame bootime stamp * @prev_qtimer_ts previous frame qtimer csid timestamp + * @ppi_hw_intf interface to ppi hardware + * @ppi_enabled flag to specify if the hardware has ppi bridge + * or not * */ struct cam_tfe_csid_hw { @@ -439,6 +444,8 @@ struct cam_tfe_csid_hw { void *event_cb_priv; uint64_t prev_boot_timestamp; uint64_t prev_qtimer_ts; + struct cam_hw_intf *ppi_hw_intf[CAM_CSID_PPI_HW_MAX]; + bool ppi_enable; }; int cam_tfe_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c index 2eb42ce2673d..5618d1ec6c23 100644 --- a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include @@ -1902,6 +1902,7 @@ static int cam_tfe_camif_resource_start( uint32_t epoch0_irq_mask; uint32_t epoch1_irq_mask; uint32_t computed_epoch_line_cfg; + uint32_t camera_hw_version = 0; if (!camif_res || !core_info) { CAM_ERR(CAM_ISP, "Error Invalid input arguments"); @@ -1947,13 +1948,18 @@ static int cam_tfe_camif_resource_start( CAM_DBG(CAM_ISP, "TFE:%d core_cfg 0 val:0x%x", core_info->core_index, val); - val = cam_io_r(rsrc_data->mem_base + - rsrc_data->common_reg->core_cfg_1); - val &= ~BIT(0); - cam_io_w_mb(val, rsrc_data->mem_base + - rsrc_data->common_reg->core_cfg_1); - CAM_DBG(CAM_ISP, "TFE:%d core_cfg 1 val:0x%x", core_info->core_index, - val); + if (cam_cpas_get_cpas_hw_version(&camera_hw_version)) + CAM_ERR(CAM_ISP, "Failed to get HW version"); + + if (camera_hw_version == CAM_CPAS_TITAN_540_V100) { + val = cam_io_r(rsrc_data->mem_base + + rsrc_data->common_reg->core_cfg_1); + val &= ~BIT(0); + cam_io_w_mb(val, rsrc_data->mem_base + + rsrc_data->common_reg->core_cfg_1); + CAM_DBG(CAM_ISP, "TFE:%d core_cfg 1 val:0x%x", + core_info->core_index, val); + } /* Epoch config */ epoch0_irq_mask = ((rsrc_data->last_line - diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c index ee8cbc5326fc..7322301f69be 100644 --- a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2021, The Linux Foundation. All rights reserved. */ #include @@ -400,6 +400,7 @@ static int cam_top_tpg_start(void *hw_priv, void *start_args, const struct cam_top_tpg_reg_offset *tpg_reg; struct cam_top_tpg_cfg *tpg_data; uint32_t i, val; + uint32_t in_format = 0; if (!hw_priv || !start_args || (arg_size != sizeof(struct cam_isp_resource_node))) { @@ -456,6 +457,56 @@ static int cam_top_tpg_start(void *hw_priv, void *start_args, cam_io_w_mb(0x2581F4, soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg1); + /* configure tpg pattern */ + in_format = tpg_data->dt_cfg[0].encode_format & 0xF; + val = in_format << tpg_reg->tpg_dt_encode_format_shift; + + switch (tpg_hw->tpg_pattern) { + case 0x0: + val = val | tpg_hw->tpg_pattern; + break; + case 0x1: + val = val | tpg_hw->tpg_pattern; + break; + case 0x2: + val = val | tpg_hw->tpg_pattern; + break; + case 0x3: + val = val | tpg_hw->tpg_pattern; + break; + case 0x4: + val = val | tpg_hw->tpg_pattern; + break; + case 0x5: + val = val | tpg_hw->tpg_pattern; + break; + case 0x6: + val = val | tpg_hw->tpg_pattern; + break; + case 0x7: + val = val | tpg_hw->tpg_pattern; + break; + case 0x8: + /* unicolor bar selection */ + val = 0x1 | (1 << tpg_reg->top_unicolor_bar_shift); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_color_bar_cfg); + val = (in_format << tpg_reg->tpg_dt_encode_format_shift) | + tpg_hw->tpg_pattern; + break; + default: + /* frame with split color bar */ + val = 1 << tpg_reg->tpg_split_en_shift; + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_color_bar_cfg); + val = (in_format << tpg_reg->tpg_dt_encode_format_shift) | + CAM_TOP_TPG_DEFAULT_PATTERN; + break; + } + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + tpg_reg->tpg_dt_0_cfg_2); + val = (1 << tpg_reg->tpg_split_en_shift); cam_io_w_mb(tpg_data->pix_pattern, soc_info->reg_map[0].mem_base + tpg_reg->tpg_common_gen_cfg); @@ -469,8 +520,14 @@ static int cam_top_tpg_start(void *hw_priv, void *start_args, soc_info->reg_map[0].mem_base + tpg_reg->tpg_vbi_cfg); /* Set the TOP tpg mux sel*/ - cam_io_w_mb((1 << tpg_hw->hw_intf->hw_idx), + val = cam_io_r_mb(soc_info->reg_map[1].mem_base + + tpg_reg->top_mux_reg_offset); + val |= (1 << tpg_hw->hw_intf->hw_idx); + + cam_io_w_mb(val, soc_info->reg_map[1].mem_base + tpg_reg->top_mux_reg_offset); + CAM_DBG(CAM_ISP, "TPG:%d Set top Mux: 0x%x", + tpg_hw->hw_intf->hw_idx, val); val = ((tpg_data->num_active_lanes - 1) << tpg_reg->tpg_num_active_lines_shift) | @@ -498,6 +555,7 @@ static int cam_top_tpg_stop(void *hw_priv, struct cam_isp_resource_node *tpg_res; const struct cam_top_tpg_reg_offset *tpg_reg; struct cam_top_tpg_cfg *tpg_data; + uint32_t val; if (!hw_priv || !stop_args || (arg_size != sizeof(struct cam_isp_resource_node))) { @@ -524,6 +582,16 @@ static int cam_top_tpg_stop(void *hw_priv, cam_io_w_mb(0, soc_info->reg_map[0].mem_base + tpg_reg->tpg_ctrl); + /* Reset the TOP tpg mux sel*/ + val = cam_io_r_mb(soc_info->reg_map[1].mem_base + + tpg_reg->top_mux_reg_offset); + val &= ~(1 << tpg_hw->hw_intf->hw_idx); + + cam_io_w_mb(val, + soc_info->reg_map[1].mem_base + tpg_reg->top_mux_reg_offset); + CAM_DBG(CAM_ISP, "TPG:%d Reset Top Mux: 0x%x", + tpg_hw->hw_intf->hw_idx, val); + tpg_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; CAM_DBG(CAM_ISP, "TPG:%d stopped", tpg_hw->hw_intf->hw_idx); @@ -563,6 +631,19 @@ static int cam_top_tpg_set_phy_clock( return 0; } +static int cam_top_tpg_set_top_tpg_pattern(struct cam_top_tpg_hw *tpg_hw, + void *cmd_args) +{ + uint32_t *top_tpg_pattern; + + top_tpg_pattern = (uint32_t *) cmd_args; + tpg_hw->tpg_pattern = *top_tpg_pattern; + CAM_DBG(CAM_ISP, "TPG:%d set tpg debug value:%d", + tpg_hw->hw_intf->hw_idx, tpg_hw->tpg_pattern); + + return 0; +} + static int cam_top_tpg_process_cmd(void *hw_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -582,6 +663,9 @@ static int cam_top_tpg_process_cmd(void *hw_priv, case CAM_ISP_HW_CMD_TPG_PHY_CLOCK_UPDATE: rc = cam_top_tpg_set_phy_clock(tpg_hw, cmd_args); break; + case CAM_ISP_HW_CMD_TPG_SET_PATTERN: + rc = cam_top_tpg_set_top_tpg_pattern(tpg_hw, cmd_args); + break; default: CAM_ERR(CAM_ISP, "TPG:%d unsupported cmd:%d", tpg_hw->hw_intf->hw_idx, cmd_type); diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h index 5a859ffb5d38..c3aeb228a5bb 100644 --- a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_TOP_TPG_HW_H_ @@ -60,6 +60,7 @@ struct cam_top_tpg_reg_offset { uint32_t tpg_payload_mode_color; uint32_t tpg_split_en_shift; uint32_t top_mux_reg_offset; + uint32_t top_unicolor_bar_shift; }; /** @@ -129,7 +130,7 @@ struct cam_top_tpg_cfg { * @hw_info: tpg hw device information * @tpg_info: tpg hw specific information * @tpg_res: tpg resource - * @tpg_cfg: tpg configuration + * @tpg_pattern: tpg pattern configuration * @clk_rate clock rate * @lock_state lock state * @tpg_complete tpg completion @@ -140,6 +141,7 @@ struct cam_top_tpg_hw { struct cam_hw_info *hw_info; struct cam_top_tpg_hw_info *tpg_info; struct cam_isp_resource_node tpg_res; + uint32_t tpg_pattern; uint64_t clk_rate; spinlock_t lock_state; struct completion tpg_complete; diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.h b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.h index addd8a2e5988..aedc666bb792 100644 --- a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.h +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/top_tpg/cam_top_tpg_v1.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_TOP_TPG_V1_H_ @@ -48,6 +48,7 @@ static struct cam_top_tpg_reg_offset cam_top_tpg_v1_reg_offset = { .tpg_payload_mode_color = 0x8, .tpg_split_en_shift = 5, .top_mux_reg_offset = 0x1C, + .top_unicolor_bar_shift = 2, }; #endif /*_CAM_TOP_TPG_V1_H_ */ diff --git a/techpack/camera/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/techpack/camera/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index 24511b904da0..ee353c094d6d 100644 --- a/techpack/camera/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/techpack/camera/drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -732,10 +732,12 @@ static int cam_jpeg_mgr_prepare_hw_update(void *hw_mgr_priv, } if ((packet->num_cmd_buf > 5) || !packet->num_patches || - !packet->num_io_configs) { - CAM_ERR(CAM_JPEG, "wrong number of cmd/patch info: %u %u", - packet->num_cmd_buf, - packet->num_patches); + !packet->num_io_configs || + (packet->num_io_configs > CAM_JPEG_IMAGE_MAX)) { + CAM_ERR(CAM_JPEG, + "wrong number of cmd/patch/io_configs info: %u %u %u", + packet->num_cmd_buf, packet->num_patches, + packet->num_io_configs); return -EINVAL; } diff --git a/techpack/camera/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c b/techpack/camera/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c index dbbd3c89053c..fd0eeecb6432 100644 --- a/techpack/camera/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c +++ b/techpack/camera/drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -695,15 +695,14 @@ static int32_t cam_ope_process_request_timer(void *priv, void *data) } CAM_ERR(CAM_OPE, - "pending requests means, issue is with HW for ctx %d", - ctx_data->ctx_id); - CAM_ERR(CAM_OPE, "ctx: %d, lrt: %llu, lct: %llu", + "pending req at HW, ctx %d lrt %llu lct %llu", ctx_data->ctx_id, ctx_data->last_req_time, ope_hw_mgr->last_callback_time); hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( hw_mgr->ope_dev_intf[i]->hw_priv, OPE_HW_DUMP_DEBUG, NULL, 0); + task = cam_req_mgr_workq_get_task(ope_hw_mgr->msg_work); if (!task) { CAM_ERR(CAM_OPE, "no empty task"); @@ -1601,6 +1600,7 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, struct timespec64 ts; bool flag = false; bool dump_flag = true; + int i; if (!userdata) { CAM_ERR(CAM_OPE, "Invalid ctx from CDM callback"); @@ -1660,9 +1660,17 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata, ope_req->request_id, ctx->ctx_id); CAM_INFO(CAM_OPE, "Rst of CDM and OPE for error reqid = %lld", ope_req->request_id); + if (status != CAM_CDM_CB_STATUS_HW_FLUSH) { cam_ope_dump_req_data(ope_req); dump_flag = false; + + CAM_INFO(CAM_OPE, "bach_size: %d", + ctx->req_list[cookie]->num_batch); + for (i = 0; i < ctx->req_list[cookie]->num_batch; i++) + CAM_INFO(CAM_OPE, "i: %d num_stripes: %d", + i, + ctx->req_list[cookie]->num_stripes[i]); } rc = cam_ope_mgr_reset_hw(); flag = true; @@ -1753,7 +1761,7 @@ static int cam_ope_mgr_create_kmd_buf(struct cam_ope_hw_mgr *hw_mgr, static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr, struct cam_packet *packet, - struct cam_hw_prepare_update_args *prep_args, + struct cam_hw_prepare_update_args *prep_arg, struct cam_ope_ctx *ctx_data, uint32_t req_idx) { @@ -1764,8 +1772,8 @@ static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr, struct cam_ope_request *ope_request; ope_request = ctx_data->req_list[req_idx]; - prep_args->num_out_map_entries = 0; - prep_args->num_in_map_entries = 0; + prep_arg->num_out_map_entries = 0; + prep_arg->num_in_map_entries = 0; ope_request = ctx_data->req_list[req_idx]; CAM_DBG(CAM_OPE, "E: req_idx = %u %x", req_idx, packet); @@ -1775,8 +1783,16 @@ static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr, io_buf = ope_request->io_buf[i][l]; if (io_buf->direction == CAM_BUF_INPUT) { if (io_buf->fence != -1) { - sync_in_obj[j++] = io_buf->fence; - prep_args->num_in_map_entries++; + if (j < CAM_MAX_IN_RES) { + sync_in_obj[j++] = + io_buf->fence; + prep_arg->num_in_map_entries++; + } else { + CAM_ERR(CAM_OPE, + "reached max in_res %d %d", + io_buf->resource_type, + ope_request->request_id); + } } else { CAM_ERR(CAM_OPE, "Invalid fence %d %d", io_buf->resource_type, @@ -1784,10 +1800,10 @@ static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr, } } else { if (io_buf->fence != -1) { - prep_args->out_map_entries[k].sync_id = + prep_arg->out_map_entries[k].sync_id = io_buf->fence; k++; - prep_args->num_out_map_entries++; + prep_arg->num_out_map_entries++; } else { if (io_buf->resource_type != OPE_OUT_RES_STATS_LTM) { @@ -1808,38 +1824,38 @@ static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr, } } - if (prep_args->num_in_map_entries > 1 && - prep_args->num_in_map_entries <= CAM_MAX_IN_RES) - prep_args->num_in_map_entries = + if (prep_arg->num_in_map_entries > 1 && + prep_arg->num_in_map_entries <= CAM_MAX_IN_RES) + prep_arg->num_in_map_entries = cam_common_util_remove_duplicate_arr( - sync_in_obj, prep_args->num_in_map_entries); + sync_in_obj, prep_arg->num_in_map_entries); - if (prep_args->num_in_map_entries > 1 && - prep_args->num_in_map_entries <= CAM_MAX_IN_RES) { + if (prep_arg->num_in_map_entries > 1 && + prep_arg->num_in_map_entries <= CAM_MAX_IN_RES) { rc = cam_sync_merge(&sync_in_obj[0], - prep_args->num_in_map_entries, &merged_sync_in_obj); + prep_arg->num_in_map_entries, &merged_sync_in_obj); if (rc) { - prep_args->num_out_map_entries = 0; - prep_args->num_in_map_entries = 0; + prep_arg->num_out_map_entries = 0; + prep_arg->num_in_map_entries = 0; return rc; } ope_request->in_resource = merged_sync_in_obj; - prep_args->in_map_entries[0].sync_id = merged_sync_in_obj; - prep_args->num_in_map_entries = 1; + prep_arg->in_map_entries[0].sync_id = merged_sync_in_obj; + prep_arg->num_in_map_entries = 1; CAM_DBG(CAM_REQ, "ctx_id: %u req_id: %llu Merged Sync obj: %d", ctx_data->ctx_id, packet->header.request_id, merged_sync_in_obj); - } else if (prep_args->num_in_map_entries == 1) { - prep_args->in_map_entries[0].sync_id = sync_in_obj[0]; - prep_args->num_in_map_entries = 1; + } else if (prep_arg->num_in_map_entries == 1) { + prep_arg->in_map_entries[0].sync_id = sync_in_obj[0]; + prep_arg->num_in_map_entries = 1; ope_request->in_resource = 0; CAM_DBG(CAM_OPE, "fence = %d", sync_in_obj[0]); } else { CAM_DBG(CAM_OPE, "Invalid count of input fences, count: %d", - prep_args->num_in_map_entries); - prep_args->num_in_map_entries = 0; + prep_arg->num_in_map_entries); + prep_arg->num_in_map_entries = 0; ope_request->in_resource = 0; rc = -EINVAL; } @@ -2740,6 +2756,10 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args) ctx->ctxt_event_cb = args->event_cb; cam_ope_ctx_clk_info_init(ctx); ctx->ctx_state = OPE_CTX_STATE_ACQUIRED; + kzfree(cdm_acquire); + cdm_acquire = NULL; + kzfree(bw_update); + bw_update = NULL; mutex_unlock(&ctx->ctx_mutex); mutex_unlock(&hw_mgr->hw_mgr_mutex); diff --git a/techpack/camera/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c b/techpack/camera/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c index 4b39b6770c30..1edc6e313fd5 100644 --- a/techpack/camera/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c +++ b/techpack/camera/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include @@ -787,6 +787,11 @@ static uint32_t *ope_create_stripe_cmd(struct cam_ope_hw_mgr *hw_mgr, uint32_t *print_ptr; int num_dmi = 0; struct cam_cdm_utils_ops *cdm_ops; + uint32_t reg_val_pair[2]; + struct cam_hw_info *ope_dev; + struct cam_ope_device_core_info *core_info; + struct ope_hw *ope_hw; + struct cam_ope_top_reg *top_reg; if (s_idx >= OPE_MAX_CMD_BUFS || batch_idx >= OPE_MAX_BATCH_SIZE) { @@ -868,10 +873,21 @@ static uint32_t *ope_create_stripe_cmd(struct cam_ope_hw_mgr *hw_mgr, } CAM_DBG(CAM_OPE, "Stripe:%d Indirect:X", stripe_idx); } + if (hw_mgr->frame_dump_enable) dump_stripe_cmd(frm_proc, stripe_idx, i, k, iova_addr, kmd_buf, buf_len); } + + ope_dev = hw_mgr->ope_dev_intf[0]->hw_priv; + core_info = (struct cam_ope_device_core_info *)ope_dev->core_info; + ope_hw = core_info->ope_hw_info->ope_hw; + top_reg = ope_hw->top_reg; + + reg_val_pair[0] = top_reg->offset + top_reg->scratch_reg; + reg_val_pair[1] = stripe_idx; + kmd_buf = cdm_ops->cdm_write_regrandom(kmd_buf, 1, reg_val_pair); + return kmd_buf; } diff --git a/techpack/camera/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c b/techpack/camera/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c index e7d1528a63d1..8a5f629e7fd9 100644 --- a/techpack/camera/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c +++ b/techpack/camera/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include @@ -66,6 +66,7 @@ static int cam_ope_init_hw_version(struct cam_hw_soc_info *soc_info, switch (core_info->hw_version) { case OPE_HW_VER_1_0_0: + case OPE_HW_VER_1_1_0: core_info->ope_hw_info->ope_hw = &ope_hw_100; break; default: diff --git a/techpack/camera/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h b/techpack/camera/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h index bb5a2bbff27f..fc188e69546c 100644 --- a/techpack/camera/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h +++ b/techpack/camera/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw.h @@ -1,12 +1,13 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef CAM_OPE_HW_H #define CAM_OPE_HW_H #define OPE_HW_VER_1_0_0 0x10000000 +#define OPE_HW_VER_1_1_0 0x10010000 #define OPE_DEV_OPE 0 #define OPE_DEV_MAX 1 @@ -72,6 +73,7 @@ struct cam_ope_top_reg { uint32_t violation_status; uint32_t throttle_cnt_cfg; uint32_t debug_cfg; + uint32_t scratch_reg; uint32_t num_debug_registers; struct cam_ope_debug_register *debug_regs; }; diff --git a/techpack/camera/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h b/techpack/camera/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h index 727b43c68512..cdf9c2d64b11 100644 --- a/techpack/camera/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h +++ b/techpack/camera/drivers/cam_ope/ope_hw_mgr/ope_hw/ope_hw_100.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #ifndef CAM_OPE_HW_100_H @@ -70,6 +70,9 @@ static struct cam_ope_debug_register ope_debug_regs[OPE_MAX_DEBUG_REGISTER] = { { .offset = 0xD0, }, + { + .offset = 0xD4, + }, }; static struct cam_ope_top_reg ope_top_reg = { @@ -87,7 +90,8 @@ static struct cam_ope_top_reg ope_top_reg = { .violation_status = 0x28, .throttle_cnt_cfg = 0x2C, .debug_cfg = 0xDC, - .num_debug_registers = 9, + .scratch_reg = 0x1F0, + .num_debug_registers = 10, .debug_regs = ope_debug_regs, }; diff --git a/techpack/camera/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c b/techpack/camera/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c index 2ebcafd88842..35f4d85e9632 100644 --- a/techpack/camera/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c +++ b/techpack/camera/drivers/cam_ope/ope_hw_mgr/ope_hw/top/ope_top.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include @@ -31,15 +31,27 @@ static struct ope_top ope_top_info; static int cam_ope_top_dump_debug_reg(struct ope_hw *ope_hw_info) { - uint32_t i, val; + uint32_t i, val[3]; struct cam_ope_top_reg *top_reg; top_reg = ope_hw_info->top_reg; - for (i = 0; i < top_reg->num_debug_registers; i++) { - val = cam_io_r_mb(top_reg->base + + for (i = 0; i < top_reg->num_debug_registers; i = i+3) { + val[0] = cam_io_r_mb(top_reg->base + top_reg->debug_regs[i].offset); - CAM_INFO(CAM_OPE, "Debug_status_%d val: 0x%x", i, val); + val[1] = ((i+1) < top_reg->num_debug_registers) ? + cam_io_r_mb(top_reg->base + + top_reg->debug_regs[i+1].offset) : 0; + val[2] = ((i+2) < top_reg->num_debug_registers) ? + cam_io_r_mb(top_reg->base + + top_reg->debug_regs[i+2].offset) : 0; + + CAM_INFO(CAM_OPE, "status[%d-%d] : 0x%x 0x%x 0x%x", + i, i+2, val[0], val[1], val[2]); } + + CAM_INFO(CAM_OPE, "scrath reg: 0x%x, stripe_idx: %d", + top_reg->offset + top_reg->scratch_reg, + cam_io_r_mb(top_reg->base + top_reg->scratch_reg)); return 0; } diff --git a/techpack/camera/drivers/cam_req_mgr/cam_req_mgr_util.c b/techpack/camera/drivers/cam_req_mgr/cam_req_mgr_util.c index df180a615104..f4bef0ce0d7b 100644 --- a/techpack/camera/drivers/cam_req_mgr/cam_req_mgr_util.c +++ b/techpack/camera/drivers/cam_req_mgr/cam_req_mgr_util.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "CAM-REQ-MGR_UTIL %s:%d " fmt, __func__, __LINE__ @@ -114,7 +114,7 @@ static int32_t cam_get_free_handle_index(void) idx = find_first_zero_bit(hdl_tbl->bitmap, hdl_tbl->bits); if (idx >= CAM_REQ_MGR_MAX_HANDLES_V2 || idx < 0) { - CAM_DBG(CAM_CRM, "idx: %d", idx); + CAM_ERR(CAM_CRM, "No free index found idx: %d", idx); return -ENOSR; } @@ -123,20 +123,6 @@ static int32_t cam_get_free_handle_index(void) return idx; } -void cam_dump_tbl_info(void) -{ - int i; - - for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES_V2; i++) - CAM_INFO(CAM_CRM, - "i: %d session_hdl=0x%x hdl_value=0x%x type=%d state=%d dev_id=0x%llx", - i, hdl_tbl->hdl[i].session_hdl, - hdl_tbl->hdl[i].hdl_value, - hdl_tbl->hdl[i].type, - hdl_tbl->hdl[i].state, - hdl_tbl->hdl[i].dev_id); -} - int32_t cam_create_session_hdl(void *priv) { int idx; @@ -153,7 +139,6 @@ int32_t cam_create_session_hdl(void *priv) idx = cam_get_free_handle_index(); if (idx < 0) { CAM_ERR(CAM_CRM, "Unable to create session handle"); - cam_dump_tbl_info(); spin_unlock_bh(&hdl_tbl_lock); return idx; } @@ -189,7 +174,6 @@ int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data) if (idx < 0) { CAM_ERR(CAM_CRM, "Unable to create device handle(idx= %d)", idx); - cam_dump_tbl_info(); spin_unlock_bh(&hdl_tbl_lock); return idx; } diff --git a/techpack/camera/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h b/techpack/camera/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h index b2b813df8e90..2c273b9d5dd9 100644 --- a/techpack/camera/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h +++ b/techpack/camera/drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_1_hwreg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CSIPHY_1_2_1_HWREG_H_ @@ -13,10 +13,10 @@ struct csiphy_reg_parms_t csiphy_v1_2_1 = { .mipi_csiphy_interrupt_clear0_addr = 0x858, .mipi_csiphy_glbl_irq_cmd_addr = 0x828, .csiphy_interrupt_status_size = 11, - .csiphy_common_array_size = 6, + .csiphy_common_array_size = 7, .csiphy_reset_array_size = 5, .csiphy_2ph_config_array_size = 20, - .csiphy_3ph_config_array_size = 34, + .csiphy_3ph_config_array_size = 33, .csiphy_2ph_clock_lane = 0x1, .csiphy_2ph_combo_ck_ln = 0x10, }; @@ -26,6 +26,7 @@ struct csiphy_reg_t csiphy_common_reg_1_2_1[] = { {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x081C, 0x02, 0x00, CSIPHY_2PH_REGS}, {0x081C, 0x52, 0x00, CSIPHY_3PH_REGS}, + {0x0800, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_2PH_REGS}, {0x0800, 0x0E, 0x00, CSIPHY_3PH_REGS}, }; @@ -34,7 +35,7 @@ struct csiphy_reg_t csiphy_reset_reg_1_2_1[] = { {0x0814, 0x00, 0x05, CSIPHY_LANE_ENABLE}, {0x0818, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x081C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0800, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x01, 0x01, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, }; @@ -59,7 +60,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0900, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0908, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0904, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0904, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0904, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0034, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -70,7 +71,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0000, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0024, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -81,7 +82,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0C80, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C88, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C84, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C84, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0734, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -92,7 +93,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x070c, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0724, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -103,7 +104,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0A00, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A04, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0234, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -114,7 +115,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0200, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0224, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -125,7 +126,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0B00, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B04, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0434, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -136,7 +137,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0400, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0424, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -147,7 +148,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0C00, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0C04, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0634, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -158,7 +159,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0600, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x060c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0628, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0624, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -184,7 +185,7 @@ struct csiphy_reg_t {0x0000, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0024, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -206,7 +207,7 @@ struct csiphy_reg_t {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x070c, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0724, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -228,7 +229,7 @@ struct csiphy_reg_t {0x0200, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0224, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -250,7 +251,7 @@ struct csiphy_reg_t {0x0400, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x040C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0428, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0424, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS}, @@ -272,9 +273,9 @@ struct csiphy_reg_t {0x0600, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x060C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0638, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0628, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0624, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0624, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, @@ -289,10 +290,11 @@ csiphy_reg_t csiphy_3ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0990, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0994, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0998, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x098C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0168, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x098C, 0xAF, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x015C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0104, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x010C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x010C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0108, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x0114, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0150, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -307,28 +309,27 @@ csiphy_reg_t csiphy_3ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x012C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0160, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x01DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x09C0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x09C4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x09C8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0984, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x09AC, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x09B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0A90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A98, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0A8C, 0xBF, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0368, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0A8C, 0xAF, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x035C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0304, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x030C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x030C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0308, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x0314, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0350, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -343,16 +344,14 @@ csiphy_reg_t csiphy_3ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x032C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0360, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x03DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0AC0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0AC4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0AC8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0AAC, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0AB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, { {0x0B90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -361,10 +360,11 @@ csiphy_reg_t csiphy_3ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x0B90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0B8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0568, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0B8C, 0xAF, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x055C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0504, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x050C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x050C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {0x0508, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, {0x0514, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0550, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -379,16 +379,14 @@ csiphy_reg_t csiphy_3ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = { {0x052C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0560, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x05DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0BC0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0BC4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x0BC8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0BAC, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0BB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, }, }; @@ -398,82 +396,55 @@ struct data_rate_settings_t data_rate_delta_table_1_2_1 = { { /* (2.5 * 10**3 * 2.28) rounded value*/ .bandwidth = 5700000000, - .data_rate_reg_array_size = 12, + .data_rate_reg_array_size = 9, .csiphy_data_rate_regs = { - {0x15C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x35C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x55C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x144, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x344, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x544, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x16C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x36C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x56C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x164, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x364, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x564, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x144, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, } }, { /* (3.5 * 10**3 * 2.28) rounded value */ .bandwidth = 7980000000, - .data_rate_reg_array_size = 24, + .data_rate_reg_array_size = 12, .csiphy_data_rate_regs = { - {0x15C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x35C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x55C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x9B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x544, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x13C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x33C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x53C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x140, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x340, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x540, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, }, }, { /* (4.5 * 10**3 * 2.28) rounded value */ .bandwidth = 10260000000, - .data_rate_reg_array_size = 24, + .data_rate_reg_array_size = 12, .csiphy_data_rate_regs = { - {0x15C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x35C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x55C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x9B4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x9B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xAB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0xBB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x544, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x13C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x33C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x53C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x140, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x340, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x540, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x16C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x36C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, - {0x56C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x02, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x02, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x02, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, }, } } diff --git a/techpack/camera/drivers/cam_sensor_module/cam_flash/cam_flash_core.c b/techpack/camera/drivers/cam_sensor_module/cam_flash/cam_flash_core.c index e4f896d886c9..49aa0e8e1d9a 100644 --- a/techpack/camera/drivers/cam_sensor_module/cam_flash/cam_flash_core.c +++ b/techpack/camera/drivers/cam_sensor_module/cam_flash/cam_flash_core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -474,7 +474,6 @@ static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl, CAM_DBG(CAM_FLASH, "Led_Torch[%d]: Current: %d", i, curr); - cam_res_mgr_led_trigger_event( flash_ctrl->torch_trigger[i], curr); } @@ -509,6 +508,8 @@ static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl, int cam_flash_off(struct cam_flash_ctrl *flash_ctrl) { + int rc = 0; + if (!flash_ctrl) { CAM_ERR(CAM_FLASH, "Flash control Null"); return -EINVAL; @@ -519,6 +520,18 @@ int cam_flash_off(struct cam_flash_ctrl *flash_ctrl) (enum led_brightness)LED_SWITCH_OFF); flash_ctrl->flash_state = CAM_FLASH_STATE_START; + + if ((flash_ctrl->i2c_data.streamoff_settings.is_settings_valid) && + (flash_ctrl->i2c_data.streamoff_settings.request_id == 0)) { + flash_ctrl->apply_streamoff = true; + rc = cam_flash_i2c_apply_setting(flash_ctrl, 0); + if (rc < 0) { + CAM_ERR(CAM_SENSOR, + "cannot apply streamoff settings"); + } + flash_ctrl->flash_state = CAM_FLASH_STATE_CONFIG; + } + return 0; } @@ -621,6 +634,21 @@ static int cam_flash_i2c_delete_req(struct cam_flash_ctrl *fctrl, CAM_DBG(CAM_FLASH, "top: %llu, del_req_id:%llu", top, del_req_id); + + for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) { + if ((del_req_id > + fctrl->i2c_data.per_frame[i].request_id) && ( + fctrl->i2c_data.per_frame[i].is_settings_valid + == 1)) { + fctrl->i2c_data.per_frame[i].request_id = 0; + rc = delete_request( + &(fctrl->i2c_data.per_frame[i])); + if (rc < 0) + CAM_ERR(CAM_SENSOR, + "Delete request Fail:%lld rc:%d", + del_req_id, rc); + } + } } cam_flash_i2c_flush_nrt(fctrl); @@ -720,10 +748,27 @@ int cam_flash_i2c_apply_setting(struct cam_flash_ctrl *fctrl, struct i2c_settings_list *i2c_list; struct i2c_settings_array *i2c_set = NULL; int frame_offset = 0, rc = 0; - + CAM_DBG(CAM_FLASH, "req_id=%llu", req_id); if (req_id == 0) { /* NonRealTime Init settings*/ - if (fctrl->i2c_data.init_settings.is_settings_valid == true) { + if (fctrl->apply_streamoff == true) { + fctrl->apply_streamoff = false; + i2c_set = &fctrl->i2c_data.streamoff_settings; + list_for_each_entry(i2c_list, + &(i2c_set->list_head), + list) { + rc = cam_sensor_util_i2c_apply_setting + (&(fctrl->io_master_info), i2c_list); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed to apply stream on settings: %d", + rc); + return rc; + } + break; + } + } else if (fctrl->i2c_data.init_settings.is_settings_valid == + true) { list_for_each_entry(i2c_list, &(fctrl->i2c_data.init_settings.list_head), list) { @@ -1202,7 +1247,8 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) rc = fctrl->func_tbl.apply_setting(fctrl, 0); if (rc) { - CAM_ERR(CAM_FLASH, "cannot apply settings rc = %d", rc); + CAM_ERR(CAM_FLASH, + "cannot apply settings rc = %d", rc); return rc; } @@ -1218,6 +1264,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) i2c_reg_settings = &fctrl->i2c_data.per_frame[frm_offset]; if (i2c_reg_settings->is_settings_valid == true) { + CAM_DBG(CAM_FLASH, "settings already valid"); i2c_reg_settings->request_id = 0; i2c_reg_settings->is_settings_valid = false; goto update_req_mgr; @@ -1234,6 +1281,18 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) "Failed in parsing i2c packets"); return rc; } + if ((fctrl->flash_state == CAM_FLASH_STATE_ACQUIRE) || + (fctrl->flash_state == CAM_FLASH_STATE_CONFIG)) { + fctrl->flash_state = CAM_FLASH_STATE_CONFIG; + rc = fctrl->func_tbl.apply_setting(fctrl, 1); + if (rc) { + CAM_ERR(CAM_FLASH, + "cannot apply fire settings rc = %d", + rc); + return rc; + } + return rc; + } break; } case CAM_FLASH_PACKET_OPCODE_NON_REALTIME_SET_OPS: { @@ -1272,21 +1331,48 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg) return rc; } case CAM_PKT_NOP_OPCODE: { + frm_offset = csl_packet->header.request_id % + MAX_PER_FRAME_ARRAY; if ((fctrl->flash_state == CAM_FLASH_STATE_INIT) || (fctrl->flash_state == CAM_FLASH_STATE_ACQUIRE)) { CAM_WARN(CAM_FLASH, "Rxed NOP packets without linking"); - frm_offset = csl_packet->header.request_id % - MAX_PER_FRAME_ARRAY; fctrl->i2c_data.per_frame[frm_offset].is_settings_valid = false; return 0; } - + i2c_reg_settings = + &fctrl->i2c_data.per_frame[frm_offset]; + i2c_reg_settings->is_settings_valid = true; + i2c_reg_settings->request_id = + csl_packet->header.request_id; CAM_DBG(CAM_FLASH, "NOP Packet is Received: req_id: %u", csl_packet->header.request_id); goto update_req_mgr; } + case CAM_FLASH_PACKET_OPCODE_STREAM_OFF: { + if (fctrl->streamoff_count > 0) + return rc; + + CAM_DBG(CAM_FLASH, "Received Stream off Settings"); + i2c_data = &(fctrl->i2c_data); + fctrl->streamoff_count = fctrl->streamoff_count + 1; + i2c_reg_settings = &i2c_data->streamoff_settings; + i2c_reg_settings->request_id = 0; + i2c_reg_settings->is_settings_valid = 1; + offset = (uint32_t *)((uint8_t *)&csl_packet->payload + + csl_packet->cmd_buf_offset); + cmd_desc = (struct cam_cmd_buf_desc *)(offset); + rc = cam_sensor_i2c_command_parser(&fctrl->io_master_info, + i2c_reg_settings, + cmd_desc, 1, NULL); + if (rc) { + CAM_ERR(CAM_FLASH, + "Failed in parsing i2c Stream off packets"); + return rc; + } + break; + } default: CAM_ERR(CAM_FLASH, "Wrong Opcode : %d", (csl_packet->header.op_code & 0xFFFFFF)); @@ -1827,6 +1913,16 @@ int cam_flash_release_dev(struct cam_flash_ctrl *fctrl) { int rc = 0; + if (fctrl->i2c_data.streamoff_settings.is_settings_valid == true) { + fctrl->i2c_data.streamoff_settings.is_settings_valid = false; + rc = delete_request(&fctrl->i2c_data.streamoff_settings); + if (rc) { + CAM_WARN(CAM_FLASH, + "Failed to delete Stream off i2c_setting: %d", + rc); + } + } + if (fctrl->bridge_intf.device_hdl != 1) { rc = cam_destroy_device_hdl(fctrl->bridge_intf.device_hdl); if (rc) @@ -1837,6 +1933,7 @@ int cam_flash_release_dev(struct cam_flash_ctrl *fctrl) fctrl->bridge_intf.link_hdl = -1; fctrl->bridge_intf.session_hdl = -1; fctrl->last_flush_req = 0; + fctrl->streamoff_count = 0; } return rc; diff --git a/techpack/camera/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c b/techpack/camera/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c index 4d07bd8186a9..cb8e3559a177 100644 --- a/techpack/camera/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c +++ b/techpack/camera/drivers/cam_sensor_module/cam_flash/cam_flash_dev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -71,6 +71,7 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, flash_acq_dev.device_handle; fctrl->bridge_intf.session_hdl = flash_acq_dev.session_handle; + fctrl->apply_streamoff = false; rc = copy_to_user(u64_to_user_ptr(cmd->handle), &flash_acq_dev, @@ -123,6 +124,7 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, if (fctrl->func_tbl.power_ops(fctrl, false)) CAM_WARN(CAM_FLASH, "Power Down Failed"); + fctrl->streamoff_count = 0; fctrl->flash_state = CAM_FLASH_STATE_INIT; break; } @@ -130,7 +132,8 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, struct cam_flash_query_cap_info flash_cap = {0}; CAM_DBG(CAM_FLASH, "CAM_QUERY_CAP"); - flash_cap.slot_info = fctrl->soc_info.index; + flash_cap.slot_info = fctrl->soc_info.index; + flash_cap.flash_type = soc_private->flash_type; for (i = 0; i < fctrl->flash_num_sources; i++) { flash_cap.max_current_flash[i] = soc_private->flash_max_current[i]; @@ -161,6 +164,7 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl, goto release_mutex; } + fctrl->apply_streamoff = false; fctrl->flash_state = CAM_FLASH_STATE_START; break; } @@ -401,8 +405,9 @@ static int cam_flash_init_subdev(struct cam_flash_ctrl *fctrl) static int32_t cam_flash_platform_probe(struct platform_device *pdev) { int32_t rc = 0, i = 0; - struct cam_flash_ctrl *fctrl = NULL; - struct device_node *of_parent = NULL; + struct cam_flash_ctrl *fctrl = NULL; + struct device_node *of_parent = NULL; + struct cam_hw_soc_info *soc_info = NULL; CAM_DBG(CAM_FLASH, "Enter"); if (!pdev->dev.of_node) { @@ -418,6 +423,7 @@ static int32_t cam_flash_platform_probe(struct platform_device *pdev) fctrl->soc_info.pdev = pdev; fctrl->soc_info.dev = &pdev->dev; fctrl->soc_info.dev_name = pdev->name; + fctrl->of_node = pdev->dev.of_node; platform_set_drvdata(pdev, fctrl); @@ -458,6 +464,25 @@ static int32_t cam_flash_platform_probe(struct platform_device *pdev) fctrl->io_master_info.cci_client->cci_device = fctrl->cci_num; CAM_DBG(CAM_FLASH, "cci-index %d", fctrl->cci_num, rc); + soc_info = &fctrl->soc_info; + if (!soc_info->gpio_data) { + CAM_DBG(CAM_FLASH, "No GPIO found"); + } else { + if (!soc_info->gpio_data->cam_gpio_common_tbl_size) { + CAM_ERR(CAM_FLASH, "Invalid gpio table size"); + rc = -EINVAL; + goto free_cci_resource; + } + + rc = cam_sensor_util_init_gpio_pin_tbl(soc_info, + &fctrl->power_info.gpio_num_info); + if ((rc < 0) || (!fctrl->power_info.gpio_num_info)) { + CAM_ERR(CAM_FLASH, "No/Error Flash GPIOs"); + rc = -EINVAL; + goto free_cci_resource; + } + } + fctrl->i2c_data.per_frame = kzalloc(sizeof(struct i2c_settings_array) * MAX_PER_FRAME_ARRAY, GFP_KERNEL); @@ -469,6 +494,7 @@ static int32_t cam_flash_platform_probe(struct platform_device *pdev) INIT_LIST_HEAD(&(fctrl->i2c_data.init_settings.list_head)); INIT_LIST_HEAD(&(fctrl->i2c_data.config_settings.list_head)); + INIT_LIST_HEAD(&(fctrl->i2c_data.streamoff_settings.list_head)); for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) INIT_LIST_HEAD( &(fctrl->i2c_data.per_frame[i].list_head)); @@ -526,13 +552,17 @@ static int32_t cam_flash_i2c_driver_probe(struct i2c_client *client, { int32_t rc = 0, i = 0; struct cam_flash_ctrl *fctrl; + struct cam_hw_soc_info *soc_info = NULL; - if (client == NULL || id == NULL) { - CAM_ERR(CAM_FLASH, "Invalid Args client: %pK id: %pK", - client, id); + if (client == NULL) { + CAM_ERR(CAM_FLASH, "Invalid Args client: %pK", client); return -EINVAL; } + if (id == NULL) { + CAM_DBG(CAM_FLASH, "device id is Null"); + } + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { CAM_ERR(CAM_FLASH, "%s :: i2c_check_functionality failed", client->name); @@ -541,22 +571,51 @@ static int32_t cam_flash_i2c_driver_probe(struct i2c_client *client, /* Create sensor control structure */ fctrl = kzalloc(sizeof(*fctrl), GFP_KERNEL); - if (!fctrl) + if (!fctrl) { + CAM_ERR(CAM_FLASH, "Failed to allocate memory for fctrl"); return -ENOMEM; + } i2c_set_clientdata(client, fctrl); fctrl->io_master_info.client = client; + fctrl->of_node = client->dev.of_node; fctrl->soc_info.dev = &client->dev; fctrl->soc_info.dev_name = client->name; fctrl->io_master_info.master_type = I2C_MASTER; + rc = cam_flash_init_default_params(fctrl); + if (rc) { + CAM_ERR(CAM_FLASH, + "failed: cam_flash_init_default_params rc %d", rc); + goto free_ctrl; + } + rc = cam_flash_get_dt_data(fctrl, &fctrl->soc_info); if (rc) { CAM_ERR(CAM_FLASH, "failed: cam_sensor_parse_dt rc %d", rc); goto free_ctrl; } + soc_info = &fctrl->soc_info; + if (!soc_info->gpio_data) { + CAM_DBG(CAM_FLASH, "No GPIO found"); + } else { + if (!soc_info->gpio_data->cam_gpio_common_tbl_size) { + CAM_ERR(CAM_FLASH, "Invalid gpio table size"); + rc = -EINVAL; + goto free_ctrl; + } + + rc = cam_sensor_util_init_gpio_pin_tbl(soc_info, + &fctrl->power_info.gpio_num_info); + if ((rc < 0) || (!fctrl->power_info.gpio_num_info)) { + CAM_ERR(CAM_FLASH, "No/Error Flash GPIOs"); + rc = -EINVAL; + goto free_ctrl; + } + } + rc = cam_flash_init_subdev(fctrl); if (rc) goto free_ctrl; @@ -571,6 +630,7 @@ static int32_t cam_flash_i2c_driver_probe(struct i2c_client *client, INIT_LIST_HEAD(&(fctrl->i2c_data.init_settings.list_head)); INIT_LIST_HEAD(&(fctrl->i2c_data.config_settings.list_head)); + INIT_LIST_HEAD(&(fctrl->i2c_data.streamoff_settings.list_head)); for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) INIT_LIST_HEAD(&(fctrl->i2c_data.per_frame[i].list_head)); @@ -624,6 +684,7 @@ static struct i2c_driver cam_flash_i2c_driver = { .remove = cam_flash_i2c_driver_remove, .driver = { .name = FLASH_DRIVER_I2C, + .of_match_table = cam_flash_dt_match, }, }; @@ -632,14 +693,13 @@ static int32_t __init cam_flash_init_module(void) int32_t rc = 0; rc = platform_driver_register(&cam_flash_platform_driver); - if (rc == 0) { - CAM_DBG(CAM_FLASH, "platform probe success"); - return 0; - } + if (rc < 0) + CAM_ERR(CAM_FLASH, "platform probe failed rc: %d", rc); rc = i2c_add_driver(&cam_flash_i2c_driver); - if (rc) + if (rc < 0) CAM_ERR(CAM_FLASH, "i2c_add_driver failed rc: %d", rc); + return rc; } diff --git a/techpack/camera/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h b/techpack/camera/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h index 29e352e47ce9..28f2fa14e167 100644 --- a/techpack/camera/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h +++ b/techpack/camera/drivers/cam_sensor_module/cam_flash/cam_flash_dev.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, 2021 The Linux Foundation. All rights reserved. */ #ifndef _CAM_FLASH_DEV_H_ @@ -24,6 +24,7 @@ #include "cam_subdev.h" #include "cam_mem_mgr.h" #include "cam_sensor_cmn_header.h" +#include "cam_sensor_util.h" #include "cam_soc_util.h" #include "cam_debug_util.h" #include "cam_sensor_io.h" @@ -39,6 +40,7 @@ #define CAM_FLASH_PACKET_OPCODE_INIT 0 #define CAM_FLASH_PACKET_OPCODE_SET_OPS 1 #define CAM_FLASH_PACKET_OPCODE_NON_REALTIME_SET_OPS 2 +#define CAM_FLASH_PACKET_OPCODE_STREAM_OFF 3 struct cam_flash_ctrl; @@ -130,6 +132,7 @@ struct cam_flash_frame_setting { * @torch_op_current : Torch operational current * @torch_max_current : Max supported current for LED in torch mode * @is_wled_flash : Detection between WLED/LED flash + * @flash_type : Flash type */ struct cam_flash_private_soc { @@ -142,6 +145,7 @@ struct cam_flash_private_soc { uint32_t torch_op_current[CAM_FLASH_MAX_LED_TRIGGERS]; uint32_t torch_max_current[CAM_FLASH_MAX_LED_TRIGGERS]; bool is_wled_flash; + uint32_t flash_type; }; struct cam_flash_func_tbl { @@ -179,6 +183,8 @@ struct cam_flash_func_tbl { * @io_master_info : Information about the communication master * @i2c_data : I2C register settings * @last_flush_req : last request to flush + * @streamoff_count : Count to hold the number of times stream off called + * @apply_streamoff : variable to store when to apply stream off */ struct cam_flash_ctrl { char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH]; @@ -207,6 +213,8 @@ struct cam_flash_ctrl { struct camera_io_master io_master_info; struct i2c_data_settings i2c_data; uint32_t last_flush_req; + uint32_t streamoff_count; + int32_t apply_streamoff; }; int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg); diff --git a/techpack/camera/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c b/techpack/camera/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c index 4c544b1170f3..4b3ee2f62e73 100644 --- a/techpack/camera/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c +++ b/techpack/camera/drivers/cam_sensor_module/cam_flash/cam_flash_soc.c @@ -1,12 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, 2020, 2021 The Linux Foundation. All rights reserved. */ #include #include #include "cam_flash_soc.h" #include "cam_res_mgr_api.h" +#include static int32_t cam_get_source_node_info( struct device_node *of_node, @@ -22,6 +23,13 @@ static int32_t cam_get_source_node_info( soc_private->is_wled_flash = of_property_read_bool(of_node, "wled-flash-support"); + rc = of_property_read_u32(of_node, + "flash-type", &soc_private->flash_type); + if (rc) { + CAM_ERR(CAM_FLASH, "flash-type read failed rc=%d", rc); + soc_private->flash_type = CAM_FLASH_TYPE_PMIC; + } + switch_src_node = of_parse_phandle(of_node, "switch-source", 0); if (!switch_src_node) { CAM_WARN(CAM_FLASH, "switch_src_node NULL"); @@ -232,7 +240,14 @@ int cam_flash_get_dt_data(struct cam_flash_ctrl *fctrl, rc = -ENOMEM; goto release_soc_res; } - of_node = fctrl->pdev->dev.of_node; + + if (fctrl->of_node == NULL) { + CAM_ERR(CAM_FLASH, "device node is NULL"); + rc = -EINVAL; + goto free_soc_private; + } + + of_node = fctrl->of_node; rc = cam_soc_util_get_dt_properties(soc_info); if (rc) { diff --git a/techpack/camera/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c b/techpack/camera/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c index c87540f7950f..58a927426d86 100644 --- a/techpack/camera/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c +++ b/techpack/camera/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -9,6 +9,7 @@ #include #include #include +#include #include "cam_debug_util.h" #include "cam_res_mgr_api.h" #include "cam_res_mgr_private.h" @@ -604,15 +605,13 @@ EXPORT_SYMBOL(cam_res_mgr_shared_clk_config); static int cam_res_mgr_parse_dt(struct device *dev) { - int rc = 0; + int rc = 0, i = 0; struct device_node *of_node = NULL; struct cam_res_mgr_dt *dt = &cam_res->dt; of_node = dev->of_node; - dt->num_shared_gpio = of_property_count_u32_elems(of_node, - "shared-gpios"); - + dt->num_shared_gpio = of_gpio_count(of_node); if (dt->num_shared_gpio > MAX_SHARED_GPIO_SIZE || dt->num_shared_gpio <= 0) { /* @@ -624,11 +623,14 @@ static int cam_res_mgr_parse_dt(struct device *dev) return -EINVAL; } - rc = of_property_read_u32_array(of_node, "shared-gpios", - dt->shared_gpio, dt->num_shared_gpio); - if (rc) { - CAM_ERR(CAM_RES, "Get shared gpio array failed."); - return -EINVAL; + for (i = 0; i < dt->num_shared_gpio; i++) { + dt->shared_gpio[i] = of_get_gpio(of_node, i); + if (dt->shared_gpio[i] < 0) { + CAM_ERR(CAM_RES, "Get shared gpio array failed."); + return -EINVAL; + } + CAM_DBG(CAM_UTIL, "shared_gpio[%d] = %d", + i, dt->shared_gpio[i]); } dt->pinctrl_info.pinctrl = devm_pinctrl_get(dev); diff --git a/techpack/camera/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/techpack/camera/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index 746e4d063de1..a76ff61cbfc9 100644 --- a/techpack/camera/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/techpack/camera/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -1134,7 +1134,8 @@ int cam_sensor_power_up(struct cam_sensor_ctrl_t *s_ctrl) //add by hzt 2021-9-4 for control external gpio power_info->imx582_avdd18_gpio=s_ctrl->imx582_avdd18_gpio; //add by hzt 2021-9-4 for control external gpio - + power_info->imx582_avdd28_gpio=s_ctrl->imx582_avdd28_gpio; + rc = cam_sensor_core_power_up(power_info, soc_info); if (rc < 0) { CAM_ERR(CAM_SENSOR, "power up the core is failed:%d", rc); diff --git a/techpack/camera/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h b/techpack/camera/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h index 135a284b5fd4..846636db8117 100644 --- a/techpack/camera/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h +++ b/techpack/camera/drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h @@ -114,6 +114,7 @@ struct cam_sensor_ctrl_t { //add by hzt 2021-9-4 for control external gpio int imx582_avdd18_gpio; //add by hzt 2021-9-4 for control external gpio + int imx582_avdd28_gpio; }; #endif /* _CAM_SENSOR_DEV_H_ */ diff --git a/techpack/camera/drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.c b/techpack/camera/drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.c index 0df88cc5b781..571e851d65a0 100644 --- a/techpack/camera/drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.c +++ b/techpack/camera/drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.c @@ -255,11 +255,12 @@ int32_t cam_sensor_parse_dt(struct cam_sensor_ctrl_t *s_ctrl) } //add by hzt 2021-9-4 for control external gpio - + s_ctrl->imx582_avdd18_gpio = of_get_named_gpio(s_ctrl->of_node, "imx582_avdd18,pwr-gpio", 0); - + //add by hzt 2021-9-4 for control external gpio + s_ctrl->imx582_avdd28_gpio = of_get_named_gpio(s_ctrl->of_node, "imx582_avdd28,pwr-gpio", 0); /* Initialize mutex */ diff --git a/techpack/camera/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c b/techpack/camera/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c index a9fd0881aabf..80c8cc8d9a48 100644 --- a/techpack/camera/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c +++ b/techpack/camera/drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include "cam_sensor_cmn_header.h" @@ -32,9 +32,14 @@ static int32_t cam_qup_i2c_rxdata( }, }; rc = i2c_transfer(dev_client->adapter, msgs, 2); - if (rc < 0) + if (rc < 0) { CAM_ERR(CAM_SENSOR, "failed 0x%x", saddr); - return rc; + return rc; + } + /* Returns negative errno */ + /* else the number of messages executed. */ + /* So positive values are not errors. */ + return 0; } @@ -53,9 +58,14 @@ static int32_t cam_qup_i2c_txdata( }, }; rc = i2c_transfer(dev_client->client->adapter, msg, 1); - if (rc < 0) + if (rc < 0) { CAM_ERR(CAM_SENSOR, "failed 0x%x", saddr); - return rc; + return rc; + } + /* Returns negative errno, */ + /* else the number of messages executed. */ + /* So positive values are not errors. */ + return 0; } int32_t cam_qup_i2c_read(struct i2c_client *client, diff --git a/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h index 017b56036d3d..79883da8c5a1 100644 --- a/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h +++ b/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h @@ -319,6 +319,7 @@ struct cam_sensor_power_ctrl_t { //add by hzt 2021-9-4 for control external gpio int imx582_avdd18_gpio; //add by hzt 2021-9-4 for control external gpio + int imx582_avdd28_gpio; }; struct cam_camera_slave_info { diff --git a/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c index 9f3c0dff92b0..1d1ee5db39b3 100644 --- a/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c +++ b/techpack/camera/drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c @@ -8,11 +8,11 @@ #include "cam_mem_mgr.h" #include "cam_res_mgr_api.h" - + //add by hzt 2021-7-1 for debug //#undef CAM_DBG //#define CAM_DBG(fmt,args...) CAM_ERR(fmt,##args) - + #define CAM_SENSOR_PINCTRL_STATE_SLEEP "cam_suspend" @@ -1774,8 +1774,9 @@ int msm_cam_sensor_handle_reg_gpio(int seq_type, //add by hzt 2021-9-4 for control external gpio //s_ctrl.imx582_avdd18_gpio = of_get_named_gpio(s_ctrl->of_node, "imx582_avdd18,pwr-gpio", 0); + //s_ctrl.imx582_avdd28_gpio = of_get_named_gpio(s_ctrl->of_node, "imx582_avdd28,pwr-gpio", 0); //add by hzt 2021-9-4 control external gpio - + return 0; } @@ -1892,7 +1893,7 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl, CAM_DBG(CAM_SENSOR, "power setting size: %d", ctrl->power_setting_size); - + @@ -2058,8 +2059,8 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl, //add by hzt 2021-9-4 for control external gpio if(power_setting->seq_type==SENSOR_VANA) - { - + { + CAM_DBG(CAM_SENSOR, "before to request imx582_avdd18_gpio:%d,,\n",ctrl->imx582_avdd18_gpio); ret = gpio_request(ctrl->imx582_avdd18_gpio, "imx582_avdd18_gpio"); if (ret < 0) { @@ -2068,6 +2069,15 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl, //gpio_set_value_cansleep(ctrl->imx582_avdd18_gpio, 1); gpio_direction_output(ctrl->imx582_avdd18_gpio,1); gpio_free(ctrl->imx582_avdd18_gpio); + + CAM_DBG(CAM_SENSOR, "before to request imx582_avdd28_gpio:%d,,\n",ctrl->imx582_avdd28_gpio); + ret = gpio_request(ctrl->imx582_avdd28_gpio, "imx582_avdd28_gpio"); + if (ret < 0) { + CAM_DBG(CAM_SENSOR, "Failed to request imx582_avdd28_gpio:%d,,\n",ctrl->imx582_avdd28_gpio); + } + //gpio_set_value_cansleep(ctrl->imx582_avdd28_gpio, 1); + gpio_direction_output(ctrl->imx582_avdd28_gpio,1); + gpio_free(ctrl->imx582_avdd28_gpio); } //add by hzt 2021-9-4 control external gpio @@ -2356,8 +2366,7 @@ int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl, //add by hzt 2021-9-4 for control external gpio if(pd->seq_val==SENSOR_VANA) - { - + { CAM_DBG(CAM_SENSOR, "before to request imx582_avdd18_gpio:%d,,\n",ctrl->imx582_avdd18_gpio); ret = gpio_request(ctrl->imx582_avdd18_gpio, "imx582_avdd18_gpio"); if (ret < 0) { @@ -2366,6 +2375,15 @@ int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl, //gpio_set_value_cansleep(ctrl->imx582_avdd18_gpio, 0); gpio_direction_output(ctrl->imx582_avdd18_gpio,0); gpio_free(ctrl->imx582_avdd18_gpio); + + CAM_DBG(CAM_SENSOR, "before to request imx582_avdd28_gpio:%d,,\n",ctrl->imx582_avdd28_gpio); + ret = gpio_request(ctrl->imx582_avdd28_gpio, "imx582_avdd28_gpio"); + if (ret < 0) { + CAM_DBG(CAM_SENSOR, "Failed to request imx582_avdd28_gpio:%d,,\n",ctrl->imx582_avdd28_gpio); + } + //gpio_set_value_cansleep(ctrl->imx582_avdd28_gpio, 0); + gpio_direction_output(ctrl->imx582_avdd28_gpio,0); + gpio_free(ctrl->imx582_avdd28_gpio); } //add by hzt 2021-9-4 control external gpio diff --git a/techpack/camera/drivers/cam_smmu/cam_smmu_api.c b/techpack/camera/drivers/cam_smmu/cam_smmu_api.c index 034de6ee564b..49db0ec16079 100644 --- a/techpack/camera/drivers/cam_smmu/cam_smmu_api.c +++ b/techpack/camera/drivers/cam_smmu/cam_smmu_api.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. */ #include @@ -203,6 +203,8 @@ struct cam_dma_buff_info { struct cam_sec_buff_info { struct dma_buf *buf; + struct dma_buf_attachment *attach; + struct sg_table *table; enum dma_data_direction dir; int ref_count; dma_addr_t paddr; @@ -2674,6 +2676,8 @@ static int cam_smmu_map_stage2_buffer_and_add_to_list(int idx, int ion_fd, mapping_info->dir = dma_dir; mapping_info->ref_count = 1; mapping_info->buf = dmabuf; + mapping_info->attach = attach; + mapping_info->table = table; CAM_DBG(CAM_SMMU, "idx=%d, ion_fd=%d, dev=%pK, paddr=%pK, len=%u", idx, ion_fd, @@ -2774,11 +2778,28 @@ static int cam_smmu_secure_unmap_buf_and_remove_from_list( struct cam_sec_buff_info *mapping_info, int idx) { - if (!mapping_info) { - CAM_ERR(CAM_SMMU, "Error: List doesn't exist"); + if ((!mapping_info->buf) || (!mapping_info->table) || + (!mapping_info->attach)) { + CAM_ERR(CAM_SMMU, + "Error: Invalid params dev = %pK, table = %pK", + (void *)iommu_cb_set.cb_info[idx].dev, + (void *)mapping_info->table); + CAM_ERR(CAM_SMMU, "Error:dma_buf = %pK, attach = %pK\n", + (void *)mapping_info->buf, + (void *)mapping_info->attach); return -EINVAL; } + + /* skip cache operations */ + mapping_info->attach->dma_map_attrs |= DMA_ATTR_SKIP_CPU_SYNC; + + /* iommu buffer clean up */ + dma_buf_unmap_attachment(mapping_info->attach, + mapping_info->table, mapping_info->dir); + dma_buf_detach(mapping_info->buf, mapping_info->attach); dma_buf_put(mapping_info->buf); + mapping_info->buf = NULL; + list_del_init(&mapping_info->list); CAM_DBG(CAM_SMMU, "unmap fd: %d, idx : %d", mapping_info->ion_fd, idx); diff --git a/techpack/camera/drivers/cam_sync/cam_sync.c b/techpack/camera/drivers/cam_sync/cam_sync.c index 6daadc3120e4..d548933f2320 100644 --- a/techpack/camera/drivers/cam_sync/cam_sync.c +++ b/techpack/camera/drivers/cam_sync/cam_sync.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -471,6 +471,7 @@ static int cam_sync_handle_create(struct cam_private_ioctl_arg *k_ioctl) u64_to_user_ptr(k_ioctl->ioctl_ptr), k_ioctl->size)) return -EFAULT; + sync_create.name[SYNC_DEBUG_NAME_LEN] = '\0'; result = cam_sync_create(&sync_create.sync_obj, sync_create.name); diff --git a/techpack/camera/include/uapi/media/cam_sensor.h b/techpack/camera/include/uapi/media/cam_sensor.h index cc86f2706c63..9d16af961904 100644 --- a/techpack/camera/include/uapi/media/cam_sensor.h +++ b/techpack/camera/include/uapi/media/cam_sensor.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, 2021 The Linux Foundation. All rights reserved. */ #ifndef __UAPI_CAM_SENSOR_H__ @@ -474,6 +474,7 @@ struct cam_flash_query_curr { * @max_current_flash : max supported current for flash * @max_duration_flash : max flash turn on duration * @max_current_torch : max supported current for torch + * @flash_type : Indicates about the flash type -I2C,GPIO,PMIC * */ struct cam_flash_query_cap_info { @@ -481,6 +482,7 @@ struct cam_flash_query_cap_info { uint32_t max_current_flash[CAM_FLASH_MAX_LED_TRIGGERS]; uint32_t max_duration_flash[CAM_FLASH_MAX_LED_TRIGGERS]; uint32_t max_current_torch[CAM_FLASH_MAX_LED_TRIGGERS]; + uint32_t flash_type; } __attribute__ ((packed)); #endif diff --git a/techpack/display/msm/Makefile b/techpack/display/msm/Makefile index 51b0edbf245a..18eb12c35530 100644 --- a/techpack/display/msm/Makefile +++ b/techpack/display/msm/Makefile @@ -70,6 +70,7 @@ msm_drm-$(CONFIG_DRM_MSM_SDE) += sde/sde_crtc.o \ sde/sde_hw_qdss.o \ sde_dbg.o \ sde_dbg_evtlog.o \ + sde/sde_hw_rc.o \ msm_drm-$(CONFIG_DRM_SDE_WB) += sde/sde_wb.o \ sde/sde_encoder_phys_wb.o \ diff --git a/techpack/display/msm/dp/dp_display.c b/techpack/display/msm/dp/dp_display.c index af3bc7365aba..623b3022054a 100644 --- a/techpack/display/msm/dp/dp_display.c +++ b/techpack/display/msm/dp/dp_display.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -2570,6 +2570,27 @@ static int dp_display_config_hdr(struct dp_display *dp_display, void *panel, core_clk_rate, flush_hdr); } +static int dp_display_get_display_type(struct dp_display *dp_display, + const char **display_type) +{ + struct dp_display_private *dp; + + if (!dp_display || !display_type) { + pr_err("invalid input\n"); + return -EINVAL; + } + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + *display_type = dp->parser->display_type; + + if (!strcmp(*display_type, "primary")) + dp_display->is_primary = true; + + return 0; +} + + static int dp_display_setup_colospace(struct dp_display *dp_display, void *panel, u32 colorspace) @@ -3100,6 +3121,7 @@ static int dp_display_probe(struct platform_device *pdev) g_dp_display->post_open = NULL; g_dp_display->post_init = dp_display_post_init; g_dp_display->config_hdr = dp_display_config_hdr; + g_dp_display->get_display_type = dp_display_get_display_type; g_dp_display->mst_install = dp_display_mst_install; g_dp_display->mst_uninstall = dp_display_mst_uninstall; g_dp_display->mst_connector_install = dp_display_mst_connector_install; diff --git a/techpack/display/msm/dp/dp_display.h b/techpack/display/msm/dp/dp_display.h index ebfeb1d67423..3f4b8d9bc2d3 100644 --- a/techpack/display/msm/dp/dp_display.h +++ b/techpack/display/msm/dp/dp_display.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #ifndef _DP_DISPLAY_H_ @@ -72,6 +72,7 @@ struct dp_display { u32 max_pclk_khz; u32 no_mst_encoder; void *dp_mst_prv_info; + bool is_primary; int (*enable)(struct dp_display *dp_display, void *panel); int (*post_enable)(struct dp_display *dp_display, void *panel); @@ -126,6 +127,8 @@ struct dp_display { struct drm_connector *connector, char *pps_cmd); void (*wakeup_phy_layer)(struct dp_display *dp_display, bool wakeup); + int (*get_display_type)(struct dp_display *dp_display, + const char **display_type); }; #ifdef CONFIG_DRM_MSM_DP diff --git a/techpack/display/msm/dp/dp_drm.c b/techpack/display/msm/dp/dp_drm.c index 976e0ebb8faf..30446724cea7 100644 --- a/techpack/display/msm/dp/dp_drm.c +++ b/techpack/display/msm/dp/dp_drm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved. */ #include @@ -580,6 +580,19 @@ int dp_connector_get_modes(struct drm_connector *connector, return rc; } +int dp_connnector_set_info_blob(struct drm_connector *connector, + void *info, void *display, struct msm_mode_info *mode_info) +{ + struct dp_display *dp_display = display; + const char *display_type = NULL; + + dp_display->get_display_type(dp_display, &display_type); + sde_kms_info_add_keystr(info, + "display type", display_type); + + return 0; +} + int dp_drm_bridge_init(void *data, struct drm_encoder *encoder) { int rc = 0; diff --git a/techpack/display/msm/dp/dp_drm.h b/techpack/display/msm/dp/dp_drm.h index 07f606e8a70b..930b3aa911cf 100644 --- a/techpack/display/msm/dp/dp_drm.h +++ b/techpack/display/msm/dp/dp_drm.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved. */ #ifndef _DP_DRM_H_ @@ -177,6 +177,18 @@ int dp_mst_init(struct dp_display *dp_display); * @display: Pointer to private display structure */ void dp_mst_deinit(struct dp_display *dp_display); + +/** + * dp_conn_set_info_blob - callback to perform info blob initialization + * @connector: Pointer to drm connector structure + * @info: Pointer to sde connector info structure + * @display: Pointer to private display handle + * @mode_info: Pointer to mode info structure + * Returns: Zero on success + */ +int dp_connnector_set_info_blob(struct drm_connector *connector, + void *info, void *display, struct msm_mode_info *mode_info); + #else static inline int dp_connector_config_hdr(struct drm_connector *connector, void *display, struct sde_connector_state *c_state) @@ -278,6 +290,13 @@ static inline int dp_mst_deinit(struct dp_display *dp_display) { return 0; } + +int dp_connnector_set_info_blob(struct drm_connector *connector, + void *info, void *display, struct msm_mode_info *mode_info) +{ + return 0; +} + #endif #endif /* _DP_DRM_H_ */ diff --git a/techpack/display/msm/dp/dp_parser.c b/techpack/display/msm/dp/dp_parser.c index 40a2401b1c4c..4c37aa2c33a2 100644 --- a/techpack/display/msm/dp/dp_parser.c +++ b/techpack/display/msm/dp/dp_parser.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #include @@ -166,6 +166,10 @@ static int dp_parser_misc(struct dp_parser *parser) if (rc) parser->max_lclk_khz = DP_MAX_LINK_CLK_KHZ; + parser->display_type = of_get_property(of_node, "label", NULL); + if (!parser->display_type) + parser->display_type = "unknown"; + return 0; } diff --git a/techpack/display/msm/dp/dp_parser.h b/techpack/display/msm/dp/dp_parser.h index 0970dff71ed0..5d937ca274d4 100644 --- a/techpack/display/msm/dp/dp_parser.h +++ b/techpack/display/msm/dp/dp_parser.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #ifndef _DP_PARSER_H_ @@ -198,6 +198,7 @@ static inline char *dp_phy_aux_config_type_to_string(u32 cfg_type) * @max_dp_dsc_input_width_pixs: Maximum input width for DSC block * @has_widebus: widebus (2PPC) feature eanble status *@mst_fixed_port: mst port_num reserved for fixed topology + * @display_type: display type as defined in device tree. * @parse: function to be called by client to parse device tree. * @get_io: function to be called by client to get io data. * @get_io_buf: function to be called by client to get io buffers. @@ -230,6 +231,8 @@ struct dp_parser { bool lphw_hpd; u32 mst_fixed_port[MAX_DP_MST_STREAMS]; + const char *display_type; + int (*parse)(struct dp_parser *parser); struct dp_io_data *(*get_io)(struct dp_parser *parser, char *name); void (*get_io_buf)(struct dp_parser *parser, char *name); diff --git a/techpack/display/msm/dsi/dsi_panel.c b/techpack/display/msm/dsi/dsi_panel.c index 63ba92f9badc..aa511c454395 100644 --- a/techpack/display/msm/dsi/dsi_panel.c +++ b/techpack/display/msm/dsi/dsi_panel.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #include @@ -466,7 +466,6 @@ void set_lcd_vcc_3v3_gpio(int enable){ } EXPORT_SYMBOL(set_lcd_vcc_3v3_gpio);//by eric.wang - static int dsi_panel_power_on(struct dsi_panel *panel) { int rc = 0; @@ -662,12 +661,29 @@ static int dsi_panel_wled_register(struct dsi_panel *panel, return 0; } +static int dsi_panel_dcs_set_display_brightness_c2(struct mipi_dsi_device *dsi, + u32 bl_lvl) +{ + u16 brightness = (u16)bl_lvl; + u8 first_byte = brightness & 0xff; + u8 second_byte = brightness >> 8; + u8 payload[8] = {second_byte, first_byte, + second_byte, first_byte, + second_byte, first_byte, + second_byte, first_byte}; + + return mipi_dsi_dcs_write(dsi, 0xC2, payload, sizeof(payload)); +} + + + static int dsi_panel_update_backlight(struct dsi_panel *panel, u32 bl_lvl) { int rc = 0; static int old_bkl = 0; struct mipi_dsi_device *dsi; + struct dsi_backlight_config *bl; //DSI_ERR("----------update dcs backlight:%d,by eric.wang------\n", bl_lvl); if(bl_lvl==0&&old_bkl>0){ set_lcd_vcc_3v3_gpio(0); @@ -682,11 +698,16 @@ static int dsi_panel_update_backlight(struct dsi_panel *panel, } dsi = &panel->mipi_device; + bl = &panel->bl_config; if (panel->bl_config.bl_inverted_dbv) bl_lvl = (((bl_lvl & 0xff) << 8) | (bl_lvl >> 8)); - rc = mipi_dsi_dcs_set_display_brightness(dsi, bl_lvl); + if (panel->bl_config.bl_dcs_subtype == 0xc2) + rc = dsi_panel_dcs_set_display_brightness_c2(dsi, bl_lvl); + else + rc = mipi_dsi_dcs_set_display_brightness(dsi, bl_lvl); + if (rc < 0) DSI_ERR("failed to update dcs backlight:%d\n", bl_lvl); @@ -1907,7 +1928,7 @@ static int dsi_panel_create_cmd_packets(const char *data, cmd[i].msg.type = data[0]; cmd[i].last_command = (data[1] == 1); cmd[i].msg.channel = data[2]; - cmd[i].msg.flags |= (data[3] == 1 ? MIPI_DSI_MSG_REQ_ACK : 0); + cmd[i].msg.flags |= data[3]; cmd[i].msg.ctrl = 0; cmd[i].post_wait_ms = cmd[i].msg.wait_ms = data[4]; cmd[i].msg.tx_len = ((data[5] << 8) | (data[6])); @@ -2417,6 +2438,16 @@ static int dsi_panel_parse_bl_config(struct dsi_panel *panel) panel->bl_config.brightness_max_level = val; } + rc = utils->read_u32(utils->data, "qcom,mdss-dsi-bl-ctrl-dcs-subtype", + &val); + if (rc) { + DSI_DEBUG("[%s] bl-ctrl-dcs-subtype, defautling to zero\n", + panel->name); + panel->bl_config.bl_dcs_subtype = 0; + } else { + panel->bl_config.bl_dcs_subtype = val; + } + panel->bl_config.bl_inverted_dbv = utils->read_bool(utils->data, "qcom,mdss-dsi-bl-inverted-dbv"); diff --git a/techpack/display/msm/dsi/dsi_panel.h b/techpack/display/msm/dsi/dsi_panel.h index 9f0e1cb17e40..ee30cd5375b4 100644 --- a/techpack/display/msm/dsi/dsi_panel.h +++ b/techpack/display/msm/dsi/dsi_panel.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef _DSI_PANEL_H_ @@ -122,6 +122,7 @@ struct dsi_backlight_config { u32 bl_scale; u32 bl_scale_sv; bool bl_inverted_dbv; + u32 bl_dcs_subtype; int en_gpio; /* PWM params */ diff --git a/techpack/display/msm/msm_drv.c b/techpack/display/msm/msm_drv.c index abdf61e6be50..7025d9d84f1f 100644 --- a/techpack/display/msm/msm_drv.c +++ b/techpack/display/msm/msm_drv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -61,6 +61,8 @@ #define MSM_VERSION_MINOR 3 #define MSM_VERSION_PATCHLEVEL 0 +static DEFINE_MUTEX(msm_release_lock); + static void msm_fb_output_poll_changed(struct drm_device *dev) { struct msm_drm_private *priv = NULL; @@ -1460,14 +1462,27 @@ void msm_mode_object_event_notify(struct drm_mode_object *obj, static int msm_release(struct inode *inode, struct file *filp) { - struct drm_file *file_priv = filp->private_data; - struct drm_minor *minor = file_priv->minor; - struct drm_device *dev = minor->dev; - struct msm_drm_private *priv = dev->dev_private; + struct drm_file *file_priv; + struct drm_minor *minor; + struct drm_device *dev; + struct msm_drm_private *priv; struct msm_drm_event *node, *temp, *tmp_node; u32 count; unsigned long flags; LIST_HEAD(tmp_head); + int ret = 0; + + mutex_lock(&msm_release_lock); + + file_priv = filp->private_data; + if (!file_priv) { + ret = -EINVAL; + goto end; + } + + minor = file_priv->minor; + dev = minor->dev; + priv = dev->dev_private; spin_lock_irqsave(&dev->event_lock, flags); list_for_each_entry_safe(node, temp, &priv->client_event_list, @@ -1504,7 +1519,11 @@ static int msm_release(struct inode *inode, struct file *filp) */ msm_preclose(dev, file_priv); - return drm_release(inode, filp); + ret = drm_release(inode, filp); + filp->private_data = NULL; +end: + mutex_unlock(&msm_release_lock); + return ret; } /** diff --git a/techpack/display/msm/msm_drv.h b/techpack/display/msm/msm_drv.h index 20969665356c..4ba732d86d7c 100644 --- a/techpack/display/msm/msm_drv.h +++ b/techpack/display/msm/msm_drv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -138,6 +138,7 @@ enum msm_mdp_crtc_property { CRTC_PROP_DEST_SCALER_LUT_ED, CRTC_PROP_DEST_SCALER_LUT_CIR, CRTC_PROP_DEST_SCALER_LUT_SEP, + CRTC_PROP_DSPP_INFO, /* # of blob properties */ CRTC_PROP_BLOBCOUNT, diff --git a/techpack/display/msm/sde/sde_color_processing.c b/techpack/display/msm/sde/sde_color_processing.c index 6777d0e4c31b..799dfdd4495d 100644 --- a/techpack/display/msm/sde/sde_color_processing.c +++ b/techpack/display/msm/sde/sde_color_processing.c @@ -1,11 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "%s: " fmt, __func__ #include +#include #include #include "sde_color_processing.h" #include "sde_kms.h" @@ -29,6 +30,7 @@ struct sde_cp_node { struct list_head active_list; struct list_head dirty_list; bool is_dspp_feature; + bool lm_flush_override; u32 prop_blob_sz; struct sde_irq_callback *irq; }; @@ -55,6 +57,8 @@ static void dspp_ad_install_property(struct drm_crtc *crtc); static void dspp_ltm_install_property(struct drm_crtc *crtc); +static void dspp_rc_install_property(struct drm_crtc *crtc); + static void dspp_vlut_install_property(struct drm_crtc *crtc); static void dspp_gamut_install_property(struct drm_crtc *crtc); @@ -111,6 +115,7 @@ do { \ func[SDE_DSPP_IGC] = dspp_igc_install_property; \ func[SDE_DSPP_HIST] = dspp_hist_install_property; \ func[SDE_DSPP_DITHER] = dspp_dither_install_property; \ + func[SDE_DSPP_RC] = dspp_rc_install_property; \ } while (0) typedef void (*lm_prop_install_func_t)(struct drm_crtc *crtc); @@ -122,7 +127,7 @@ static void lm_gc_install_property(struct drm_crtc *crtc); #define setup_lm_prop_install_funcs(func) \ (func[SDE_MIXER_GC] = lm_gc_install_property) -enum { +enum sde_cp_crtc_features { /* Append new DSPP features before SDE_CP_CRTC_DSPP_MAX */ /* DSPP Features start */ SDE_CP_CRTC_DSPP_IGC, @@ -158,6 +163,7 @@ enum { SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF2, SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF3, SDE_CP_CRTC_DSPP_LTM_VLUT, + SDE_CP_CRTC_DSPP_RC_MASK, SDE_CP_CRTC_DSPP_MAX, /* DSPP features end */ @@ -169,12 +175,52 @@ enum { SDE_CP_CRTC_MAX_FEATURES, }; +enum sde_cp_crtc_pu_features { + SDE_CP_CRTC_DSPP_RC_PU, + SDE_CP_CRTC_MAX_PU_FEATURES, +}; + +typedef void (*dspp_cap_update_func_t)(struct sde_crtc *crtc, + struct sde_kms_info *info); +enum sde_dspp_caps_features { + SDE_CP_RC_CAPS, + SDE_CP_CAPS_MAX, +}; + +static void rc_caps_update(struct sde_crtc *crtc, struct sde_kms_info *info); +static dspp_cap_update_func_t dspp_cap_update_func[SDE_CP_CAPS_MAX]; + +#define setup_dspp_caps_funcs(func) \ + (func[SDE_CP_RC_CAPS] = rc_caps_update) + static void _sde_cp_crtc_enable_hist_irq(struct sde_crtc *sde_crtc); -typedef int (*set_feature_wrapper)(struct sde_hw_dspp *hw_dspp, +typedef int (*feature_wrapper)(struct sde_hw_dspp *hw_dspp, struct sde_hw_cp_cfg *hw_cfg, struct sde_crtc *hw_crtc); + +static struct sde_kms *get_kms(struct drm_crtc *crtc) +{ + struct msm_drm_private *priv = crtc->dev->dev_private; + + return to_sde_kms(priv->kms); +} + +static void update_pu_feature_enable(struct sde_crtc *sde_crtc, + u32 feature, bool enable) +{ + if (!sde_crtc || feature > SDE_CP_CRTC_MAX_PU_FEATURES) { + DRM_ERROR("invalid args feature %d\n", feature); + return; + } + + if (enable) + sde_crtc->cp_pu_feature_mask |= BIT(feature); + else + sde_crtc->cp_pu_feature_mask &= ~BIT(feature); +} + static int set_dspp_vlut_feature(struct sde_hw_dspp *hw_dspp, struct sde_hw_cp_cfg *hw_cfg, struct sde_crtc *hw_crtc) @@ -655,9 +701,127 @@ static int set_ltm_hist_crtl_feature(struct sde_hw_dspp *hw_dspp, return ret; } -set_feature_wrapper crtc_feature_wrappers[SDE_CP_CRTC_MAX_FEATURES]; +static int check_rc_mask_feature(struct sde_hw_dspp *hw_dspp, + struct sde_hw_cp_cfg *hw_cfg, + struct sde_crtc *sde_crtc) +{ + int ret = 0; -#define setup_crtc_feature_wrappers(wrappers) \ + if (!hw_dspp || !hw_cfg || !sde_crtc) { + DRM_ERROR("invalid arguments"); + return -EINVAL; + } + + if (!hw_dspp->ops.validate_rc_mask) { + DRM_ERROR("invalid rc ops"); + return -EINVAL; + } + + ret = hw_dspp->ops.validate_rc_mask(hw_dspp, hw_cfg); + if (ret) + DRM_ERROR("failed to validate rc mask %d", ret); + + return ret; +} + +static int set_rc_mask_feature(struct sde_hw_dspp *hw_dspp, + struct sde_hw_cp_cfg *hw_cfg, + struct sde_crtc *sde_crtc) +{ + int ret = 0; + + if (!hw_dspp || !hw_cfg || !sde_crtc) { + DRM_ERROR("invalid arguments\n"); + return -EINVAL; + } + + if (!hw_dspp->ops.setup_rc_mask || !hw_dspp->ops.setup_rc_data) { + DRM_ERROR("invalid rc ops\n"); + return -EINVAL; + } + + DRM_DEBUG_DRIVER("dspp %d setup mask for rc instance %u\n", + hw_dspp->idx, hw_dspp->cap->sblk->rc.idx); + + ret = hw_dspp->ops.setup_rc_mask(hw_dspp, hw_cfg); + if (ret) { + DRM_ERROR("failed to setup rc mask, ret %d\n", ret); + goto exit; + } + + /* rc data should be programmed once if dspp are in multi-pipe mode */ + if (hw_dspp->cap->sblk->rc.idx % hw_cfg->num_of_mixers == 0) { + ret = hw_dspp->ops.setup_rc_data(hw_dspp, hw_cfg); + if (ret) { + DRM_ERROR("failed to setup rc data, ret %d\n", ret); + goto exit; + } + } + + update_pu_feature_enable(sde_crtc, SDE_CP_CRTC_DSPP_RC_PU, + hw_cfg->payload != NULL); +exit: + return ret; +} + +static int set_rc_pu_feature(struct sde_hw_dspp *hw_dspp, + struct sde_hw_cp_cfg *hw_cfg, + struct sde_crtc *sde_crtc) +{ + int ret = 0; + + if (!hw_dspp || !hw_cfg || !sde_crtc) { + DRM_ERROR("invalid arguments\n"); + return -EINVAL; + } + + if (!hw_dspp->ops.setup_rc_pu_roi) { + DRM_ERROR("invalid rc ops\n"); + return -EINVAL; + } + + DRM_DEBUG_DRIVER("dspp %d setup pu roi for rc instance %u\n", + hw_dspp->idx, hw_dspp->cap->sblk->rc.idx); + + ret = hw_dspp->ops.setup_rc_pu_roi(hw_dspp, hw_cfg); + if (ret < 0) + DRM_ERROR("failed to setup rc pu roi, ret %d\n", ret); + + return ret; +} + +static int check_rc_pu_feature(struct sde_hw_dspp *hw_dspp, + struct sde_hw_cp_cfg *hw_cfg, + struct sde_crtc *sde_crtc) +{ + int ret = 0; + + if (!hw_dspp || !hw_cfg || !sde_crtc) { + DRM_ERROR("invalid arguments\n"); + return -EINVAL; + } + + if (!hw_dspp->ops.validate_rc_pu_roi) { + SDE_ERROR("invalid rc ops"); + return -EINVAL; + } + + ret = hw_dspp->ops.validate_rc_pu_roi(hw_dspp, hw_cfg); + if (ret) + SDE_ERROR("failed to validate rc pu roi, ret %d", ret); + + return ret; +} + +feature_wrapper check_crtc_feature_wrappers[SDE_CP_CRTC_MAX_FEATURES]; +#define setup_check_crtc_feature_wrappers(wrappers) \ +do { \ + memset(wrappers, 0, sizeof(wrappers)); \ + wrappers[SDE_CP_CRTC_DSPP_RC_MASK] = check_rc_mask_feature; \ +} while (0) + +feature_wrapper set_crtc_feature_wrappers[SDE_CP_CRTC_MAX_FEATURES]; +#define setup_set_crtc_feature_wrappers(wrappers) \ do { \ memset(wrappers, 0, sizeof(wrappers)); \ wrappers[SDE_CP_CRTC_DSPP_VLUT] = set_dspp_vlut_feature; \ @@ -697,6 +861,21 @@ do { \ wrappers[SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF2] = set_ltm_queue_buf_feature; \ wrappers[SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF3] = set_ltm_queue_buf_feature; \ wrappers[SDE_CP_CRTC_DSPP_LTM_HIST_CTL] = set_ltm_hist_crtl_feature; \ + wrappers[SDE_CP_CRTC_DSPP_RC_MASK] = set_rc_mask_feature; \ +} while (0) + +feature_wrapper set_crtc_pu_feature_wrappers[SDE_CP_CRTC_MAX_PU_FEATURES]; +#define setup_set_crtc_pu_feature_wrappers(wrappers) \ +do { \ + memset(wrappers, 0, sizeof(wrappers)); \ + wrappers[SDE_CP_CRTC_DSPP_RC_PU] = set_rc_pu_feature; \ +} while (0) + +feature_wrapper check_crtc_pu_feature_wrappers[SDE_CP_CRTC_MAX_PU_FEATURES]; +#define setup_check_crtc_pu_feature_wrappers(wrappers) \ +do { \ + memset(wrappers, 0, sizeof(wrappers)); \ + wrappers[SDE_CP_CRTC_DSPP_RC_PU] = check_rc_pu_feature; \ } while (0) #define INIT_PROP_ATTACH(p, crtc, prop, node, feature, val) \ @@ -886,12 +1065,6 @@ static int sde_cp_enable_crtc_property(struct drm_crtc *crtc, return ret; } -static struct sde_kms *get_kms(struct drm_crtc *crtc) -{ - struct msm_drm_private *priv = crtc->dev->dev_private; - - return to_sde_kms(priv->kms); -} static void sde_cp_crtc_prop_attach(struct sde_cp_prop_attach *prop_attach) { @@ -938,6 +1111,9 @@ void sde_cp_crtc_init(struct drm_crtc *crtc) if (IS_ERR(sde_crtc->hist_blob)) sde_crtc->hist_blob = NULL; + msm_property_install_blob(&sde_crtc->property_info, + "dspp_caps", DRM_MODE_PROP_IMMUTABLE, CRTC_PROP_DSPP_INFO); + mutex_init(&sde_crtc->crtc_cp_lock); INIT_LIST_HEAD(&sde_crtc->active_list); INIT_LIST_HEAD(&sde_crtc->dirty_list); @@ -948,6 +1124,7 @@ void sde_cp_crtc_init(struct drm_crtc *crtc) spin_lock_init(&sde_crtc->ltm_lock); INIT_LIST_HEAD(&sde_crtc->ltm_buf_free); INIT_LIST_HEAD(&sde_crtc->ltm_buf_busy); + sde_cp_crtc_disable(crtc); } static void sde_cp_crtc_install_immutable_property(struct drm_crtc *crtc, @@ -1182,6 +1359,70 @@ static void _sde_cp_crtc_enable_hist_irq(struct sde_crtc *sde_crtc) spin_unlock_irqrestore(&node->state_lock, flags); } +static int sde_cp_crtc_checkfeature(struct sde_cp_node *prop_node, + struct sde_crtc *sde_crtc, struct sde_crtc_state *sde_crtc_state) +{ + struct sde_hw_cp_cfg hw_cfg; + struct sde_hw_mixer *hw_lm; + struct sde_hw_dspp *hw_dspp; + u32 num_mixers; + int i = 0, ret = 0; + bool feature_enabled = false; + feature_wrapper check_feature = NULL; + + if (!prop_node || !sde_crtc || !sde_crtc_state) { + DRM_ERROR("invalid arguments"); + return -EINVAL; + } + + num_mixers = sde_crtc->num_mixers; + + if (prop_node->feature >= SDE_CP_CRTC_MAX_FEATURES) { + DRM_ERROR("invalid feature %d\n", prop_node->feature); + return -EINVAL; + } + + check_feature = check_crtc_feature_wrappers[prop_node->feature]; + if (check_feature == NULL) + return 0; + + memset(&hw_cfg, 0, sizeof(hw_cfg)); + sde_cp_get_hw_payload(prop_node, &hw_cfg, &feature_enabled); + hw_cfg.num_of_mixers = sde_crtc->num_mixers; + hw_cfg.last_feature = 0; + + for (i = 0; i < num_mixers; i++) { + hw_dspp = sde_crtc->mixers[i].hw_dspp; + if (!hw_dspp || i >= DSPP_MAX) + continue; + hw_cfg.dspp[i] = hw_dspp; + } + + for (i = 0; i < num_mixers && !ret; i++) { + hw_lm = sde_crtc->mixers[i].hw_lm; + hw_dspp = sde_crtc->mixers[i].hw_dspp; + if (!hw_lm) { + ret = -EINVAL; + continue; + } + hw_cfg.ctl = sde_crtc->mixers[i].hw_ctl; + hw_cfg.mixer_info = hw_lm; + + /* use incoming state information */ + hw_cfg.displayh = num_mixers * + sde_crtc_state->lm_roi[i].w; + hw_cfg.displayv = sde_crtc_state->lm_roi[i].h; + + DRM_DEBUG_DRIVER("check cp feature %d on mixer %d\n", + prop_node->feature, hw_lm->idx - LM_0); + ret = check_feature(hw_dspp, &hw_cfg, sde_crtc); + if (ret) + break; + } + + return ret; +} + static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node, struct sde_crtc *sde_crtc) { @@ -1206,11 +1447,11 @@ static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node, } if ((prop_node->feature >= SDE_CP_CRTC_MAX_FEATURES) || - crtc_feature_wrappers[prop_node->feature] == NULL) { + set_crtc_feature_wrappers[prop_node->feature] == NULL) { ret = -EINVAL; } else { - set_feature_wrapper set_feature = - crtc_feature_wrappers[prop_node->feature]; + feature_wrapper set_feature = + set_crtc_feature_wrappers[prop_node->feature]; catalog = get_kms(&sde_crtc->base)->catalog; hw_cfg.broadcast_disabled = catalog->dma_cfg.broadcast_disabled; @@ -1252,6 +1493,257 @@ static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node, list_del_init(&prop_node->dirty_list); } +static int sde_cp_crtc_check_pu_features(struct drm_crtc *crtc) +{ + int ret = 0, i = 0, j = 0; + struct sde_crtc *sde_crtc; + struct sde_crtc_state *sde_crtc_state; + struct sde_hw_cp_cfg hw_cfg; + struct sde_hw_dspp *hw_dspp; + + if (!crtc) { + DRM_ERROR("invalid crtc %pK\n", crtc); + return -EINVAL; + } + + sde_crtc = to_sde_crtc(crtc); + if (!sde_crtc) { + DRM_ERROR("invalid sde_crtc %pK\n", sde_crtc); + return -EINVAL; + } + + sde_crtc_state = to_sde_crtc_state(crtc->state); + if (!sde_crtc_state) { + DRM_ERROR("invalid sde_crtc_state %pK\n", sde_crtc_state); + return -EINVAL; + } + + for (i = 0; i < sde_crtc->num_mixers; i++) { + if (!sde_crtc->mixers[i].hw_lm) { + DRM_ERROR("invalid lm in mixer %d\n", i); + return -EINVAL; + } + + if (!sde_crtc->mixers[i].hw_ctl) { + DRM_ERROR("invalid ctl in mixer %d\n", i); + return -EINVAL; + } + } + + /* early return when not a partial update frame */ + if (sde_crtc_state->user_roi_list.num_rects == 0) { + DRM_DEBUG_DRIVER("no partial update required\n"); + return 0; + } + + memset(&hw_cfg, 0, sizeof(hw_cfg)); + hw_cfg.num_of_mixers = sde_crtc->num_mixers; + hw_cfg.payload = &sde_crtc_state->user_roi_list; + hw_cfg.len = sizeof(sde_crtc_state->user_roi_list); + for (i = 0; i < hw_cfg.num_of_mixers; i++) + hw_cfg.dspp[i] = sde_crtc->mixers[i].hw_dspp; + + for (i = 0; i < SDE_CP_CRTC_MAX_PU_FEATURES; i++) { + feature_wrapper check_pu_feature = + check_crtc_pu_feature_wrappers[i]; + + if (!check_pu_feature || + !(sde_crtc->cp_pu_feature_mask & BIT(i))) + continue; + + for (j = 0; j < hw_cfg.num_of_mixers; j++) { + hw_dspp = sde_crtc->mixers[j].hw_dspp; + + /* use incoming state information */ + hw_cfg.mixer_info = sde_crtc->mixers[j].hw_lm; + hw_cfg.ctl = sde_crtc->mixers[j].hw_ctl; + hw_cfg.displayh = hw_cfg.num_of_mixers * + sde_crtc_state->lm_roi[j].w; + hw_cfg.displayv = sde_crtc_state->lm_roi[j].h; + + ret = check_pu_feature(hw_dspp, &hw_cfg, sde_crtc); + if (ret) { + DRM_ERROR("failed pu feature %d in mixer %d\n", + i, j); + return -EAGAIN; + } + } + } + + return ret; +} + +int sde_cp_crtc_check_properties(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + struct sde_crtc *sde_crtc = NULL; + struct sde_crtc_state *sde_crtc_state = NULL; + struct sde_cp_node *prop_node = NULL, *n = NULL; + int ret = 0; + + if (!crtc || !crtc->dev || !state) { + DRM_ERROR("invalid crtc %pK dev %pK state %pK\n", crtc, + (crtc ? crtc->dev : NULL), state); + return -EINVAL; + } + + sde_crtc = to_sde_crtc(crtc); + if (!sde_crtc) { + DRM_ERROR("invalid sde_crtc %pK\n", sde_crtc); + return -EINVAL; + } + + sde_crtc_state = to_sde_crtc_state(state); + if (!sde_crtc_state) { + DRM_ERROR("invalid sde_crtc_state %pK\n", sde_crtc_state); + return -EINVAL; + } + mutex_lock(&sde_crtc->crtc_cp_lock); + + ret = sde_cp_crtc_check_pu_features(crtc); + if (ret) { + DRM_ERROR("failed check pu features, ret %d\n", ret); + goto exit; + } + + if (list_empty(&sde_crtc->dirty_list)) { + DRM_DEBUG_DRIVER("Dirty list is empty\n"); + goto exit; + } + + list_for_each_entry_safe(prop_node, n, &sde_crtc->dirty_list, + dirty_list) { + ret = sde_cp_crtc_checkfeature(prop_node, sde_crtc, + sde_crtc_state); + if (ret) { + DRM_ERROR("failed check on prop_node %u\n", + prop_node->property_id); + /* remove invalid feature from dirty list */ + list_del_init(&prop_node->dirty_list); + goto exit; + } + } + +exit: + mutex_unlock(&sde_crtc->crtc_cp_lock); + return ret; +} + +static int sde_cp_crtc_set_pu_features(struct drm_crtc *crtc, bool *need_flush) +{ + int ret = 0, i = 0, j = 0; + struct sde_crtc *sde_crtc; + struct sde_crtc_state *sde_crtc_state; + struct sde_hw_cp_cfg hw_cfg; + struct sde_hw_dspp *hw_dspp; + struct sde_hw_mixer *hw_lm; + struct sde_mdss_cfg *catalog; + struct sde_rect user_rect, cached_rect; + + if (!need_flush) { + DRM_ERROR("invalid need_flush %pK\n", need_flush); + return -EINVAL; + } + + if (!crtc) { + DRM_ERROR("invalid crtc %pK\n", crtc); + return -EINVAL; + } + + sde_crtc = to_sde_crtc(crtc); + if (!sde_crtc) { + DRM_ERROR("invalid sde_crtc %pK\n", sde_crtc); + return -EINVAL; + } + + sde_crtc_state = to_sde_crtc_state(crtc->state); + if (!sde_crtc_state) { + DRM_ERROR("invalid sde_crtc_state %pK\n", sde_crtc_state); + return -EINVAL; + } + + for (i = 0; i < sde_crtc->num_mixers; i++) { + if (!sde_crtc->mixers[i].hw_lm) { + DRM_ERROR("invalid lm in mixer %d\n", i); + return -EINVAL; + } + + if (!sde_crtc->mixers[i].hw_ctl) { + DRM_ERROR("invalid ctl in mixer %d\n", i); + return -EINVAL; + } + } + + /* early return if not a partial update frame or no change in rois */ + if ((sde_crtc_state->user_roi_list.num_rects == 0) && + (sde_crtc->cached_user_roi_list.num_rects == 0)) { + DRM_DEBUG_DRIVER("no partial update required\n"); + return 0; + } else if (sde_crtc_state->user_roi_list.num_rects == 0) { + DRM_DEBUG_DRIVER("transition from PU to full update\n"); + memset(&sde_crtc->cached_user_roi_list, 0, + sizeof(struct msm_roi_list)); + } else { + sde_kms_rect_merge_rectangles(&sde_crtc_state->user_roi_list, + &user_rect); + sde_kms_rect_merge_rectangles( + &sde_crtc->cached_user_roi_list, + &cached_rect); + if (sde_kms_rect_is_equal(&user_rect, &cached_rect)) { + DRM_DEBUG_DRIVER("no change in list of ROIs\n"); + return 0; + } + } + + catalog = get_kms(&sde_crtc->base)->catalog; + memset(&hw_cfg, 0, sizeof(hw_cfg)); + hw_cfg.num_of_mixers = sde_crtc->num_mixers; + hw_cfg.broadcast_disabled = catalog->dma_cfg.broadcast_disabled; + hw_cfg.payload = (sde_crtc_state->user_roi_list.num_rects) ? + &sde_crtc_state->user_roi_list : NULL; + hw_cfg.len = sizeof(sde_crtc_state->user_roi_list); + for (i = 0; i < hw_cfg.num_of_mixers; i++) + hw_cfg.dspp[i] = sde_crtc->mixers[i].hw_dspp; + + for (i = 0; i < SDE_CP_CRTC_MAX_PU_FEATURES; i++) { + feature_wrapper set_pu_feature = + set_crtc_pu_feature_wrappers[i]; + + if (!set_pu_feature || + !(sde_crtc->cp_pu_feature_mask & BIT(i))) + continue; + + for (j = 0; j < hw_cfg.num_of_mixers; j++) { + hw_lm = sde_crtc->mixers[j].hw_lm; + hw_dspp = sde_crtc->mixers[j].hw_dspp; + + hw_cfg.mixer_info = hw_lm; + hw_cfg.ctl = sde_crtc->mixers[j].hw_ctl; + hw_cfg.displayh = hw_cfg.num_of_mixers * + hw_lm->cfg.out_width; + hw_cfg.displayv = hw_lm->cfg.out_height; + + ret = set_pu_feature(hw_dspp, &hw_cfg, sde_crtc); + /* feature does not need flush when ret > 0 */ + if (ret < 0) { + DRM_ERROR("failed pu feature %d in mixer %d\n", + i, j); + return ret; + } else if (ret == 0) { + *need_flush = true; + } + } + } + + if (sde_crtc_state->user_roi_list.num_rects != 0) { + memcpy(&sde_crtc->cached_user_roi_list, + &sde_crtc_state->user_roi_list, + sizeof(struct msm_roi_list)); + } + + return 0; +} + void sde_cp_crtc_apply_properties(struct drm_crtc *crtc) { struct sde_crtc *sde_crtc = NULL; @@ -1259,6 +1751,8 @@ void sde_cp_crtc_apply_properties(struct drm_crtc *crtc) struct sde_cp_node *prop_node = NULL, *n = NULL; struct sde_hw_ctl *ctl; u32 num_mixers = 0, i = 0; + int rc = 0; + bool need_flush = false; if (!crtc || !crtc->dev) { DRM_ERROR("invalid crtc %pK dev %pK\n", crtc, @@ -1274,42 +1768,49 @@ void sde_cp_crtc_apply_properties(struct drm_crtc *crtc) num_mixers = sde_crtc->num_mixers; if (!num_mixers) { - DRM_DEBUG_DRIVER("no mixers for this crtc\n"); + DRM_ERROR("no mixers for this crtc\n"); return; } mutex_lock(&sde_crtc->crtc_cp_lock); - /* Check if dirty lists are empty and ad features are disabled for - * early return. If ad properties are active then we need to issue - * dspp flush. - **/ if (list_empty(&sde_crtc->dirty_list) && - list_empty(&sde_crtc->ad_dirty)) { - if (list_empty(&sde_crtc->ad_active)) { - DRM_DEBUG_DRIVER("Dirty list is empty\n"); - goto exit; - } - set_dspp_flush = true; + list_empty(&sde_crtc->ad_dirty) && + list_empty(&sde_crtc->ad_active) && + list_empty(&sde_crtc->active_list)) { + DRM_DEBUG_DRIVER("all lists are empty\n"); + goto exit; } - if (!list_empty(&sde_crtc->ad_active)) - sde_cp_ad_set_prop(sde_crtc, AD_IPC_RESET); + rc = sde_cp_crtc_set_pu_features(crtc, &need_flush); + if (rc) { + DRM_ERROR("failed set pu features, skip cp updates\n"); + goto exit; + } else if (need_flush) { + set_dspp_flush = true; + set_lm_flush = true; + } list_for_each_entry_safe(prop_node, n, &sde_crtc->dirty_list, - dirty_list) { + dirty_list) { sde_cp_crtc_setfeature(prop_node, sde_crtc); /* Set the flush flag to true */ - if (prop_node->is_dspp_feature) + if (prop_node->is_dspp_feature && + !prop_node->lm_flush_override) set_dspp_flush = true; else set_lm_flush = true; } - list_for_each_entry_safe(prop_node, n, &sde_crtc->ad_dirty, - dirty_list) { + if (!list_empty(&sde_crtc->ad_active)) { + sde_cp_ad_set_prop(sde_crtc, AD_IPC_RESET); set_dspp_flush = true; + } + + list_for_each_entry_safe(prop_node, n, &sde_crtc->ad_dirty, + dirty_list) { sde_cp_crtc_setfeature(prop_node, sde_crtc); + set_dspp_flush = true; } for (i = 0; i < num_mixers; i++) { @@ -1381,7 +1882,13 @@ void sde_cp_crtc_install_properties(struct drm_crtc *crtc) SDE_CP_CRTC_MAX_FEATURES), GFP_KERNEL); setup_dspp_prop_install_funcs(dspp_prop_install_func); setup_lm_prop_install_funcs(lm_prop_install_func); - setup_crtc_feature_wrappers(crtc_feature_wrappers); + setup_set_crtc_feature_wrappers(set_crtc_feature_wrappers); + setup_check_crtc_feature_wrappers(check_crtc_feature_wrappers); + setup_set_crtc_pu_feature_wrappers( + set_crtc_pu_feature_wrappers); + setup_check_crtc_pu_feature_wrappers( + check_crtc_pu_feature_wrappers); + setup_dspp_caps_funcs(dspp_cap_update_func); } if (!priv->cp_property) goto exit; @@ -1659,6 +2166,7 @@ void sde_cp_crtc_clear(struct drm_crtc *crtc) list_del_init(&sde_crtc->dirty_list); list_del_init(&sde_crtc->ad_active); list_del_init(&sde_crtc->ad_dirty); + sde_crtc->cp_pu_feature_mask = 0; mutex_unlock(&sde_crtc->crtc_cp_lock); spin_lock_irqsave(&sde_crtc->spin_lock, flags); @@ -1944,6 +2452,57 @@ static void dspp_ltm_install_property(struct drm_crtc *crtc) } } +static void dspp_rc_install_property(struct drm_crtc *crtc) +{ + char feature_name[256]; + struct sde_kms *kms = NULL; + struct sde_mdss_cfg *catalog = NULL; + struct sde_cp_node *prop_node = NULL; + struct sde_crtc *sde_crtc = NULL; + u32 version; + + if (!crtc) { + DRM_ERROR("invalid arguments"); + return; + } + + sde_crtc = to_sde_crtc(crtc); + if (!sde_crtc) { + DRM_ERROR("invalid sde_crtc %pK\n", sde_crtc); + return; + } + + kms = get_kms(crtc); + catalog = kms->catalog; + version = catalog->dspp[0].sblk->rc.version >> 16; + switch (version) { + case 1: + snprintf(feature_name, ARRAY_SIZE(feature_name), "%s%d", + "SDE_DSPP_RC_MASK_V", version); + sde_cp_crtc_install_blob_property(crtc, feature_name, + SDE_CP_CRTC_DSPP_RC_MASK, + sizeof(struct drm_msm_rc_mask_cfg)); + + /* Override flush mechanism to use layer mixer flush bits */ + if (!catalog->rc_lm_flush_override) + break; + + DRM_DEBUG("rc using lm flush override\n"); + list_for_each_entry(prop_node, &sde_crtc->feature_list, + feature_list) { + if (prop_node->feature == SDE_CP_CRTC_DSPP_RC_MASK) { + prop_node->lm_flush_override = true; + break; + } + } + + break; + default: + DRM_ERROR("version %d not supported\n", version); + break; + } +} + static void lm_gc_install_property(struct drm_crtc *crtc) { char feature_name[256]; @@ -3373,3 +3932,72 @@ void sde_cp_mode_switch_prop_dirty(struct drm_crtc *crtc_drm) } mutex_unlock(&crtc->crtc_cp_lock); } + +static void rc_caps_update(struct sde_crtc *crtc, struct sde_kms_info *info) +{ + struct sde_mdss_cfg *catalog = get_kms(&crtc->base)->catalog; + u32 i, num_mixers = crtc->num_mixers; + char blk_name[256]; + + if (!catalog->rc_count || num_mixers > catalog->rc_count) + return; + + for (i = 0; i < num_mixers; i++) { + struct sde_hw_dspp *dspp = crtc->mixers[i].hw_dspp; + + if (!dspp || (dspp->idx - DSPP_0) >= catalog->rc_count) + continue; + snprintf(blk_name, sizeof(blk_name), "rc%u", + (dspp->idx - DSPP_0)); + sde_kms_info_add_keyint(info, blk_name, 1); + } +} + +void sde_cp_crtc_enable(struct drm_crtc *drm_crtc) +{ + struct sde_crtc *crtc; + struct sde_kms_info *info = NULL; + u32 i, num_mixers; + + if (!drm_crtc) { + DRM_ERROR("invalid crtc handle"); + return; + } + crtc = to_sde_crtc(drm_crtc); + num_mixers = crtc->num_mixers; + if (!num_mixers) + return; + mutex_lock(&crtc->crtc_cp_lock); + info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL); + if (info) { + for (i = 0; i < ARRAY_SIZE(dspp_cap_update_func); i++) + dspp_cap_update_func[i](crtc, info); + msm_property_set_blob(&crtc->property_info, + &crtc->dspp_blob_info, + info->data, SDE_KMS_INFO_DATALEN(info), + CRTC_PROP_DSPP_INFO); + } + kfree(info); + mutex_unlock(&crtc->crtc_cp_lock); +} + +void sde_cp_crtc_disable(struct drm_crtc *drm_crtc) +{ + struct sde_kms_info *info = NULL; + struct sde_crtc *crtc; + + if (!drm_crtc) { + DRM_ERROR("invalid crtc handle"); + return; + } + crtc = to_sde_crtc(drm_crtc); + mutex_lock(&crtc->crtc_cp_lock); + info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL); + if (info) + msm_property_set_blob(&crtc->property_info, + &crtc->dspp_blob_info, + info->data, SDE_KMS_INFO_DATALEN(info), + CRTC_PROP_DSPP_INFO); + mutex_unlock(&crtc->crtc_cp_lock); + kfree(info); +} diff --git a/techpack/display/msm/sde/sde_color_processing.h b/techpack/display/msm/sde/sde_color_processing.h index 0b831977d740..277e3e6f368b 100644 --- a/techpack/display/msm/sde/sde_color_processing.h +++ b/techpack/display/msm/sde/sde_color_processing.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, 2021, The Linux Foundation. All rights reserved. */ #ifndef _SDE_COLOR_PROCESSING_H @@ -93,6 +93,15 @@ void sde_cp_crtc_destroy_properties(struct drm_crtc *crtc); */ int sde_cp_crtc_set_property(struct drm_crtc *crtc, struct drm_property *property, uint64_t val); +/** + * sde_cp_crtc_check_properties: Verify color processing properties for a crtc. + * Should be called during atomic check call. + * @crtc: Pointer to crtc. + * @state: Pointer to crtc state. + * @returns: 0 on success, non-zero otherwise + */ +int sde_cp_crtc_check_properties(struct drm_crtc *crtc, + struct drm_crtc_state *state); /** * sde_cp_crtc_apply_properties: Enable/disable properties @@ -196,4 +205,18 @@ int sde_cp_ltm_off_event_handler(struct drm_crtc *crtc_drm, bool en, * @crtc_drm: Pointer to crtc. */ void sde_cp_mode_switch_prop_dirty(struct drm_crtc *crtc_drm); + +/** + * sde_cp_crtc_enable(): enable color processing info in the crtc. + * Should be called during crtc enable. + * @crtc: Pointer to drm_crtc. + */ +void sde_cp_crtc_enable(struct drm_crtc *crtc); + +/** + * sde_cp_crtc_disable(): disable color processing info in the crtc. + * Should be called during crtc disable. + * @crtc: Pointer to drm_crtc. + */ +void sde_cp_crtc_disable(struct drm_crtc *crtc); #endif /*_SDE_COLOR_PROCESSING_H */ diff --git a/techpack/display/msm/sde/sde_core_perf.c b/techpack/display/msm/sde/sde_core_perf.c index 3add93d9a61e..e3c02e089ff3 100644 --- a/techpack/display/msm/sde/sde_core_perf.c +++ b/techpack/display/msm/sde/sde_core_perf.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ @@ -676,6 +676,10 @@ static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms, bus_ab_quota = max(bw_sum_of_intfs, kms->perf.perf_tune.min_bus_vote); bus_ib_quota = perf.max_per_pipe_ib[bus_id]; + if (!kms->perf.sde_rsc_available) + bus_ib_quota = max(SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA, + bus_ib_quota); + if (kms->perf.perf_tune.mode == SDE_PERF_MODE_FIXED) { bus_ab_quota = max(kms->perf.fix_core_ab_vote, bus_ab_quota); diff --git a/techpack/display/msm/sde/sde_crtc.c b/techpack/display/msm/sde/sde_crtc.c index 5f3aede1f8ca..46bb184a5152 100644 --- a/techpack/display/msm/sde/sde_crtc.c +++ b/techpack/display/msm/sde/sde_crtc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -781,6 +781,9 @@ static int _sde_crtc_set_crtc_roi(struct drm_crtc *crtc, } sde_kms_rect_merge_rectangles(&sde_conn_state->rois, &conn_roi); + SDE_DEBUG("conn_roi x:%u, y:%u, w:%u, h:%u\n", + conn_roi.x, conn_roi.y, + conn_roi.w, conn_roi.h); SDE_EVT32_VERBOSE(DRMID(crtc), DRMID(conn), conn_roi.x, conn_roi.y, conn_roi.w, conn_roi.h); @@ -4079,6 +4082,7 @@ static void sde_crtc_disable(struct drm_crtc *crtc) /* disable clk & bw control until clk & bw properties are set */ cstate->bw_control = false; cstate->bw_split_vote = false; + sde_cp_crtc_disable(crtc); mutex_unlock(&sde_crtc->crtc_lock); } @@ -4150,7 +4154,7 @@ static void sde_crtc_enable(struct drm_crtc *crtc, } sde_crtc->enabled = true; - + sde_cp_crtc_enable(crtc); /* update color processing on resume */ event.type = DRM_EVENT_CRTC_POWER; event.length = sizeof(u32); @@ -4903,6 +4907,12 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, goto end; } + rc = sde_cp_crtc_check_properties(crtc, state); + if (rc) { + SDE_ERROR("crtc%d failed cp properties check %d\n", + crtc->base.id, rc); + goto end; + } end: kfree(pstates); kfree(multirect_plane); @@ -4989,6 +4999,26 @@ static void sde_kms_add_ubwc_info(struct sde_kms_info *info, sde_kms_info_add_keystr(info, "DDR version", "DDR5"); } +/** + * _sde_crtc_install_cp_properties - install color properties for crtc + * @info: Pointer to kms info structure + * @catalog: Pointer to catalog structure + */ +static void _sde_crtc_install_cp_properties(struct sde_kms_info *info, + struct sde_mdss_cfg *catalog) +{ + if (!info || !catalog) { + SDE_ERROR("invalid info or catalog\n"); + return; + } + + sde_kms_info_add_keyint(info, "has_hdr", catalog->has_hdr); + sde_kms_info_add_keyint(info, "has_hdr_plus", catalog->has_hdr_plus); + if (catalog->dspp_count && catalog->rc_count) + sde_kms_info_add_keyint(info, "rc_mem_size", + catalog->dspp[0].sblk->rc.mem_total_size); +} + /** * sde_crtc_install_properties - install all drm properties for crtc * @crtc: Pointer to drm crtc structure @@ -5189,8 +5219,7 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc, } sde_kms_info_add_keyint(info, "has_src_split", catalog->has_src_split); - sde_kms_info_add_keyint(info, "has_hdr", catalog->has_hdr); - sde_kms_info_add_keyint(info, "has_hdr_plus", catalog->has_hdr_plus); + _sde_crtc_install_cp_properties(info, catalog); if (catalog->perf.max_bw_low) sde_kms_info_add_keyint(info, "max_bandwidth_low", catalog->perf.max_bw_low * 1000LL); diff --git a/techpack/display/msm/sde/sde_crtc.h b/techpack/display/msm/sde/sde_crtc.h index e7330f7fba1a..bd16cd3da6fe 100644 --- a/techpack/display/msm/sde/sde_crtc.h +++ b/techpack/display/msm/sde/sde_crtc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021 The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -276,6 +276,8 @@ struct sde_crtc_misr_info { * @cur_perf : current performance committed to clock/bandwidth driver * @plane_mask_old: keeps track of the planes used in the previous commit * @frame_trigger_mode: frame trigger mode + * @cp_pu_feature_mask: mask indicating cp feature enable for partial update + * @cached_user_roi_list : Copy of user_roi_list from previous PU frame * @ltm_buffer_cnt : number of ltm buffers * @ltm_buffers : struct stores ltm buffer related data * @ltm_buf_free : list of LTM buffers that are available @@ -285,6 +287,7 @@ struct sde_crtc_misr_info { * @ltm_lock : Spinlock to protect ltm buffer_cnt, hist_en and ltm lists * @needs_hw_reset : Initiate a hw ctl reset * @comp_ratio : Compression ratio + * @dspp_blob_info : blob containing dspp hw capability information */ struct sde_crtc { struct drm_crtc base; @@ -358,6 +361,9 @@ struct sde_crtc { struct drm_property_blob *hist_blob; enum frame_trigger_mode_type frame_trigger_mode; + u32 cp_pu_feature_mask; + struct msm_roi_list cached_user_roi_list; + u32 ltm_buffer_cnt; struct sde_ltm_buffer *ltm_buffers[LTM_BUFFER_SIZE]; struct list_head ltm_buf_free; @@ -369,6 +375,8 @@ struct sde_crtc { bool needs_hw_reset; int comp_ratio; + + struct drm_property_blob *dspp_blob_info; }; #define to_sde_crtc(x) container_of(x, struct sde_crtc, base) @@ -389,7 +397,7 @@ struct sde_crtc { * @lm_roi : Current LM ROI, possibly sub-rectangle of mode. * Origin top left of CRTC. * @user_roi_list : List of user's requested ROIs as from set property - * @property_state: Local storage for msm_prop properties + * @property_state: Local storage for msm_prop properties * @property_values: Current crtc property values * @input_fence_timeout_ns : Cached input fence timeout, in ns * @num_dim_layers: Number of dim layers diff --git a/techpack/display/msm/sde/sde_hw_catalog.c b/techpack/display/msm/sde/sde_hw_catalog.c index 2e8bb2af68c0..6a20a15c55d0 100644 --- a/techpack/display/msm/sde/sde_hw_catalog.c +++ b/techpack/display/msm/sde/sde_hw_catalog.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ @@ -383,6 +383,14 @@ enum { LTM_PROP_MAX, }; +enum { + RC_OFF, + RC_LEN, + RC_VERSION, + RC_MEM_TOTAL_SIZE, + RC_PROP_MAX, +}; + enum { MIXER_OFF, MIXER_LEN, @@ -692,6 +700,13 @@ static struct sde_prop_type ltm_prop[] = { {LTM_VERSION, "qcom,sde-dspp-ltm-version", false, PROP_TYPE_U32}, }; +static struct sde_prop_type rc_prop[] = { + {RC_OFF, "qcom,sde-dspp-rc-off", false, PROP_TYPE_U32_ARRAY}, + {RC_LEN, "qcom,sde-dspp-rc-size", false, PROP_TYPE_U32}, + {RC_VERSION, "qcom,sde-dspp-rc-version", false, PROP_TYPE_U32}, + {RC_MEM_TOTAL_SIZE, "qcom,sde-dspp-rc-mem-size", false, PROP_TYPE_U32}, +}; + static struct sde_prop_type ds_top_prop[] = { {DS_TOP_OFF, "qcom,sde-dest-scaler-top-off", false, PROP_TYPE_U32}, {DS_TOP_LEN, "qcom,sde-dest-scaler-top-size", false, PROP_TYPE_U32}, @@ -2357,14 +2372,15 @@ static int sde_dspp_parse_dt(struct device_node *np, { int rc, prop_count[DSPP_PROP_MAX], i; int ad_prop_count[AD_PROP_MAX]; - int ltm_prop_count[LTM_PROP_MAX]; + int ltm_prop_count[LTM_PROP_MAX], rc_prop_count[RC_PROP_MAX]; bool prop_exists[DSPP_PROP_MAX], ad_prop_exists[AD_PROP_MAX]; - bool ltm_prop_exists[LTM_PROP_MAX]; + bool ltm_prop_exists[LTM_PROP_MAX], rc_prop_exists[RC_PROP_MAX]; bool blocks_prop_exists[DSPP_BLOCKS_PROP_MAX]; struct sde_prop_value *ad_prop_value = NULL, *ltm_prop_value = NULL; + struct sde_prop_value *rc_prop_value = NULL; int blocks_prop_count[DSPP_BLOCKS_PROP_MAX]; struct sde_prop_value *prop_value = NULL, *blocks_prop_value = NULL; - u32 off_count, ad_off_count, ltm_off_count; + u32 off_count, ad_off_count, ltm_off_count, rc_off_count; struct sde_dspp_cfg *dspp; struct sde_dspp_sub_blks *sblk; struct device_node *snp = NULL; @@ -2426,6 +2442,22 @@ static int sde_dspp_parse_dt(struct device_node *np, if (rc) goto end; + /* Parse RC dtsi entries */ + rc_prop_value = kcalloc(RC_PROP_MAX, + sizeof(struct sde_prop_value), GFP_KERNEL); + if (!rc_prop_value) { + rc = -ENOMEM; + goto end; + } + rc = _validate_dt_entry(np, rc_prop, ARRAY_SIZE(rc_prop), + rc_prop_count, &rc_off_count); + if (rc) + goto end; + rc = _read_dt_entry(np, rc_prop, ARRAY_SIZE(rc_prop), rc_prop_count, + rc_prop_exists, rc_prop_value); + if (rc) + goto end; + /* get DSPP feature dt properties if they exist */ snp = of_get_child_by_name(np, dspp_prop[DSPP_BLOCKS].prop_name); if (snp) { @@ -2489,6 +2521,22 @@ static int sde_dspp_parse_dt(struct device_node *np, set_bit(SDE_DSPP_LTM, &dspp->features); } + sblk->rc.id = SDE_DSPP_RC; + sde_cfg->rc_count = rc_off_count; + if (rc_prop_value && (i < rc_off_count) && + rc_prop_exists[RC_OFF]) { + sblk->rc.base = PROP_VALUE_ACCESS(rc_prop_value, + RC_OFF, i); + sblk->rc.len = PROP_VALUE_ACCESS(rc_prop_value, + RC_LEN, 0); + sblk->rc.version = PROP_VALUE_ACCESS(rc_prop_value, + RC_VERSION, 0); + sblk->rc.mem_total_size = PROP_VALUE_ACCESS( + rc_prop_value, RC_MEM_TOTAL_SIZE, + 0); + sblk->rc.idx = i; + set_bit(SDE_DSPP_RC, &dspp->features); + } } end: @@ -2496,6 +2544,8 @@ static int sde_dspp_parse_dt(struct device_node *np, kfree(ad_prop_value); kfree(ltm_prop_value); kfree(blocks_prop_value); + kfree(rc_prop_value); + return rc; } @@ -4383,6 +4433,23 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->allow_gdsc_toggle = true; clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs); clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs); + } else if (IS_KHAJE_TARGET(hw_rev)) { + sde_cfg->has_cwb_support = false; + sde_cfg->has_qsync = true; + sde_cfg->perf.min_prefill_lines = 24; + sde_cfg->vbif_qos_nlvl = 8; + sde_cfg->ts_prefill_rev = 2; + sde_cfg->ctl_rev = SDE_CTL_CFG_VERSION_1_0_0; + sde_cfg->delay_prg_fetch_start = true; + sde_cfg->sui_ns_allowed = true; + sde_cfg->sui_misr_supported = true; + sde_cfg->sui_block_xin_mask = 0xC01; + sde_cfg->has_hdr = false; + sde_cfg->has_sui_blendstage = true; + sde_cfg->allow_gdsc_toggle = true; + clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs); + clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs); + sde_cfg->rc_lm_flush_override = true; } else { SDE_ERROR("unsupported chipset id:%X\n", hw_rev); sde_cfg->perf.min_prefill_lines = 0xffff; diff --git a/techpack/display/msm/sde/sde_hw_catalog.h b/techpack/display/msm/sde/sde_hw_catalog.h index bed02d96fbde..8a4d1930c1ef 100644 --- a/techpack/display/msm/sde/sde_hw_catalog.h +++ b/techpack/display/msm/sde/sde_hw_catalog.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #ifndef _SDE_HW_CATALOG_H @@ -56,6 +56,7 @@ #define SDE_HW_VER_630 SDE_HW_VER(6, 3, 0) /* bengal */ #define SDE_HW_VER_640 SDE_HW_VER(6, 4, 0) /* lagoon */ #define SDE_HW_VER_650 SDE_HW_VER(6, 5, 0) /* scuba */ +#define SDE_HW_VER_6100 SDE_HW_VER(6, 10, 0) /* khaje */ #define IS_MSM8996_TARGET(rev) IS_SDE_MAJOR_MINOR_SAME((rev), SDE_HW_VER_170) #define IS_MSM8998_TARGET(rev) IS_SDE_MAJOR_MINOR_SAME((rev), SDE_HW_VER_300) @@ -71,6 +72,7 @@ #define IS_BENGAL_TARGET(rev) IS_SDE_MAJOR_MINOR_SAME((rev), SDE_HW_VER_630) #define IS_LAGOON_TARGET(rev) IS_SDE_MAJOR_MINOR_SAME((rev), SDE_HW_VER_640) #define IS_SCUBA_TARGET(rev) IS_SDE_MAJOR_MINOR_SAME((rev), SDE_HW_VER_650) +#define IS_KHAJE_TARGET(rev) IS_SDE_MAJOR_MINOR_SAME((rev), SDE_HW_VER_6100) #define SDE_HW_BLK_NAME_LEN 16 @@ -313,6 +315,7 @@ enum { * @SDE_DSPP_VLUT PA VLUT block * @SDE_DSPP_AD AD block * @SDE_DSPP_LTM LTM block + * @SDE_DSPP_RC RC block * @SDE_DSPP_MAX maximum value */ enum { @@ -328,6 +331,7 @@ enum { SDE_DSPP_VLUT, SDE_DSPP_AD, SDE_DSPP_LTM, + SDE_DSPP_RC, SDE_DSPP_MAX }; @@ -662,6 +666,20 @@ struct sde_lm_sub_blks { struct sde_pp_blk gc; }; +/** + * struct sde_dspp_rc: Pixel processing rounded corner sub-blk information + * @info: HW register and features supported by this sub-blk. + * @version: HW Algorithm version. + * @idx: HW block instance id. + * @mem_total_size: data memory size. + */ +struct sde_dspp_rc { + SDE_HW_SUBBLK_INFO; + u32 version; + u32 idx; + u32 mem_total_size; +}; + struct sde_dspp_sub_blks { struct sde_pp_blk igc; struct sde_pp_blk pcc; @@ -675,6 +693,7 @@ struct sde_dspp_sub_blks { struct sde_pp_blk ad; struct sde_pp_blk ltm; struct sde_pp_blk vlut; + struct sde_dspp_rc rc; }; struct sde_pingpong_sub_blks { @@ -1269,6 +1288,7 @@ struct sde_limit_cfg { * @has_base_layer Supports staging layer as base layer * @allow_gdsc_toggle Flag to check if gdsc toggle is needed after crtc is * disabled when external vote is present + * @rc_lm_flush_override Support Rounded Corner using layer mixer flush * @sc_cfg: system cache configuration * @uidle_cfg Settings for uidle feature * @sui_misr_supported indicate if secure-ui-misr is supported @@ -1285,6 +1305,7 @@ struct sde_limit_cfg { * @has_vig_p010 indicates if vig pipe supports p010 format * @inline_rot_formats formats supported by the inline rotator feature * @mdss_irqs bitmap with the irqs supported by the target + * @rc_count number of rounded corner hardware instances */ struct sde_mdss_cfg { u32 hwversion; @@ -1327,6 +1348,7 @@ struct sde_mdss_cfg { bool update_tcsr_disp_glitch; bool has_base_layer; bool allow_gdsc_toggle; + bool rc_lm_flush_override; struct sde_sc_cfg sc_cfg; @@ -1392,6 +1414,7 @@ struct sde_mdss_cfg { u32 ad_count; u32 ltm_count; + u32 rc_count; u32 merge_3d_count; struct sde_merge_3d_cfg merge_3d[MAX_BLOCKS]; @@ -1439,6 +1462,7 @@ struct sde_mdss_hw_cfg_handler { #define BLK_WB(s) ((s)->wb) #define BLK_AD(s) ((s)->ad) #define BLK_LTM(s) ((s)->ltm) +#define BLK_RC(s) ((s)->rc) /** * sde_hw_set_preference: populate the individual hw lm preferences, diff --git a/techpack/display/msm/sde/sde_hw_dspp.c b/techpack/display/msm/sde/sde_hw_dspp.c index 5b66b83be806..d45dc5b8d832 100644 --- a/techpack/display/msm/sde/sde_hw_dspp.c +++ b/techpack/display/msm/sde/sde_hw_dspp.c @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2019, 2021, The Linux Foundation. All rights reserved. */ + #include #include "sde_hw_mdss.h" #include "sde_hwio.h" @@ -10,6 +11,7 @@ #include "sde_hw_color_processing.h" #include "sde_dbg.h" #include "sde_ad4.h" +#include "sde_hw_rc.h" #include "sde_kms.h" static struct sde_dspp_cfg *_dspp_offset(enum sde_dspp dspp, @@ -229,6 +231,37 @@ static void dspp_ltm(struct sde_hw_dspp *c) } } +static void dspp_rc(struct sde_hw_dspp *c) +{ + int ret = 0; + + if (!c) { + SDE_ERROR("invalid arguments\n"); + return; + } + + if (c->cap->sblk->rc.version == SDE_COLOR_PROCESS_VER(0x1, 0x0)) { + ret = sde_hw_rc_init(c); + if (ret) { + SDE_ERROR("rc init failed, ret %d\n", ret); + return; + } + + ret = reg_dmav1_init_dspp_op_v4(SDE_DSPP_RC, c->idx); + if (!ret) + c->ops.setup_rc_data = + sde_hw_rc_setup_data_dma; + else + c->ops.setup_rc_data = + sde_hw_rc_setup_data_ahb; + + c->ops.validate_rc_mask = sde_hw_rc_check_mask; + c->ops.setup_rc_mask = sde_hw_rc_setup_mask; + c->ops.validate_rc_pu_roi = sde_hw_rc_check_pu_roi; + c->ops.setup_rc_pu_roi = sde_hw_rc_setup_pu_roi; + } +} + static void (*dspp_blocks[SDE_DSPP_MAX])(struct sde_hw_dspp *c); static void _init_dspp_ops(void) @@ -245,6 +278,7 @@ static void _init_dspp_ops(void) dspp_blocks[SDE_DSPP_VLUT] = dspp_vlut; dspp_blocks[SDE_DSPP_AD] = dspp_ad; dspp_blocks[SDE_DSPP_LTM] = dspp_ltm; + dspp_blocks[SDE_DSPP_RC] = dspp_rc; } static void _setup_dspp_ops(struct sde_hw_dspp *c, unsigned long features) @@ -274,6 +308,7 @@ struct sde_hw_dspp *sde_hw_dspp_init(enum sde_dspp idx, struct sde_hw_dspp *c; struct sde_dspp_cfg *cfg; int rc; + char buf[256]; if (!addr || !m) return ERR_PTR(-EINVAL); @@ -317,6 +352,13 @@ struct sde_hw_dspp *sde_hw_dspp_init(enum sde_dspp idx, c->hw.xin_id); } + if ((cfg->sblk->rc.id == SDE_DSPP_RC) && cfg->sblk->rc.base) { + snprintf(buf, ARRAY_SIZE(buf), "%s_%d", "rc", c->idx - DSPP_0); + sde_dbg_reg_register_dump_range(SDE_DBG_NAME, buf, + c->hw.blk_off + cfg->sblk->rc.base, + c->hw.blk_off + cfg->sblk->rc.base + + cfg->sblk->rc.len, c->hw.xin_id); + } return c; blk_init_error: diff --git a/techpack/display/msm/sde/sde_hw_dspp.h b/techpack/display/msm/sde/sde_hw_dspp.h index dfc2ff1e4927..f44e617601a3 100644 --- a/techpack/display/msm/sde/sde_hw_dspp.h +++ b/techpack/display/msm/sde/sde_hw_dspp.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2019, 2021, The Linux Foundation. All rights reserved. */ #ifndef _SDE_HW_DSPP_H @@ -209,6 +209,46 @@ struct sde_hw_dspp_ops { * @status: Pointer to u32 where ltm status value is dumped. */ void (*ltm_read_intr_status)(struct sde_hw_dspp *ctx, u32 *status); + + /** + * validate_rc_mask - Validate RC mask configuration + * @ctx: Pointer to dspp context. + * @cfg: Pointer to configuration. + * Return: 0 on success, non-zero otherwise. + */ + int (*validate_rc_mask)(struct sde_hw_dspp *ctx, void *cfg); + + /** + * setup_rc_mask - Setup RC mask configuration + * @ctx: Pointer to dspp context. + * @cfg: Pointer to configuration. + * Return: 0 on success, non-zero otherwise. + */ + int (*setup_rc_mask)(struct sde_hw_dspp *ctx, void *cfg); + + /** + * validate_rc_pu_roi - Validate RC regions in during partial update. + * @ctx: Pointer to dspp context. + * @cfg: Pointer to configuration. + * Return: 0 on success, non-zero otherwise. + */ + int (*validate_rc_pu_roi)(struct sde_hw_dspp *ctx, void *cfg); + + /** + * setup_rc_pu_roi - Setup RC regions in during partial update. + * @ctx: Pointer to dspp context. + * @cfg: Pointer to configuration. + * Return: 0 on success, non-zero otherwise. + */ + int (*setup_rc_pu_roi)(struct sde_hw_dspp *ctx, void *cfg); + + /** + * setup_rc_data - Program RC mask data + * @ctx: Pointer to dspp context. + * @cfg: Pointer to configuration. + * Return: 0 on success, non-zero otherwise. + */ + int (*setup_rc_data)(struct sde_hw_dspp *ctx, void *cfg); }; /** diff --git a/techpack/display/msm/sde/sde_hw_mdss.h b/techpack/display/msm/sde/sde_hw_mdss.h index 6a75881176ce..15f0b91d3c2a 100644 --- a/techpack/display/msm/sde/sde_hw_mdss.h +++ b/techpack/display/msm/sde/sde_hw_mdss.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2019, 2021, The Linux Foundation. All rights reserved. */ #ifndef _SDE_HW_MDSS_H @@ -171,6 +171,7 @@ enum sde_stage { SDE_STAGE_10, SDE_STAGE_MAX }; + enum sde_dspp { DSPP_0 = 1, DSPP_1, @@ -185,6 +186,12 @@ enum sde_ltm { LTM_MAX }; +enum sde_rc { + RC_0 = DSPP_0, + RC_1, + RC_MAX +}; + enum sde_ds { DS_TOP, DS_0, diff --git a/techpack/display/msm/sde/sde_hw_rc.c b/techpack/display/msm/sde/sde_hw_rc.c new file mode 100644 index 000000000000..38106898b2f2 --- /dev/null +++ b/techpack/display/msm/sde/sde_hw_rc.c @@ -0,0 +1,1069 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. + */ + +#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ +#include +#include "sde_kms.h" +#include "sde_reg_dma.h" +#include "sde_hw_rc.h" +#include "sde_hw_catalog.h" +#include "sde_hw_util.h" +#include "sde_hw_dspp.h" +#include "sde_hw_reg_dma_v1_color_proc.h" + +/** + * Hardware register set + */ +#define SDE_HW_RC_REG0 0x00 +#define SDE_HW_RC_REG1 0x04 +#define SDE_HW_RC_REG2 0x08 +#define SDE_HW_RC_REG3 0x0C +#define SDE_HW_RC_REG4 0x10 +#define SDE_HW_RC_REG5 0x14 +#define SDE_HW_RC_REG6 0x18 +#define SDE_HW_RC_REG7 0x1C +#define SDE_HW_RC_REG8 0x20 +#define SDE_HW_RC_REG9 0x24 +#define SDE_HW_RC_REG10 0x28 +#define SDE_HW_RC_REG11 0x2C +#define SDE_HW_RC_REG12 0x30 +#define SDE_HW_RC_REG13 0x34 + +#define SDE_HW_RC_DATA_REG_SIZE 18 +#define SDE_HW_RC_SKIP_DATA_PROG 0x1 + +#define SDE_HW_RC_DISABLE_R1 0x01E +#define SDE_HW_RC_DISABLE_R2 0x1E0 + +#define SDE_HW_RC_PU_SKIP_OP 0x1 + +/** + * struct sde_hw_rc_state - rounded corner cached state per RC instance + * + * @last_rc_mask_cfg: cached value of most recent programmed mask. + * @mask_programmed: true if mask was programmed at least once to RC hardware. + * @last_roi_list: cached value of most recent processed list of ROIs. + * @roi_programmed: true if list of ROIs were processed at least once. + */ +struct sde_hw_rc_state { + struct drm_msm_rc_mask_cfg *last_rc_mask_cfg; + bool mask_programmed; + struct msm_roi_list *last_roi_list; + bool roi_programmed; +}; + +static struct sde_hw_rc_state rc_state[RC_MAX - RC_0] = { + { + .last_rc_mask_cfg = NULL, + .last_roi_list = NULL, + .mask_programmed = false, + .roi_programmed = false, + }, + { + .last_rc_mask_cfg = NULL, + .last_roi_list = NULL, + .mask_programmed = false, + .roi_programmed = false, + }, +}; +#define RC_STATE(hw_dspp) rc_state[hw_dspp->cap->sblk->rc.idx] + +enum rc_param_r { + RC_PARAM_R0 = 0x0, + RC_PARAM_R1 = 0x1, + RC_PARAM_R2 = 0x2, + RC_PARAM_R1R2 = (RC_PARAM_R1 | RC_PARAM_R2), +}; + +enum rc_param_a { + RC_PARAM_A0 = 0x2, + RC_PARAM_A1 = 0x4, +}; + +enum rc_param_b { + RC_PARAM_B0 = 0x0, + RC_PARAM_B1 = 0x1, + RC_PARAM_B2 = 0x2, + RC_PARAM_B1B2 = (RC_PARAM_B1 | RC_PARAM_B2), +}; + +enum rc_param_c { + RC_PARAM_C0 = (BIT(8)), + RC_PARAM_C1 = (BIT(10)), + RC_PARAM_C2 = (BIT(10) | BIT(11)), + RC_PARAM_C3 = (BIT(8) | BIT(10)), + RC_PARAM_C4 = (BIT(8) | BIT(9)), + RC_PARAM_C5 = (BIT(8) | BIT(9) | BIT(10) | BIT(11)), +}; + +enum rc_merge_mode { + RC_MERGE_SINGLE_PIPE = 0x0, + RC_MERGE_DUAL_PIPE = 0x1 +}; + +struct rc_config_table { + enum rc_param_a param_a; + enum rc_param_b param_b; + enum rc_param_c param_c; + enum rc_merge_mode merge_mode; + enum rc_merge_mode merge_mode_en; +}; + +static struct rc_config_table config_table[] = { + /* RC_PARAM_A0 configurations */ + { + .param_a = RC_PARAM_A0, + .param_b = RC_PARAM_B0, + .param_c = RC_PARAM_C5, + .merge_mode = RC_MERGE_SINGLE_PIPE, + .merge_mode_en = RC_MERGE_SINGLE_PIPE, + + }, + { + .param_a = RC_PARAM_A0, + .param_b = RC_PARAM_B1B2, + .param_c = RC_PARAM_C3, + .merge_mode = RC_MERGE_SINGLE_PIPE, + .merge_mode_en = RC_MERGE_SINGLE_PIPE, + + }, + { + .param_a = RC_PARAM_A0, + .param_b = RC_PARAM_B1, + .param_c = RC_PARAM_C0, + .merge_mode = RC_MERGE_SINGLE_PIPE, + .merge_mode_en = RC_MERGE_SINGLE_PIPE, + + }, + { + .param_a = RC_PARAM_A0, + .param_b = RC_PARAM_B2, + .param_c = RC_PARAM_C1, + .merge_mode = RC_MERGE_SINGLE_PIPE, + .merge_mode_en = RC_MERGE_SINGLE_PIPE, + + }, + { + .param_a = RC_PARAM_A0, + .param_b = RC_PARAM_B0, + .param_c = RC_PARAM_C5, + .merge_mode = RC_MERGE_DUAL_PIPE, + .merge_mode_en = RC_MERGE_DUAL_PIPE, + + }, + { + .param_a = RC_PARAM_A0, + .param_b = RC_PARAM_B1B2, + .param_c = RC_PARAM_C3, + .merge_mode = RC_MERGE_DUAL_PIPE, + .merge_mode_en = RC_MERGE_DUAL_PIPE, + + }, + { + .param_a = RC_PARAM_A0, + .param_b = RC_PARAM_B1, + .param_c = RC_PARAM_C0, + .merge_mode = RC_MERGE_DUAL_PIPE, + .merge_mode_en = RC_MERGE_SINGLE_PIPE, + + }, + { + .param_a = RC_PARAM_A0, + .param_b = RC_PARAM_B2, + .param_c = RC_PARAM_C1, + .merge_mode = RC_MERGE_DUAL_PIPE, + .merge_mode_en = RC_MERGE_SINGLE_PIPE, + }, + + /* RC_PARAM_A1 configurations */ + { + .param_a = RC_PARAM_A1, + .param_b = RC_PARAM_B0, + .param_c = RC_PARAM_C5, + .merge_mode = RC_MERGE_SINGLE_PIPE, + .merge_mode_en = RC_MERGE_SINGLE_PIPE, + + }, + { + .param_a = RC_PARAM_A1, + .param_b = RC_PARAM_B1B2, + .param_c = RC_PARAM_C5, + .merge_mode = RC_MERGE_SINGLE_PIPE, + .merge_mode_en = RC_MERGE_SINGLE_PIPE, + + }, + { + .param_a = RC_PARAM_A1, + .param_b = RC_PARAM_B1, + .param_c = RC_PARAM_C4, + .merge_mode = RC_MERGE_SINGLE_PIPE, + .merge_mode_en = RC_MERGE_SINGLE_PIPE, + + }, + { + .param_a = RC_PARAM_A1, + .param_b = RC_PARAM_B2, + .param_c = RC_PARAM_C2, + .merge_mode = RC_MERGE_SINGLE_PIPE, + .merge_mode_en = RC_MERGE_SINGLE_PIPE, + + }, + { + .param_a = RC_PARAM_A1, + .param_b = RC_PARAM_B0, + .param_c = RC_PARAM_C5, + .merge_mode = RC_MERGE_DUAL_PIPE, + .merge_mode_en = RC_MERGE_DUAL_PIPE, + + }, + { + .param_a = RC_PARAM_A1, + .param_b = RC_PARAM_B1B2, + .param_c = RC_PARAM_C5, + .merge_mode = RC_MERGE_DUAL_PIPE, + .merge_mode_en = RC_MERGE_DUAL_PIPE, + + }, + { + .param_a = RC_PARAM_A1, + .param_b = RC_PARAM_B1, + .param_c = RC_PARAM_C4, + .merge_mode = RC_MERGE_DUAL_PIPE, + .merge_mode_en = RC_MERGE_SINGLE_PIPE, + + }, + { + .param_a = RC_PARAM_A1, + .param_b = RC_PARAM_B2, + .param_c = RC_PARAM_C2, + .merge_mode = RC_MERGE_DUAL_PIPE, + .merge_mode_en = RC_MERGE_SINGLE_PIPE, + + }, +}; + +static inline void _sde_hw_rc_reg_write( + struct sde_hw_dspp *hw_dspp, + int offset, + u32 value) +{ + u32 address = hw_dspp->cap->sblk->rc.base + offset; + + SDE_DEBUG("rc:%u, address:0x%08X, value:0x%08X\n", + hw_dspp->cap->sblk->rc.idx, + hw_dspp->hw.blk_off + address, value); + SDE_REG_WRITE(&hw_dspp->hw, address, value); +} + +static int _sde_hw_rc_get_enable_bits( + enum rc_param_a param_a, + enum rc_param_b param_b, + enum rc_param_c *param_c, + u32 merge_mode, + u32 *merge_mode_en) +{ + int i = 0; + + if (!param_c || !merge_mode_en) { + SDE_ERROR("invalid arguments\n"); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(config_table); i++) { + if (merge_mode == config_table[i].merge_mode && + param_a == config_table[i].param_a && + param_b == config_table[i].param_b) { + *param_c = config_table[i].param_c; + *merge_mode_en = config_table[i].merge_mode_en; + SDE_DEBUG("found param_c:0x%08X, merge_mode_en:%d\n", + *param_c, *merge_mode_en); + return 0; + } + } + SDE_ERROR("configuration not supported"); + + return -EINVAL; +} + +static int _sde_hw_rc_get_merge_mode( + const struct sde_hw_cp_cfg *hw_cfg, + u32 *merge_mode) +{ + int rc = 0; + + if (!hw_cfg || !merge_mode) { + SDE_ERROR("invalid arguments\n"); + return -EINVAL; + } + + if (hw_cfg->num_of_mixers == 1) + *merge_mode = RC_MERGE_SINGLE_PIPE; + else if (hw_cfg->num_of_mixers == 2) + *merge_mode = RC_MERGE_DUAL_PIPE; + else { + SDE_ERROR("invalid number of mixers:%d\n", + hw_cfg->num_of_mixers); + return -EINVAL; + } + + SDE_DEBUG("number mixers:%u, merge mode:%u\n", + hw_cfg->num_of_mixers, *merge_mode); + + return rc; +} + +static int _sde_hw_rc_get_ajusted_roi( + const struct sde_hw_cp_cfg *hw_cfg, + const struct sde_rect *pu_roi, + struct sde_rect *rc_roi) +{ + int rc = 0; + + if (!hw_cfg || !pu_roi || !rc_roi) { + SDE_ERROR("invalid arguments\n"); + return -EINVAL; + } + + /*when partial update is disabled, use full screen ROI*/ + if (pu_roi->w == 0 && pu_roi->h == 0) { + rc_roi->x = pu_roi->x; + rc_roi->y = pu_roi->y; + rc_roi->w = hw_cfg->displayh; + rc_roi->h = hw_cfg->displayv; + } else { + memcpy(rc_roi, pu_roi, sizeof(struct sde_rect)); + } + + SDE_DEBUG("displayh:%u, displayv:%u\n", hw_cfg->displayh, + hw_cfg->displayv); + SDE_DEBUG("pu_roi x:%u, y:%u, w:%u, h:%u\n", pu_roi->x, pu_roi->y, + pu_roi->w, pu_roi->h); + SDE_DEBUG("rc_roi x:%u, y:%u, w:%u, h:%u\n", rc_roi->x, rc_roi->y, + rc_roi->w, rc_roi->h); + + return rc; +} + +static int _sde_hw_rc_get_param_rb( + const struct drm_msm_rc_mask_cfg *rc_mask_cfg, + const struct sde_rect *rc_roi, + enum rc_param_r *param_r, + enum rc_param_b *param_b) +{ + int rc = 0; + int half_panel_x = 0, half_panel_w = 0; + int cfg_param_01 = 0, cfg_param_02 = 0; + int x1 = 0, x2 = 0, y1 = 0, y2 = 0; + + if (!rc_mask_cfg || !rc_roi || !param_r || !param_b) { + SDE_ERROR("invalid arguments\n"); + return -EINVAL; + } + + if (rc_mask_cfg->cfg_param_03 == RC_PARAM_A1) + half_panel_w = rc_mask_cfg->cfg_param_04[0] + + rc_mask_cfg->cfg_param_04[1]; + else if (rc_mask_cfg->cfg_param_03 == RC_PARAM_A0) + half_panel_w = rc_mask_cfg->cfg_param_04[0]; + else { + SDE_ERROR("invalid cfg_param_03:%u\n", + rc_mask_cfg->cfg_param_03); + return -EINVAL; + } + + cfg_param_01 = rc_mask_cfg->cfg_param_01; + cfg_param_02 = rc_mask_cfg->cfg_param_02; + x1 = rc_roi->x; + x2 = rc_roi->x + rc_roi->w - 1; + y1 = rc_roi->y; + y2 = rc_roi->y + rc_roi->h - 1; + half_panel_x = half_panel_w - 1; + + SDE_DEBUG("x1:%u y1:%u x2:%u y2:%u\n", x1, y1, x2, y2); + SDE_DEBUG("cfg_param_01:%u cfg_param_02:%u half_panel_x:%u", + cfg_param_01, cfg_param_02, half_panel_x); + + if (x1 < 0 || x2 < 0 || y1 < 0 || y2 < 0 || half_panel_x < 0 || + x1 >= x2 || y1 >= y2) { + SDE_ERROR("invalid coordinates\n"); + return -EINVAL; + } + + if (y1 <= cfg_param_01) { + *param_r |= RC_PARAM_R1; + if (x1 <= half_panel_x && x2 <= half_panel_x) + *param_b |= RC_PARAM_B1; + else if (x1 > half_panel_x && x2 > half_panel_x) + *param_b |= RC_PARAM_B2; + else + *param_b |= RC_PARAM_B1B2; + } + + if (y2 >= cfg_param_02) { + *param_r |= RC_PARAM_R2; + if (x1 <= half_panel_x && x2 <= half_panel_x) + *param_b |= RC_PARAM_B1; + else if (x1 > half_panel_x && x2 > half_panel_x) + *param_b |= RC_PARAM_B2; + else + *param_b |= RC_PARAM_B1B2; + } + + SDE_DEBUG("param_r:0x%08X param_b:0x%08X\n", *param_r, *param_b); + SDE_EVT32(rc_roi->x, rc_roi->y, rc_roi->w, rc_roi->h); + SDE_EVT32(x1, y1, x2, y2, cfg_param_01, cfg_param_02, half_panel_x); + + return rc; +} + +static int _sde_hw_rc_program_enable_bits( + struct sde_hw_dspp *hw_dspp, + struct drm_msm_rc_mask_cfg *rc_mask_cfg, + enum rc_param_a param_a, + enum rc_param_b param_b, + enum rc_param_r param_r, + int merge_mode, + struct sde_rect *rc_roi) +{ + int rc = 0; + u32 val = 0, param_c = 0, rc_merge_mode = 0, ystart = 0; + u64 flags = 0; + bool r1_valid = false, r2_valid = false; + bool pu_in_r1 = false, pu_in_r2 = false; + bool r1_enable = false, r2_enable = false; + + if (!hw_dspp || !rc_mask_cfg || !rc_roi) { + SDE_ERROR("invalid arguments\n"); + return -EINVAL; + } + + rc = _sde_hw_rc_get_enable_bits(param_a, param_b, ¶m_c, + merge_mode, &rc_merge_mode); + if (rc) { + SDE_ERROR("invalid enable bits, rc:%d\n", rc); + return rc; + } + + flags = rc_mask_cfg->flags; + r1_valid = ((flags & SDE_HW_RC_DISABLE_R1) != SDE_HW_RC_DISABLE_R1); + r2_valid = ((flags & SDE_HW_RC_DISABLE_R2) != SDE_HW_RC_DISABLE_R2); + pu_in_r1 = (param_r == RC_PARAM_R1 || param_r == RC_PARAM_R1R2); + pu_in_r2 = (param_r == RC_PARAM_R2 || param_r == RC_PARAM_R1R2); + r1_enable = (r1_valid && pu_in_r1); + r2_enable = (r2_valid && pu_in_r2); + + if (r1_enable) + val |= BIT(0); + + if (r2_enable) + val |= BIT(4); + + /*corner case for partial update in R2 region*/ + if (!r1_enable && r2_enable) + ystart = rc_roi->y; + + SDE_DEBUG("flags:%x, R1 valid:%d, R2 valid:%d\n", + flags, r1_valid, r2_valid); + SDE_DEBUG("PU in R1:%d, PU in R2:%d, Y_START:%d\n", + pu_in_r1, pu_in_r2, ystart); + SDE_EVT32(flags, r1_valid, r2_valid, pu_in_r1, pu_in_r2, ystart); + + val |= param_c; + _sde_hw_rc_reg_write(hw_dspp, SDE_HW_RC_REG1, val); + _sde_hw_rc_reg_write(hw_dspp, SDE_HW_RC_REG13, ystart); + _sde_hw_rc_reg_write(hw_dspp, SDE_HW_RC_REG9, rc_merge_mode); + + return rc; +} + +static int _sde_hw_rc_program_roi( + struct sde_hw_dspp *hw_dspp, + struct drm_msm_rc_mask_cfg *rc_mask_cfg, + int merge_mode, + struct sde_rect *rc_roi) +{ + int rc = 0; + u32 val2 = 0, val3 = 0, val4 = 0; + enum rc_param_r param_r = RC_PARAM_R0; + enum rc_param_a param_a = RC_PARAM_A0; + enum rc_param_b param_b = RC_PARAM_B0; + + if (!hw_dspp || !rc_mask_cfg || !rc_roi) { + SDE_ERROR("invalid arguments\n"); + return -EINVAL; + } + + rc = _sde_hw_rc_get_param_rb(rc_mask_cfg, rc_roi, ¶m_r, + ¶m_b); + if (rc) { + SDE_ERROR("invalid rc roi, rc:%d\n", rc); + return rc; + } + + param_a = rc_mask_cfg->cfg_param_03; + rc = _sde_hw_rc_program_enable_bits(hw_dspp, rc_mask_cfg, + param_a, param_b, param_r, merge_mode, rc_roi); + if (rc) { + SDE_ERROR("failed to program enable bits, rc:%d\n", rc); + return rc; + } + + val2 = ((rc_mask_cfg->cfg_param_01 & 0x0000FFFF) | + ((rc_mask_cfg->cfg_param_02 << 16) & 0xFFFF0000)); + if (param_a == RC_PARAM_A1) { + val3 = (rc_mask_cfg->cfg_param_04[0] | + (rc_mask_cfg->cfg_param_04[1] << 16)); + val4 = (rc_mask_cfg->cfg_param_04[2] | + (rc_mask_cfg->cfg_param_04[3] << 16)); + } else if (param_a == RC_PARAM_A0) { + val3 = (rc_mask_cfg->cfg_param_04[0]); + val4 = (rc_mask_cfg->cfg_param_04[1]); + } + + _sde_hw_rc_reg_write(hw_dspp, SDE_HW_RC_REG2, val2); + _sde_hw_rc_reg_write(hw_dspp, SDE_HW_RC_REG3, val3); + _sde_hw_rc_reg_write(hw_dspp, SDE_HW_RC_REG4, val4); + + return 0; +} + +static int _sde_hw_rc_program_data_offset( + struct sde_hw_dspp *hw_dspp, + struct drm_msm_rc_mask_cfg *rc_mask_cfg) +{ + int rc = 0; + u32 val5 = 0, val6 = 0, val7 = 0, val8 = 0; + u32 cfg_param_07; + + if (!hw_dspp || !rc_mask_cfg) { + SDE_ERROR("invalid arguments\n"); + return -EINVAL; + } + + cfg_param_07 = rc_mask_cfg->cfg_param_07; + if (rc_mask_cfg->cfg_param_03 == RC_PARAM_A1) { + val5 = ((rc_mask_cfg->cfg_param_05[0] + cfg_param_07) | + ((rc_mask_cfg->cfg_param_05[1] + cfg_param_07) + << 16)); + val6 = ((rc_mask_cfg->cfg_param_05[2] + cfg_param_07)| + ((rc_mask_cfg->cfg_param_05[3] + cfg_param_07) + << 16)); + val7 = ((rc_mask_cfg->cfg_param_06[0] + cfg_param_07) | + ((rc_mask_cfg->cfg_param_06[1] + cfg_param_07) + << 16)); + val8 = ((rc_mask_cfg->cfg_param_06[2] + cfg_param_07) | + ((rc_mask_cfg->cfg_param_06[3] + cfg_param_07) + << 16)); + } else if (rc_mask_cfg->cfg_param_03 == RC_PARAM_A0) { + val5 = (rc_mask_cfg->cfg_param_05[0] + cfg_param_07); + val6 = (rc_mask_cfg->cfg_param_05[1] + cfg_param_07); + val7 = (rc_mask_cfg->cfg_param_06[0] + cfg_param_07); + val8 = (rc_mask_cfg->cfg_param_06[1] + cfg_param_07); + } + + _sde_hw_rc_reg_write(hw_dspp, SDE_HW_RC_REG5, val5); + _sde_hw_rc_reg_write(hw_dspp, SDE_HW_RC_REG6, val6); + _sde_hw_rc_reg_write(hw_dspp, SDE_HW_RC_REG7, val7); + _sde_hw_rc_reg_write(hw_dspp, SDE_HW_RC_REG8, val8); + + return rc; +} + +static int sde_hw_rc_check_mask_cfg( + struct sde_hw_dspp *hw_dspp, + struct sde_hw_cp_cfg *hw_cfg, + struct drm_msm_rc_mask_cfg *rc_mask_cfg) +{ + int rc = 0; + u32 i = 0; + u32 half_panel_width; + u64 flags; + u32 cfg_param_01, cfg_param_02, cfg_param_03; + u32 cfg_param_07, cfg_param_08; + u32 *cfg_param_04, *cfg_param_05, *cfg_param_06; + bool r1_enable, r2_enable; + + if (!hw_dspp || !hw_cfg || !rc_mask_cfg) { + SDE_ERROR("invalid arguments\n"); + return -EINVAL; + } + + flags = rc_mask_cfg->flags; + cfg_param_01 = rc_mask_cfg->cfg_param_01; + cfg_param_02 = rc_mask_cfg->cfg_param_02; + cfg_param_03 = rc_mask_cfg->cfg_param_03; + cfg_param_04 = rc_mask_cfg->cfg_param_04; + cfg_param_05 = rc_mask_cfg->cfg_param_05; + cfg_param_06 = rc_mask_cfg->cfg_param_06; + cfg_param_07 = rc_mask_cfg->cfg_param_07; + cfg_param_08 = rc_mask_cfg->cfg_param_08; + r1_enable = ((flags & SDE_HW_RC_DISABLE_R1) != SDE_HW_RC_DISABLE_R1); + r2_enable = ((flags & SDE_HW_RC_DISABLE_R2) != SDE_HW_RC_DISABLE_R2); + + if (cfg_param_07 > hw_dspp->cap->sblk->rc.mem_total_size) { + SDE_ERROR("invalid cfg_param_07:%d\n", cfg_param_07); + return -EINVAL; + } + + if (cfg_param_08 > RC_DATA_SIZE_MAX) { + SDE_ERROR("invalid cfg_param_08:%d\n", cfg_param_08); + return -EINVAL; + } + + if ((cfg_param_07 + cfg_param_08) > + hw_dspp->cap->sblk->rc.mem_total_size) { + SDE_ERROR("invalid cfg_param_08:%d, cfg_param_07:%d, max:%u\n", + cfg_param_08, cfg_param_07, + hw_dspp->cap->sblk->rc.mem_total_size); + return -EINVAL; + } + + if (!(cfg_param_03 == RC_PARAM_A1 || cfg_param_03 == RC_PARAM_A0)) { + SDE_ERROR("invalid cfg_param_03:%d\n", cfg_param_03); + return -EINVAL; + } + + for (i = 0; i < cfg_param_03; i++) { + if (cfg_param_04[i] < 4) { + SDE_ERROR("invalid cfg_param_04[%d]:%d\n", i, + cfg_param_04[i]); + return -EINVAL; + } + } + + half_panel_width = hw_cfg->displayh / cfg_param_03 * 2; + for (i = 0; i < cfg_param_03; i += 2) { + if (cfg_param_04[i] + cfg_param_04[i+1] != half_panel_width) { + SDE_ERROR("invalid ratio [%d]:%d, [%d]:%d, %d\n", + i, cfg_param_04[i], i+1, + cfg_param_04[i+1], half_panel_width); + return -EINVAL; + } + } + + if (r1_enable && r2_enable) { + if (cfg_param_01 > cfg_param_02) { + SDE_ERROR("invalid cfg_param_01:%d, cfg_param_02:%d\n", + cfg_param_01, cfg_param_02); + return -EINVAL; + } + } else { + SDE_DEBUG("R1 or R2 disabled, skip overlap check"); + } + + if (r1_enable) { + if (cfg_param_01 < 1) { + SDE_ERROR("invalid min cfg_param_01:%d\n", + cfg_param_01); + return -EINVAL; + } + + for (i = 0; i < cfg_param_03 - 1; i++) { + if (cfg_param_05[i] >= cfg_param_05[i+1]) { + SDE_ERROR("invalid cfg_param_05 %d, %d\n", + cfg_param_05[i], + cfg_param_05[i+1]); + return -EINVAL; + } + } + + for (i = 0; i < cfg_param_03; i++) { + if (cfg_param_05[i] > RC_DATA_SIZE_MAX) { + SDE_ERROR("invalid cfg_param_05[%d]:%d\n", i, + cfg_param_05[i]); + return -EINVAL; + } + + } + } else { + SDE_DEBUG("R1 is disabled, skip parameter checks\n"); + } + + if (r2_enable) { + if ((hw_cfg->displayv - cfg_param_02) < 1) { + SDE_ERROR("invalid max cfg_param_02:%d\n", + cfg_param_02); + return -EINVAL; + } + + for (i = 0; i < cfg_param_03 - 1; i++) { + if (cfg_param_06[i] >= cfg_param_06[i+1]) { + SDE_ERROR("invalid cfg_param_06 %d, %d\n", + cfg_param_06[i], + cfg_param_06[i+1]); + return -EINVAL; + } + } + + for (i = 0; i < cfg_param_03; i++) { + if (cfg_param_06[i] > RC_DATA_SIZE_MAX) { + SDE_ERROR("invalid cfg_param_06[%d]:%d\n", i, + cfg_param_06[i]); + return -EINVAL; + } + + } + } else { + SDE_DEBUG("R2 is disabled, skip parameter checks\n"); + } + + return rc; +} + +int sde_hw_rc_check_mask(struct sde_hw_dspp *hw_dspp, void *cfg) +{ + int rc = 0; + struct sde_hw_cp_cfg *hw_cfg = cfg; + struct drm_msm_rc_mask_cfg *rc_mask_cfg; + + if (!hw_dspp || !hw_cfg) { + SDE_ERROR("invalid arguments\n"); + return -EINVAL; + } + + if ((hw_cfg->len == 0 && hw_cfg->payload == NULL)) { + SDE_DEBUG("RC feature disabled, skip mask checks\n"); + return 0; + } + + if (hw_cfg->len != sizeof(struct drm_msm_rc_mask_cfg) || + !hw_cfg->payload) { + SDE_ERROR("invalid payload\n"); + return -EINVAL; + } + + rc_mask_cfg = hw_cfg->payload; + if (hw_cfg->num_of_mixers != 1 && hw_cfg->num_of_mixers != 2) { + SDE_ERROR("invalid number of mixers:%d\n", + hw_cfg->num_of_mixers); + return -EINVAL; + } + + rc = sde_hw_rc_check_mask_cfg(hw_dspp, hw_cfg, rc_mask_cfg); + if (rc) { + SDE_ERROR("invalid rc mask configuration, rc:%d\n", rc); + return rc; + } + + return 0; +} + +int sde_hw_rc_check_pu_roi(struct sde_hw_dspp *hw_dspp, void *cfg) +{ + int rc = 0; + struct sde_hw_cp_cfg *hw_cfg = cfg; + struct msm_roi_list *roi_list; + struct msm_roi_list empty_roi_list; + struct sde_rect rc_roi, merged_roi; + struct drm_msm_rc_mask_cfg *rc_mask_cfg; + bool mask_programmed = false; + enum rc_param_r param_r = RC_PARAM_R0; + enum rc_param_b param_b = RC_PARAM_B0; + + if (!hw_dspp || !hw_cfg) { + SDE_ERROR("invalid arguments\n"); + return -EINVAL; + } + + if (hw_cfg->len != sizeof(struct sde_drm_roi_v1)) { + SDE_ERROR("invalid payload size\n"); + return -EINVAL; + } + + roi_list = hw_cfg->payload; + if (!roi_list) { + SDE_DEBUG("full frame update\n"); + memset(&empty_roi_list, 0, sizeof(struct msm_roi_list)); + roi_list = &empty_roi_list; + } + + rc_mask_cfg = RC_STATE(hw_dspp).last_rc_mask_cfg; + mask_programmed = RC_STATE(hw_dspp).mask_programmed; + + /* early return when there is no mask in memory */ + if (!mask_programmed || !rc_mask_cfg) { + SDE_DEBUG("no previous rc mask programmed\n"); + return SDE_HW_RC_PU_SKIP_OP; + } + + rc = sde_hw_rc_check_mask_cfg(hw_dspp, hw_cfg, rc_mask_cfg); + if (rc) { + SDE_ERROR("invalid rc mask configuration, rc:%d\n", rc); + return rc; + } + + sde_kms_rect_merge_rectangles(roi_list, &merged_roi); + rc = _sde_hw_rc_get_ajusted_roi(hw_cfg, &merged_roi, &rc_roi); + if (rc) { + SDE_ERROR("failed to get adjusted roi, rc:%d\n", rc); + return rc; + } + + rc = _sde_hw_rc_get_param_rb(rc_mask_cfg, &rc_roi, + ¶m_r, ¶m_b); + if (rc) { + SDE_ERROR("invalid rc roi, rc:%d\n", rc); + return rc; + } + + return 0; +} + +int sde_hw_rc_setup_pu_roi(struct sde_hw_dspp *hw_dspp, void *cfg) +{ + int rc = 0; + struct sde_hw_cp_cfg *hw_cfg = cfg; + struct msm_roi_list *roi_list; + struct msm_roi_list empty_roi_list; + struct sde_rect rc_roi, merged_roi; + struct drm_msm_rc_mask_cfg *rc_mask_cfg; + enum rc_param_r param_r = RC_PARAM_R0; + enum rc_param_a param_a = RC_PARAM_A0; + enum rc_param_b param_b = RC_PARAM_B0; + u32 merge_mode = 0; + bool mask_programmed = false; + + if (!hw_dspp || !hw_cfg) { + SDE_ERROR("invalid arguments\n"); + return -EINVAL; + } + + if (hw_cfg->len != sizeof(struct sde_drm_roi_v1)) { + SDE_ERROR("invalid payload size\n"); + return -EINVAL; + } + + roi_list = hw_cfg->payload; + if (!roi_list) { + SDE_DEBUG("full frame update\n"); + memset(&empty_roi_list, 0, sizeof(struct msm_roi_list)); + roi_list = &empty_roi_list; + } + + rc_mask_cfg = RC_STATE(hw_dspp).last_rc_mask_cfg; + mask_programmed = RC_STATE(hw_dspp).mask_programmed; + + /* early return when there is no mask in memory */ + if (!mask_programmed || !rc_mask_cfg) { + SDE_DEBUG("no previous rc mask programmed\n"); + return SDE_HW_RC_PU_SKIP_OP; + } + + sde_kms_rect_merge_rectangles(roi_list, &merged_roi); + rc = _sde_hw_rc_get_ajusted_roi(hw_cfg, &merged_roi, &rc_roi); + if (rc) { + SDE_ERROR("failed to get adjusted roi, rc:%d\n", rc); + return rc; + } + + rc = _sde_hw_rc_get_merge_mode(hw_cfg, &merge_mode); + if (rc) { + SDE_ERROR("invalid merge_mode, rc:%d\n"); + return rc; + } + + rc = _sde_hw_rc_get_param_rb(rc_mask_cfg, &rc_roi, ¶m_r, + ¶m_b); + if (rc) { + SDE_ERROR("invalid roi, rc:%d\n", rc); + return rc; + } + + param_a = rc_mask_cfg->cfg_param_03; + rc = _sde_hw_rc_program_enable_bits(hw_dspp, rc_mask_cfg, + param_a, param_b, param_r, merge_mode, &rc_roi); + if (rc) { + SDE_ERROR("failed to program enable bits, rc:%d\n", rc); + return rc; + } + + memcpy(RC_STATE(hw_dspp).last_roi_list, + roi_list, sizeof(struct msm_roi_list)); + RC_STATE(hw_dspp).roi_programmed = true; + + return 0; +} + +int sde_hw_rc_setup_mask(struct sde_hw_dspp *hw_dspp, void *cfg) +{ + int rc = 0; + struct sde_hw_cp_cfg *hw_cfg = cfg; + struct drm_msm_rc_mask_cfg *rc_mask_cfg; + struct sde_rect rc_roi, merged_roi; + struct msm_roi_list *last_roi_list; + u32 merge_mode = 0; + bool roi_programmed = false; + + if (!hw_dspp || !hw_cfg) { + SDE_ERROR("invalid arguments\n"); + return -EINVAL; + } + + if ((hw_cfg->len == 0 && hw_cfg->payload == NULL)) { + SDE_DEBUG("RC feature disabled\n"); + _sde_hw_rc_reg_write(hw_dspp, SDE_HW_RC_REG1, 0); + + memset(RC_STATE(hw_dspp).last_rc_mask_cfg, 0, + sizeof(struct drm_msm_rc_mask_cfg)); + RC_STATE(hw_dspp).mask_programmed = false; + memset(RC_STATE(hw_dspp).last_roi_list, 0, + sizeof(struct msm_roi_list)); + RC_STATE(hw_dspp).roi_programmed = false; + + return 0; + } + + if (hw_cfg->len != sizeof(struct drm_msm_rc_mask_cfg) || + !hw_cfg->payload) { + SDE_ERROR("invalid payload\n"); + return -EINVAL; + } + + rc_mask_cfg = hw_cfg->payload; + last_roi_list = RC_STATE(hw_dspp).last_roi_list; + roi_programmed = RC_STATE(hw_dspp).roi_programmed; + + if (!roi_programmed) { + SDE_DEBUG("full frame update\n"); + memset(&merged_roi, 0, sizeof(struct sde_rect)); + } else { + SDE_DEBUG("partial frame update\n"); + sde_kms_rect_merge_rectangles(last_roi_list, &merged_roi); + } + + rc = _sde_hw_rc_get_ajusted_roi(hw_cfg, &merged_roi, &rc_roi); + if (rc) { + SDE_ERROR("failed to get adjusted roi, rc:%d\n", rc); + return rc; + } + + rc = _sde_hw_rc_get_merge_mode(hw_cfg, &merge_mode); + if (rc) { + SDE_ERROR("invalid merge_mode, rc:%d\n"); + return rc; + } + + rc = _sde_hw_rc_program_roi(hw_dspp, rc_mask_cfg, + merge_mode, &rc_roi); + if (rc) { + SDE_ERROR("unable to program rc roi, rc:%d\n", rc); + return rc; + } + + rc = _sde_hw_rc_program_data_offset(hw_dspp, rc_mask_cfg); + if (rc) { + SDE_ERROR("unable to program data offsets, rc:%d\n", rc); + return rc; + } + + memcpy(RC_STATE(hw_dspp).last_rc_mask_cfg, rc_mask_cfg, + sizeof(struct drm_msm_rc_mask_cfg)); + RC_STATE(hw_dspp).mask_programmed = true; + + return 0; +} + +int sde_hw_rc_setup_data_dma(struct sde_hw_dspp *hw_dspp, void *cfg) +{ + int rc = 0; + struct sde_hw_cp_cfg *hw_cfg = cfg; + struct drm_msm_rc_mask_cfg *rc_mask_cfg; + + if (!hw_dspp || !hw_cfg) { + SDE_ERROR("invalid arguments\n"); + return -EINVAL; + } + + if ((hw_cfg->len == 0 && hw_cfg->payload == NULL)) { + SDE_DEBUG("RC feature disabled, skip data programming\n"); + return 0; + } + + if (hw_cfg->len != sizeof(struct drm_msm_rc_mask_cfg) || + !hw_cfg->payload) { + SDE_ERROR("invalid payload\n"); + return -EINVAL; + } + + rc_mask_cfg = hw_cfg->payload; + + if (rc_mask_cfg->flags & SDE_HW_RC_SKIP_DATA_PROG) { + SDE_DEBUG("skip data programming\n"); + return 0; + } + + rc = reg_dmav1_setup_rc_datav1(hw_dspp, cfg); + if (rc) { + SDE_ERROR("unable to setup rc with dma, rc:%d\n", rc); + return rc; + } + + return rc; +} + +int sde_hw_rc_setup_data_ahb(struct sde_hw_dspp *hw_dspp, void *cfg) +{ + int rc = 0, i = 0; + u32 data = 0, cfg_param_07 = 0; + struct sde_hw_cp_cfg *hw_cfg = cfg; + struct drm_msm_rc_mask_cfg *rc_mask_cfg; + + if (!hw_dspp || !hw_cfg) { + SDE_ERROR("invalid arguments\n"); + return -EINVAL; + } + + if ((hw_cfg->len == 0 && hw_cfg->payload == NULL)) { + SDE_DEBUG("rc feature disabled, skip data programming\n"); + return 0; + } + + if (hw_cfg->len != sizeof(struct drm_msm_rc_mask_cfg) || + !hw_cfg->payload) { + SDE_ERROR("invalid payload\n"); + return -EINVAL; + } + + rc_mask_cfg = hw_cfg->payload; + + if (rc_mask_cfg->flags & SDE_HW_RC_SKIP_DATA_PROG) { + SDE_DEBUG("skip data programming\n"); + return 0; + } + + cfg_param_07 = rc_mask_cfg->cfg_param_07; + SDE_DEBUG("cfg_param_07:%u\n", cfg_param_07); + + for (i = 0; i < rc_mask_cfg->cfg_param_08; i++) { + SDE_DEBUG("cfg_param_09[%d] = 0x%016lX at %u\n", i, + rc_mask_cfg->cfg_param_09[i], i + cfg_param_07); + + data = (i == 0) ? (BIT(30) | (cfg_param_07 << 18)) : 0; + data |= (rc_mask_cfg->cfg_param_09[i] & 0x3FFFF); + _sde_hw_rc_reg_write(hw_dspp, SDE_HW_RC_REG10, data); + data = ((rc_mask_cfg->cfg_param_09[i] >> + SDE_HW_RC_DATA_REG_SIZE) & 0x3FFFF); + _sde_hw_rc_reg_write(hw_dspp, SDE_HW_RC_REG10, data); + } + + return rc; +} + +int sde_hw_rc_init(struct sde_hw_dspp *hw_dspp) +{ + int rc = 0; + + RC_STATE(hw_dspp).last_roi_list = kzalloc( + sizeof(struct msm_roi_list), GFP_KERNEL); + if (!RC_STATE(hw_dspp).last_roi_list) + return -ENOMEM; + + RC_STATE(hw_dspp).last_rc_mask_cfg = kzalloc( + sizeof(struct drm_msm_rc_mask_cfg), GFP_KERNEL); + if (!RC_STATE(hw_dspp).last_rc_mask_cfg) + return -ENOMEM; + + return rc; +} diff --git a/techpack/display/msm/sde/sde_hw_rc.h b/techpack/display/msm/sde/sde_hw_rc.h new file mode 100644 index 000000000000..9fc6d71c867d --- /dev/null +++ b/techpack/display/msm/sde/sde_hw_rc.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. + */ + +#ifndef _SDE_HW_RC_H +#define _SDE_HW_RC_H + +#include "sde_hw_mdss.h" + + +/** + * sde_hw_rc_init - Initialize RC internal state object and ops + * @hw_dspp: DSPP instance. + * Return: 0 on success, non-zero otherwise. + */ +int sde_hw_rc_init(struct sde_hw_dspp *hw_dspp); + +/** + * sde_hw_rc_check_mask - Validate RC mask configuration + * @hw_dspp: DSPP instance. + * @cfg: Pointer to configuration blob. + * Return: 0 on success, non-zero otherwise. + */ +int sde_hw_rc_check_mask(struct sde_hw_dspp *hw_dspp, void *cfg); + +/** + * sde_hw_rc_setup_mask - Setup RC mask configuration + * @hw_dspp: DSPP instance. + * @cfg: Pointer to configuration blob. + * Return: 0 on success, non-zero otherwise. + */ +int sde_hw_rc_setup_mask(struct sde_hw_dspp *hw_dspp, void *cfg); + +/** + * sde_hw_rc_check_pu_roi - Validate RC partial update region of interest + * @hw_dspp: DSPP instance. + * @cfg: Pointer to configuration blob. + * Return: 0 on success. + * > 0 on early return. + * < 0 on error. + */ +int sde_hw_rc_check_pu_roi(struct sde_hw_dspp *hw_dspp, void *cfg); + +/** + * sde_hw_rc_setup_pu_roi - Setup RC partial update region of interest + * @hw_dspp: DSPP instance. + * @cfg: Pointer to configuration blob. + * Return: 0 on success. + * > 0 on early return. + * < 0 on error. + */ +int sde_hw_rc_setup_pu_roi(struct sde_hw_dspp *hw_dspp, void *cfg); + +/** + * sde_hw_rc_setup_data_ahb - Program mask data with AHB + * @hw_dspp: DSPP instance. + * @cfg: Pointer to configuration blob. + * Return: 0 on success, non-zero otherwise. + */ +int sde_hw_rc_setup_data_ahb(struct sde_hw_dspp *hw_dspp, void *cfg); + +/** + * sde_hw_rc_setup_data_dma - Program mask data with DMA + * @hw_dspp: DSPP instance. + * @cfg: Pointer to configuration blob. + * Return: 0 on success, non-zero otherwise. + */ +int sde_hw_rc_setup_data_dma(struct sde_hw_dspp *hw_dspp, void *cfg); + +#endif diff --git a/techpack/display/msm/sde/sde_hw_reg_dma_v1.c b/techpack/display/msm/sde/sde_hw_reg_dma_v1.c index e8911cf80661..f28e73b9d19f 100644 --- a/techpack/display/msm/sde/sde_hw_reg_dma_v1.c +++ b/techpack/display/msm/sde/sde_hw_reg_dma_v1.c @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved. */ + #include #include "sde_hw_mdss.h" #include "sde_hw_ctl.h" @@ -14,6 +15,7 @@ #define ALIGNED_OFFSET (U32_MAX & ~(GUARD_BYTES)) #define ADDR_ALIGN BIT(8) #define MAX_RELATIVE_OFF (BIT(20) - 1) +#define ABSOLUTE_RANGE BIT(27) #define DECODE_SEL_OP (BIT(HW_BLK_SELECT)) #define REG_WRITE_OP ((BIT(REG_SINGLE_WRITE)) | (BIT(REG_BLK_WRITE_SINGLE)) | \ @@ -39,6 +41,7 @@ #define GRP_DMA_HW_BLK_SELECT (DMA0 | DMA1 | DMA2 | DMA3) #define GRP_DSPP_HW_BLK_SELECT (DSPP0 | DSPP1 | DSPP2 | DSPP3) #define GRP_LTM_HW_BLK_SELECT (LTM0 | LTM1) +#define GRP_MDSS_HW_BLK_SELECT (MDSS) #define BUFFER_SPACE_LEFT(cfg) ((cfg)->dma_buf->buffer_size - \ (cfg)->dma_buf->index) @@ -162,7 +165,7 @@ static void get_decode_sel(unsigned long blk, u32 *decode_sel) int i = 0; *decode_sel = 0; - for_each_set_bit(i, &blk, 31) { + for_each_set_bit(i, &blk, REG_DMA_BLK_MAX) { switch (BIT(i)) { case VIG0: *decode_sel |= BIT(0); @@ -212,6 +215,9 @@ static void get_decode_sel(unsigned long blk, u32 *decode_sel) case LTM1: *decode_sel |= BIT(23); break; + case MDSS: + *decode_sel |= BIT(31); + break; default: DRM_ERROR("block not supported %zx\n", (size_t)BIT(i)); break; @@ -240,6 +246,9 @@ int write_multi_reg_index(struct sde_reg_dma_setup_ops_cfg *cfg) cfg->dma_buf->index); loc[0] = HW_INDEX_REG_WRITE_OPCODE; loc[0] |= (cfg->blk_offset & MAX_RELATIVE_OFF); + if (cfg->blk == MDSS) + loc[0] |= ABSOLUTE_RANGE; + loc[1] = SIZE_DWORD(cfg->data_size); cfg->dma_buf->index += ops_mem_size[cfg->ops]; @@ -253,6 +262,9 @@ int write_multi_reg_inc(struct sde_reg_dma_setup_ops_cfg *cfg) loc = (u32 *)((u8 *)cfg->dma_buf->vaddr + cfg->dma_buf->index); loc[0] = AUTO_INC_REG_WRITE_OPCODE; + if (cfg->blk == MDSS) + loc[0] |= ABSOLUTE_RANGE; + loc[0] |= (cfg->blk_offset & MAX_RELATIVE_OFF); loc[1] = SIZE_DWORD(cfg->data_size); cfg->dma_buf->index += ops_mem_size[cfg->ops]; @@ -268,6 +280,9 @@ static int write_multi_lut_reg(struct sde_reg_dma_setup_ops_cfg *cfg) cfg->dma_buf->index); loc[0] = BLK_REG_WRITE_OPCODE; loc[0] |= (cfg->blk_offset & MAX_RELATIVE_OFF); + if (cfg->blk == MDSS) + loc[0] |= ABSOLUTE_RANGE; + loc[1] = (cfg->inc) ? 0 : BIT(31); loc[1] |= (cfg->wrap_size & WRAP_MAX_SIZE) << 16; loc[1] |= ((SIZE_DWORD(cfg->data_size)) & MAX_DWORDS_SZ); @@ -285,6 +300,9 @@ static int write_single_reg(struct sde_reg_dma_setup_ops_cfg *cfg) cfg->dma_buf->index); loc[0] = SINGLE_REG_WRITE_OPCODE; loc[0] |= (cfg->blk_offset & MAX_RELATIVE_OFF); + if (cfg->blk == MDSS) + loc[0] |= ABSOLUTE_RANGE; + loc[1] = *cfg->data; cfg->dma_buf->index += ops_mem_size[cfg->ops]; cfg->dma_buf->ops_completed |= REG_WRITE_OP; @@ -301,6 +319,9 @@ static int write_single_modify(struct sde_reg_dma_setup_ops_cfg *cfg) cfg->dma_buf->index); loc[0] = SINGLE_REG_MODIFY_OPCODE; loc[0] |= (cfg->blk_offset & MAX_RELATIVE_OFF); + if (cfg->blk == MDSS) + loc[0] |= ABSOLUTE_RANGE; + loc[1] = cfg->mask; loc[2] = *cfg->data; cfg->dma_buf->index += ops_mem_size[cfg->ops]; @@ -381,6 +402,7 @@ static int validate_write_reg(struct sde_reg_dma_setup_ops_cfg *cfg) static int validate_write_decode_sel(struct sde_reg_dma_setup_ops_cfg *cfg) { u32 remain_len; + bool vig_blk, dma_blk, dspp_blk, mdss_blk; remain_len = BUFFER_SPACE_LEFT(cfg); if (remain_len < ops_mem_size[HW_BLK_SELECT]) { @@ -393,15 +415,16 @@ static int validate_write_decode_sel(struct sde_reg_dma_setup_ops_cfg *cfg) DRM_ERROR("blk set as 0\n"); return -EINVAL; } - /* VIG, DMA and DSPP can't be combined */ - if (((cfg->blk & GRP_VIG_HW_BLK_SELECT) && - (cfg->blk & GRP_DSPP_HW_BLK_SELECT)) || - ((cfg->blk & GRP_DMA_HW_BLK_SELECT) && - (cfg->blk & GRP_DSPP_HW_BLK_SELECT)) || - ((cfg->blk & GRP_VIG_HW_BLK_SELECT) && - (cfg->blk & GRP_DMA_HW_BLK_SELECT))) { - DRM_ERROR("invalid blk combination %x\n", - cfg->blk); + + vig_blk = (cfg->blk & GRP_VIG_HW_BLK_SELECT) ? true : false; + dma_blk = (cfg->blk & GRP_DMA_HW_BLK_SELECT) ? true : false; + dspp_blk = (cfg->blk & GRP_DSPP_HW_BLK_SELECT) ? true : false; + mdss_blk = (cfg->blk & MDSS) ? true : false; + + if ((vig_blk && dspp_blk) || (dma_blk && dspp_blk) || + (vig_blk && dma_blk) || + (mdss_blk && (vig_blk | dma_blk | dspp_blk))) { + DRM_ERROR("invalid blk combination %x\n", cfg->blk); return -EINVAL; } @@ -672,6 +695,8 @@ int init_v12(struct sde_hw_reg_dma *cfg) v1_supported[LTM_INIT] = GRP_LTM_HW_BLK_SELECT; v1_supported[LTM_ROI] = GRP_LTM_HW_BLK_SELECT; v1_supported[LTM_VLUT] = GRP_LTM_HW_BLK_SELECT; + v1_supported[RC_DATA] = (GRP_DSPP_HW_BLK_SELECT | + GRP_MDSS_HW_BLK_SELECT); return 0; } @@ -685,7 +710,8 @@ static int check_support_v1(enum sde_reg_dma_features feature, if (!is_supported) return -EINVAL; - if (feature >= REG_DMA_FEATURES_MAX || blk >= MDSS) { + if (feature >= REG_DMA_FEATURES_MAX + || blk >= BIT_ULL(REG_DMA_BLK_MAX)) { *is_supported = false; return ret; } @@ -805,7 +831,8 @@ static struct sde_reg_dma_buffer *alloc_reg_dma_buf_v1(u32 size) int rc = 0; if (!size || SIZE_DWORD(size) > MAX_DWORDS_SZ) { - DRM_ERROR("invalid buffer size %d\n", size); + DRM_ERROR("invalid buffer size %d, max %d\n", + SIZE_DWORD(size), MAX_DWORDS_SZ); return ERR_PTR(-EINVAL); } diff --git a/techpack/display/msm/sde/sde_hw_reg_dma_v1_color_proc.c b/techpack/display/msm/sde/sde_hw_reg_dma_v1_color_proc.c index 4d7a4d009069..54629ab004fd 100644 --- a/techpack/display/msm/sde/sde_hw_reg_dma_v1_color_proc.c +++ b/techpack/display/msm/sde/sde_hw_reg_dma_v1_color_proc.c @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ + #include #include "sde_reg_dma.h" #include "sde_hw_reg_dma_v1_color_proc.h" @@ -65,6 +66,9 @@ #define MEMCOLOR_MEM_SIZE ((sizeof(struct drm_msm_memcol)) + \ REG_DMA_HEADERS_BUFFER_SZ) +#define RC_MEM_SIZE ((RC_DATA_SIZE_MAX * 2 * sizeof(u32)) + \ + REG_DMA_HEADERS_BUFFER_SZ) + #define QSEED3_MEM_SIZE (sizeof(struct sde_hw_scaler3_cfg) + \ (450 * sizeof(u32)) + \ REG_DMA_HEADERS_BUFFER_SZ) @@ -131,6 +135,7 @@ static u32 feature_map[SDE_DSPP_MAX] = { [SDE_DSPP_DITHER] = REG_DMA_FEATURES_MAX, [SDE_DSPP_HIST] = REG_DMA_FEATURES_MAX, [SDE_DSPP_AD] = REG_DMA_FEATURES_MAX, + [SDE_DSPP_RC] = RC_DATA, }; static u32 sspp_feature_map[SDE_SSPP_MAX] = { @@ -157,6 +162,7 @@ static u32 feature_reg_dma_sz[SDE_DSPP_MAX] = { [SDE_DSPP_HSIC] = HSIC_MEM_SIZE, [SDE_DSPP_SIXZONE] = SIXZONE_MEM_SIZE, [SDE_DSPP_MEMCOLOR] = MEMCOLOR_MEM_SIZE, + [SDE_DSPP_RC] = RC_MEM_SIZE, }; static u32 sspp_feature_reg_dma_sz[SDE_SSPP_MAX] = { @@ -1103,6 +1109,89 @@ void reg_dmav1_setup_dspp_igcv31(struct sde_hw_dspp *ctx, void *cfg) DRM_ERROR("failed to kick off ret %d\n", rc); } +int reg_dmav1_setup_rc_datav1(struct sde_hw_dspp *ctx, void *cfg) +{ + struct drm_msm_rc_mask_cfg *rc_mask_cfg; + struct sde_hw_reg_dma_ops *dma_ops; + struct sde_reg_dma_kickoff_cfg kick_off; + struct sde_hw_cp_cfg *hw_cfg = cfg; + struct sde_reg_dma_setup_ops_cfg dma_write_cfg; + int rc = 0; + u32 i = 0; + u32 *data = NULL; + u32 buf_sz = 0, abs_offset = 0; + u32 cfg_param_07; + u64 cfg_param_09; + + rc = reg_dma_dspp_check(ctx, cfg, RC_DATA); + if (rc) { + DRM_ERROR("invalid dma dspp check rc = %d\n"); + return -EINVAL; + } + + if (hw_cfg->len != sizeof(struct drm_msm_rc_mask_cfg)) { + DRM_ERROR("invalid size of payload len %d exp %zd\n", + hw_cfg->len, sizeof(struct drm_msm_rc_mask_cfg)); + return -EINVAL; + } + + rc_mask_cfg = hw_cfg->payload; + buf_sz = rc_mask_cfg->cfg_param_08 * 2 * sizeof(u32); + abs_offset = ctx->hw.blk_off + ctx->cap->sblk->rc.base + 0x28; + + dma_ops = sde_reg_dma_get_ops(); + dma_ops->reset_reg_dma_buf(dspp_buf[RC_DATA][ctx->idx]); + REG_DMA_INIT_OPS(dma_write_cfg, MDSS, RC_DATA, + dspp_buf[RC_DATA][ctx->idx]); + + REG_DMA_SETUP_OPS(dma_write_cfg, 0, NULL, 0, HW_BLK_SELECT, 0, 0, 0); + rc = dma_ops->setup_payload(&dma_write_cfg); + if (rc) { + DRM_ERROR("write decode select failed ret %d\n", rc); + return -ENOMEM; + } + + DRM_DEBUG_DRIVER("allocating %u bytes of memory for dma\n", buf_sz); + data = kzalloc(buf_sz, GFP_KERNEL); + if (!data) { + DRM_ERROR("memory allocation failed ret %d\n", rc); + return -ENOMEM; + } + + cfg_param_07 = rc_mask_cfg->cfg_param_07; + for (i = 0; i < rc_mask_cfg->cfg_param_08; i++) { + cfg_param_09 = rc_mask_cfg->cfg_param_09[i]; + DRM_DEBUG_DRIVER("cfg_param_09[%d] = 0x%016lX at %u\n", i, + cfg_param_09, + i + cfg_param_07); + data[i * 2] = (i == 0) ? (BIT(30) | (cfg_param_07 << 18)) : 0; + data[i * 2] |= (cfg_param_09 & 0x3FFFF); + data[i * 2 + 1] = ((cfg_param_09 >> 18) & 0x3FFFF); + } + + REG_DMA_SETUP_OPS(dma_write_cfg, abs_offset, data, buf_sz, + REG_BLK_WRITE_INC, 0, 0, 0); + rc = dma_ops->setup_payload(&dma_write_cfg); + if (rc) { + DRM_ERROR("rc dma write failed ret %d\n", rc); + goto exit; + } + + /* defer trigger to kickoff phase */ + REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl, + dspp_buf[RC_DATA][ctx->idx], REG_DMA_WRITE, + DMA_CTL_QUEUE0, WRITE_TRIGGER); + rc = dma_ops->kick_off(&kick_off); + if (rc) { + DRM_ERROR("failed to kick off ret %d\n", rc); + goto exit; + } + +exit: + kfree(data); + return rc; +} + static void _dspp_pccv4_off(struct sde_hw_dspp *ctx, void *cfg) { struct sde_reg_dma_kickoff_cfg kick_off; diff --git a/techpack/display/msm/sde/sde_hw_reg_dma_v1_color_proc.h b/techpack/display/msm/sde/sde_hw_reg_dma_v1_color_proc.h index cad0787ec473..41c382a96883 100644 --- a/techpack/display/msm/sde/sde_hw_reg_dma_v1_color_proc.h +++ b/techpack/display/msm/sde/sde_hw_reg_dma_v1_color_proc.h @@ -1,7 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved. */ + #ifndef _SDE_HW_REG_DMA_V1_COLOR_PROC_H #define _SDE_HW_REG_DMA_V1_COLOR_PROC_H @@ -242,6 +243,14 @@ void reg_dmav1_setup_ltm_roiv1(struct sde_hw_dspp *ctx, void *cfg); */ void reg_dmav1_setup_ltm_vlutv1(struct sde_hw_dspp *ctx, void *cfg); +/** + * reg_dmav1_setup_rc_datav1() - RC DATA v1 implementation using reg dma v1. + * @ctx: dspp ctx info + * @cfg: pointer to struct sde_hw_cp_cfg + * @returns: 0 if success, non-zero otherwise + */ +int reg_dmav1_setup_rc_datav1(struct sde_hw_dspp *ctx, void *cfg); + /** * reg_dmav1_deinit_ltm_ops() - deinitialize the ltm feature op for sde v4 * which were initialized. diff --git a/techpack/display/msm/sde/sde_kms.c b/techpack/display/msm/sde/sde_kms.c index f2f5f9714dd4..d5ac13a62314 100644 --- a/techpack/display/msm/sde/sde_kms.c +++ b/techpack/display/msm/sde/sde_kms.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -1450,6 +1450,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .get_panel_vfp = NULL, }; static const struct sde_connector_ops dp_ops = { + .set_info_blob = dp_connnector_set_info_blob, .post_init = dp_connector_post_init, .detect = dp_connector_detect, .get_modes = dp_connector_get_modes, diff --git a/techpack/display/msm/sde/sde_plane.c b/techpack/display/msm/sde/sde_plane.c index 6b2341ba663f..e991cbe7314b 100644 --- a/techpack/display/msm/sde/sde_plane.c +++ b/techpack/display/msm/sde/sde_plane.c @@ -126,6 +126,7 @@ struct sde_plane { struct sde_csc_cfg *csc_usr_ptr; struct sde_csc_cfg *csc_ptr; + uint32_t cached_lut_flag; const struct sde_sspp_sub_blks *pipe_sblk; char pipe_name[SDE_NAME_SIZE]; @@ -3201,6 +3202,21 @@ static void _sde_plane_update_properties(struct drm_plane *plane, pstate->dirty = 0x0; } +static void _sde_plane_check_lut_dirty(struct sde_plane *psde, + struct sde_plane_state *pstate) +{ + /** + * Valid configuration if scaler is not enabled or + * lut flag is set + */ + if (pstate->scaler3_cfg.lut_flag || !pstate->scaler3_cfg.enable) + return; + + pstate->scaler3_cfg.lut_flag = psde->cached_lut_flag; + SDE_EVT32(DRMID(&psde->base), pstate->scaler3_cfg.lut_flag, + SDE_EVTLOG_ERROR); +} + static int sde_plane_sspp_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state) { @@ -3251,10 +3267,16 @@ static int sde_plane_sspp_atomic_update(struct drm_plane *plane, state->crtc_w, state->crtc_h, state->crtc_x, state->crtc_y); + /* Caching the valid lut flag in sde plane */ + if (pstate->scaler3_cfg.enable && + pstate->scaler3_cfg.lut_flag) + psde->cached_lut_flag = pstate->scaler3_cfg.lut_flag; + /* force reprogramming of all the parameters, if the flag is set */ if (psde->revalidate) { SDE_DEBUG("plane:%d - reconfigure all the parameters\n", plane->base.id); + _sde_plane_check_lut_dirty(psde, pstate); pstate->dirty = SDE_PLANE_DIRTY_ALL | SDE_PLANE_DIRTY_CP; psde->revalidate = false; } diff --git a/techpack/display/msm/sde/sde_reg_dma.h b/techpack/display/msm/sde/sde_reg_dma.h index 1454e41457b3..9941d8a30d42 100644 --- a/techpack/display/msm/sde/sde_reg_dma.h +++ b/techpack/display/msm/sde/sde_reg_dma.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved. */ #ifndef _SDE_REG_DMA_H @@ -57,6 +57,7 @@ enum sde_reg_dma_read_sel { * @LTM_INIT: LTM INIT * @LTM_ROI: LTM ROI * @LTM_VLUT: LTM VLUT + * @RC_DATA: Rounded corner data * @REG_DMA_FEATURES_MAX: invalid selection */ enum sde_reg_dma_features { @@ -75,6 +76,7 @@ enum sde_reg_dma_features { LTM_INIT, LTM_ROI, LTM_VLUT, + RC_DATA, REG_DMA_FEATURES_MAX, }; @@ -131,6 +133,8 @@ enum sde_reg_dma_setup_ops { REG_DMA_SETUP_OPS_MAX, }; +#define REG_DMA_BLK_MAX 32 + /** * enum sde_reg_dma_blk - defines blocks for which reg dma op should be * performed diff --git a/techpack/display/msm/sde/sde_rm.c b/techpack/display/msm/sde/sde_rm.c index 76e908b4c044..e77f9905ce3c 100644 --- a/techpack/display/msm/sde/sde_rm.c +++ b/techpack/display/msm/sde/sde_rm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "[drm:%s] " fmt, __func__ @@ -2184,13 +2184,15 @@ int sde_rm_reserve( * Poll for rsvp_nxt clear, allow the check_only commit if rsvp_nxt * gets cleared and bailout if it does not get cleared before timeout. */ - if (test_only && rsvp_cur && rsvp_nxt) { + if (test_only && rsvp_nxt) { rsvp_nxt = _sde_rm_poll_get_rsvp_nxt_locked(rm, enc); + rsvp_cur = _sde_rm_get_rsvp(rm, enc); if (rsvp_nxt) { SDE_ERROR("poll timeout cur %d nxt %d enc %d\n", - rsvp_cur->seq, rsvp_nxt->seq, enc->base.id); - SDE_EVT32(rsvp_cur->seq, rsvp_nxt->seq, - enc->base.id, SDE_EVTLOG_ERROR); + (rsvp_cur) ? rsvp_cur->seq : -1, + rsvp_nxt->seq, enc->base.id); + SDE_EVT32(enc->base.id, (rsvp_cur) ? rsvp_cur->seq : -1, + rsvp_nxt->seq, SDE_EVTLOG_ERROR); ret = -EINVAL; goto end; } diff --git a/techpack/display/msm/sde_dbg.h b/techpack/display/msm/sde_dbg.h index 61764c048bc9..333260e9cd2b 100644 --- a/techpack/display/msm/sde_dbg.h +++ b/techpack/display/msm/sde_dbg.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef SDE_DBG_H_ @@ -156,11 +156,10 @@ struct sde_dbg_reglog { u32 first; u32 last; u32 last_dump; - u32 curr; + atomic64_t curr; u32 next; u32 enable; u32 enable_mask; - spinlock_t spin_lock; }; extern struct sde_dbg_reglog *sde_dbg_base_reglog; diff --git a/techpack/display/msm/sde_dbg_evtlog.c b/techpack/display/msm/sde_dbg_evtlog.c index ddb4c996c021..5724d4cdb5e1 100644 --- a/techpack/display/msm/sde_dbg_evtlog.c +++ b/techpack/display/msm/sde_dbg_evtlog.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "sde_dbg:[%s] " fmt, __func__ @@ -103,27 +103,22 @@ void sde_evtlog_log(struct sde_dbg_evtlog *evtlog, const char *name, int line, void sde_reglog_log(u8 blk_id, u32 val, u32 addr) { - unsigned long flags; struct sde_dbg_reglog_log *log; struct sde_dbg_reglog *reglog = sde_dbg_base_reglog; + int index; if (!reglog) return; - spin_lock_irqsave(®log->spin_lock, flags); - - log = ®log->logs[reglog->curr]; + index = abs(atomic64_inc_return(®log->curr) % SDE_REGLOG_ENTRY); + log = ®log->logs[index]; log->blk_id = blk_id; log->val = val; log->addr = addr; log->time = local_clock(); log->pid = current->pid; - - reglog->curr = (reglog->curr + 1) % SDE_REGLOG_ENTRY; reglog->last++; - - spin_unlock_irqrestore(®log->spin_lock, flags); } /* always dump the last entries which are not dumped yet */ @@ -244,7 +239,7 @@ struct sde_dbg_reglog *sde_reglog_init(void) if (!reglog) return ERR_PTR(-ENOMEM); - spin_lock_init(®log->spin_lock); + atomic64_set(®log->curr, 0); return reglog; } diff --git a/techpack/display/msm/sde_power_handle.h b/techpack/display/msm/sde_power_handle.h index 257c844d56ac..650357c94283 100644 --- a/techpack/display/msm/sde_power_handle.h +++ b/techpack/display/msm/sde_power_handle.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef _SDE_POWER_HANDLE_H_ @@ -10,7 +10,7 @@ #define SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA 0 #define SDE_POWER_HANDLE_DISABLE_BUS_AB_QUOTA 0 -#define SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA 400000000 +#define SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA 400000000ULL #define SDE_POWER_HANDLE_ENABLE_NRT_BUS_IB_QUOTA 0 #define SDE_POWER_HANDLE_DISABLE_BUS_IB_QUOTA 0 diff --git a/techpack/display/pll/dsi_pll_7nm.c b/techpack/display/pll/dsi_pll_7nm.c index 581fa3ba13b8..b08a8555cd1e 100644 --- a/techpack/display/pll/dsi_pll_7nm.c +++ b/techpack/display/pll/dsi_pll_7nm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "%s: " fmt, __func__ @@ -559,7 +559,7 @@ static void dsi_pll_config_slave(struct mdss_pll_resources *rsc) rsc->slave = NULL; if (!orsc) { - pr_warn("slave PLL unavilable, assuming standalone config\n"); + pr_debug("slave PLL unavailable, assuming standalone config\n"); return; } diff --git a/techpack/display/rotator/sde_rotator_base.h b/techpack/display/rotator/sde_rotator_base.h index bdb319dc28a9..204f900e8304 100644 --- a/techpack/display/rotator/sde_rotator_base.h +++ b/techpack/display/rotator/sde_rotator_base.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #ifndef __SDE_ROTATOR_BASE_H__ @@ -46,6 +46,7 @@ #define SDE_MDP_HW_REV_540 SDE_MDP_REV(5, 4, 0) /* sdmtrinket v1.0 */ #define SDE_MDP_HW_REV_600 SDE_MDP_REV(6, 0, 0) /* msmnile+ v1.0 */ #define SDE_MDP_HW_REV_630 SDE_MDP_REV(6, 3, 0) /* bengal v1.0 */ +#define SDE_MDP_HW_REV_6100 SDE_MDP_REV(6, 10, 0) /* khaje v1.0 */ #define SDE_MDP_VBIF_4_LEVEL_REMAPPER 4 #define SDE_MDP_VBIF_8_LEVEL_REMAPPER 8 diff --git a/techpack/display/rotator/sde_rotator_r3.c b/techpack/display/rotator/sde_rotator_r3.c index 0d36bd549c43..a3a367e3c03e 100644 --- a/techpack/display/rotator/sde_rotator_r3.c +++ b/techpack/display/rotator/sde_rotator_r3.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "%s:%d: " fmt, __func__, __LINE__ @@ -3486,7 +3486,9 @@ static int sde_rotator_hw_rev_init(struct sde_hw_rotator *rot) rot->downscale_caps = "LINEAR/1.5/2/4/8/16/32/64 TILE/1.5/2/4 TP10/1.5/2"; } else if (IS_SDE_MAJOR_MINOR_SAME(mdata->mdss_version, - SDE_MDP_HW_REV_630)) { + SDE_MDP_HW_REV_630) || + IS_SDE_MAJOR_MINOR_SAME(mdata->mdss_version, + SDE_MDP_HW_REV_6100)) { SDEROT_DBG("Sys cache inline rotation not supported\n"); set_bit(SDE_CAPS_PARTIALWR, mdata->sde_caps_map); set_bit(SDE_CAPS_HW_TIMESTAMP, mdata->sde_caps_map); diff --git a/techpack/video/msm/vidc/hfi_common.c b/techpack/video/msm/vidc/hfi_common.c index d7223d8287b3..ae412f28cf88 100644 --- a/techpack/video/msm/vidc/hfi_common.c +++ b/techpack/video/msm/vidc/hfi_common.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #include @@ -990,20 +990,22 @@ static void __set_registers(struct venus_hfi_device *device, u32 sid) } } -static int __vote_bandwidth(struct bus_info *bus, - unsigned long bw_kbps, u32 sid) +static int __vote_bandwidth(struct bus_info *bus, unsigned long ab_kbps, + unsigned long ib_kbps, u32 sid) { int rc = 0; - uint64_t ab = 0; + uint64_t ab = 0, ib = 0; /* Bus Driver expects values in Bps */ - ab = bw_kbps * 1000; - s_vpr_p(sid, "Voting bus %s to ab %llu bps\n", bus->name, ab); - rc = msm_bus_scale_update_bw(bus->client, ab, 0); + ab = ab_kbps * 1000; + ib = ib_kbps * 1000; + s_vpr_p(sid, "Voting bus %s to ab %llu ib %llu bps\n", + bus->name, ab, ib); + rc = msm_bus_scale_update_bw(bus->client, ab, ib); if (rc) - s_vpr_e(sid, "Failed voting bus %s to ab %llu, rc=%d\n", - bus->name, ab, rc); - + s_vpr_e(sid, + "Failed voting bus %s to ab %llu ib %llu bps rc=%d\n", + bus->name, ab, ib, rc); return rc; } @@ -1015,7 +1017,7 @@ int __unvote_buses(struct venus_hfi_device *device, u32 sid) device->bus_vote = DEFAULT_BUS_VOTE; venus_hfi_for_each_bus(device, bus) { - rc = __vote_bandwidth(bus, 0, sid); + rc = __vote_bandwidth(bus, 0, 0, sid); if (rc) goto err_unknown_device; } @@ -1029,7 +1031,7 @@ static int __vote_buses(struct venus_hfi_device *device, { int rc = 0; struct bus_info *bus = NULL; - unsigned long bw_kbps = 0, bw_prev = 0; + unsigned long ab_kbps = 0, ib_kbps = 0, bw_prev = 0; enum vidc_bus_type type; venus_hfi_for_each_bus(device, bus) { @@ -1037,33 +1039,36 @@ static int __vote_buses(struct venus_hfi_device *device, type = get_type_frm_name(bus->name); if (type == DDR) { - bw_kbps = bw_ddr; + ab_kbps = bw_ddr; bw_prev = device->bus_vote.total_bw_ddr; } else if (type == LLCC) { - bw_kbps = bw_llcc; + ab_kbps = bw_llcc; bw_prev = device->bus_vote.total_bw_llcc; } else { - bw_kbps = bus->range[1]; + ab_kbps = bus->range[1]; bw_prev = device->bus_vote.total_bw_ddr ? - bw_kbps : 0; + ab_kbps : 0; } /* ensure freq is within limits */ - bw_kbps = clamp_t(typeof(bw_kbps), bw_kbps, + ab_kbps = clamp_t(typeof(ab_kbps), ab_kbps, bus->range[0], bus->range[1]); - if (TRIVIAL_BW_CHANGE(bw_kbps, bw_prev) && bw_prev) { + if (TRIVIAL_BW_CHANGE(ab_kbps, bw_prev) && bw_prev) { s_vpr_l(sid, "Skip voting bus %s to %llu bps", - bus->name, bw_kbps * 1000); + bus->name, ab_kbps * 1000); continue; } - rc = __vote_bandwidth(bus, bw_kbps, sid); + if (device->res->vpu_ver == VPU_VERSION_AR50_LITE) + ib_kbps = 2 * ab_kbps; + + rc = __vote_bandwidth(bus, ab_kbps, ib_kbps, sid); if (type == DDR) - device->bus_vote.total_bw_ddr = bw_kbps; + device->bus_vote.total_bw_ddr = ab_kbps; else if (type == LLCC) - device->bus_vote.total_bw_llcc = bw_kbps; + device->bus_vote.total_bw_llcc = ab_kbps; } else { s_vpr_e(sid, "No BUS to Vote\n"); } diff --git a/techpack/video/msm/vidc/msm_cvp_internal.c b/techpack/video/msm/vidc/msm_cvp_internal.c index 3432484ceaac..82fc710a9644 100644 --- a/techpack/video/msm/vidc/msm_cvp_internal.c +++ b/techpack/video/msm/vidc/msm_cvp_internal.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #include "msm_cvp_internal.h" @@ -233,14 +233,14 @@ static int msm_cvp_scale_clocks_and_bus(struct msm_vidc_inst *inst) return -EINVAL; } - rc = msm_vidc_set_clocks(inst->core, inst->sid); + rc = msm_vidc_set_clocks(inst->core, inst->sid, false); if (rc) { s_vpr_e(inst->sid, "%s: failed set_clocks for inst %pK\n", __func__, inst); goto exit; } - rc = msm_comm_vote_bus(inst); + rc = msm_comm_vote_bus(inst, false); if (rc) { s_vpr_e(inst->sid, "%s: failed vote_bus for inst %pK\n", __func__, inst); diff --git a/techpack/video/msm/vidc/msm_v4l2_vidc.c b/techpack/video/msm/vidc/msm_v4l2_vidc.c index 0fd761e87343..5f6a82acd47f 100644 --- a/techpack/video/msm/vidc/msm_v4l2_vidc.c +++ b/techpack/video/msm/vidc/msm_v4l2_vidc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #include @@ -490,6 +490,11 @@ static int msm_vidc_probe_vidc_device(struct platform_device *pdev) return -ENOMEM; core->platform_data = vidc_get_drv_data(&pdev->dev); + if(!core->platform_data) { + d_vpr_e("Failed to get platform data\n"); + rc = -EINVAL; + goto err_core_init; + } dev_set_drvdata(&pdev->dev, core); rc = msm_vidc_initialize_core(pdev, core); if (rc) { @@ -504,6 +509,12 @@ static int msm_vidc_probe_vidc_device(struct platform_device *pdev) core->id = MSM_VIDC_CORE_VENUS; + vidc_driver->ctxt = kcalloc(core->platform_data->max_inst_count, + sizeof(*vidc_driver->ctxt), GFP_KERNEL); + if (!vidc_driver->ctxt) + goto err_vidc_context; + vidc_driver->num_ctxt = core->platform_data->max_inst_count; + rc = v4l2_device_register(&pdev->dev, &core->v4l2_dev); if (rc) { d_vpr_e("Failed to register v4l2 device\n"); @@ -616,6 +627,8 @@ static int msm_vidc_probe_vidc_device(struct platform_device *pdev) err_dec: v4l2_device_unregister(&core->v4l2_dev); err_v4l2_register: + kfree(vidc_driver->ctxt); +err_vidc_context: sysfs_remove_group(&pdev->dev.kobj, &msm_vidc_core_attr_group); err_core_init: dev_set_drvdata(&pdev->dev, NULL); @@ -701,6 +714,7 @@ static int msm_vidc_remove(struct platform_device *pdev) mutex_destroy(&core->resources.cb_lock); mutex_destroy(&core->lock); kfree(core); + kfree(vidc_driver->ctxt); return rc; } diff --git a/techpack/video/msm/vidc/msm_vdec.c b/techpack/video/msm/vidc/msm_vdec.c index 54923e18b3a0..7b7b52cba75e 100644 --- a/techpack/video/msm/vidc/msm_vdec.c +++ b/techpack/video/msm/vidc/msm_vdec.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #include @@ -927,6 +927,15 @@ int msm_vdec_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) case V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE: if (!is_valid_operating_rate(inst, ctrl->val)) break; + /* + * reset the resources like clock and bus as per the updated + * flag. When switch from TURBO to normal, need not wait for + * next qbuf to scale down the resources. + */ + if ((inst->flags & VIDC_TURBO) && (ctrl->val != INT_MAX)) { + inst->flags &= ~VIDC_TURBO; + msm_comm_reset_clocks_and_bus(inst); + } inst->flags &= ~VIDC_TURBO; if (ctrl->val == INT_MAX) inst->flags |= VIDC_TURBO; diff --git a/techpack/video/msm/vidc/msm_venc.c b/techpack/video/msm/vidc/msm_venc.c index 80e8e00f3dd4..02c924a5976b 100644 --- a/techpack/video/msm/vidc/msm_venc.c +++ b/techpack/video/msm/vidc/msm_venc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #include #include "msm_venc.h" @@ -1205,6 +1205,7 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst) inst->buff_req.buffer[13].buffer_type = HAL_BUFFER_INTERNAL_RECON; msm_vidc_init_buffer_size_calculators(inst); inst->static_rotation_flip_enabled = false; + inst->hdr10_sei_enabled = false; return rc; } @@ -1699,6 +1700,7 @@ int msm_venc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) u32 info_type = ((u32)ctrl->val >> 28) & 0xF; u32 val = (ctrl->val & 0xFFFFFFF); + inst->hdr10_sei_enabled = true; s_vpr_h(sid, "Ctrl:%d, HDR Info with value %u (%#X)", info_type, val, ctrl->val); switch (info_type) { @@ -3206,6 +3208,10 @@ int msm_venc_set_slice_control_mode(struct msm_vidc_inst *inst) /* Update Slice Config */ mb_per_frame = NUM_MBS_PER_FRAME(output_height, output_width); + if (codec == V4L2_PIX_FMT_HEVC) + mb_per_frame = + NUM_MBS_PER_FRAME_HEVC(output_height, output_width); + mbps = NUM_MBS_PER_SEC(output_height, output_width, fps); if (slice_mode == HFI_MULTI_SLICE_BY_MB_COUNT) { @@ -4383,7 +4389,8 @@ int msm_venc_set_hdr_info(struct msm_vidc_inst *inst) } hdev = inst->core->device; - if (get_v4l2_codec(inst) != V4L2_PIX_FMT_HEVC) + if (get_v4l2_codec(inst) != V4L2_PIX_FMT_HEVC || + !inst->hdr10_sei_enabled) return 0; profile = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_PROFILE); diff --git a/techpack/video/msm/vidc/msm_vidc_buffer_calculations.c b/techpack/video/msm/vidc/msm_vidc_buffer_calculations.c index a2d2aa35f700..1382255e8a98 100644 --- a/techpack/video/msm/vidc/msm_vidc_buffer_calculations.c +++ b/techpack/video/msm/vidc/msm_vidc_buffer_calculations.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ #include "msm_vidc_debug.h" @@ -1043,7 +1043,7 @@ u32 msm_vidc_calculate_enc_output_frame_size(struct msm_vidc_inst *inst) goto calc_done; if (mbs_per_frame <= NUM_MBS_480P) - goto calc_done; /* Default frame_size = YUVsize * 2 */ + (void)frame_size; /* Default frame_size = YUVsize * 2 */ else if (mbs_per_frame <= NUM_MBS_4k) frame_size = frame_size >> 2; else diff --git a/techpack/video/msm/vidc/msm_vidc_clocks.c b/techpack/video/msm/vidc/msm_vidc_clocks.c index 5fdfe530d608..b365101c467d 100644 --- a/techpack/video/msm/vidc/msm_vidc_clocks.c +++ b/techpack/video/msm/vidc/msm_vidc_clocks.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include "msm_vidc_common.h" @@ -274,7 +274,7 @@ static int fill_dynamic_stats(struct msm_vidc_inst *inst, return 0; } -int msm_comm_set_buses(struct msm_vidc_core *core, u32 sid) +int msm_comm_set_buses(struct msm_vidc_core *core, u32 sid, bool force_reset) { int rc = 0; struct msm_vidc_inst *inst = NULL; @@ -306,7 +306,7 @@ int msm_comm_set_buses(struct msm_vidc_core *core, u32 sid) } mutex_unlock(&inst->registeredbufs.lock); - if ((!filled_len || !device_addr) && + if ((!filled_len || !device_addr) && !force_reset && (inst->session_type != MSM_VIDC_CVP)) { s_vpr_l(sid, "%s: no input\n", __func__); continue; @@ -333,7 +333,7 @@ int msm_comm_set_buses(struct msm_vidc_core *core, u32 sid) return rc; } -int msm_comm_vote_bus(struct msm_vidc_inst *inst) +int msm_comm_vote_bus(struct msm_vidc_inst *inst, bool force_reset) { int rc = 0; struct msm_vidc_core *core; @@ -368,7 +368,7 @@ int msm_comm_vote_bus(struct msm_vidc_inst *inst) } mutex_unlock(&inst->registeredbufs.lock); - if ((!filled_len || !device_addr) && + if ((!filled_len || !device_addr) && !force_reset && (inst->session_type != MSM_VIDC_CVP)) { s_vpr_l(inst->sid, "%s: no input\n", __func__); return 0; @@ -457,7 +457,7 @@ int msm_comm_vote_bus(struct msm_vidc_inst *inst) call_core_op(core, calc_bw, vote_data); } - rc = msm_comm_set_buses(core, inst->sid); + rc = msm_comm_set_buses(core, inst->sid, force_reset); return rc; } @@ -877,7 +877,7 @@ static unsigned long msm_vidc_calc_freq_iris2(struct msm_vidc_inst *inst, return (unsigned long) freq; } -int msm_vidc_set_clocks(struct msm_vidc_core *core, u32 sid) +int msm_vidc_set_clocks(struct msm_vidc_core *core, u32 sid, bool force_reset) { struct hfi_device *hdev; unsigned long freq_core_1 = 0, freq_core_2 = 0, rate = 0; @@ -915,7 +915,7 @@ int msm_vidc_set_clocks(struct msm_vidc_core *core, u32 sid) } mutex_unlock(&inst->registeredbufs.lock); - if (!filled_len || !device_addr) { + if ((!filled_len || !device_addr) && !force_reset) { s_vpr_l(sid, "%s: no input\n", __func__); continue; } @@ -988,7 +988,7 @@ int msm_vidc_set_clocks(struct msm_vidc_core *core, u32 sid) return rc; } -int msm_comm_scale_clocks(struct msm_vidc_inst *inst) +int msm_comm_scale_clocks(struct msm_vidc_inst *inst, bool force_reset) { struct msm_vidc_buffer *temp, *next; unsigned long freq = 0; @@ -1013,7 +1013,7 @@ int msm_comm_scale_clocks(struct msm_vidc_inst *inst) } mutex_unlock(&inst->registeredbufs.lock); - if (!filled_len || !device_addr) { + if ((!filled_len || !device_addr) && !force_reset) { s_vpr_l(inst->sid, "%s: no input\n", __func__); return 0; } @@ -1032,7 +1032,7 @@ int msm_comm_scale_clocks(struct msm_vidc_inst *inst) msm_dcvs_scale_clocks(inst, freq); } - msm_vidc_set_clocks(inst->core, inst->sid); + msm_vidc_set_clocks(inst->core, inst->sid, force_reset); return 0; } @@ -1055,13 +1055,13 @@ int msm_comm_scale_clocks_and_bus(struct msm_vidc_inst *inst, bool do_bw_calc) inst->active = true; } - if (msm_comm_scale_clocks(inst)) { + if (msm_comm_scale_clocks(inst, false)) { s_vpr_e(inst->sid, "Failed to scale clocks. May impact performance\n"); } if (do_bw_calc) { - if (msm_comm_vote_bus(inst)) { + if (msm_comm_vote_bus(inst, false)) { s_vpr_e(inst->sid, "Failed to scale DDR bus. May impact perf\n"); } @@ -1070,6 +1070,25 @@ int msm_comm_scale_clocks_and_bus(struct msm_vidc_inst *inst, bool do_bw_calc) return 0; } +int msm_comm_reset_clocks_and_bus(struct msm_vidc_inst *inst) +{ + if (!inst) { + d_vpr_e("%s: invalid params %pK\n", __func__, inst); + return -EINVAL; + } + + if (msm_comm_scale_clocks(inst, true)) { + s_vpr_e(inst->sid, + "Failed to reset clocks. May impact performance\n"); + } + + if (msm_comm_vote_bus(inst, true)) { + s_vpr_e(inst->sid, + "Failed to reset DDR bus. May impact perf\n"); + } + return 0; +} + int msm_dcvs_try_enable(struct msm_vidc_inst *inst) { bool disable_hfr_dcvs = false; @@ -1751,8 +1770,12 @@ int msm_vidc_decide_core_and_power_mode_iris1(struct msm_vidc_inst *inst) msm_vidc_move_core_to_power_save_mode(core, VIDC_CORE_ID_1, inst->sid); } else { - s_vpr_e(inst->sid, "Core cannot support this load\n"); - return -EINVAL; + if (!is_realtime_session(inst)) { + s_vpr_h(inst->sid, "Supporting NRT session"); + } else { + s_vpr_e(inst->sid, "Core cannot support this load\n"); + return -EINVAL; + } } inst->clk_data.core_id = VIDC_CORE_ID_1; diff --git a/techpack/video/msm/vidc/msm_vidc_clocks.h b/techpack/video/msm/vidc/msm_vidc_clocks.h index 7515a4b49d68..0cb30379b5fb 100644 --- a/techpack/video/msm/vidc/msm_vidc_clocks.h +++ b/techpack/video/msm/vidc/msm_vidc_clocks.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #ifndef _MSM_VIDC_CLOCKS_H_ @@ -9,8 +9,8 @@ void msm_clock_data_reset(struct msm_vidc_inst *inst); void msm_dcvs_reset(struct msm_vidc_inst *inst); -int msm_vidc_set_clocks(struct msm_vidc_core *core, u32 sid); -int msm_comm_vote_bus(struct msm_vidc_inst *inst); +int msm_vidc_set_clocks(struct msm_vidc_core *core, u32 sid, bool force_reset); +int msm_comm_vote_bus(struct msm_vidc_inst *inst, bool force_reset); int msm_dcvs_try_enable(struct msm_vidc_inst *inst); bool res_is_less_than(u32 width, u32 height, u32 ref_width, u32 ref_height); bool res_is_greater_than(u32 width, u32 height, u32 ref_width, u32 ref_height); @@ -21,6 +21,7 @@ bool res_is_greater_than_or_equal_to(u32 width, u32 height, int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst *inst); int msm_vidc_get_fps(struct msm_vidc_inst *inst); int msm_comm_scale_clocks_and_bus(struct msm_vidc_inst *inst, bool do_bw_calc); +int msm_comm_reset_clocks_and_bus(struct msm_vidc_inst *inst); int msm_comm_init_clocks_and_bus_data(struct msm_vidc_inst *inst); int msm_vidc_decide_work_route_iris1(struct msm_vidc_inst *inst); int msm_vidc_decide_work_mode_iris1(struct msm_vidc_inst *inst); diff --git a/techpack/video/msm/vidc/msm_vidc_common.c b/techpack/video/msm/vidc/msm_vidc_common.c index 2619d1f89d41..207908b7c94e 100644 --- a/techpack/video/msm/vidc/msm_vidc_common.c +++ b/techpack/video/msm/vidc/msm_vidc_common.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #include @@ -3074,7 +3074,6 @@ static int msm_comm_init_core(struct msm_vidc_inst *inst) core->state = VIDC_CORE_INIT; core->smmu_fault_handled = false; core->trigger_ssr = false; - core->resources.max_inst_count = MAX_SUPPORTED_INSTANCES; core->resources.max_secure_inst_count = core->resources.max_secure_inst_count ? core->resources.max_secure_inst_count : @@ -4827,6 +4826,7 @@ int msm_comm_qbufs_batch(struct msm_vidc_inst *inst, int rc = 0; struct msm_vidc_buffer *buf; int do_bw_calc = 0; + int num_buffers_queued = 0; do_bw_calc = mbuf ? mbuf->vvb.vb2_buf.type == INPUT_MPLANE : 0; rc = msm_comm_scale_clocks_and_bus(inst, do_bw_calc); @@ -4852,10 +4852,13 @@ int msm_comm_qbufs_batch(struct msm_vidc_inst *inst, __func__, rc); break; } + num_buffers_queued++; loop_end: - /* Queue pending buffers till the current buffer only */ - if (buf == mbuf) + /* Queue pending buffers till batch size */ + if (num_buffers_queued == inst->batch.size) { + s_vpr_e(inst->sid, "%s: Queue buffers till batch size\n"); break; + } } mutex_unlock(&inst->registeredbufs.lock); @@ -6186,10 +6189,12 @@ int msm_vidc_check_session_supported(struct msm_vidc_inst *inst) width_min, height_min); rc = -ENOTSUPP; } - if (!rc && output_width > width_max) { + if (!rc && (output_width > width_max || + output_height > height_max)) { s_vpr_e(sid, - "Unsupported width = %u supported max width = %u\n", - output_width, width_max); + "Unsupported WxH (%u)x(%u), max supported is (%u)x(%u)\n", + output_width, output_height, + width_max, height_max); rc = -ENOTSUPP; } diff --git a/techpack/video/msm/vidc/msm_vidc_debug.c b/techpack/video/msm/vidc/msm_vidc_debug.c index e803269aa6bd..75b6d2e96e12 100644 --- a/techpack/video/msm/vidc/msm_vidc_debug.c +++ b/techpack/video/msm/vidc/msm_vidc_debug.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #define CREATE_TRACE_POINTS @@ -31,8 +31,6 @@ int msm_vidc_err_recovery_disable = !1; atomic_read(&__binfo->ref_count) >= 2 ? "video driver" : "firmware";\ }) -struct log_cookie ctxt[MAX_SUPPORTED_INSTANCES]; - struct core_inst_pair { struct msm_vidc_core *core; struct msm_vidc_inst *inst; @@ -611,16 +609,16 @@ int get_sid(u32 *sid, u32 session_type) { int i; - for (i = 0; i < MAX_SUPPORTED_INSTANCES; i++) { - if (!ctxt[i].used) { - ctxt[i].used = 1; + for (i = 0; i < vidc_driver->num_ctxt; i++) { + if (!vidc_driver->ctxt[i].used) { + vidc_driver->ctxt[i].used = 1; *sid = i+1; update_log_ctxt(*sid, session_type, 0); break; } } - return (i == MAX_SUPPORTED_INSTANCES); + return (i == vidc_driver->num_ctxt); } inline void update_log_ctxt(u32 sid, u32 session_type, u32 fourcc) @@ -629,7 +627,7 @@ inline void update_log_ctxt(u32 sid, u32 session_type, u32 fourcc) char type; u32 s_type = 0; - if (!sid || sid > MAX_SUPPORTED_INSTANCES) { + if (!sid || sid > vidc_driver->num_ctxt) { d_vpr_e("%s: invalid sid %#x\n", __func__, sid); } @@ -685,10 +683,10 @@ inline void update_log_ctxt(u32 sid, u32 session_type, u32 fourcc) break; } - ctxt[sid-1].session_type = s_type; - ctxt[sid-1].codec_type = fourcc; - memcpy(&ctxt[sid-1].name, codec, 4); - ctxt[sid-1].name[4] = type; - ctxt[sid-1].name[5] = '\0'; + vidc_driver->ctxt[sid-1].session_type = s_type; + vidc_driver->ctxt[sid-1].codec_type = fourcc; + memcpy(&vidc_driver->ctxt[sid-1].name, codec, 4); + vidc_driver->ctxt[sid-1].name[4] = type; + vidc_driver->ctxt[sid-1].name[5] = '\0'; } diff --git a/techpack/video/msm/vidc/msm_vidc_debug.h b/techpack/video/msm/vidc/msm_vidc_debug.h index 7ddc7be76378..080b7f64c530 100644 --- a/techpack/video/msm/vidc/msm_vidc_debug.h +++ b/techpack/video/msm/vidc/msm_vidc_debug.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #ifndef __MSM_VIDC_DEBUG__ @@ -69,13 +69,6 @@ enum vidc_err_recovery_disable { VIDC_DISABLE_NON_NOC_ERR_RECOV = 0x0002 }; -struct log_cookie { - u32 used; - u32 session_type; - u32 codec_type; - char name[20]; -}; - extern int msm_vidc_debug; extern int msm_vidc_fw_debug_mode; extern bool msm_vidc_fw_coverage; @@ -85,7 +78,6 @@ extern bool msm_vidc_syscache_disable; extern bool msm_vidc_lossless_encode; extern bool msm_vidc_cvp_usage; extern int msm_vidc_err_recovery_disable; -extern struct log_cookie ctxt[MAX_SUPPORTED_INSTANCES]; #define dprintk(__level, sid, __fmt, ...) \ do { \ @@ -213,10 +205,10 @@ static inline bool is_print_allowed(u32 sid, u32 level) if (!((msm_vidc_debug >> 8) & 0xF)) return true; - if (!sid || sid > MAX_SUPPORTED_INSTANCES) + if (!sid || sid > vidc_driver->num_ctxt) return true; - if (ctxt[sid-1].session_type & msm_vidc_debug) + if (vidc_driver->ctxt[sid-1].session_type & msm_vidc_debug) return true; return false; @@ -224,21 +216,21 @@ static inline bool is_print_allowed(u32 sid, u32 level) static inline char *get_codec_name(u32 sid) { - if (!sid || sid > MAX_SUPPORTED_INSTANCES) + if (!sid || sid > vidc_driver->num_ctxt) return "....."; - return ctxt[sid-1].name; + return vidc_driver->ctxt[sid-1].name; } static inline void put_sid(u32 sid) { - if (!sid || sid > MAX_SUPPORTED_INSTANCES) { + if (!sid || sid > vidc_driver->num_ctxt) { d_vpr_e("%s: invalid sid %#x\n", __func__, sid); return; } - if (ctxt[sid-1].used) - ctxt[sid-1].used = 0; + if (vidc_driver->ctxt[sid-1].used) + vidc_driver->ctxt[sid-1].used = 0; } static inline void tic(struct msm_vidc_inst *i, enum profiling_points p, diff --git a/techpack/video/msm/vidc/msm_vidc_internal.h b/techpack/video/msm/vidc/msm_vidc_internal.h index 363571997e90..55f11e0b1eaf 100644 --- a/techpack/video/msm/vidc/msm_vidc_internal.h +++ b/techpack/video/msm/vidc/msm_vidc_internal.h @@ -47,7 +47,8 @@ #define MAX_NUM_INPUT_BUFFERS VIDEO_MAX_FRAME // same as VB2_MAX_FRAME #define MAX_NUM_OUTPUT_BUFFERS VIDEO_MAX_FRAME // same as VB2_MAX_FRAME -#define MAX_SUPPORTED_INSTANCES 24 +#define MAX_SUPPORTED_INSTANCES 16 +#define MAX_SUPPORTED_INSTANCES_24 24 /* Maintains the number of FTB's between each FBD over a window */ #define DCVS_FTB_WINDOW 16 @@ -79,6 +80,9 @@ #define NUM_MBS_PER_FRAME(__height, __width) \ ((ALIGN(__height, 16) / 16) * (ALIGN(__width, 16) / 16)) +#define NUM_MBS_PER_FRAME_HEVC(__height, __width) \ + ((ALIGN(__height, 32) / 32) * (ALIGN(__width, 32) / 32)) + #define call_core_op(c, op, ...) \ (((c) && (c)->core_ops && (c)->core_ops->op) ? \ ((c)->core_ops->op(__VA_ARGS__)) : 0) @@ -300,6 +304,7 @@ struct msm_vidc_platform_data { uint32_t vpu_ver; uint32_t num_vpp_pipes; struct msm_vidc_ubwc_config_data *ubwc_config; + uint32_t max_inst_count; }; struct msm_vidc_format_desc { @@ -326,6 +331,13 @@ struct msm_vidc_format_constraint { u32 uv_buffer_alignment; }; +struct log_cookie { + u32 used; + u32 session_type; + u32 codec_type; + char name[20]; +}; + struct msm_vidc_drv { struct mutex lock; struct list_head cores; @@ -333,6 +345,8 @@ struct msm_vidc_drv { struct dentry *debugfs_root; int thermal_level; u32 sku_version; + struct log_cookie *ctxt; + u32 num_ctxt; }; struct msm_video_device { @@ -551,6 +565,7 @@ struct msm_vidc_inst { bool static_rotation_flip_enabled; struct internal_buf *dpb_extra_binfo; struct msm_vidc_codec_data *codec_data; + bool hdr10_sei_enabled; struct hal_hdr10_pq_sei hdr10_sei_params; struct batch_mode batch; struct delayed_work batch_work; diff --git a/techpack/video/msm/vidc/msm_vidc_platform.c b/techpack/video/msm/vidc/msm_vidc_platform.c index 3b97cc23dcd5..90a63ec710bd 100644 --- a/techpack/video/msm/vidc/msm_vidc_platform.c +++ b/techpack/video/msm/vidc/msm_vidc_platform.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -1879,6 +1879,7 @@ static struct msm_vidc_platform_data default_data = { .vpu_ver = VPU_VERSION_IRIS2, .num_vpp_pipes = 0x4, .ubwc_config = 0x0, + .max_inst_count = MAX_SUPPORTED_INSTANCES, }; static struct msm_vidc_platform_data lito_data = { @@ -1899,6 +1900,7 @@ static struct msm_vidc_platform_data lito_data = { .codecs_count = ARRAY_SIZE(default_codecs), .codec_caps = lito_capabilities_v0, .codec_caps_count = ARRAY_SIZE(lito_capabilities_v0), + .max_inst_count = MAX_SUPPORTED_INSTANCES, }; static struct msm_vidc_platform_data kona_data = { @@ -1919,6 +1921,7 @@ static struct msm_vidc_platform_data kona_data = { .codecs_count = ARRAY_SIZE(default_codecs), .codec_caps = kona_capabilities, .codec_caps_count = ARRAY_SIZE(kona_capabilities), + .max_inst_count = MAX_SUPPORTED_INSTANCES, }; static struct msm_vidc_platform_data lagoon_data = { @@ -1939,6 +1942,7 @@ static struct msm_vidc_platform_data lagoon_data = { .codecs_count = ARRAY_SIZE(lagoon_codecs), .codec_caps = lagoon_capabilities_v0, .codec_caps_count = ARRAY_SIZE(lagoon_capabilities_v0), + .max_inst_count = MAX_SUPPORTED_INSTANCES, }; static struct msm_vidc_platform_data sm6150_data = { @@ -1955,6 +1959,7 @@ static struct msm_vidc_platform_data sm6150_data = { .vpu_ver = VPU_VERSION_AR50, .num_vpp_pipes = 0x1, .ubwc_config = 0x0, + .max_inst_count = MAX_SUPPORTED_INSTANCES, }; static struct msm_vidc_platform_data bengal_data = { @@ -1975,6 +1980,7 @@ static struct msm_vidc_platform_data bengal_data = { .codecs_count = ARRAY_SIZE(bengal_codecs), .codec_caps = bengal_capabilities_v0, .codec_caps_count = ARRAY_SIZE(bengal_capabilities_v0), + .max_inst_count = MAX_SUPPORTED_INSTANCES, }; static struct msm_vidc_platform_data scuba_data = { @@ -1995,6 +2001,7 @@ static struct msm_vidc_platform_data scuba_data = { .codecs_count = ARRAY_SIZE(scuba_codecs), .codec_caps = scuba_capabilities, .codec_caps_count = ARRAY_SIZE(scuba_capabilities), + .max_inst_count = MAX_SUPPORTED_INSTANCES, }; static struct msm_vidc_platform_data sm8150_data = { @@ -2011,6 +2018,7 @@ static struct msm_vidc_platform_data sm8150_data = { .vpu_ver = VPU_VERSION_IRIS1, .num_vpp_pipes = 0x2, .ubwc_config = 0x0, + .max_inst_count = MAX_SUPPORTED_INSTANCES, }; static struct msm_vidc_platform_data sdm845_data = { @@ -2027,6 +2035,7 @@ static struct msm_vidc_platform_data sdm845_data = { .vpu_ver = VPU_VERSION_AR50, .num_vpp_pipes = 0x1, .ubwc_config = 0x0, + .max_inst_count = MAX_SUPPORTED_INSTANCES, }; static struct msm_vidc_platform_data sdm670_data = { @@ -2043,6 +2052,7 @@ static struct msm_vidc_platform_data sdm670_data = { .vpu_ver = VPU_VERSION_AR50, .num_vpp_pipes = 0x1, .ubwc_config = 0x0, + .max_inst_count = MAX_SUPPORTED_INSTANCES, }; static const struct of_device_id msm_vidc_dt_match[] = { @@ -2054,6 +2064,10 @@ static const struct of_device_id msm_vidc_dt_match[] = { .compatible = "qcom,kona-vidc", .data = &kona_data, }, + { + .compatible = "qcom,qcs8250-vidc", + .data = &kona_data, + }, { .compatible = "qcom,sm6150-vidc", .data = &sm6150_data, @@ -2205,6 +2219,21 @@ void *vidc_get_drv_data(struct device *dev) d_vpr_h("DDR Type 0x%x hbb 0x%x\n", ddr_type, driver_data->ubwc_config ? driver_data->ubwc_config->highest_bank_bit : -1); + } else if (!strcmp(match->compatible, "qcom,qcs8250-vidc")) { + ddr_type = of_fdt_get_ddrtype(); + if (ddr_type == -ENOENT) + d_vpr_e("Failed to get ddr type, use LPDDR5\n"); + + if (driver_data->ubwc_config && + (ddr_type == DDR_TYPE_LPDDR4 || + ddr_type == DDR_TYPE_LPDDR4X)) + driver_data->ubwc_config->highest_bank_bit = 0xf; + + d_vpr_h("DDR Type 0x%x hbb 0x%x\n", + ddr_type, driver_data->ubwc_config ? + driver_data->ubwc_config->highest_bank_bit : -1); + + driver_data->max_inst_count = MAX_SUPPORTED_INSTANCES_24; } else if (!strcmp(match->compatible, "qcom,bengal-vidc")) { rc = msm_vidc_read_rank(driver_data, dev); if (rc) { diff --git a/techpack/video/msm/vidc/msm_vidc_res_parse.c b/techpack/video/msm/vidc/msm_vidc_res_parse.c index 1b9e9942cb44..2f84f960f2f6 100644 --- a/techpack/video/msm/vidc/msm_vidc_res_parse.c +++ b/techpack/video/msm/vidc/msm_vidc_res_parse.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #include @@ -846,6 +846,7 @@ int read_platform_resources_from_drv_data( res->vpu_ver = platform_data->vpu_ver; res->ubwc_config = platform_data->ubwc_config; + res->max_inst_count = platform_data->max_inst_count; return rc;