Import F(x)tec Pro1-X BSP kernel changes as of 2022-06-01

This commit is contained in:
TheKit 2022-06-11 02:20:21 +03:00
parent c3bcbab00e
commit f13e1f4e3e
128 changed files with 5284 additions and 757 deletions

View file

@ -647,7 +647,6 @@ CONFIG_SQUASHFS_LZ4=y
# CONFIG_NETWORK_FILESYSTEMS is not set # CONFIG_NETWORK_FILESYSTEMS is not set
CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y CONFIG_NLS_ISO8859_1=y
CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
CONFIG_SECURITY=y CONFIG_SECURITY=y
CONFIG_HARDENED_USERCOPY=y CONFIG_HARDENED_USERCOPY=y
CONFIG_HARDENED_USERCOPY_PAGESPAN=y CONFIG_HARDENED_USERCOPY_PAGESPAN=y

View file

@ -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", 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)) {
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", dev_info(&pdev->dev, "Bus frequency is set to %dHz\n",
gi2c->i2c_rsc.clk_freq_out); gi2c->i2c_rsc.clk_freq_out);

View file

@ -22,16 +22,18 @@ static DECLARE_WAIT_QUEUE_HEAD(screenwaitq);
static DECLARE_WAIT_QUEUE_HEAD(gWaitq); static DECLARE_WAIT_QUEUE_HEAD(gWaitq);
static DECLARE_WAIT_QUEUE_HEAD(U1_Waitq); static DECLARE_WAIT_QUEUE_HEAD(U1_Waitq);
static DECLARE_WAIT_QUEUE_HEAD(U2_Waitq); static DECLARE_WAIT_QUEUE_HEAD(U2_Waitq);
#ifdef CONFIG_PM_WAKELOCKS #ifdef CONFIG_PM_WAKELOCKS
struct wakeup_source *gIntWakeLock = NULL; struct wakeup_source *gIntWakeLock = NULL;
struct wakeup_source *gProcessWakeLock = NULL; struct wakeup_source *gProcessWakeLock = NULL;
#else #else
struct wake_lock gIntWakeLock; struct wake_lock gIntWakeLock;
struct wake_lock gProcessWakeLock; struct wake_lock gProcessWakeLock;
#endif #endif //CONFIG_PM_WAKELOCKS
struct work_struct gWork; struct work_struct gWork;
struct workqueue_struct *gWorkq; struct workqueue_struct *gWorkq;
//
static LIST_HEAD(dev_list); static LIST_HEAD(dev_list);
static DEFINE_MUTEX(dev_lock); static DEFINE_MUTEX(dev_lock);
static DEFINE_MUTEX(drv_lock); static DEFINE_MUTEX(drv_lock);
@ -55,17 +57,17 @@ static void mas_work(struct work_struct *pws) {
smas->f_irq = 1; smas->f_irq = 1;
wake_up(&gWaitq); wake_up(&gWaitq);
#ifdef COMPATIBLE_VERSION3 #ifdef COMPATIBLE_VERSION3
wake_up(&drv_waitq); wake_up(&drv_waitq);
#endif #endif
} }
static irqreturn_t mas_interrupt(int irq, void *dev_id) { static irqreturn_t mas_interrupt(int irq, void *dev_id) {
#ifdef DOUBLE_EDGE_IRQ #ifdef DOUBLE_EDGE_IRQ
if(mas_get_interrupt_gpio(0)==1){ if(mas_get_interrupt_gpio(0)==1){
//TODO IRQF_TRIGGER_RISING //TODO IRQF_TRIGGER_RISING
}else{ }else{
//TODO IRQF_TRIGGER_FALLING //TODO IRQF_TRIGGER_FALLING
} }
#else #else
printk("mas_interrupt.\n"); printk("mas_interrupt.\n");
#ifdef CONFIG_PM_WAKELOCKS #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) { static void mas_set_input(void) {
struct input_dev *input = NULL; 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; smas->f_irq = 1;
wake_up(&gWaitq); wake_up(&gWaitq);
break; break;
#ifndef USE_PLATFORM_DRIVE
case ENABLE_CLK: case ENABLE_CLK:
mas_enable_spi_clock(smas->spi); //if the spi clock is not opening always, do this methods mas_enable_spi_clock(smas->spi); //if the spi clock is not opening always, do this methods
break; break;
case DISABLE_CLK: case DISABLE_CLK:
mas_disable_spi_clock(smas->spi); //disable the spi clock mas_disable_spi_clock(smas->spi); //disable the spi clock
break; break;
#endif
case ENABLE_INTERRUPT: case ENABLE_INTERRUPT:
enable_irq(irq); //enable the irq,in fact, you can make irq enable always enable_irq(irq); //enable the irq,in fact, you can make irq enable always
break; break;
@ -362,10 +345,12 @@ int version3_ioctl(int cmd, int arg){
break; break;
case IOCTL_IRQ_ENABLE: case IOCTL_IRQ_ENABLE:
break; break;
#ifndef USE_PLATFORM_DRIVE
case IOCTL_SPI_SPEED: case IOCTL_SPI_SPEED:
smas->spi->max_speed_hz = (u32) arg; smas->spi->max_speed_hz = (u32) arg;
spi_setup(smas->spi); spi_setup(smas->spi);
break; break;
#endif //USE_PLATFORM_DRIVE
case IOCTL_COVER_NUM: case IOCTL_COVER_NUM:
ret = COVER_NUM; ret = COVER_NUM;
break; break;
@ -444,13 +429,14 @@ int version3_ioctl(int cmd, int arg){
} }
#endif #endif
#ifndef USE_PLATFORM_DRIVE
/* 写数据 /* 写数据
* @return :count, -1count太大-2 * @return :count, -1count太大-2
*/ */
static ssize_t mas_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { static ssize_t mas_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) {
int val = 0; int val = 0;
// MALOGD("start"); // MALOGD("start");
if(count==6) { //cmd ioctl, old version used the write interface to do ioctl, this is only for the old version if(count==6) { //cmd ioctl, old version used the write interface to do ioctl, this is only for the old version
int cmd, arg; int cmd, arg;
u8 tmp[6]; u8 tmp[6];
ret = copy_from_user(tmp, buf, count); 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 += tmp[4];
arg <<= 8; arg <<= 8;
arg += tmp[5]; arg += tmp[5];
#ifdef COMPATIBLE_VERSION3 #ifdef COMPATIBLE_VERSION3
val = (int)version3_ioctl(NULL, (unsigned int)cmd, (unsigned long)arg); val = (int)version3_ioctl(NULL, (unsigned int)cmd, (unsigned long)arg);
#endif #endif
} else { } else {
memset(stxb, 0, FBUF); memset(stxb, 0, FBUF);
ret = copy_from_user(stxb, buf, count); ret = copy_from_user(stxb, buf, count);
if(ret) { if(ret) {
@ -477,9 +463,32 @@ static ssize_t mas_write(struct file *filp, const char __user *buf, size_t count
val = count; val = count;
} }
} }
// MALOGD("end"); // MALOGD("end");
return val; 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; void * kernel_memaddr = NULL;
unsigned long kernel_memesize = 0; unsigned long kernel_memesize = 0;
@ -526,8 +535,10 @@ static unsigned int mas_poll(struct file *filp, struct poll_table_struct *wait)
/*---------------------------------- fops ------------------------------------*/ /*---------------------------------- fops ------------------------------------*/
static const struct file_operations sfops = { static const struct file_operations sfops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
#ifndef USE_PLATFORM_DRIVE
.write = mas_write, .write = mas_write,
.read = mas_read, .read = mas_read,
#endif
.unlocked_ioctl = mas_ioctl, .unlocked_ioctl = mas_ioctl,
.mmap = mas_mmap, .mmap = mas_mmap,
//.ioctl = mas_ioctl, //.ioctl = mas_ioctl,
@ -543,56 +554,64 @@ static const struct file_operations sfops = {
static int init_file_node(void) static int init_file_node(void)
{ {
int ret; int ret;
//MALOGF("start"); //MALOGF("start");
ret = alloc_chrdev_region(&sdev->idd, 0, 1, MA_CHR_DEV_NAME); ret = alloc_chrdev_region(&sdev->idd, 0, 1, MA_CHR_DEV_NAME);
if(ret < 0) if(ret < 0)
{ {
MALOGW("alloc_chrdev_region error!"); MALOGW("alloc_chrdev_region error!");
return -1; return -1;
} }
sdev->chd = cdev_alloc();
if (!sdev->chd) sdev->chd = cdev_alloc();
{ if (!sdev->chd)
MALOGW("cdev_alloc error!"); {
return -1; MALOGW("cdev_alloc error!");
} return -1;
sdev->chd->owner = THIS_MODULE; }
sdev->chd->ops = &sfops;
cdev_add(sdev->chd, sdev->idd, 1); sdev->chd->owner = THIS_MODULE;
sdev->cls = class_create(THIS_MODULE, MA_CHR_DEV_NAME); sdev->chd->ops = &sfops;
if (IS_ERR(sdev->cls)) {
MALOGE("class_create"); cdev_add(sdev->chd, sdev->idd, 1);
return -1;
} sdev->cls = class_create(THIS_MODULE, MA_CHR_DEV_NAME);
sdev->dev = device_create(sdev->cls, NULL, sdev->idd, NULL, MA_CHR_FILE_NAME); if (IS_ERR(sdev->cls)) {
ret = IS_ERR(sdev->dev) ? PTR_ERR(sdev->dev) : 0; MALOGE("class_create");
if(ret){ return -1;
MALOGE("device_create"); }
}
//MALOGF("end"); sdev->dev = device_create(sdev->cls, NULL, sdev->idd, NULL, MA_CHR_FILE_NAME);
return 0; 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) static int deinit_file_node(void)
{ {
cdev_del(sdev->chd); cdev_del(sdev->chd);
sdev->chd = NULL; sdev->chd = NULL;
kfree(sdev->chd); kfree(sdev->chd);
device_destroy(sdev->cls, sdev->idd); device_destroy(sdev->cls, sdev->idd);
unregister_chrdev_region(sdev->idd, 1); unregister_chrdev_region(sdev->idd, 1);
class_destroy(sdev->cls); class_destroy(sdev->cls);
return 0; return 0;
} }
static int init_interrupt(void) static int init_interrupt(void)
{ {
const char*tname = MA_EINT_NAME; const char*tname = MA_EINT_NAME;
int ret = 0;
irq = mas_get_irq(); irq = mas_get_irq();
if(irq<=0){ if(irq<=0){
ret = irq; ret = irq;
MALOGE("mas_get_irq"); MALOGE("mas_get_irq");
} }
#ifdef DOUBLE_EDGE_IRQ #ifdef DOUBLE_EDGE_IRQ
ret = request_irq(irq, mas_interrupt, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, tname, NULL); ret = request_irq(irq, mas_interrupt, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, tname, NULL);
#else #else
@ -601,23 +620,25 @@ static int init_interrupt(void)
if(ret<0){ if(ret<0){
MALOGE("request_irq"); MALOGE("request_irq");
} }
return ret; return ret;
} }
static int deinit_interrupt(void) static int deinit_interrupt(void)
{ {
if(irq) if(irq)
{disable_irq(irq); {disable_irq(irq);
free_irq(irq, NULL); free_irq(irq, NULL);
} }
return 0; return 0;
} }
static int init_vars(void) static int init_vars(void)
{ {
sdev = kmalloc(sizeof(struct fprint_dev), GFP_KERNEL); sdev = kmalloc(sizeof(struct fprint_dev), GFP_KERNEL);
smas = kmalloc(sizeof(struct fprint_spi), 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 ) { if (sdev==NULL || smas==NULL ) {
MALOGW("smas kmalloc failed."); MALOGW("smas kmalloc failed.");
if(sdev!=NULL) kfree(sdev); if(sdev!=NULL) kfree(sdev);
@ -625,10 +646,15 @@ static int init_vars(void)
return -ENOMEM; return -ENOMEM;
} }
printk("[%s][%d]smas %p \r\n",__func__,__LINE__, smas); stxb = kmalloc(FBUF, GFP_KERNEL);
printk("[%s][%d]sdev %p \r\n",__func__,__LINE__, sdev); srxb = kmalloc(FBUF, GFP_KERNEL);
printk("[%s][%d]stxb %p \r\n",__func__,__LINE__, stxb); if (stxb==NULL || srxb==NULL ) {
printk("[%s][%d]srxb %p \r\n",__func__,__LINE__, srxb); MALOGW("stxb srxb kmalloc failed.");
if(stxb!=NULL) kfree(stxb);
if(srxb!=NULL) kfree(srxb);
return -ENOMEM;
}
#ifdef CONFIG_PM_WAKELOCKS #ifdef CONFIG_PM_WAKELOCKS
gIntWakeLock = wakeup_source_register(NULL, "microarray_int_wakelock"); gIntWakeLock = wakeup_source_register(NULL, "microarray_int_wakelock");
@ -655,13 +681,23 @@ static int deinit_vars(void)
wake_lock_destroy(&gIntWakeLock); wake_lock_destroy(&gIntWakeLock);
wake_lock_destroy(&gProcessWakeLock); wake_lock_destroy(&gProcessWakeLock);
#endif #endif
if(sdev!=NULL) kfree(sdev); if(sdev!=NULL)
if(smas!=NULL) kfree(smas); kfree(sdev);
// if(stxb!=NULL) kfree(stxb);
// if(srxb!=NULL) kfree(srxb); if(smas!=NULL)
kfree(smas);
if(stxb!=NULL)
kfree(stxb);
if(srxb!=NULL)
kfree(srxb);
return 0; return 0;
} }
#ifndef USE_PLATFORM_DRIVE
static int init_spi(struct spi_device *spi){ static int init_spi(struct spi_device *spi){
msleep(50); msleep(50);
smas->spi = spi; smas->spi = spi;
@ -673,16 +709,21 @@ static int init_spi(struct spi_device *spi){
return 0; return 0;
} }
static int deinit_spi(struct spi_device *spi){ static int deinit_spi(struct spi_device *spi){
smas->spi = NULL; smas->spi = NULL;
mas_disable_spi_clock(spi); mas_disable_spi_clock(spi);
return 0; return 0;
} }
#endif
/* /*
* init_connect function to check whether the chip is microarray's * init_connect function to check whether the chip is microarray's
* @return 0 not 1 yes * @return 0 not 1 yes
* param void * param void
*/ */
#ifdef REE
int init_connect(void){ int init_connect(void){
int i; int i;
int res = 0; int res = 0;
@ -721,6 +762,7 @@ int init_connect(void){
int deinit_connect(void){ int deinit_connect(void){
return 0; return 0;
} }
#endif
static int mas_fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data){ static int mas_fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data){
struct fb_event *evdata = data; struct fb_event *evdata = data;
@ -748,72 +790,96 @@ static int init_notifier_call(void);
static int deinit_notifier_call(void); static int deinit_notifier_call(void);
static int init_notifier_call(){ static int init_notifier_call(){
notifier.notifier_call = mas_fb_notifier_callback; notifier.notifier_call = mas_fb_notifier_callback;
fb_register_client(&notifier); fb_register_client(&notifier);
is_screen_on = 1; is_screen_on = 1;
return 0; return 0;
} }
static int deinit_notifier_call(){ static int deinit_notifier_call(){
fb_unregister_client(&notifier); fb_unregister_client(&notifier);
return 0; return 0;
} }
#ifdef USE_PLATFORM_DRIVE
int mas_probe(struct platform_device *spi){
#else
int mas_probe(struct spi_device *spi) { 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); ret= mas_qcm_platform_init(spi);
pr_err("mas_qcm_platform_init:ret=%d,by eric.wang\n",ret);
if(ret) if(ret)
goto err0; goto err0;
ret = init_vars(); ret = init_vars();
pr_err("init_vars:ret=%d,by eric.wang\n",ret);
if(ret){ if(ret){
goto err1; goto err1;
} }
ret = init_interrupt(); ret = init_interrupt();
pr_err("init_interrupt:ret=%d,by eric.wang\n",ret);
if(ret){ if(ret){
goto err2; goto err2;
} }
ret = init_file_node(); ret = init_file_node();
pr_err("init_file_node:ret=%d,by eric.wang\n",ret);
if(ret){ if(ret){
goto err3; goto err3;
} }
#ifndef USE_PLATFORM_DRIVE
ret = init_spi(spi); ret = init_spi(spi);
pr_err("init_spi:ret=%d,by eric.wang\n",ret);
if(ret){ if(ret){
goto err4; goto err4;
} }
#endif
#ifdef REE #ifdef REE
ret = init_connect(); ret = init_connect();
#elif defined TEE #elif defined TEE
ret = 1; ret = 1;
#endif #endif
if(ret == 0){//not chip if(ret == 0){//not chip
compatible = 0; 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; goto err5;
#endif
} }
else else
pr_info("%s:init_connect successfully.\n", __func__); pr_err("%s:init_connect successfully.\n", __func__);
mas_set_input(); mas_set_input();
MALOGF("end"); MALOGF("end");
ret = init_notifier_call(); ret = init_notifier_call();
if(ret != 0){ if(ret != 0){
ret = -ENODEV; ret = -ENODEV;
goto err6; goto err6;
} }
mas_set_wakeup(spi); mas_set_wakeup(spi);
//Fingerprint_name="Microarray_A121N"; //Fingerprint_name="Microarray_A121N";
pr_info("%s:completed.\n", __func__); pr_err("%s:completed.\n", __func__);
return ret; return ret;
err6: err6:
deinit_notifier_call(); deinit_notifier_call();
#ifdef REE
err5: err5:
deinit_connect(); deinit_connect();
#endif
#ifndef USE_PLATFORM_DRIVE
err4: err4:
deinit_spi(spi); deinit_spi(spi);
#endif
err3: err3:
deinit_file_node(); deinit_file_node();
err2: err2:
@ -825,7 +891,11 @@ int mas_probe(struct spi_device *spi) {
return -EINVAL; return -EINVAL;
} }
#ifdef USE_PLATFORM_DRIVE
int mas_remove(struct platform_device *spi) {
#else
int mas_remove(struct spi_device *spi) { int mas_remove(struct spi_device *spi) {
#endif
deinit_file_node(); deinit_file_node();
deinit_interrupt(); deinit_interrupt();
deinit_vars(); deinit_vars();

View file

@ -1,24 +1,26 @@
/* Copyright (C) MicroArray /* Copyright (C) MicroArray
* MicroArray Fprint Driver Code * madev.h * MicroArray Fprint Driver Code * madev.h
* Date: 2017-3-9 * Date: 2017-3-9
* Version: v4.0.05 * Version: v4.0.05
* Author: guq * Author: guq
* Contact: guq@microarray.com.cn * Contact: guq@microarray.com.cn
*/ */
#ifndef __MADEV_H_ #ifndef __MADEV_H_
#define __MADEV_H_ #define __MADEV_H_
//settings macro //settings macro
#define QUALCOMM //[MTK|QUALCOMM|SPRD] #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 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_FILE_NAME "madev0" //do not neeed modify usually
#define MA_CHR_DEV_NAME "madev" //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" #define MA_EINT_NAME "afs121_irq"
@ -120,12 +122,12 @@
//fprint_spi struct use to save the value //fprint_spi struct use to save the value
struct fprint_spi { struct fprint_spi {
u8 do_what; //工作内容 u8 do_what; //工作内容
u8 f_wake; //唤醒标志 u8 f_wake; //唤醒标志
int value; int value;
volatile u8 f_irq; //中断标志 volatile u8 f_irq; //中断标志
volatile u8 u1_flag; //reserve for ours thread interrupt volatile u8 u1_flag; //reserve for ours thread interrupt
volatile u8 u2_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; spinlock_t spi_lock;
struct spi_device *spi; struct spi_device *spi;
struct list_head dev_entry; struct list_head dev_entry;
@ -146,8 +148,8 @@ struct fprint_spi {
//end //end
struct fprint_dev { struct fprint_dev {
dev_t idd; dev_t idd;
int major; int major;
int minor; int minor;
struct cdev *chd; struct cdev *chd;
struct class *cls; struct class *cls;
@ -157,21 +159,27 @@ struct fprint_dev {
//function define //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_init(struct spi_device *spi);
extern int mas_qcm_platform_uninit(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 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_enable_spi_clock(struct spi_device *spi);
extern void mas_disable_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 ma_spi_change(struct spi_device *spi, unsigned int speed, int flag);
extern void mas_set_wakeup(struct spi_device *spi); 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); extern int mas_get_interrupt_gpio(unsigned int index);
//end //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 //ioctl cmd
#ifdef COMPATIBLE_VERSION3 #ifdef COMPATIBLE_VERSION3

View file

@ -22,13 +22,15 @@ struct mas_platform_data {
//kingsun/zlc: //kingsun/zlc:
int clk_enabled; int clk_enabled;
struct clk *core_clk; struct clk *core_clk;
struct clk *iface_clk; struct clk *iface_clk;
unsigned int int_irq; unsigned int int_irq;
//end //end
}; };
struct mas_platform_data *mas_pdata; struct mas_platform_data *mas_pdata;
int first_int_after_suspend=0; //kingsun/zlc: int first_int_after_suspend=0; //kingsun/zlc:
#ifdef CONFIG_OF #ifdef CONFIG_OF
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
#ifdef CONFIG_HAS_EARLYSUSPEND #ifdef CONFIG_HAS_EARLYSUSPEND
@ -36,10 +38,12 @@ int mas_suspend(struct spi_device *spi, pm_message_t mesg)
{ {
printk("%s start\n",__func__); printk("%s start\n",__func__);
if (device_may_wakeup(&spi->dev)) 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"); printk("mas_ioctl_clk_disable\n");
mas_disable_spi_clock(spi); mas_disable_spi_clock(spi);
#endif //USE_PLATFORM_DRIVE
first_int_after_suspend=1; first_int_after_suspend=1;
printk("%s end\n",__func__); printk("%s end\n",__func__);
return 0; return 0;
@ -49,18 +53,27 @@ int mas_suspend(struct spi_device *spi, pm_message_t mesg)
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
int mas_resume(struct spi_device *spi) int mas_resume(struct spi_device *spi)
{ {
printk("%s start\n",__func__); printk("%s start\n",__func__);
if (device_may_wakeup(&spi->dev)) if (device_may_wakeup(&spi->dev))
disable_irq_wake(mas_pdata->int_irq); disable_irq_wake(mas_pdata->int_irq);
#ifndef USE_PLATFORM_DRIVE
printk("mas_enable_spi_clock\n"); printk("mas_enable_spi_clock\n");
mas_enable_spi_clock(spi); mas_enable_spi_clock(spi);
#endif //USE_PLATFORM_DRIVE
printk("%s end\n",__func__); printk("%s end\n",__func__);
return 0; return 0;
} }
#else #else
int mas_suspend(struct device *dev) int mas_suspend(struct device *dev)
{ {
#ifdef USE_PLATFORM_DRIVE
printk("%s start\n",__func__);
#else
struct spi_device *spi = NULL; struct spi_device *spi = NULL;
printk("%s start\n",__func__); printk("%s start\n",__func__);
@ -69,20 +82,28 @@ int mas_suspend(struct device *dev)
printk("%s get spi device failed\n",__func__); printk("%s get spi device failed\n",__func__);
return -1; return -1;
} }
#endif //USE_PLATFORM_DRIVE
if (device_may_wakeup(dev)) 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"); printk("mas_ioctl_clk_disable\n");
mas_disable_spi_clock(spi); mas_disable_spi_clock(spi);
#endif //USE_PLATFORM_DRIVE
first_int_after_suspend=1; first_int_after_suspend=1;
printk("%s end\n",__func__); printk("%s end\n",__func__);
return 0; return 0;
} }
int mas_resume(struct device *dev) int mas_resume(struct device *dev)
{ {
#ifdef USE_PLATFORM_DRIVE
printk("%s start\n",__func__);
#else
struct spi_device *spi = NULL; struct spi_device *spi = NULL;
printk("%s start\n",__func__); printk("%s start\n",__func__);
spi = to_spi_device(dev); spi = to_spi_device(dev);
@ -90,61 +111,76 @@ int mas_resume(struct device *dev)
printk("%s get spi device failed\n",__func__); printk("%s get spi device failed\n",__func__);
return -1; return -1;
} }
#endif //USE_PLATFORM_DRIVE
if (device_may_wakeup(dev)) if (device_may_wakeup(dev))
disable_irq_wake(mas_pdata->int_irq); disable_irq_wake(mas_pdata->int_irq);
#ifndef USE_PLATFORM_DRIVE
printk("mas_enable_spi_clock\n"); printk("mas_enable_spi_clock\n");
mas_enable_spi_clock(spi); mas_enable_spi_clock(spi);
#endif //USE_PLATFORM_DRIVE
printk("%s end\n",__func__); printk("%s end\n",__func__);
return 0; return 0;
} }
#endif #endif //CONFIG_HAS_EARLYSUSPEND
static struct of_device_id mas_of_match[] = { static struct of_device_id mas_of_match[] = {
{.compatible = "microarray,fingerprint",}, {.compatible = "microarray,fingerprint",},
{} {}
}; };
MODULE_DEVICE_TABLE(of, mas_of_match); MODULE_DEVICE_TABLE(of, mas_of_match);
#ifndef CONFIG_HAS_EARLYSUSPEND #ifndef CONFIG_HAS_EARLYSUSPEND
const struct dev_pm_ops mas_pm_ops = { const struct dev_pm_ops mas_pm_ops = {
.suspend = mas_suspend, .suspend = mas_suspend,
.resume = mas_resume, .resume = mas_resume,
}; };
#endif #endif //CONFIG_HAS_EARLYSUSPEND
#endif
#endif//CONFIG_OF
#ifndef USE_PLATFORM_DRIVE
struct spi_device_id sdev_id = {MA_DRV_NAME, 0}; 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 = { struct spi_driver sdrv = {
.driver = { #endif //USE_PLATFORM_DRIVE
.name = MA_DRV_NAME, .driver = {
//.bus = &spi_bus_type, .name = MA_DRV_NAME,
.owner = THIS_MODULE, //.bus = &spi_bus_type,
.owner = THIS_MODULE,
#ifndef CONFIG_HAS_EARLYSUSPEND #ifndef CONFIG_HAS_EARLYSUSPEND
.pm = &mas_pm_ops, .pm = &mas_pm_ops,
#endif #endif //CONFIG_HAS_EARLYSUSPEND
#ifdef CONFIG_OF #ifdef CONFIG_OF
.of_match_table = mas_of_match, .of_match_table = mas_of_match,
#endif #endif //CONFIG_OF
}, },
.id_table = &sdev_id, #ifndef USE_PLATFORM_DRIVE
.probe = mas_probe, .id_table = &sdev_id,
.remove = mas_remove, #endif //USE_PLATFORM_DRIVE
.probe = mas_probe,
.remove = mas_remove,
#ifdef CONFIG_HAS_EARLYSUSPEND #ifdef CONFIG_HAS_EARLYSUSPEND
.suspend = mas_suspend, .suspend = mas_suspend,
.resume = mas_resume, .resume = mas_resume,
#endif #endif //CONFIG_HAS_EARLYSUSPEND
}; };
//driver end //driver end
#ifndef USE_PLATFORM_DRIVE
/** /**
* the spi struct date start,for getting the spi_device to set the spi clock enable end * 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) { void mas_select_transfer(struct spi_device *spi, int len) {
return ; 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) 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__); pr_info("%s: enter\n", __func__);
if (!IS_ERR_OR_NULL(data->core_clk)) { 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) 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) if (!data->clk_enabled)
return 0; return 0;
@ -300,11 +338,15 @@ static int mas_ioctl_clk_disable(struct mas_platform_data *data)
return 0; return 0;
} }
#endif //USE_PLATFORM_DRIVE
int mas_get_platform(void) { int mas_get_platform(void) {
int ret; int ret;
#ifdef USE_PLATFORM_DRIVE
ret = platform_driver_register(&sdrv);
#else
ret = spi_register_driver(&sdrv); ret = spi_register_driver(&sdrv);
#endif
pr_err("MAFP_ spi_register_driver ret = %d",ret); pr_err("MAFP_ spi_register_driver ret = %d",ret);
if(ret) { if(ret) {
@ -314,7 +356,11 @@ int mas_get_platform(void) {
} }
int mas_remove_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; return 0;
} }
@ -447,34 +493,44 @@ static int mas_gpio_configure(bool on)
return rc; 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 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); mas_ioctl_clk_uninit(mas_pdata);
#endif
mas_fingerprint_power(false); mas_fingerprint_power(false);
#if 0 #if 0
if(mas_pdata->vcc_io_l6) if(mas_pdata->vcc_io_l6)
regulator_put(mas_pdata->vcc_io_l6); regulator_put(mas_pdata->vcc_io_l6);
#endif #endif
mas_gpio_configure(false); mas_gpio_configure(false);
mas_pdata->int_irq=0; mas_pdata->int_irq=0;
kfree(mas_pdata); kfree(mas_pdata);
return ret; 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) int mas_qcm_platform_init(struct spi_device *spi)
#endif
{ {
int ret=0; int ret=0;
mas_pdata = kmalloc(sizeof(struct mas_platform_data), GFP_KERNEL); mas_pdata = kmalloc(sizeof(struct mas_platform_data), GFP_KERNEL);
if (mas_pdata == NULL) { if (mas_pdata == NULL) {
pr_info("%s:Failed to allocate buffer\n", __func__); pr_info("%s:Failed to allocate buffer\n", __func__);
ret=-ENOMEM; ret=-ENOMEM;
goto err_devm_kzalloc; goto fingeriprnt_err_devm_kzalloc;
} }
ret = mas_get_of_pdata(&spi->dev); ret = mas_get_of_pdata(&spi->dev);
if(ret<0) if(ret<0)
goto get_of_pdata_err; goto fingeriprnt_get_of_pdata_err;
ret = mas_gpio_configure(true); ret = mas_gpio_configure(true);
if(ret<0) if(ret<0)
@ -484,26 +540,32 @@ int mas_qcm_platform_init(struct spi_device *spi)
if(ret<0) if(ret<0)
goto fingeriprnt_power_err; goto fingeriprnt_power_err;
#ifndef USE_PLATFORM_DRIVE
if (mas_ioctl_clk_init(spi, mas_pdata)) if (mas_ioctl_clk_init(spi, mas_pdata))
goto fingeriprnt_power_err; goto fingeriprnt_power_err;
if (mas_ioctl_clk_enable(mas_pdata)) if (mas_ioctl_clk_enable(mas_pdata))
goto fingeriprnt_clk_enable_failed; goto fingeriprnt_clk_enable_failed;
spi_clock_set(mas_pdata, 9600000); spi_clock_set(mas_pdata, 9600000);
#endif
return ret; return ret;
#ifndef USE_PLATFORM_DRIVE
fingeriprnt_clk_enable_failed: fingeriprnt_clk_enable_failed:
mas_ioctl_clk_uninit(mas_pdata); mas_ioctl_clk_uninit(mas_pdata);
#endif
fingeriprnt_power_err: fingeriprnt_power_err:
//if(mas_pdata->vcc_io_l6) //if(mas_pdata->vcc_io_l6)
//regulator_put(mas_pdata->vcc_io_l6); //regulator_put(mas_pdata->vcc_io_l6);
fingeriprnt_gpio_configure_err: fingeriprnt_gpio_configure_err:
get_of_pdata_err: fingeriprnt_get_of_pdata_err:
kfree(mas_pdata); kfree(mas_pdata);
err_devm_kzalloc: fingeriprnt_err_devm_kzalloc:
return ret; return ret;
} }
#ifndef USE_PLATFORM_DRIVE
void mas_enable_spi_clock(struct spi_device *spi) void mas_enable_spi_clock(struct spi_device *spi)
{ {
mas_ioctl_clk_enable(mas_pdata); 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); mas_ioctl_clk_disable(mas_pdata);
} }
#endif
unsigned int mas_get_irq(void){ unsigned int mas_get_irq(void){
unsigned int irq=0; unsigned int irq=0;
irq = gpio_to_irq(mas_pdata->irq_gpio); irq = gpio_to_irq(mas_pdata->irq_gpio);
if(irq) if(irq)
printk("mas_get_irq: %d\n",irq); printk("mas_get_irq: %d\n",irq);
mas_pdata->int_irq=irq; mas_pdata->int_irq=irq;
return irq; return irq;
} }
#ifdef USE_PLATFORM_DRIVE
void mas_set_wakeup(struct platform_device *spi)
#else
void mas_set_wakeup(struct spi_device *spi) void mas_set_wakeup(struct spi_device *spi)
#endif
{ {
device_init_wakeup(&spi->dev, 1); device_init_wakeup(&spi->dev, 1);
} }

View file

@ -46,6 +46,7 @@
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include "madev.h"
//macro settings //macro settings
#define MA_DRV_NAME "madev" #define MA_DRV_NAME "madev"
@ -53,10 +54,18 @@
#define MA_DTS_NAME "mediatek,hct_finger" #define MA_DTS_NAME "mediatek,hct_finger"
#define MA_EINT_DTS_NAME "mediatek,hct_finger" #define MA_EINT_DTS_NAME "mediatek,hct_finger"
//macro settings end //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_probe(struct spi_device *spi);
extern int mas_remove(struct spi_device *spi); extern int mas_remove(struct spi_device *spi);
#endif
/* add for spi cls ctl start */ /* add for spi cls ctl start */
struct mt_spi_t { struct mt_spi_t {

View file

@ -143,14 +143,14 @@ static struct input_dev *aw9523b_input_dev = NULL;
static struct i2c_client *g_client = NULL; static struct i2c_client *g_client = NULL;
static const unsigned short key_array[Y_NUM][X_NUM] = { 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 }, { 0xFFFF, KEY_J, KEY_N, KEY_7, KEY_UP, KEY_ENTER, KEY_U, KEY_DOT },
{ KEY_3, KEY_S, KEY_Z, KEY_M, KEY_I, KEY_9, KEY_W, KEY_J }, { KEY_3, KEY_D, KEY_X, KEY_COMMA, KEY_O, KEY_9, KEY_E, KEY_K },
{ KEY_LEFT, KEY_G, KEY_V, KEY_6, KEY_RIGHT, KEY_DELETE, KEY_T, KEY_DOT }, { KEY_LEFT, KEY_H, KEY_B, KEY_6, KEY_RIGHT, KEY_DELETE, KEY_Y, KEY_SLASH },
{ KEY_SYM, KEY_A, KEY_RIGHTBRACE, KEY_HOMEPAGE, KEY_P, KEY_MINUS, KEY_Q, KEY_L }, { KEY_SYM, KEY_S, KEY_Z, KEY_HOMEPAGE, KEY_LEFTBRACE, KEY_MINUS, KEY_W, KEY_SEMICOLON },
{ KEY_BACKSPACE, KEY_D, KEY_X, KEY_K, KEY_SEMICOLON, KEY_EQUAL, KEY_E, KEY_APOSTROPHE }, { KEY_BACKSPACE, KEY_F, KEY_C, 0xFFFF, KEY_RIGHTBRACE,KEY_EQUAL, KEY_R, KEY_APOSTROPHE },
{ KEY_CAPSLOCK, KEY_BACKSLASH, KEY_LEFTBRACE, KEY_DOWN, KEY_O, KEY_0, KEY_GRAVE, KEY_K }, { KEY_CAPSLOCK, KEY_A, KEY_GRAVE, KEY_DOWN, KEY_P, KEY_0, KEY_Q, KEY_L },
{ KEY_SPACE, KEY_F, KEY_C, KEY_N, KEY_U, KEY_8, KEY_R, KEY_5 }, { 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 } { 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). // 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 i;
int count; int count;
struct device_node *node; struct device_node *node;
struct drm_panel *panel; struct drm_panel *panel;
//需要在屏dts初始化后才能找到panel的字段 //需要在屏dts初始化后才能找到panel的字段
count = of_count_phandle_with_args(np, "panel", NULL); count = of_count_phandle_with_args(np, "panel", NULL);

View file

@ -42,12 +42,12 @@
//IIC的写地址={10110AD1AD00}AD0,AD1接低则为0xB0 接高则是0xB6 //IIC的写地址={10110AD1AD00}AD0,AD1接低则为0xB0 接高则是0xB6
#define IIC_ADDRESS_WRITE (0xB0) //0x58 #define IIC_ADDRESS_WRITE (0xB0) //0x58
#define IIC_ADDRESS_READ (0xB1) #define IIC_ADDRESS_READ (0xB1)
#define X_NUM (8) //列 #define X_NUM (8) //列
#define Y_NUM (8) //行 #define Y_NUM (8) //行
//i2c tranfer ,repeat try times //i2c tranfer ,repeat try times
#define AW9523_I2C_MAX_LOOP (50) #define AW9523_I2C_MAX_LOOP (50)

View file

@ -77,3 +77,4 @@ obj-$(CONFIG_QTI_MAXIM_FAN_CONTROLLER) += max31760.o
obj-$(CONFIG_QTI_XR_SMRTVWR_MISC) += qxr-stdalonevwr.o obj-$(CONFIG_QTI_XR_SMRTVWR_MISC) += qxr-stdalonevwr.o
obj-$(CONFIG_FPR_FPC) += fpr_FingerprintCard/ obj-$(CONFIG_FPR_FPC) += fpr_FingerprintCard/
obj-y += qrc/ obj-y += qrc/
obj-$(CONFIG_AW862XX_HAPTIC) += aw862xx_haptic/

View file

@ -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", 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[0], (int)desc->ret[2],
(int)desc->ret[1], ret); (int)desc->ret[1], ret);
desc->ret[0] = resp.resp_type; desc->ret[0] = resp.result;
desc->ret[1] = resp.result; desc->ret[1] = resp.resp_type;
desc->ret[2] = resp.data; desc->ret[2] = resp.data;
return ret; return ret;
} }

View file

@ -62,7 +62,7 @@ static void scm_disable_sdi(void);
* There is no API from TZ to re-enable the registers. * There is no API from TZ to re-enable the registers.
* So the SDI cannot be re-enabled when it already by-passed. * 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 struct kobject dload_kobj;
static int in_panic; static int in_panic;

View file

@ -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); pr_err("Failed reading BAT_TEMP over ADC rc=%d\n", rc);
return rc; return rc;
} }
//pr_err("batt_temp = %d,by eric.wang\n", *temp);//by eric.wang pr_debug("batt_temp = %d\n", *temp);
//*temp = 250;
return 0; return 0;
} }

View file

@ -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); 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) { switch (stat & DETECTED_SRC_TYPE_MASK) {
case SNK_RP_STD_BIT: case SNK_RP_STD_BIT:
case SNK_RP_STD_DAM_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_err(chg, "Couldn't disable DPDM rc=%d\n", rc);
smblib_update_usb_type(chg); 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) 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 rp med or high, use rp value */
typec_mode = smblib_get_prop_typec_mode(chg); typec_mode = smblib_get_prop_typec_mode(chg);
if (typec_rp_med_high(chg, typec_mode)) { if (typec_rp_med_high(chg, typec_mode)) {
rp_ua = get_rp_based_dcp_current(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); 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; return;
apsd_result = smblib_update_usb_type(chg); apsd_result = smblib_update_usb_type(chg);
update_sw_icl_max(chg, apsd_result->pst); update_sw_icl_max(chg, apsd_result->pst);
switch (apsd_result->bit) { 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) == FORCE_FLOAT_SDP_CFG_BIT)
return; return;
} }
update_sw_icl_max(chg, apsd->pst); update_sw_icl_max(chg, apsd->pst);
smblib_dbg(chg, PR_MISC, "CC change old_mode=%d new_mode=%d\n", smblib_dbg(chg, PR_MISC, "CC change old_mode=%d new_mode=%d\n",

View file

@ -3589,6 +3589,13 @@ static int msm_geni_serial_probe(struct platform_device *pdev)
if (!uart_console(uport)) if (!uart_console(uport))
spin_lock_init(&dev_port->rx_lock); 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__, IPC_LOG_MSG(dev_port->ipc_log_misc, "%s: port:%s irq:%d\n", __func__,
uport->name, uport->irq); uport->name, uport->irq);

View file

@ -1958,8 +1958,11 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
return buf; return buf;
} }
case 'K': case 'K':
/*
if (!kptr_restrict || if (!kptr_restrict ||
IS_ENABLED(CONFIG_DEBUG_CONSOLE_UNHASHED_POINTERS)) IS_ENABLED(CONFIG_DEBUG_CONSOLE_UNHASHED_POINTERS))
*/
if (!kptr_restrict)
break; break;
return restricted_pointer(buf, end, ptr, spec); return restricted_pointer(buf, end, ptr, spec);
case 'N': case 'N':

View file

@ -13,6 +13,10 @@ ifeq ($(CONFIG_ARCH_BENGAL), y)
include $(srctree)/techpack/camera/config/bengalcamera.conf include $(srctree)/techpack/camera/config/bengalcamera.conf
endif endif
ifeq ($(CONFIG_ARCH_KHAJE), y)
include $(srctree)/techpack/camera/config/khajecamera.conf
endif
ifeq ($(CONFIG_ARCH_KONA), y) ifeq ($(CONFIG_ARCH_KONA), y)
LINUXINCLUDE += \ LINUXINCLUDE += \
-include $(srctree)/techpack/camera/config/konacameraconf.h -include $(srctree)/techpack/camera/config/konacameraconf.h
@ -28,6 +32,11 @@ LINUXINCLUDE += \
-include $(srctree)/techpack/camera/config/bengalcameraconf.h -include $(srctree)/techpack/camera/config/bengalcameraconf.h
endif endif
ifeq ($(CONFIG_ARCH_KHAJE), y)
LINUXINCLUDE += \
-include $(srctree)/techpack/camera/config/khajecameraconf.h
endif
ifdef CONFIG_SPECTRA_CAMERA ifdef CONFIG_SPECTRA_CAMERA
# Use USERINCLUDE when you must reference the UAPI directories only. # Use USERINCLUDE when you must reference the UAPI directories only.
USERINCLUDE += \ USERINCLUDE += \

View file

@ -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

View file

@ -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

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #ifndef _CAM_CDM_H_
@ -83,6 +83,7 @@
#define CAM_CDM_RESET_HW_STATUS 0x4 #define CAM_CDM_RESET_HW_STATUS 0x4
#define CAM_CDM_ERROR_HW_STATUS 0x5 #define CAM_CDM_ERROR_HW_STATUS 0x5
#define CAM_CDM_FLUSH_HW_STATUS 0x6 #define CAM_CDM_FLUSH_HW_STATUS 0x6
#define CAM_CDM_RESET_ERR_STATUS 0x7
/* Curent BL command masks and shifts */ /* Curent BL command masks and shifts */
#define CAM_CDM_CURRENT_BL_LEN 0xFFFFF #define CAM_CDM_CURRENT_BL_LEN 0xFFFFF
@ -276,6 +277,7 @@ struct cam_cdm_common_reg_data {
* wait, etc. * wait, etc.
* @core_en: offset to pause/enable CDM * @core_en: offset to pause/enable CDM
* @fe_cfg: offset to configure CDM fetch engine * @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_rb: offset to set BL_FIFO read back
* @bl_fifo_base_rb: offset to read back base address on offset set by * @bl_fifo_base_rb: offset to read back base address on offset set by
* bl_fifo_rb * bl_fifo_rb
@ -319,6 +321,7 @@ struct cam_cdm_common_regs {
uint32_t core_cfg; uint32_t core_cfg;
uint32_t core_en; uint32_t core_en;
uint32_t fe_cfg; uint32_t fe_cfg;
uint32_t irq_context_status;
uint32_t bl_fifo_rb; uint32_t bl_fifo_rb;
uint32_t bl_fifo_base_rb; uint32_t bl_fifo_base_rb;
uint32_t bl_fifo_len_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_FLUSH_HW,
CAM_CDM_HW_INTF_CMD_HANDLE_ERROR, CAM_CDM_HW_INTF_CMD_HANDLE_ERROR,
CAM_CDM_HW_INTF_CMD_HANG_DETECT, CAM_CDM_HW_INTF_CMD_HANG_DETECT,
CAM_CDM_HW_INTF_DUMP_DBG_REGS,
CAM_CDM_HW_INTF_CMD_INVALID, 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_1 = 0x10010000,
CAM_CDM_VERSION_1_2 = 0x10020000, CAM_CDM_VERSION_1_2 = 0x10020000,
CAM_CDM_VERSION_2_0 = 0x20000000, CAM_CDM_VERSION_2_0 = 0x20000000,
CAM_CDM_VERSION_2_1 = 0x20010000,
CAM_CDM_VERSION_MAX, CAM_CDM_VERSION_MAX,
}; };

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/delay.h> #include <linux/delay.h>
@ -49,6 +49,7 @@ bool cam_cdm_set_cam_hw_version(
case CAM_CDM110_VERSION: case CAM_CDM110_VERSION:
case CAM_CDM120_VERSION: case CAM_CDM120_VERSION:
case CAM_CDM200_VERSION: case CAM_CDM200_VERSION:
case CAM_CDM210_VERSION:
cam_version->major = (ver & 0xF0000000); cam_version->major = (ver & 0xF0000000);
cam_version->minor = (ver & 0xFFF0000); cam_version->minor = (ver & 0xFFF0000);
cam_version->incr = (ver & 0xFFFF); cam_version->incr = (ver & 0xFFFF);
@ -81,6 +82,7 @@ struct cam_cdm_utils_ops *cam_cdm_get_ops(
case CAM_CDM110_VERSION: case CAM_CDM110_VERSION:
case CAM_CDM120_VERSION: case CAM_CDM120_VERSION:
case CAM_CDM200_VERSION: case CAM_CDM200_VERSION:
case CAM_CDM210_VERSION:
return &CDM170_ops; return &CDM170_ops;
default: default:
CAM_ERR(CAM_CDM, "CDM Version=%x not supported in util", 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; (struct cam_cdm_bl_cb_request_entry *)data;
client_idx = CAM_CDM_GET_CLIENT_IDX(node->client_hdl); client_idx = CAM_CDM_GET_CLIENT_IDX(node->client_hdl);
mutex_lock(&cdm_hw->hw_mutex);
client = core->clients[client_idx]; client = core->clients[client_idx];
if ((!client) || (client->handle != node->client_hdl)) { if ((!client) || (client->handle != node->client_hdl)) {
CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client, CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client,
node->client_hdl); node->client_hdl);
mutex_unlock(&cdm_hw->hw_mutex);
return; return;
} }
cam_cdm_get_client_refcount(client); 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); mutex_unlock(&client->lock);
cam_cdm_put_client_refcount(client); cam_cdm_put_client_refcount(client);
mutex_unlock(&cdm_hw->hw_mutex);
return; return;
} else if (status == CAM_CDM_CB_STATUS_HW_RESET_DONE || } else if (status == CAM_CDM_CB_STATUS_HW_RESET_DONE ||
status == CAM_CDM_CB_STATUS_HW_FLUSH || 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)) { if ((!client) || (client->handle != node->client_hdl)) {
CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client, CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client,
node->client_hdl); node->client_hdl);
return; return;
} }
cam_cdm_get_client_refcount(client); cam_cdm_get_client_refcount(client);
mutex_lock(&client->lock); 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++) { for (i = 0; i < CAM_PER_CDM_MAX_REGISTERED_CLIENTS; i++) {
if (core->clients[i] != NULL) { if (core->clients[i] != NULL) {
mutex_lock(&cdm_hw->hw_mutex);
client = core->clients[i]; client = core->clients[i];
cam_cdm_get_client_refcount(client); cam_cdm_get_client_refcount(client);
mutex_lock(&client->lock); mutex_lock(&client->lock);
@ -259,6 +265,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
} }
mutex_unlock(&client->lock); mutex_unlock(&client->lock);
cam_cdm_put_client_refcount(client); 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; return -EINVAL;
core = (struct cam_cdm *)cdm_hw->core_info; core = (struct cam_cdm *)cdm_hw->core_info;
mutex_lock(&cdm_hw->hw_mutex);
client_idx = CAM_CDM_GET_CLIENT_IDX(*handle); client_idx = CAM_CDM_GET_CLIENT_IDX(*handle);
client = core->clients[client_idx]; client = core->clients[client_idx];
if (!client) { if (!client) {
CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client, *handle); CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client, *handle);
mutex_unlock(&cdm_hw->hw_mutex);
return -EINVAL; return -EINVAL;
} }
cam_cdm_get_client_refcount(client); cam_cdm_get_client_refcount(client);
if (*handle != client->handle) { if (*handle != client->handle) {
CAM_ERR(CAM_CDM, "client id given handle=%x invalid", *handle); CAM_ERR(CAM_CDM, "client id given handle=%x invalid", *handle);
cam_cdm_put_client_refcount(client); rc = -EINVAL;
return -EINVAL; goto end;
} }
if (operation == true) { if (operation == true) {
if (true == client->stream_on) { if (true == client->stream_on) {
CAM_ERR(CAM_CDM, CAM_ERR(CAM_CDM,
"Invalid CDM client is already streamed ON"); "Invalid CDM client is already streamed ON");
cam_cdm_put_client_refcount(client); goto end;
return rc;
} }
} else { } else {
if (client->stream_on == false) { if (client->stream_on == false) {
CAM_ERR(CAM_CDM, CAM_ERR(CAM_CDM,
"Invalid CDM client is already streamed Off"); "Invalid CDM client is already streamed Off");
cam_cdm_put_client_refcount(client); goto end;
return rc;
} }
} }
mutex_lock(&cdm_hw->hw_mutex);
if (operation == true) { if (operation == true) {
if (!cdm_hw->open_count) { if (!cdm_hw->open_count) {
struct cam_ahb_vote ahb_vote; 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); rc = cam_hw_cdm_hang_detect(cdm_hw, *handle);
break; 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: default:
CAM_ERR(CAM_CDM, "CDM HW intf command not valid =%d", cmd); CAM_ERR(CAM_CDM, "CDM HW intf command not valid =%d", cmd);
break; break;

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #ifndef _CAM_CDM_CORE_COMMON_H_
@ -12,6 +12,7 @@
#define CAM_CDM110_VERSION 0x10010000 #define CAM_CDM110_VERSION 0x10010000
#define CAM_CDM120_VERSION 0x10020000 #define CAM_CDM120_VERSION 0x10020000
#define CAM_CDM200_VERSION 0x20000000 #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_1 (BIT(1) - 1)
#define CAM_CDM_AHB_BURST_LEN_4 (BIT(2) - 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); uint32_t tag, struct list_head *bl_list);
void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw, void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
enum cam_cdm_cb_status status, void *data); 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_ */ #endif /* _CAM_CDM_CORE_COMMON_H_ */

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/delay.h> #include <linux/delay.h>
@ -22,6 +22,7 @@
#include "cam_cdm_hw_reg_1_1.h" #include "cam_cdm_hw_reg_1_1.h"
#include "cam_cdm_hw_reg_1_2.h" #include "cam_cdm_hw_reg_1_2.h"
#include "cam_cdm_hw_reg_2_0.h" #include "cam_cdm_hw_reg_2_0.h"
#include "cam_cdm_hw_reg_2_1.h"
#include "cam_trace.h" #include "cam_trace.h"
#include "cam_req_mgr_workq.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, .compatible = CAM_HW_CDM_OPE_NAME_2_0,
.data = &cam_cdm_2_0_reg_offset, .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) 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, if (strnstr(name, CAM_HW_CDM_OPE_NAME_2_0,
strlen(CAM_HW_CDM_CPAS_NAME_2_0))) strlen(CAM_HW_CDM_CPAS_NAME_2_0)))
return CAM_CDM_OPE; 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; 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; 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; int rc = 0;
struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info;
if (cam_cdm_write_hw_reg(cdm_hw, if (cam_cdm_write_hw_reg(cdm_hw,
core->offsets->cmn_reg->core_debug, core->offsets->cmn_reg->core_debug,
0x10100)) { value)) {
CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug"); CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug");
rc = -EIO; rc = -EIO;
} }
@ -241,24 +264,7 @@ int cam_hw_cdm_bl_fifo_pending_bl_rb_in_fifo(
return rc; return rc;
} }
int cam_hw_cdm_enable_core_dbg_per_fifo( static void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw)
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)
{ {
struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info;
int i, j; 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++) { for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) {
cam_hw_cdm_bl_fifo_pending_bl_rb_in_fifo(cdm_hw, cam_hw_cdm_bl_fifo_pending_bl_rb_in_fifo(cdm_hw,
i, &num_pending_req); i, &num_pending_req);
for (j = 0; j < num_pending_req ; j++) {
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++) {
cam_cdm_write_hw_reg(cdm_hw, cam_cdm_write_hw_reg(cdm_hw,
core->offsets->cmn_reg->bl_fifo_rb, j); core->offsets->cmn_reg->bl_fifo_rb, j);
cam_cdm_read_hw_reg(cdm_hw, 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( void cam_hw_cdm_dump_core_debug_registers(struct cam_hw_info *cdm_hw,
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; int i;
bool is_core_paused_already;
struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info; 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_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en,
CAM_INFO(CAM_CDM, "CDM HW core status=%x", dump_reg); &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, cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->usr_data,
&dump_reg); &dump_reg[1]);
CAM_INFO(CAM_CDM, "CDM HW core userdata=0x%x", dump_reg);
usleep_range(1000, 1010);
cam_cdm_read_hw_reg(cdm_hw, cam_cdm_read_hw_reg(cdm_hw,
core->offsets->cmn_reg->debug_status, core->offsets->cmn_reg->debug_status,
&dump_reg); &dump_reg[2]);
CAM_INFO(CAM_CDM, "CDM HW Debug status reg=%x", dump_reg);
cam_cdm_read_hw_reg(cdm_hw, CAM_INFO(CAM_CDM, "Core stat 0x%x udata 0x%x dbg_stat 0x%x",
core->offsets->cmn_reg->core_debug, dump_reg[0], dump_reg[1], dump_reg[2]);
&core_dbg);
if (core_dbg & 0x100) { if (core_dbg & 0x100) {
cam_cdm_read_hw_reg(cdm_hw, cam_cdm_read_hw_reg(cdm_hw,
core->offsets->cmn_reg->last_ahb_addr, core->offsets->cmn_reg->last_ahb_addr,
&dump_reg); &dump_reg[0]);
CAM_INFO(CAM_CDM, "AHB dump reglastaddr=%x", dump_reg);
cam_cdm_read_hw_reg(cdm_hw, cam_cdm_read_hw_reg(cdm_hw,
core->offsets->cmn_reg->last_ahb_data, core->offsets->cmn_reg->last_ahb_data,
&dump_reg); &dump_reg[1]);
CAM_INFO(CAM_CDM, "AHB dump reglastdata=%x", dump_reg); CAM_INFO(CAM_CDM, "AHB dump lastaddr=0x%x lastdata=0x%x",
dump_reg[0], dump_reg[1]);
} else { } else {
CAM_INFO(CAM_CDM, "CDM HW AHB dump not enable"); 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, cam_cdm_read_hw_reg(cdm_hw,
core->offsets->cmn_reg->core_cfg, &dump_reg); core->offsets->cmn_reg->core_cfg, &dump_reg[0]);
CAM_INFO(CAM_CDM, "CDM HW core cfg=%x", dump_reg); CAM_INFO(CAM_CDM, "CDM HW core cfg=0x%x", dump_reg[0]);
for (i = 0; i < for (i = 0; i <
core->offsets->reg_data->num_bl_fifo_irq; core->offsets->reg_data->num_bl_fifo_irq;
i++) { i++) {
cam_cdm_read_hw_reg(cdm_hw, cam_cdm_read_hw_reg(cdm_hw,
core->offsets->irq_reg[i]->irq_status, &dump_reg); core->offsets->irq_reg[i]->irq_status, &dump_reg[0]);
CAM_INFO(CAM_CDM, "CDM HW irq status%d=%x", i, dump_reg);
cam_cdm_read_hw_reg(cdm_hw, cam_cdm_read_hw_reg(cdm_hw,
core->offsets->irq_reg[i]->irq_set, &dump_reg); core->offsets->irq_reg[i]->irq_set, &dump_reg[1]);
CAM_INFO(CAM_CDM, "CDM HW irq set%d=%x", i, dump_reg);
cam_cdm_read_hw_reg(cdm_hw, cam_cdm_read_hw_reg(cdm_hw,
core->offsets->irq_reg[i]->irq_mask, &dump_reg); core->offsets->irq_reg[i]->irq_mask, &dump_reg[2]);
CAM_INFO(CAM_CDM, "CDM HW irq mask%d=%x", i, dump_reg);
cam_cdm_read_hw_reg(cdm_hw, cam_cdm_read_hw_reg(cdm_hw,
core->offsets->irq_reg[i]->irq_clear, &dump_reg); core->offsets->irq_reg[i]->irq_clear, &dump_reg[3]);
CAM_INFO(CAM_CDM, "CDM HW irq clear%d=%x", i, dump_reg);
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, cam_cdm_read_hw_reg(cdm_hw,
core->offsets->cmn_reg->current_bl_base, &dump_reg); core->offsets->cmn_reg->current_bl_base, &dump_reg[0]);
CAM_INFO(CAM_CDM, "CDM HW current BL base=%x", dump_reg); 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, 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, CAM_INFO(CAM_CDM,
"CDM HW current BL len=%d ARB %d FIFO %d tag=%d, ", "CDM HW current BL len=%d ARB %d FIFO %d tag=%d, ",
(dump_reg & CAM_CDM_CURRENT_BL_LEN), (dump_reg[0] & CAM_CDM_CURRENT_BL_LEN),
(dump_reg & CAM_CDM_CURRENT_BL_ARB) >> (dump_reg[0] & CAM_CDM_CURRENT_BL_ARB) >>
CAM_CDM_CURRENT_BL_ARB_SHIFT, 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, 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_CURRENT_BL_TAG_SHIFT);
cam_cdm_read_hw_reg(cdm_hw, cam_hw_cdm_disable_core_dbg(cdm_hw);
core->offsets->cmn_reg->current_used_ahb_base, &dump_reg); if (pause_core)
CAM_INFO(CAM_CDM, "CDM HW current AHB base=%x", dump_reg); cam_hw_cdm_pause_core(cdm_hw, false);
} }
enum cam_cdm_arbitration cam_cdm_get_arbitration_type( enum cam_cdm_arbitration cam_cdm_get_arbitration_type(
@ -1084,11 +1147,15 @@ static void cam_hw_cdm_reset_cleanup(
int i; int i;
struct cam_cdm_bl_cb_request_entry *node, *tnode; struct cam_cdm_bl_cb_request_entry *node, *tnode;
bool flush_hw = false; bool flush_hw = false;
bool reset_err = false;
if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status) || if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status) ||
test_bit(CAM_CDM_FLUSH_HW_STATUS, &core->cdm_status)) test_bit(CAM_CDM_FLUSH_HW_STATUS, &core->cdm_status))
flush_hw = true; 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++) { for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) {
list_for_each_entry_safe(node, tnode, list_for_each_entry_safe(node, tnode,
&core->bl_fifo[i].bl_request_list, entry) { &core->bl_fifo[i].bl_request_list, entry) {
@ -1097,12 +1164,19 @@ static void cam_hw_cdm_reset_cleanup(
CAM_DBG(CAM_CDM, CAM_DBG(CAM_CDM,
"Notifying client %d for tag %d", "Notifying client %d for tag %d",
node->client_hdl, node->bl_tag); 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, cam_cdm_notify_clients(cdm_hw,
(node->client_hdl == handle) ? (node->client_hdl == handle) ?
CAM_CDM_CB_STATUS_HW_FLUSH : CAM_CDM_CB_STATUS_HW_FLUSH :
CAM_CDM_CB_STATUS_HW_RESUBMIT, status,
(void *)node); (void *)node);
}
else else
cam_cdm_notify_clients(cdm_hw, cam_cdm_notify_clients(cdm_hw,
CAM_CDM_CB_STATUS_HW_RESET_DONE, 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 * to dump debug info
*/ */
cam_hw_cdm_pause_core(cdm_hw, true); 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 & if (payload->irq_status &
CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK) { 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)) CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK))
clear_bit(CAM_CDM_ERROR_HW_STATUS, clear_bit(CAM_CDM_ERROR_HW_STATUS,
&core->cdm_status); &core->cdm_status);
} else {
CAM_ERR(CAM_CDM, "NULL payload");
} }
kfree(payload); kfree(payload);
payload = NULL; 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++) for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++)
mutex_lock(&core->bl_fifo[i].fifo_lock); mutex_lock(&core->bl_fifo[i].fifo_lock);
if (cdm_hw->hw_state == CAM_HW_STATE_POWER_UP) { if (cdm_hw->hw_state == CAM_HW_STATE_POWER_UP) {
/* cam_hw_cdm_dump_core_debug_registers(cdm_hw, true);
* First pause CDM, If it fails still proceed } else
* 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_INFO(CAM_CDM, "CDM hw is power in off state"); CAM_INFO(CAM_CDM, "CDM hw is power in off state");
for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++)
mutex_unlock(&core->bl_fifo[i].fifo_lock); 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}; struct cam_cdm_work_payload *payload[CAM_CDM_BL_FIFO_MAX] = {0};
uint32_t user_data = 0; uint32_t user_data = 0;
uint32_t irq_status[CAM_CDM_BL_FIFO_MAX] = {0}; uint32_t irq_status[CAM_CDM_BL_FIFO_MAX] = {0};
uint32_t irq_context_summary = 0xF;
bool work_status; bool work_status;
int i; 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); spin_lock(&cdm_hw->hw_lock);
if (cdm_hw->hw_state == CAM_HW_STATE_POWER_DOWN) { if (cdm_hw->hw_state == CAM_HW_STATE_POWER_DOWN) {
CAM_DBG(CAM_CDM, "CDM is in power down state"); CAM_DBG(CAM_CDM, "CDM is in power down state");
spin_unlock(&cdm_hw->hw_lock); spin_unlock(&cdm_hw->hw_lock);
return IRQ_HANDLED; 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++) { 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, if (cam_cdm_read_hw_reg(cdm_hw,
cdm_core->offsets->irq_reg[i]->irq_status, cdm_core->offsets->irq_reg[i]->irq_status,
&irq_status[i])) { &irq_status[i])) {
@ -1613,7 +1692,7 @@ int cam_hw_cdm_handle_error_info(
current_fifo, current_tag); current_fifo, current_tag);
/* dump cdm registers for further debug */ /* 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++) { for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) {
reset_val = reset_val | reset_val = reset_val |
@ -1639,7 +1718,7 @@ int cam_hw_cdm_handle_error_info(
if (time_left <= 0) { if (time_left <= 0) {
rc = -ETIMEDOUT; rc = -ETIMEDOUT;
CAM_ERR(CAM_CDM, "CDM HW reset Wait failed rc=%d", rc); 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); rc = cam_hw_cdm_set_cdm_core_cfg(cdm_hw);
@ -1678,6 +1757,7 @@ int cam_hw_cdm_handle_error_info(
end: end:
clear_bit(CAM_CDM_FLUSH_HW_STATUS, &cdm_core->cdm_status); 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_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++) for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++)
mutex_unlock(&cdm_core->bl_fifo[i].fifo_lock); mutex_unlock(&cdm_core->bl_fifo[i].fifo_lock);

View file

@ -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,
};

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/delay.h> #include <linux/delay.h>
@ -506,6 +506,32 @@ int cam_cdm_detect_hang_error(uint32_t handle)
} }
EXPORT_SYMBOL(cam_cdm_detect_hang_error); 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, int cam_cdm_intf_register_hw_cdm(struct cam_hw_intf *hw,
struct cam_cdm_private_dt_data *data, enum cam_cdm_type type, struct cam_cdm_private_dt_data *data, enum cam_cdm_type type,
uint32_t *index) uint32_t *index)

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #ifndef _CAM_CDM_API_H_
@ -296,4 +296,13 @@ struct cam_cdm_utils_ops *cam_cdm_publish_ops(void);
* @return 0 on success * @return 0 on success
*/ */
int cam_cdm_detect_hang_error(uint32_t handle); 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_ */ #endif /* _CAM_CDM_API_H_ */

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #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_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_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_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, int cam_hw_cdm_soc_get_dt_properties(struct cam_hw_info *cdm_hw,
const struct of_device_id *table); const struct of_device_id *table);

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/device.h> #include <linux/device.h>
@ -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); (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) { if (rc) {
CAM_DBG(CAM_CPAS, CAM_DBG(CAM_CPAS,
"failed to read camnoc-axi-min-ib-bw rc:%d", rc); "failed to read camnoc-axi-min-ib-bw rc:%d", rc);

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #ifndef _CAM_CPAS_SOC_H_
@ -109,6 +109,8 @@ struct cam_cpas_feature_info {
* @feature_info: fuse based feature info for hw supported features * @feature_info: fuse based feature info for hw supported features
* @cx_ipeak_gpu_limit: Flag for Cx Ipeak GPU mitigation * @cx_ipeak_gpu_limit: Flag for Cx Ipeak GPU mitigation
* @gpu_pwr_limit: Handle 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 { 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]; struct cam_cpas_feature_info feature_info[CAM_CPAS_MAX_FUSE_FEATURE];
uint32_t cx_ipeak_gpu_limit; uint32_t cx_ipeak_gpu_limit;
struct kgsl_pwr_limit *gpu_pwr_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); void cam_cpas_util_debug_parse_data(struct cam_cpas_private_soc *soc_private);

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/delay.h> #include <linux/delay.h>
@ -24,6 +24,7 @@
#include "cpastop_v480_100.h" #include "cpastop_v480_100.h"
#include "cpastop_v540_100.h" #include "cpastop_v540_100.h"
#include "cpastop_v520_100.h" #include "cpastop_v520_100.h"
#include "cpastop_v545_110_518.h"
#include "cam_req_mgr_workq.h" #include "cam_req_mgr_workq.h"
struct cam_camnoc_info *camnoc_info; 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.minor == 2) &&
(hw_caps->camera_version.incr == 0)) { (hw_caps->camera_version.incr == 0)) {
soc_info->hw_version = CAM_CPAS_TITAN_520_V100; 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); 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; int rc = 0;
struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info;
struct cam_cpas_private_soc *soc_private;
CAM_DBG(CAM_CPAS, CAM_DBG(CAM_CPAS,
"hw_version=0x%x Camera Version %d.%d.%d, cpas version %d.%d.%d", "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: case CAM_CPAS_TITAN_520_V100:
camnoc_info = &cam520_cpas100_camnoc_info; camnoc_info = &cam520_cpas100_camnoc_info;
break; 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: default:
CAM_ERR(CAM_CPAS, "Camera Version not supported %d.%d.%d", CAM_ERR(CAM_CPAS, "Camera Version not supported %d.%d.%d",
hw_caps->camera_version.major, hw_caps->camera_version.major,

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #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_FD: Indicates FD HW connection to camnoc
* @CAM_CAMNOC_ICP: Indicates ICP 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: 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 * @CAM_CAMNOC_OPE: Indicates OPE HW connection to camnoc
*/ */
enum cam_camnoc_port_type { enum cam_camnoc_port_type {
@ -131,6 +133,8 @@ enum cam_camnoc_port_type {
CAM_CAMNOC_FD, CAM_CAMNOC_FD,
CAM_CAMNOC_ICP, CAM_CAMNOC_ICP,
CAM_CAMNOC_TFE, CAM_CAMNOC_TFE,
CAM_CAMNOC_TFE_1,
CAM_CAMNOC_TFE_2,
CAM_CAMNOC_OPE, CAM_CAMNOC_OPE,
}; };

View file

@ -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_ */

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #ifndef _CAM_CPAS_API_H_
@ -48,9 +48,19 @@ enum cam_cpas_hw_version {
CAM_CPAS_TITAN_480_V100 = 0x480100, CAM_CPAS_TITAN_480_V100 = 0x480100,
CAM_CPAS_TITAN_540_V100 = 0x540100, CAM_CPAS_TITAN_540_V100 = 0x540100,
CAM_CPAS_TITAN_520_V100 = 0x520100, CAM_CPAS_TITAN_520_V100 = 0x520100,
CAM_CPAS_TITAN_545_V110 = 0x545110,
CAM_CPAS_TITAN_MAX 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 * enum cam_camnoc_irq_type - Enum for camnoc irq types
* *

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/debugfs.h> #include <linux/debugfs.h>
@ -3066,6 +3066,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied(
ctx_isp->frame_id, ctx_isp->frame_id,
ctx->ctx_id); ctx->ctx_id);
ctx->ctx_crm_intf->notify_err(&notify); ctx->ctx_crm_intf->notify_err(&notify);
atomic_set(&ctx_isp->process_bubble, 1);
} else { } else {
req_isp->bubble_report = 0; 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; ctx_isp->boot_timestamp = sof_event_data->boot_time;
CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx", CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
ctx_isp->frame_id, ctx_isp->sof_timestamp_val); 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 * Signal all active requests with error and move the all the active
* requests to free list * requests to free list
@ -3144,6 +3183,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state(
ctx_isp->active_req_cnt--; ctx_isp->active_req_cnt--;
} }
end:
/* notify reqmgr with sof signal */ /* notify reqmgr with sof signal */
if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) { if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) {
notify.link_hdl = ctx->link_hdl; 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( __cam_isp_ctx_substate_val_to_type(
ctx_isp->substate_activated)); ctx_isp->substate_activated));
ctx_isp->last_sof_timestamp = ctx_isp->sof_timestamp_val;
return 0; 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->hw_acquired = false;
ctx_isp->init_received = false; ctx_isp->init_received = false;
ctx_isp->req_info.last_bufdone_req_id = 0; ctx_isp->req_info.last_bufdone_req_id = 0;
ctx_isp->last_sof_timestamp = 0;
atomic64_set(&ctx_isp->state_monitor_head, -1); 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->init_received = false;
ctx_isp->rdi_only_context = false; ctx_isp->rdi_only_context = false;
ctx_isp->req_info.last_bufdone_req_id = 0; ctx_isp->req_info.last_bufdone_req_id = 0;
ctx_isp->last_sof_timestamp = 0;
atomic64_set(&ctx_isp->state_monitor_head, -1); atomic64_set(&ctx_isp->state_monitor_head, -1);
for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) 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->hw_acquired = true;
ctx_isp->split_acquire = false; ctx_isp->split_acquire = false;
ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; ctx->ctxt_to_hw_map = param.ctxt_to_hw_map;
ctx_isp->last_sof_timestamp = 0;
atomic64_set(&ctx_isp->state_monitor_head, -1); atomic64_set(&ctx_isp->state_monitor_head, -1);
for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) 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_ctx = param.ctxt_to_hw_map;
ctx_isp->hw_acquired = true; ctx_isp->hw_acquired = true;
ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; ctx->ctxt_to_hw_map = param.ctxt_to_hw_map;
ctx_isp->last_sof_timestamp = 0;
atomic64_set(&ctx_isp->state_monitor_head, -1); 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_ctx = param.ctxt_to_hw_map;
ctx_isp->hw_acquired = true; ctx_isp->hw_acquired = true;
ctx->ctxt_to_hw_map = param.ctxt_to_hw_map; ctx->ctxt_to_hw_map = param.ctxt_to_hw_map;
ctx_isp->last_sof_timestamp = 0;
trace_cam_context_state("ISP", ctx); trace_cam_context_state("ISP", ctx);
CAM_DBG(CAM_ISP, 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 */ /* HW failure. user need to clean up the resource */
CAM_ERR(CAM_ISP, "Start HW failed"); CAM_ERR(CAM_ISP, "Start HW failed");
ctx->state = CAM_CTX_READY; 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); rc = cam_isp_ctx_dump_req(req_isp, 0, 0, NULL, false);
trace_cam_context_state("ISP", ctx);
list_del_init(&req->list); list_del_init(&req->list);
list_add(&req->list, &ctx->pending_req_list); list_add(&req->list, &ctx->pending_req_list);
goto end; goto end;
@ -4953,8 +5001,15 @@ static int cam_isp_context_debug_register(void)
goto err; 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: err:
debugfs_remove_recursive(isp_ctx_debug.dentry); debugfs_remove_recursive(isp_ctx_debug.dentry);
return -ENOMEM; return -ENOMEM;

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #ifndef _CAM_ISP_CONTEXT_H_
@ -110,13 +110,15 @@ enum cam_isp_state_change_trigger {
/** /**
* struct cam_isp_ctx_debug - Contains debug parameters * struct cam_isp_ctx_debug - Contains debug parameters
* *
* @dentry: Debugfs entry * @dentry: Debugfs entry
* @enable_state_monitor_dump: Enable isp state monitor dump * @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 cam_isp_ctx_debug {
struct dentry *dentry; struct dentry *dentry;
uint32_t enable_state_monitor_dump; 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 * @req_isp: ISP private request object storage
* @hw_ctx: HW object returned by the acquire device command * @hw_ctx: HW object returned by the acquire device command
* @sof_timestamp_val: Captured time stamp value at sof hw event * @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 * @boot_timestamp: Boot time stamp for a given req_id
* @active_req_cnt: Counter for the active request * @active_req_cnt: Counter for the active request
* @reported_req_id: Last reported request id * @reported_req_id: Last reported request id
@ -268,6 +271,7 @@ struct cam_isp_context {
void *hw_ctx; void *hw_ctx;
uint64_t sof_timestamp_val; uint64_t sof_timestamp_val;
uint64_t last_sof_timestamp;
uint64_t boot_timestamp; uint64_t boot_timestamp;
int32_t active_req_cnt; int32_t active_req_cnt;
int64_t reported_req_id; int64_t reported_req_id;

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/slab.h> #include <linux/slab.h>
@ -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)); 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; camif_debug = g_tfe_hw_mgr.debug_cfg.camif_debug;
list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) { list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) {
for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { 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) 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", g_tfe_hw_mgr.debug_cfg.dentry = debugfs_create_dir("camera_tfe",
NULL); NULL);
@ -5482,6 +5494,14 @@ static int cam_tfe_hw_mgr_debug_register(void)
goto err; 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", if (!debugfs_create_u32("enable_reg_dump",
0644, 0644,
g_tfe_hw_mgr.debug_cfg.dentry, g_tfe_hw_mgr.debug_cfg.dentry,

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #ifndef _CAM_TFE_HW_MGR_H_
@ -30,6 +30,7 @@
* @enable_recovery: enable recovery * @enable_recovery: enable recovery
* @enable_csid_recovery: enable csid recovery * @enable_csid_recovery: enable csid recovery
* @camif_debug: enable sensor diagnosis status * @camif_debug: enable sensor diagnosis status
* @set_tpg_pattern: tpg pattern information
* @enable_reg_dump: enable reg dump on error; * @enable_reg_dump: enable reg dump on error;
* @per_req_reg_dump: Enable per request reg dump * @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_recovery;
uint32_t enable_csid_recovery; uint32_t enable_csid_recovery;
uint32_t camif_debug; uint32_t camif_debug;
uint32_t set_tpg_pattern;
uint32_t enable_reg_dump; uint32_t enable_reg_dump;
uint32_t per_req_reg_dump; uint32_t per_req_reg_dump;
}; };

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <media/cam_defs.h> #include <media/cam_defs.h>
@ -140,6 +140,14 @@ static int cam_isp_update_dual_config(
} }
hw_mgr_res = &res_list_isp_out[i]; 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++) { for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) {
if (!hw_mgr_res->hw_res[j]) if (!hw_mgr_res->hw_res[j])
continue; continue;

View file

@ -3,6 +3,7 @@
obj-$(CONFIG_SPECTRA_CAMERA) += top_tpg/ obj-$(CONFIG_SPECTRA_CAMERA) += top_tpg/
ifdef CONFIG_SPECTRA_CAMERA_TFE ifdef CONFIG_SPECTRA_CAMERA_TFE
obj-$(CONFIG_SPECTRA_CAMERA) += ppi_hw/
obj-$(CONFIG_SPECTRA_CAMERA) += tfe_csid_hw/ tfe_hw/ obj-$(CONFIG_SPECTRA_CAMERA) += tfe_csid_hw/ tfe_hw/
endif endif

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #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_TPG_PHY_CLOCK_UPDATE,
CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP, CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP,
CAM_ISP_HW_CMD_DUMP_HW, CAM_ISP_HW_CMD_DUMP_HW,
CAM_ISP_HW_CMD_TPG_SET_PATTERN,
CAM_ISP_HW_CMD_MAX, CAM_ISP_HW_CMD_MAX,
}; };

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #ifndef _CAM_TOP_TPG_HW_INTF_H_
@ -13,7 +13,8 @@
#define CAM_TOP_TPG_HW_NUM_MAX 2 #define CAM_TOP_TPG_HW_NUM_MAX 2
/* Max supported number of DT for TPG */ /* Max supported number of DT for TPG */
#define CAM_TOP_TPG_MAX_SUPPORTED_DT 4 #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 * enum cam_top_tpg_id - top tpg hw instance id
*/ */

View file

@ -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

View file

@ -0,0 +1,50 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2019, 2021, The Linux Foundation. All rights reserved.
*/
#include <linux/module.h>
#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");

View file

@ -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_ */

View file

@ -0,0 +1,374 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2019, 2021, The Linux Foundation. All rights reserved.
*/
#include <linux/iopoll.h>
#include <linux/slab.h>
#include <media/cam_defs.h>
#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);
}

View file

@ -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_ */

View file

@ -0,0 +1,139 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2019, 2021, The Linux Foundation. All rights reserved.
*/
#include <linux/slab.h>
#include <linux/mod_devicetable.h>
#include <linux/of_device.h>
#include <linux/component.h>
#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);

View file

@ -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_ */

View file

@ -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/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/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/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_smmu/
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #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, .csid_csi2_rx_irq_set_addr = 0x2c,
/*CSI2 rx control */ /*CSI2 rx control */
.phy_sel_base = 1,
.csid_csi2_rx_cfg0_addr = 0x100, .csid_csi2_rx_cfg0_addr = 0x100,
.csid_csi2_rx_cfg1_addr = 0x104, .csid_csi2_rx_cfg1_addr = 0x104,
.csid_csi2_rx_capture_ctrl_addr = 0x108, .csid_csi2_rx_capture_ctrl_addr = 0x108,

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/iopoll.h> #include <linux/iopoll.h>
@ -10,6 +10,7 @@
#include <media/cam_req_mgr.h> #include <media/cam_req_mgr.h>
#include "cam_tfe_csid_core.h" #include "cam_tfe_csid_core.h"
#include "cam_csid_ppi_core.h"
#include "cam_isp_hw.h" #include "cam_isp_hw.h"
#include "cam_soc_util.h" #include "cam_soc_util.h"
#include "cam_io_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; const struct cam_tfe_csid_reg_offset *csid_reg;
struct cam_hw_soc_info *soc_info; 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; uint32_t val = 0;
csid_reg = csid_hw->csid_info->csid_reg; 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 + cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); 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; return 0;
} }
@ -810,6 +837,7 @@ static int cam_tfe_csid_disable_csi2(
{ {
const struct cam_tfe_csid_reg_offset *csid_reg; const struct cam_tfe_csid_reg_offset *csid_reg;
struct cam_hw_soc_info *soc_info; struct cam_hw_soc_info *soc_info;
uint32_t ppi_index = 0, rc;
csid_reg = csid_hw->csid_info->csid_reg; csid_reg = csid_hw->csid_info->csid_reg;
soc_info = &csid_hw->hw_info->soc_info; 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 + cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr); 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; return 0;
} }
@ -2700,13 +2742,15 @@ irqreturn_t cam_tfe_csid_irq(int irq_num, void *data)
unsigned long flags; unsigned long flags;
uint32_t i, val; uint32_t i, val;
csid_hw = (struct cam_tfe_csid_hw *)data;
if (!data) { if (!data) {
CAM_ERR(CAM_ISP, "CSID: Invalid arguments"); CAM_ERR(CAM_ISP, "CSID: Invalid arguments");
return IRQ_HANDLED; 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; csid_reg = csid_hw->csid_info->csid_reg;
soc_info = &csid_hw->hw_info->soc_info; soc_info = &csid_hw->hw_info->soc_info;
csi2_reg = csid_reg->csi2_reg; 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->error_irq_count = 0;
tfe_csid_hw->prev_boot_timestamp = 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; return 0;
err: err:
if (rc) { if (rc) {

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #ifndef _CAM_TFE_CSID_HW_H_
@ -9,6 +9,7 @@
#include "cam_hw.h" #include "cam_hw.h"
#include "cam_tfe_csid_hw_intf.h" #include "cam_tfe_csid_hw_intf.h"
#include "cam_tfe_csid_soc.h" #include "cam_tfe_csid_soc.h"
#include "cam_csid_ppi_core.h"
#define CAM_TFE_CSID_CID_MAX 4 #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; uint32_t csid_csi2_rx_total_crc_err_addr;
/*configurations */ /*configurations */
uint32_t phy_sel_base;
uint32_t csi2_rst_srb_all; uint32_t csi2_rst_srb_all;
uint32_t csi2_rst_done_shift_val; uint32_t csi2_rst_done_shift_val;
uint32_t csi2_irq_mask_all; uint32_t csi2_irq_mask_all;
@ -407,6 +409,9 @@ struct cam_csid_evt_payload {
* @event_cb_priv: Context data * @event_cb_priv: Context data
* @prev_boot_timestamp previous frame bootime stamp * @prev_boot_timestamp previous frame bootime stamp
* @prev_qtimer_ts previous frame qtimer csid timestamp * @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 { struct cam_tfe_csid_hw {
@ -439,6 +444,8 @@ struct cam_tfe_csid_hw {
void *event_cb_priv; void *event_cb_priv;
uint64_t prev_boot_timestamp; uint64_t prev_boot_timestamp;
uint64_t prev_qtimer_ts; 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, int cam_tfe_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf,

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/delay.h> #include <linux/delay.h>
@ -1902,6 +1902,7 @@ static int cam_tfe_camif_resource_start(
uint32_t epoch0_irq_mask; uint32_t epoch0_irq_mask;
uint32_t epoch1_irq_mask; uint32_t epoch1_irq_mask;
uint32_t computed_epoch_line_cfg; uint32_t computed_epoch_line_cfg;
uint32_t camera_hw_version = 0;
if (!camif_res || !core_info) { if (!camif_res || !core_info) {
CAM_ERR(CAM_ISP, "Error Invalid input arguments"); 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, CAM_DBG(CAM_ISP, "TFE:%d core_cfg 0 val:0x%x", core_info->core_index,
val); val);
val = cam_io_r(rsrc_data->mem_base + if (cam_cpas_get_cpas_hw_version(&camera_hw_version))
rsrc_data->common_reg->core_cfg_1); CAM_ERR(CAM_ISP, "Failed to get HW version");
val &= ~BIT(0);
cam_io_w_mb(val, rsrc_data->mem_base + if (camera_hw_version == CAM_CPAS_TITAN_540_V100) {
rsrc_data->common_reg->core_cfg_1); val = cam_io_r(rsrc_data->mem_base +
CAM_DBG(CAM_ISP, "TFE:%d core_cfg 1 val:0x%x", core_info->core_index, rsrc_data->common_reg->core_cfg_1);
val); 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 */ /* Epoch config */
epoch0_irq_mask = ((rsrc_data->last_line - epoch0_irq_mask = ((rsrc_data->last_line -

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/iopoll.h> #include <linux/iopoll.h>
@ -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; const struct cam_top_tpg_reg_offset *tpg_reg;
struct cam_top_tpg_cfg *tpg_data; struct cam_top_tpg_cfg *tpg_data;
uint32_t i, val; uint32_t i, val;
uint32_t in_format = 0;
if (!hw_priv || !start_args || if (!hw_priv || !start_args ||
(arg_size != sizeof(struct cam_isp_resource_node))) { (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, cam_io_w_mb(0x2581F4,
soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg1); 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); val = (1 << tpg_reg->tpg_split_en_shift);
cam_io_w_mb(tpg_data->pix_pattern, soc_info->reg_map[0].mem_base + cam_io_w_mb(tpg_data->pix_pattern, soc_info->reg_map[0].mem_base +
tpg_reg->tpg_common_gen_cfg); 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); soc_info->reg_map[0].mem_base + tpg_reg->tpg_vbi_cfg);
/* Set the TOP tpg mux sel*/ /* 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); 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) << val = ((tpg_data->num_active_lanes - 1) <<
tpg_reg->tpg_num_active_lines_shift) | 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; struct cam_isp_resource_node *tpg_res;
const struct cam_top_tpg_reg_offset *tpg_reg; const struct cam_top_tpg_reg_offset *tpg_reg;
struct cam_top_tpg_cfg *tpg_data; struct cam_top_tpg_cfg *tpg_data;
uint32_t val;
if (!hw_priv || !stop_args || if (!hw_priv || !stop_args ||
(arg_size != sizeof(struct cam_isp_resource_node))) { (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 + cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
tpg_reg->tpg_ctrl); 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; tpg_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
CAM_DBG(CAM_ISP, "TPG:%d stopped", tpg_hw->hw_intf->hw_idx); 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; 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, static int cam_top_tpg_process_cmd(void *hw_priv,
uint32_t cmd_type, void *cmd_args, uint32_t arg_size) 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: case CAM_ISP_HW_CMD_TPG_PHY_CLOCK_UPDATE:
rc = cam_top_tpg_set_phy_clock(tpg_hw, cmd_args); rc = cam_top_tpg_set_phy_clock(tpg_hw, cmd_args);
break; break;
case CAM_ISP_HW_CMD_TPG_SET_PATTERN:
rc = cam_top_tpg_set_top_tpg_pattern(tpg_hw, cmd_args);
break;
default: default:
CAM_ERR(CAM_ISP, "TPG:%d unsupported cmd:%d", CAM_ERR(CAM_ISP, "TPG:%d unsupported cmd:%d",
tpg_hw->hw_intf->hw_idx, cmd_type); tpg_hw->hw_intf->hw_idx, cmd_type);

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #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_payload_mode_color;
uint32_t tpg_split_en_shift; uint32_t tpg_split_en_shift;
uint32_t top_mux_reg_offset; 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 * @hw_info: tpg hw device information
* @tpg_info: tpg hw specific information * @tpg_info: tpg hw specific information
* @tpg_res: tpg resource * @tpg_res: tpg resource
* @tpg_cfg: tpg configuration * @tpg_pattern: tpg pattern configuration
* @clk_rate clock rate * @clk_rate clock rate
* @lock_state lock state * @lock_state lock state
* @tpg_complete tpg completion * @tpg_complete tpg completion
@ -140,6 +141,7 @@ struct cam_top_tpg_hw {
struct cam_hw_info *hw_info; struct cam_hw_info *hw_info;
struct cam_top_tpg_hw_info *tpg_info; struct cam_top_tpg_hw_info *tpg_info;
struct cam_isp_resource_node tpg_res; struct cam_isp_resource_node tpg_res;
uint32_t tpg_pattern;
uint64_t clk_rate; uint64_t clk_rate;
spinlock_t lock_state; spinlock_t lock_state;
struct completion tpg_complete; struct completion tpg_complete;

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #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_payload_mode_color = 0x8,
.tpg_split_en_shift = 5, .tpg_split_en_shift = 5,
.top_mux_reg_offset = 0x1C, .top_mux_reg_offset = 0x1C,
.top_unicolor_bar_shift = 2,
}; };
#endif /*_CAM_TOP_TPG_V1_H_ */ #endif /*_CAM_TOP_TPG_V1_H_ */

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/uaccess.h> #include <linux/uaccess.h>
@ -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 || if ((packet->num_cmd_buf > 5) || !packet->num_patches ||
!packet->num_io_configs) { !packet->num_io_configs ||
CAM_ERR(CAM_JPEG, "wrong number of cmd/patch info: %u %u", (packet->num_io_configs > CAM_JPEG_IMAGE_MAX)) {
packet->num_cmd_buf, CAM_ERR(CAM_JPEG,
packet->num_patches); "wrong number of cmd/patch/io_configs info: %u %u %u",
packet->num_cmd_buf, packet->num_patches,
packet->num_io_configs);
return -EINVAL; return -EINVAL;
} }

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/uaccess.h> #include <linux/uaccess.h>
@ -695,15 +695,14 @@ static int32_t cam_ope_process_request_timer(void *priv, void *data)
} }
CAM_ERR(CAM_OPE, CAM_ERR(CAM_OPE,
"pending requests means, issue is with HW for ctx %d", "pending req at HW, ctx %d lrt %llu lct %llu",
ctx_data->ctx_id);
CAM_ERR(CAM_OPE, "ctx: %d, lrt: %llu, lct: %llu",
ctx_data->ctx_id, ctx_data->last_req_time, ctx_data->ctx_id, ctx_data->last_req_time,
ope_hw_mgr->last_callback_time); ope_hw_mgr->last_callback_time);
hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd( hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd(
hw_mgr->ope_dev_intf[i]->hw_priv, hw_mgr->ope_dev_intf[i]->hw_priv,
OPE_HW_DUMP_DEBUG, OPE_HW_DUMP_DEBUG,
NULL, 0); NULL, 0);
task = cam_req_mgr_workq_get_task(ope_hw_mgr->msg_work); task = cam_req_mgr_workq_get_task(ope_hw_mgr->msg_work);
if (!task) { if (!task) {
CAM_ERR(CAM_OPE, "no empty 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; struct timespec64 ts;
bool flag = false; bool flag = false;
bool dump_flag = true; bool dump_flag = true;
int i;
if (!userdata) { if (!userdata) {
CAM_ERR(CAM_OPE, "Invalid ctx from CDM callback"); 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); ope_req->request_id, ctx->ctx_id);
CAM_INFO(CAM_OPE, "Rst of CDM and OPE for error reqid = %lld", CAM_INFO(CAM_OPE, "Rst of CDM and OPE for error reqid = %lld",
ope_req->request_id); ope_req->request_id);
if (status != CAM_CDM_CB_STATUS_HW_FLUSH) { if (status != CAM_CDM_CB_STATUS_HW_FLUSH) {
cam_ope_dump_req_data(ope_req); cam_ope_dump_req_data(ope_req);
dump_flag = false; 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(); rc = cam_ope_mgr_reset_hw();
flag = true; 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, static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr,
struct cam_packet *packet, 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) 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; struct cam_ope_request *ope_request;
ope_request = ctx_data->req_list[req_idx]; ope_request = ctx_data->req_list[req_idx];
prep_args->num_out_map_entries = 0; prep_arg->num_out_map_entries = 0;
prep_args->num_in_map_entries = 0; prep_arg->num_in_map_entries = 0;
ope_request = ctx_data->req_list[req_idx]; ope_request = ctx_data->req_list[req_idx];
CAM_DBG(CAM_OPE, "E: req_idx = %u %x", req_idx, packet); 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]; io_buf = ope_request->io_buf[i][l];
if (io_buf->direction == CAM_BUF_INPUT) { if (io_buf->direction == CAM_BUF_INPUT) {
if (io_buf->fence != -1) { if (io_buf->fence != -1) {
sync_in_obj[j++] = io_buf->fence; if (j < CAM_MAX_IN_RES) {
prep_args->num_in_map_entries++; 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 { } else {
CAM_ERR(CAM_OPE, "Invalid fence %d %d", CAM_ERR(CAM_OPE, "Invalid fence %d %d",
io_buf->resource_type, io_buf->resource_type,
@ -1784,10 +1800,10 @@ static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr,
} }
} else { } else {
if (io_buf->fence != -1) { if (io_buf->fence != -1) {
prep_args->out_map_entries[k].sync_id = prep_arg->out_map_entries[k].sync_id =
io_buf->fence; io_buf->fence;
k++; k++;
prep_args->num_out_map_entries++; prep_arg->num_out_map_entries++;
} else { } else {
if (io_buf->resource_type if (io_buf->resource_type
!= OPE_OUT_RES_STATS_LTM) { != 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 && if (prep_arg->num_in_map_entries > 1 &&
prep_args->num_in_map_entries <= CAM_MAX_IN_RES) prep_arg->num_in_map_entries <= CAM_MAX_IN_RES)
prep_args->num_in_map_entries = prep_arg->num_in_map_entries =
cam_common_util_remove_duplicate_arr( 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 && if (prep_arg->num_in_map_entries > 1 &&
prep_args->num_in_map_entries <= CAM_MAX_IN_RES) { prep_arg->num_in_map_entries <= CAM_MAX_IN_RES) {
rc = cam_sync_merge(&sync_in_obj[0], 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) { if (rc) {
prep_args->num_out_map_entries = 0; prep_arg->num_out_map_entries = 0;
prep_args->num_in_map_entries = 0; prep_arg->num_in_map_entries = 0;
return rc; return rc;
} }
ope_request->in_resource = merged_sync_in_obj; ope_request->in_resource = merged_sync_in_obj;
prep_args->in_map_entries[0].sync_id = merged_sync_in_obj; prep_arg->in_map_entries[0].sync_id = merged_sync_in_obj;
prep_args->num_in_map_entries = 1; prep_arg->num_in_map_entries = 1;
CAM_DBG(CAM_REQ, "ctx_id: %u req_id: %llu Merged Sync obj: %d", CAM_DBG(CAM_REQ, "ctx_id: %u req_id: %llu Merged Sync obj: %d",
ctx_data->ctx_id, packet->header.request_id, ctx_data->ctx_id, packet->header.request_id,
merged_sync_in_obj); merged_sync_in_obj);
} else if (prep_args->num_in_map_entries == 1) { } else if (prep_arg->num_in_map_entries == 1) {
prep_args->in_map_entries[0].sync_id = sync_in_obj[0]; prep_arg->in_map_entries[0].sync_id = sync_in_obj[0];
prep_args->num_in_map_entries = 1; prep_arg->num_in_map_entries = 1;
ope_request->in_resource = 0; ope_request->in_resource = 0;
CAM_DBG(CAM_OPE, "fence = %d", sync_in_obj[0]); CAM_DBG(CAM_OPE, "fence = %d", sync_in_obj[0]);
} else { } else {
CAM_DBG(CAM_OPE, "Invalid count of input fences, count: %d", CAM_DBG(CAM_OPE, "Invalid count of input fences, count: %d",
prep_args->num_in_map_entries); prep_arg->num_in_map_entries);
prep_args->num_in_map_entries = 0; prep_arg->num_in_map_entries = 0;
ope_request->in_resource = 0; ope_request->in_resource = 0;
rc = -EINVAL; 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; ctx->ctxt_event_cb = args->event_cb;
cam_ope_ctx_clk_info_init(ctx); cam_ope_ctx_clk_info_init(ctx);
ctx->ctx_state = OPE_CTX_STATE_ACQUIRED; 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(&ctx->ctx_mutex);
mutex_unlock(&hw_mgr->hw_mgr_mutex); mutex_unlock(&hw_mgr->hw_mgr_mutex);

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/of.h> #include <linux/of.h>
@ -787,6 +787,11 @@ static uint32_t *ope_create_stripe_cmd(struct cam_ope_hw_mgr *hw_mgr,
uint32_t *print_ptr; uint32_t *print_ptr;
int num_dmi = 0; int num_dmi = 0;
struct cam_cdm_utils_ops *cdm_ops; 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 || if (s_idx >= OPE_MAX_CMD_BUFS ||
batch_idx >= OPE_MAX_BATCH_SIZE) { 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); CAM_DBG(CAM_OPE, "Stripe:%d Indirect:X", stripe_idx);
} }
if (hw_mgr->frame_dump_enable) if (hw_mgr->frame_dump_enable)
dump_stripe_cmd(frm_proc, stripe_idx, i, k, dump_stripe_cmd(frm_proc, stripe_idx, i, k,
iova_addr, kmd_buf, buf_len); 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; return kmd_buf;
} }

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/module.h> #include <linux/module.h>
@ -66,6 +66,7 @@ static int cam_ope_init_hw_version(struct cam_hw_soc_info *soc_info,
switch (core_info->hw_version) { switch (core_info->hw_version) {
case OPE_HW_VER_1_0_0: case OPE_HW_VER_1_0_0:
case OPE_HW_VER_1_1_0:
core_info->ope_hw_info->ope_hw = &ope_hw_100; core_info->ope_hw_info->ope_hw = &ope_hw_100;
break; break;
default: default:

View file

@ -1,12 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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 #ifndef CAM_OPE_HW_H
#define CAM_OPE_HW_H #define CAM_OPE_HW_H
#define OPE_HW_VER_1_0_0 0x10000000 #define OPE_HW_VER_1_0_0 0x10000000
#define OPE_HW_VER_1_1_0 0x10010000
#define OPE_DEV_OPE 0 #define OPE_DEV_OPE 0
#define OPE_DEV_MAX 1 #define OPE_DEV_MAX 1
@ -72,6 +73,7 @@ struct cam_ope_top_reg {
uint32_t violation_status; uint32_t violation_status;
uint32_t throttle_cnt_cfg; uint32_t throttle_cnt_cfg;
uint32_t debug_cfg; uint32_t debug_cfg;
uint32_t scratch_reg;
uint32_t num_debug_registers; uint32_t num_debug_registers;
struct cam_ope_debug_register *debug_regs; struct cam_ope_debug_register *debug_regs;
}; };

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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 #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 = 0xD0,
}, },
{
.offset = 0xD4,
},
}; };
static struct cam_ope_top_reg ope_top_reg = { 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, .violation_status = 0x28,
.throttle_cnt_cfg = 0x2C, .throttle_cnt_cfg = 0x2C,
.debug_cfg = 0xDC, .debug_cfg = 0xDC,
.num_debug_registers = 9, .scratch_reg = 0x1F0,
.num_debug_registers = 10,
.debug_regs = ope_debug_regs, .debug_regs = ope_debug_regs,
}; };

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/of.h> #include <linux/of.h>
@ -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) 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; struct cam_ope_top_reg *top_reg;
top_reg = ope_hw_info->top_reg; top_reg = ope_hw_info->top_reg;
for (i = 0; i < top_reg->num_debug_registers; i++) { for (i = 0; i < top_reg->num_debug_registers; i = i+3) {
val = cam_io_r_mb(top_reg->base + val[0] = cam_io_r_mb(top_reg->base +
top_reg->debug_regs[i].offset); 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; return 0;
} }

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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__ #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); idx = find_first_zero_bit(hdl_tbl->bitmap, hdl_tbl->bits);
if (idx >= CAM_REQ_MGR_MAX_HANDLES_V2 || idx < 0) { 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; return -ENOSR;
} }
@ -123,20 +123,6 @@ static int32_t cam_get_free_handle_index(void)
return idx; 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) int32_t cam_create_session_hdl(void *priv)
{ {
int idx; int idx;
@ -153,7 +139,6 @@ int32_t cam_create_session_hdl(void *priv)
idx = cam_get_free_handle_index(); idx = cam_get_free_handle_index();
if (idx < 0) { if (idx < 0) {
CAM_ERR(CAM_CRM, "Unable to create session handle"); CAM_ERR(CAM_CRM, "Unable to create session handle");
cam_dump_tbl_info();
spin_unlock_bh(&hdl_tbl_lock); spin_unlock_bh(&hdl_tbl_lock);
return idx; return idx;
} }
@ -189,7 +174,6 @@ int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data)
if (idx < 0) { if (idx < 0) {
CAM_ERR(CAM_CRM, CAM_ERR(CAM_CRM,
"Unable to create device handle(idx= %d)", idx); "Unable to create device handle(idx= %d)", idx);
cam_dump_tbl_info();
spin_unlock_bh(&hdl_tbl_lock); spin_unlock_bh(&hdl_tbl_lock);
return idx; return idx;
} }

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */ /* 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_ #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_interrupt_clear0_addr = 0x858,
.mipi_csiphy_glbl_irq_cmd_addr = 0x828, .mipi_csiphy_glbl_irq_cmd_addr = 0x828,
.csiphy_interrupt_status_size = 11, .csiphy_interrupt_status_size = 11,
.csiphy_common_array_size = 6, .csiphy_common_array_size = 7,
.csiphy_reset_array_size = 5, .csiphy_reset_array_size = 5,
.csiphy_2ph_config_array_size = 20, .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_clock_lane = 0x1,
.csiphy_2ph_combo_ck_ln = 0x10, .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}, {0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x081C, 0x02, 0x00, CSIPHY_2PH_REGS}, {0x081C, 0x02, 0x00, CSIPHY_2PH_REGS},
{0x081C, 0x52, 0x00, CSIPHY_3PH_REGS}, {0x081C, 0x52, 0x00, CSIPHY_3PH_REGS},
{0x0800, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x02, 0x00, CSIPHY_2PH_REGS}, {0x0800, 0x02, 0x00, CSIPHY_2PH_REGS},
{0x0800, 0x0E, 0x00, CSIPHY_3PH_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}, {0x0814, 0x00, 0x05, CSIPHY_LANE_ENABLE},
{0x0818, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0818, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x081C, 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}, {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}, {0x0900, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0908, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0908, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0904, 0x00, 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}, {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0034, 0x07, 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}, {0x0000, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_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}, {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0024, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0024, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0800, 0x02, 0x00, CSIPHY_DEFAULT_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}, {0x0C80, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0C88, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C88, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0C84, 0x00, 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}, {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0734, 0x07, 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}, {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x070c, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x070c, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0738, 0x1F, 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}, {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0724, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0724, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0800, 0x02, 0x00, CSIPHY_DEFAULT_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}, {0x0A00, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A04, 0x00, 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}, {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0234, 0x07, 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}, {0x0200, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_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}, {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0224, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0224, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0800, 0x02, 0x00, CSIPHY_DEFAULT_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}, {0x0B00, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B04, 0x00, 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}, {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0434, 0x07, 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}, {0x0400, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_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}, {0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0424, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0424, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0800, 0x02, 0x00, CSIPHY_DEFAULT_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}, {0x0C00, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0C08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0C08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0C04, 0x00, 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}, {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0634, 0x07, 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}, {0x0600, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x060c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x060c, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_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}, {0x0628, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0624, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0624, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
@ -184,7 +185,7 @@ struct csiphy_reg_t
{0x0000, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0000, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_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}, {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0024, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0024, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0800, 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}, {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x070c, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x070c, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0738, 0x1F, 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}, {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0724, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0724, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0800, 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}, {0x0200, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_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}, {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0224, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0224, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0800, 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}, {0x0400, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x040C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x040C, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_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}, {0x0428, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0424, 0x00, 0x00, CSIPHY_DNP_PARAMS}, {0x0424, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0800, 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}, {0x0600, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x060C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x060C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0638, 0x1F, 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}, {0x0628, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0624, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0624, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0884, 0x01, 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}, {0x0990, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0994, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0994, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0998, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0998, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x098C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x098C, 0xAF, 0x01, CSIPHY_DEFAULT_PARAMS},
{0x0168, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x015C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0104, 0x06, 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}, {0x0108, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE},
{0x0114, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0114, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0150, 0x00, 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}, {0x012C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0160, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0160, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x01DC, 0x50, 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}, {0x0984, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x09AC, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x09B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x09B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
}, },
{ {
{0x0A90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A98, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A8C, 0xBF, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A8C, 0xAF, 0x01, CSIPHY_DEFAULT_PARAMS},
{0x0368, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x035C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0304, 0x06, 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}, {0x0308, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE},
{0x0314, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0314, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0350, 0x00, 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}, {0x032C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0360, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0360, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x03DC, 0x50, 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}, {0x0A84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0A80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0AAC, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0AB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0AB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
}, },
{ {
{0x0B90, 0x00, 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}, {0x0B90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B8C, 0xAF, 0x01, CSIPHY_DEFAULT_PARAMS},
{0x0568, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x055C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0504, 0x06, 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}, {0x0508, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE},
{0x0514, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0514, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0550, 0x00, 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}, {0x052C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0560, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0560, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x05DC, 0x50, 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}, {0x0B84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0B80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0BAC, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0BB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x0BB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x0E, 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*/ /* (2.5 * 10**3 * 2.28) rounded value*/
.bandwidth = 5700000000, .bandwidth = 5700000000,
.data_rate_reg_array_size = 12, .data_rate_reg_array_size = 9,
.csiphy_data_rate_regs = { .csiphy_data_rate_regs = {
{0x15C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x164, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x35C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x364, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x55C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x564, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x144, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS},
{0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x344, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS},
{0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x544, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x144, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x344, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x544, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x16C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x36C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x56C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS},
} }
}, },
{ {
/* (3.5 * 10**3 * 2.28) rounded value */ /* (3.5 * 10**3 * 2.28) rounded value */
.bandwidth = 7980000000, .bandwidth = 7980000000,
.data_rate_reg_array_size = 24, .data_rate_reg_array_size = 12,
.csiphy_data_rate_regs = { .csiphy_data_rate_regs = {
{0x15C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x9B4, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS},
{0x35C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xAB4, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS},
{0x55C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xBB4, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS},
{0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS},
{0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS},
{0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x9B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0xAB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0xBB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x16C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x36C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x544, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x56C, 0x1D, 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},
}, },
}, },
{ {
/* (4.5 * 10**3 * 2.28) rounded value */ /* (4.5 * 10**3 * 2.28) rounded value */
.bandwidth = 10260000000, .bandwidth = 10260000000,
.data_rate_reg_array_size = 24, .data_rate_reg_array_size = 12,
.csiphy_data_rate_regs = { .csiphy_data_rate_regs = {
{0x15C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x9B4, 0x02, 0x01, CSIPHY_DEFAULT_PARAMS},
{0x35C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xAB4, 0x02, 0x01, CSIPHY_DEFAULT_PARAMS},
{0x55C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, {0xBB4, 0x02, 0x01, CSIPHY_DEFAULT_PARAMS},
{0x9B4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS},
{0xAB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS},
{0xBB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x9B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0xAB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0xBB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x544, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS}, {0x56C, 0x25, 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},
}, },
} }
} }

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/module.h> #include <linux/module.h>
@ -474,7 +474,6 @@ static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl,
CAM_DBG(CAM_FLASH, "Led_Torch[%d]: Current: %d", CAM_DBG(CAM_FLASH, "Led_Torch[%d]: Current: %d",
i, curr); i, curr);
cam_res_mgr_led_trigger_event( cam_res_mgr_led_trigger_event(
flash_ctrl->torch_trigger[i], curr); 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 cam_flash_off(struct cam_flash_ctrl *flash_ctrl)
{ {
int rc = 0;
if (!flash_ctrl) { if (!flash_ctrl) {
CAM_ERR(CAM_FLASH, "Flash control Null"); CAM_ERR(CAM_FLASH, "Flash control Null");
return -EINVAL; return -EINVAL;
@ -519,6 +520,18 @@ int cam_flash_off(struct cam_flash_ctrl *flash_ctrl)
(enum led_brightness)LED_SWITCH_OFF); (enum led_brightness)LED_SWITCH_OFF);
flash_ctrl->flash_state = CAM_FLASH_STATE_START; 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; 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", CAM_DBG(CAM_FLASH, "top: %llu, del_req_id:%llu",
top, del_req_id); 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); 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_list *i2c_list;
struct i2c_settings_array *i2c_set = NULL; struct i2c_settings_array *i2c_set = NULL;
int frame_offset = 0, rc = 0; int frame_offset = 0, rc = 0;
CAM_DBG(CAM_FLASH, "req_id=%llu", req_id);
if (req_id == 0) { if (req_id == 0) {
/* NonRealTime Init settings*/ /* 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, list_for_each_entry(i2c_list,
&(fctrl->i2c_data.init_settings.list_head), &(fctrl->i2c_data.init_settings.list_head),
list) { 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); rc = fctrl->func_tbl.apply_setting(fctrl, 0);
if (rc) { if (rc) {
CAM_ERR(CAM_FLASH, "cannot apply settings rc = %d", rc); CAM_ERR(CAM_FLASH,
"cannot apply settings rc = %d", rc);
return rc; return rc;
} }
@ -1218,6 +1264,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
i2c_reg_settings = i2c_reg_settings =
&fctrl->i2c_data.per_frame[frm_offset]; &fctrl->i2c_data.per_frame[frm_offset];
if (i2c_reg_settings->is_settings_valid == true) { if (i2c_reg_settings->is_settings_valid == true) {
CAM_DBG(CAM_FLASH, "settings already valid");
i2c_reg_settings->request_id = 0; i2c_reg_settings->request_id = 0;
i2c_reg_settings->is_settings_valid = false; i2c_reg_settings->is_settings_valid = false;
goto update_req_mgr; 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"); "Failed in parsing i2c packets");
return rc; 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; break;
} }
case CAM_FLASH_PACKET_OPCODE_NON_REALTIME_SET_OPS: { 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; return rc;
} }
case CAM_PKT_NOP_OPCODE: { case CAM_PKT_NOP_OPCODE: {
frm_offset = csl_packet->header.request_id %
MAX_PER_FRAME_ARRAY;
if ((fctrl->flash_state == CAM_FLASH_STATE_INIT) || if ((fctrl->flash_state == CAM_FLASH_STATE_INIT) ||
(fctrl->flash_state == CAM_FLASH_STATE_ACQUIRE)) { (fctrl->flash_state == CAM_FLASH_STATE_ACQUIRE)) {
CAM_WARN(CAM_FLASH, CAM_WARN(CAM_FLASH,
"Rxed NOP packets without linking"); "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 fctrl->i2c_data.per_frame[frm_offset].is_settings_valid
= false; = false;
return 0; 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", CAM_DBG(CAM_FLASH, "NOP Packet is Received: req_id: %u",
csl_packet->header.request_id); csl_packet->header.request_id);
goto update_req_mgr; 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: default:
CAM_ERR(CAM_FLASH, "Wrong Opcode : %d", CAM_ERR(CAM_FLASH, "Wrong Opcode : %d",
(csl_packet->header.op_code & 0xFFFFFF)); (csl_packet->header.op_code & 0xFFFFFF));
@ -1827,6 +1913,16 @@ int cam_flash_release_dev(struct cam_flash_ctrl *fctrl)
{ {
int rc = 0; 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) { if (fctrl->bridge_intf.device_hdl != 1) {
rc = cam_destroy_device_hdl(fctrl->bridge_intf.device_hdl); rc = cam_destroy_device_hdl(fctrl->bridge_intf.device_hdl);
if (rc) 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.link_hdl = -1;
fctrl->bridge_intf.session_hdl = -1; fctrl->bridge_intf.session_hdl = -1;
fctrl->last_flush_req = 0; fctrl->last_flush_req = 0;
fctrl->streamoff_count = 0;
} }
return rc; return rc;

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/module.h> #include <linux/module.h>
@ -71,6 +71,7 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
flash_acq_dev.device_handle; flash_acq_dev.device_handle;
fctrl->bridge_intf.session_hdl = fctrl->bridge_intf.session_hdl =
flash_acq_dev.session_handle; flash_acq_dev.session_handle;
fctrl->apply_streamoff = false;
rc = copy_to_user(u64_to_user_ptr(cmd->handle), rc = copy_to_user(u64_to_user_ptr(cmd->handle),
&flash_acq_dev, &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)) if (fctrl->func_tbl.power_ops(fctrl, false))
CAM_WARN(CAM_FLASH, "Power Down Failed"); CAM_WARN(CAM_FLASH, "Power Down Failed");
fctrl->streamoff_count = 0;
fctrl->flash_state = CAM_FLASH_STATE_INIT; fctrl->flash_state = CAM_FLASH_STATE_INIT;
break; 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}; struct cam_flash_query_cap_info flash_cap = {0};
CAM_DBG(CAM_FLASH, "CAM_QUERY_CAP"); 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++) { for (i = 0; i < fctrl->flash_num_sources; i++) {
flash_cap.max_current_flash[i] = flash_cap.max_current_flash[i] =
soc_private->flash_max_current[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; goto release_mutex;
} }
fctrl->apply_streamoff = false;
fctrl->flash_state = CAM_FLASH_STATE_START; fctrl->flash_state = CAM_FLASH_STATE_START;
break; 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) static int32_t cam_flash_platform_probe(struct platform_device *pdev)
{ {
int32_t rc = 0, i = 0; int32_t rc = 0, i = 0;
struct cam_flash_ctrl *fctrl = NULL; struct cam_flash_ctrl *fctrl = NULL;
struct device_node *of_parent = NULL; struct device_node *of_parent = NULL;
struct cam_hw_soc_info *soc_info = NULL;
CAM_DBG(CAM_FLASH, "Enter"); CAM_DBG(CAM_FLASH, "Enter");
if (!pdev->dev.of_node) { 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.pdev = pdev;
fctrl->soc_info.dev = &pdev->dev; fctrl->soc_info.dev = &pdev->dev;
fctrl->soc_info.dev_name = pdev->name; fctrl->soc_info.dev_name = pdev->name;
fctrl->of_node = pdev->dev.of_node;
platform_set_drvdata(pdev, fctrl); 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; fctrl->io_master_info.cci_client->cci_device = fctrl->cci_num;
CAM_DBG(CAM_FLASH, "cci-index %d", fctrl->cci_num, rc); 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 = fctrl->i2c_data.per_frame =
kzalloc(sizeof(struct i2c_settings_array) * kzalloc(sizeof(struct i2c_settings_array) *
MAX_PER_FRAME_ARRAY, GFP_KERNEL); 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.init_settings.list_head));
INIT_LIST_HEAD(&(fctrl->i2c_data.config_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++) for (i = 0; i < MAX_PER_FRAME_ARRAY; i++)
INIT_LIST_HEAD( INIT_LIST_HEAD(
&(fctrl->i2c_data.per_frame[i].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; int32_t rc = 0, i = 0;
struct cam_flash_ctrl *fctrl; struct cam_flash_ctrl *fctrl;
struct cam_hw_soc_info *soc_info = NULL;
if (client == NULL || id == NULL) { if (client == NULL) {
CAM_ERR(CAM_FLASH, "Invalid Args client: %pK id: %pK", CAM_ERR(CAM_FLASH, "Invalid Args client: %pK", client);
client, id);
return -EINVAL; return -EINVAL;
} }
if (id == NULL) {
CAM_DBG(CAM_FLASH, "device id is Null");
}
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
CAM_ERR(CAM_FLASH, "%s :: i2c_check_functionality failed", CAM_ERR(CAM_FLASH, "%s :: i2c_check_functionality failed",
client->name); client->name);
@ -541,22 +571,51 @@ static int32_t cam_flash_i2c_driver_probe(struct i2c_client *client,
/* Create sensor control structure */ /* Create sensor control structure */
fctrl = kzalloc(sizeof(*fctrl), GFP_KERNEL); fctrl = kzalloc(sizeof(*fctrl), GFP_KERNEL);
if (!fctrl) if (!fctrl) {
CAM_ERR(CAM_FLASH, "Failed to allocate memory for fctrl");
return -ENOMEM; return -ENOMEM;
}
i2c_set_clientdata(client, fctrl); i2c_set_clientdata(client, fctrl);
fctrl->io_master_info.client = client; fctrl->io_master_info.client = client;
fctrl->of_node = client->dev.of_node;
fctrl->soc_info.dev = &client->dev; fctrl->soc_info.dev = &client->dev;
fctrl->soc_info.dev_name = client->name; fctrl->soc_info.dev_name = client->name;
fctrl->io_master_info.master_type = I2C_MASTER; 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); rc = cam_flash_get_dt_data(fctrl, &fctrl->soc_info);
if (rc) { if (rc) {
CAM_ERR(CAM_FLASH, "failed: cam_sensor_parse_dt rc %d", rc); CAM_ERR(CAM_FLASH, "failed: cam_sensor_parse_dt rc %d", rc);
goto free_ctrl; 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); rc = cam_flash_init_subdev(fctrl);
if (rc) if (rc)
goto free_ctrl; 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.init_settings.list_head));
INIT_LIST_HEAD(&(fctrl->i2c_data.config_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++) for (i = 0; i < MAX_PER_FRAME_ARRAY; i++)
INIT_LIST_HEAD(&(fctrl->i2c_data.per_frame[i].list_head)); 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, .remove = cam_flash_i2c_driver_remove,
.driver = { .driver = {
.name = FLASH_DRIVER_I2C, .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; int32_t rc = 0;
rc = platform_driver_register(&cam_flash_platform_driver); rc = platform_driver_register(&cam_flash_platform_driver);
if (rc == 0) { if (rc < 0)
CAM_DBG(CAM_FLASH, "platform probe success"); CAM_ERR(CAM_FLASH, "platform probe failed rc: %d", rc);
return 0;
}
rc = i2c_add_driver(&cam_flash_i2c_driver); rc = i2c_add_driver(&cam_flash_i2c_driver);
if (rc) if (rc < 0)
CAM_ERR(CAM_FLASH, "i2c_add_driver failed rc: %d", rc); CAM_ERR(CAM_FLASH, "i2c_add_driver failed rc: %d", rc);
return rc; return rc;
} }

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #ifndef _CAM_FLASH_DEV_H_
@ -24,6 +24,7 @@
#include "cam_subdev.h" #include "cam_subdev.h"
#include "cam_mem_mgr.h" #include "cam_mem_mgr.h"
#include "cam_sensor_cmn_header.h" #include "cam_sensor_cmn_header.h"
#include "cam_sensor_util.h"
#include "cam_soc_util.h" #include "cam_soc_util.h"
#include "cam_debug_util.h" #include "cam_debug_util.h"
#include "cam_sensor_io.h" #include "cam_sensor_io.h"
@ -39,6 +40,7 @@
#define CAM_FLASH_PACKET_OPCODE_INIT 0 #define CAM_FLASH_PACKET_OPCODE_INIT 0
#define CAM_FLASH_PACKET_OPCODE_SET_OPS 1 #define CAM_FLASH_PACKET_OPCODE_SET_OPS 1
#define CAM_FLASH_PACKET_OPCODE_NON_REALTIME_SET_OPS 2 #define CAM_FLASH_PACKET_OPCODE_NON_REALTIME_SET_OPS 2
#define CAM_FLASH_PACKET_OPCODE_STREAM_OFF 3
struct cam_flash_ctrl; struct cam_flash_ctrl;
@ -130,6 +132,7 @@ struct cam_flash_frame_setting {
* @torch_op_current : Torch operational current * @torch_op_current : Torch operational current
* @torch_max_current : Max supported current for LED in torch mode * @torch_max_current : Max supported current for LED in torch mode
* @is_wled_flash : Detection between WLED/LED flash * @is_wled_flash : Detection between WLED/LED flash
* @flash_type : Flash type
*/ */
struct cam_flash_private_soc { 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_op_current[CAM_FLASH_MAX_LED_TRIGGERS];
uint32_t torch_max_current[CAM_FLASH_MAX_LED_TRIGGERS]; uint32_t torch_max_current[CAM_FLASH_MAX_LED_TRIGGERS];
bool is_wled_flash; bool is_wled_flash;
uint32_t flash_type;
}; };
struct cam_flash_func_tbl { struct cam_flash_func_tbl {
@ -179,6 +183,8 @@ struct cam_flash_func_tbl {
* @io_master_info : Information about the communication master * @io_master_info : Information about the communication master
* @i2c_data : I2C register settings * @i2c_data : I2C register settings
* @last_flush_req : last request to flush * @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 { struct cam_flash_ctrl {
char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH]; 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 camera_io_master io_master_info;
struct i2c_data_settings i2c_data; struct i2c_data_settings i2c_data;
uint32_t last_flush_req; 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); int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg);

View file

@ -1,12 +1,13 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/of.h> #include <linux/of.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include "cam_flash_soc.h" #include "cam_flash_soc.h"
#include "cam_res_mgr_api.h" #include "cam_res_mgr_api.h"
#include <dt-bindings/msm/msm-camera.h>
static int32_t cam_get_source_node_info( static int32_t cam_get_source_node_info(
struct device_node *of_node, struct device_node *of_node,
@ -22,6 +23,13 @@ static int32_t cam_get_source_node_info(
soc_private->is_wled_flash = soc_private->is_wled_flash =
of_property_read_bool(of_node, "wled-flash-support"); 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); switch_src_node = of_parse_phandle(of_node, "switch-source", 0);
if (!switch_src_node) { if (!switch_src_node) {
CAM_WARN(CAM_FLASH, "switch_src_node NULL"); 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; rc = -ENOMEM;
goto release_soc_res; 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); rc = cam_soc_util_get_dt_properties(soc_info);
if (rc) { if (rc) {

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/init.h> #include <linux/init.h>
@ -9,6 +9,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/of_gpio.h>
#include "cam_debug_util.h" #include "cam_debug_util.h"
#include "cam_res_mgr_api.h" #include "cam_res_mgr_api.h"
#include "cam_res_mgr_private.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) 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 device_node *of_node = NULL;
struct cam_res_mgr_dt *dt = &cam_res->dt; struct cam_res_mgr_dt *dt = &cam_res->dt;
of_node = dev->of_node; of_node = dev->of_node;
dt->num_shared_gpio = of_property_count_u32_elems(of_node, dt->num_shared_gpio = of_gpio_count(of_node);
"shared-gpios");
if (dt->num_shared_gpio > MAX_SHARED_GPIO_SIZE || if (dt->num_shared_gpio > MAX_SHARED_GPIO_SIZE ||
dt->num_shared_gpio <= 0) { dt->num_shared_gpio <= 0) {
/* /*
@ -624,11 +623,14 @@ static int cam_res_mgr_parse_dt(struct device *dev)
return -EINVAL; return -EINVAL;
} }
rc = of_property_read_u32_array(of_node, "shared-gpios", for (i = 0; i < dt->num_shared_gpio; i++) {
dt->shared_gpio, dt->num_shared_gpio); dt->shared_gpio[i] = of_get_gpio(of_node, i);
if (rc) { if (dt->shared_gpio[i] < 0) {
CAM_ERR(CAM_RES, "Get shared gpio array failed."); CAM_ERR(CAM_RES, "Get shared gpio array failed.");
return -EINVAL; return -EINVAL;
}
CAM_DBG(CAM_UTIL, "shared_gpio[%d] = %d",
i, dt->shared_gpio[i]);
} }
dt->pinctrl_info.pinctrl = devm_pinctrl_get(dev); dt->pinctrl_info.pinctrl = devm_pinctrl_get(dev);

View file

@ -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 //add by hzt 2021-9-4 for control external gpio
power_info->imx582_avdd18_gpio=s_ctrl->imx582_avdd18_gpio; power_info->imx582_avdd18_gpio=s_ctrl->imx582_avdd18_gpio;
//add by hzt 2021-9-4 for control external 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); rc = cam_sensor_core_power_up(power_info, soc_info);
if (rc < 0) { if (rc < 0) {
CAM_ERR(CAM_SENSOR, "power up the core is failed:%d", rc); CAM_ERR(CAM_SENSOR, "power up the core is failed:%d", rc);

View file

@ -114,6 +114,7 @@ struct cam_sensor_ctrl_t {
//add by hzt 2021-9-4 for control external gpio //add by hzt 2021-9-4 for control external gpio
int imx582_avdd18_gpio; int imx582_avdd18_gpio;
//add by hzt 2021-9-4 for control external gpio //add by hzt 2021-9-4 for control external gpio
int imx582_avdd28_gpio;
}; };
#endif /* _CAM_SENSOR_DEV_H_ */ #endif /* _CAM_SENSOR_DEV_H_ */

View file

@ -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 //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_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 //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 */ /* Initialize mutex */

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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" #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); rc = i2c_transfer(dev_client->adapter, msgs, 2);
if (rc < 0) if (rc < 0) {
CAM_ERR(CAM_SENSOR, "failed 0x%x", saddr); 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); rc = i2c_transfer(dev_client->client->adapter, msg, 1);
if (rc < 0) if (rc < 0) {
CAM_ERR(CAM_SENSOR, "failed 0x%x", saddr); 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, int32_t cam_qup_i2c_read(struct i2c_client *client,

View file

@ -319,6 +319,7 @@ struct cam_sensor_power_ctrl_t {
//add by hzt 2021-9-4 for control external gpio //add by hzt 2021-9-4 for control external gpio
int imx582_avdd18_gpio; int imx582_avdd18_gpio;
//add by hzt 2021-9-4 for control external gpio //add by hzt 2021-9-4 for control external gpio
int imx582_avdd28_gpio;
}; };
struct cam_camera_slave_info { struct cam_camera_slave_info {

View file

@ -8,11 +8,11 @@
#include "cam_mem_mgr.h" #include "cam_mem_mgr.h"
#include "cam_res_mgr_api.h" #include "cam_res_mgr_api.h"
//add by hzt 2021-7-1 for debug //add by hzt 2021-7-1 for debug
//#undef CAM_DBG //#undef CAM_DBG
//#define CAM_DBG(fmt,args...) CAM_ERR(fmt,##args) //#define CAM_DBG(fmt,args...) CAM_ERR(fmt,##args)
#define CAM_SENSOR_PINCTRL_STATE_SLEEP "cam_suspend" #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 //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_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 //add by hzt 2021-9-4 control external gpio
return 0; 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); 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 //add by hzt 2021-9-4 for control external gpio
if(power_setting->seq_type==SENSOR_VANA) if(power_setting->seq_type==SENSOR_VANA)
{ {
CAM_DBG(CAM_SENSOR, "before to request imx582_avdd18_gpio:%d,,\n",ctrl->imx582_avdd18_gpio); 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"); ret = gpio_request(ctrl->imx582_avdd18_gpio, "imx582_avdd18_gpio");
if (ret < 0) { 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_set_value_cansleep(ctrl->imx582_avdd18_gpio, 1);
gpio_direction_output(ctrl->imx582_avdd18_gpio,1); gpio_direction_output(ctrl->imx582_avdd18_gpio,1);
gpio_free(ctrl->imx582_avdd18_gpio); 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 //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 //add by hzt 2021-9-4 for control external gpio
if(pd->seq_val==SENSOR_VANA) if(pd->seq_val==SENSOR_VANA)
{ {
CAM_DBG(CAM_SENSOR, "before to request imx582_avdd18_gpio:%d,,\n",ctrl->imx582_avdd18_gpio); 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"); ret = gpio_request(ctrl->imx582_avdd18_gpio, "imx582_avdd18_gpio");
if (ret < 0) { 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_set_value_cansleep(ctrl->imx582_avdd18_gpio, 0);
gpio_direction_output(ctrl->imx582_avdd18_gpio,0); gpio_direction_output(ctrl->imx582_avdd18_gpio,0);
gpio_free(ctrl->imx582_avdd18_gpio); 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 //add by hzt 2021-9-4 control external gpio

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/module.h> #include <linux/module.h>
@ -203,6 +203,8 @@ struct cam_dma_buff_info {
struct cam_sec_buff_info { struct cam_sec_buff_info {
struct dma_buf *buf; struct dma_buf *buf;
struct dma_buf_attachment *attach;
struct sg_table *table;
enum dma_data_direction dir; enum dma_data_direction dir;
int ref_count; int ref_count;
dma_addr_t paddr; 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->dir = dma_dir;
mapping_info->ref_count = 1; mapping_info->ref_count = 1;
mapping_info->buf = dmabuf; 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", CAM_DBG(CAM_SMMU, "idx=%d, ion_fd=%d, dev=%pK, paddr=%pK, len=%u",
idx, ion_fd, 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, struct cam_sec_buff_info *mapping_info,
int idx) int idx)
{ {
if (!mapping_info) { if ((!mapping_info->buf) || (!mapping_info->table) ||
CAM_ERR(CAM_SMMU, "Error: List doesn't exist"); (!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; 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); dma_buf_put(mapping_info->buf);
mapping_info->buf = NULL;
list_del_init(&mapping_info->list); list_del_init(&mapping_info->list);
CAM_DBG(CAM_SMMU, "unmap fd: %d, idx : %d", mapping_info->ion_fd, idx); CAM_DBG(CAM_SMMU, "unmap fd: %d, idx : %d", mapping_info->ion_fd, idx);

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/init.h> #include <linux/init.h>
@ -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), u64_to_user_ptr(k_ioctl->ioctl_ptr),
k_ioctl->size)) k_ioctl->size))
return -EFAULT; return -EFAULT;
sync_create.name[SYNC_DEBUG_NAME_LEN] = '\0';
result = cam_sync_create(&sync_create.sync_obj, result = cam_sync_create(&sync_create.sync_obj,
sync_create.name); sync_create.name);

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* 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__ #ifndef __UAPI_CAM_SENSOR_H__
@ -474,6 +474,7 @@ struct cam_flash_query_curr {
* @max_current_flash : max supported current for flash * @max_current_flash : max supported current for flash
* @max_duration_flash : max flash turn on duration * @max_duration_flash : max flash turn on duration
* @max_current_torch : max supported current for torch * @max_current_torch : max supported current for torch
* @flash_type : Indicates about the flash type -I2C,GPIO,PMIC
* *
*/ */
struct cam_flash_query_cap_info { 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_current_flash[CAM_FLASH_MAX_LED_TRIGGERS];
uint32_t max_duration_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 max_current_torch[CAM_FLASH_MAX_LED_TRIGGERS];
uint32_t flash_type;
} __attribute__ ((packed)); } __attribute__ ((packed));
#endif #endif

View file

@ -70,6 +70,7 @@ msm_drm-$(CONFIG_DRM_MSM_SDE) += sde/sde_crtc.o \
sde/sde_hw_qdss.o \ sde/sde_hw_qdss.o \
sde_dbg.o \ sde_dbg.o \
sde_dbg_evtlog.o \ sde_dbg_evtlog.o \
sde/sde_hw_rc.o \
msm_drm-$(CONFIG_DRM_SDE_WB) += sde/sde_wb.o \ msm_drm-$(CONFIG_DRM_SDE_WB) += sde/sde_wb.o \
sde/sde_encoder_phys_wb.o \ sde/sde_encoder_phys_wb.o \

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/module.h> #include <linux/module.h>
@ -2570,6 +2570,27 @@ static int dp_display_config_hdr(struct dp_display *dp_display, void *panel,
core_clk_rate, flush_hdr); 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, static int dp_display_setup_colospace(struct dp_display *dp_display,
void *panel, void *panel,
u32 colorspace) 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_open = NULL;
g_dp_display->post_init = dp_display_post_init; g_dp_display->post_init = dp_display_post_init;
g_dp_display->config_hdr = dp_display_config_hdr; 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_install = dp_display_mst_install;
g_dp_display->mst_uninstall = dp_display_mst_uninstall; g_dp_display->mst_uninstall = dp_display_mst_uninstall;
g_dp_display->mst_connector_install = dp_display_mst_connector_install; g_dp_display->mst_connector_install = dp_display_mst_connector_install;

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #ifndef _DP_DISPLAY_H_
@ -72,6 +72,7 @@ struct dp_display {
u32 max_pclk_khz; u32 max_pclk_khz;
u32 no_mst_encoder; u32 no_mst_encoder;
void *dp_mst_prv_info; void *dp_mst_prv_info;
bool is_primary;
int (*enable)(struct dp_display *dp_display, void *panel); int (*enable)(struct dp_display *dp_display, void *panel);
int (*post_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); struct drm_connector *connector, char *pps_cmd);
void (*wakeup_phy_layer)(struct dp_display *dp_display, void (*wakeup_phy_layer)(struct dp_display *dp_display,
bool wakeup); bool wakeup);
int (*get_display_type)(struct dp_display *dp_display,
const char **display_type);
}; };
#ifdef CONFIG_DRM_MSM_DP #ifdef CONFIG_DRM_MSM_DP

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <drm/drm_atomic_helper.h> #include <drm/drm_atomic_helper.h>
@ -580,6 +580,19 @@ int dp_connector_get_modes(struct drm_connector *connector,
return rc; 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 dp_drm_bridge_init(void *data, struct drm_encoder *encoder)
{ {
int rc = 0; int rc = 0;

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #ifndef _DP_DRM_H_
@ -177,6 +177,18 @@ int dp_mst_init(struct dp_display *dp_display);
* @display: Pointer to private display structure * @display: Pointer to private display structure
*/ */
void dp_mst_deinit(struct dp_display *dp_display); 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 #else
static inline int dp_connector_config_hdr(struct drm_connector *connector, static inline int dp_connector_config_hdr(struct drm_connector *connector,
void *display, struct sde_connector_state *c_state) 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; 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
#endif /* _DP_DRM_H_ */ #endif /* _DP_DRM_H_ */

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/of_gpio.h> #include <linux/of_gpio.h>
@ -166,6 +166,10 @@ static int dp_parser_misc(struct dp_parser *parser)
if (rc) if (rc)
parser->max_lclk_khz = DP_MAX_LINK_CLK_KHZ; 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; return 0;
} }

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #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 * @max_dp_dsc_input_width_pixs: Maximum input width for DSC block
* @has_widebus: widebus (2PPC) feature eanble status * @has_widebus: widebus (2PPC) feature eanble status
*@mst_fixed_port: mst port_num reserved for fixed topology *@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. * @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: function to be called by client to get io data.
* @get_io_buf: function to be called by client to get io buffers. * @get_io_buf: function to be called by client to get io buffers.
@ -230,6 +231,8 @@ struct dp_parser {
bool lphw_hpd; bool lphw_hpd;
u32 mst_fixed_port[MAX_DP_MST_STREAMS]; u32 mst_fixed_port[MAX_DP_MST_STREAMS];
const char *display_type;
int (*parse)(struct dp_parser *parser); int (*parse)(struct dp_parser *parser);
struct dp_io_data *(*get_io)(struct dp_parser *parser, char *name); struct dp_io_data *(*get_io)(struct dp_parser *parser, char *name);
void (*get_io_buf)(struct dp_parser *parser, char *name); void (*get_io_buf)(struct dp_parser *parser, char *name);

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <linux/delay.h> #include <linux/delay.h>
@ -466,7 +466,6 @@ void set_lcd_vcc_3v3_gpio(int enable){
} }
EXPORT_SYMBOL(set_lcd_vcc_3v3_gpio);//by eric.wang EXPORT_SYMBOL(set_lcd_vcc_3v3_gpio);//by eric.wang
static int dsi_panel_power_on(struct dsi_panel *panel) static int dsi_panel_power_on(struct dsi_panel *panel)
{ {
int rc = 0; int rc = 0;
@ -662,12 +661,29 @@ static int dsi_panel_wled_register(struct dsi_panel *panel,
return 0; 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, static int dsi_panel_update_backlight(struct dsi_panel *panel,
u32 bl_lvl) u32 bl_lvl)
{ {
int rc = 0; int rc = 0;
static int old_bkl = 0; static int old_bkl = 0;
struct mipi_dsi_device *dsi; struct mipi_dsi_device *dsi;
struct dsi_backlight_config *bl;
//DSI_ERR("----------update dcs backlight:%d,by eric.wang------\n", bl_lvl); //DSI_ERR("----------update dcs backlight:%d,by eric.wang------\n", bl_lvl);
if(bl_lvl==0&&old_bkl>0){ if(bl_lvl==0&&old_bkl>0){
set_lcd_vcc_3v3_gpio(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; dsi = &panel->mipi_device;
bl = &panel->bl_config;
if (panel->bl_config.bl_inverted_dbv) if (panel->bl_config.bl_inverted_dbv)
bl_lvl = (((bl_lvl & 0xff) << 8) | (bl_lvl >> 8)); 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) if (rc < 0)
DSI_ERR("failed to update dcs backlight:%d\n", bl_lvl); 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].msg.type = data[0];
cmd[i].last_command = (data[1] == 1); cmd[i].last_command = (data[1] == 1);
cmd[i].msg.channel = data[2]; 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].msg.ctrl = 0;
cmd[i].post_wait_ms = cmd[i].msg.wait_ms = data[4]; cmd[i].post_wait_ms = cmd[i].msg.wait_ms = data[4];
cmd[i].msg.tx_len = ((data[5] << 8) | (data[6])); 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; 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, panel->bl_config.bl_inverted_dbv = utils->read_bool(utils->data,
"qcom,mdss-dsi-bl-inverted-dbv"); "qcom,mdss-dsi-bl-inverted-dbv");

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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_ #ifndef _DSI_PANEL_H_
@ -122,6 +122,7 @@ struct dsi_backlight_config {
u32 bl_scale; u32 bl_scale;
u32 bl_scale_sv; u32 bl_scale_sv;
bool bl_inverted_dbv; bool bl_inverted_dbv;
u32 bl_dcs_subtype;
int en_gpio; int en_gpio;
/* PWM params */ /* PWM params */

View file

@ -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 * Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com> * Author: Rob Clark <robdclark@gmail.com>
* *
@ -61,6 +61,8 @@
#define MSM_VERSION_MINOR 3 #define MSM_VERSION_MINOR 3
#define MSM_VERSION_PATCHLEVEL 0 #define MSM_VERSION_PATCHLEVEL 0
static DEFINE_MUTEX(msm_release_lock);
static void msm_fb_output_poll_changed(struct drm_device *dev) static void msm_fb_output_poll_changed(struct drm_device *dev)
{ {
struct msm_drm_private *priv = NULL; 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) static int msm_release(struct inode *inode, struct file *filp)
{ {
struct drm_file *file_priv = filp->private_data; struct drm_file *file_priv;
struct drm_minor *minor = file_priv->minor; struct drm_minor *minor;
struct drm_device *dev = minor->dev; struct drm_device *dev;
struct msm_drm_private *priv = dev->dev_private; struct msm_drm_private *priv;
struct msm_drm_event *node, *temp, *tmp_node; struct msm_drm_event *node, *temp, *tmp_node;
u32 count; u32 count;
unsigned long flags; unsigned long flags;
LIST_HEAD(tmp_head); 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); spin_lock_irqsave(&dev->event_lock, flags);
list_for_each_entry_safe(node, temp, &priv->client_event_list, 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); 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;
} }
/** /**

View file

@ -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 * Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com> * Author: Rob Clark <robdclark@gmail.com>
* *
@ -138,6 +138,7 @@ enum msm_mdp_crtc_property {
CRTC_PROP_DEST_SCALER_LUT_ED, CRTC_PROP_DEST_SCALER_LUT_ED,
CRTC_PROP_DEST_SCALER_LUT_CIR, CRTC_PROP_DEST_SCALER_LUT_CIR,
CRTC_PROP_DEST_SCALER_LUT_SEP, CRTC_PROP_DEST_SCALER_LUT_SEP,
CRTC_PROP_DSPP_INFO,
/* # of blob properties */ /* # of blob properties */
CRTC_PROP_BLOBCOUNT, CRTC_PROP_BLOBCOUNT,

View file

@ -1,11 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-only // 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__ #define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/dma-buf.h> #include <linux/dma-buf.h>
#include <linux/string.h>
#include <drm/msm_drm_pp.h> #include <drm/msm_drm_pp.h>
#include "sde_color_processing.h" #include "sde_color_processing.h"
#include "sde_kms.h" #include "sde_kms.h"
@ -29,6 +30,7 @@ struct sde_cp_node {
struct list_head active_list; struct list_head active_list;
struct list_head dirty_list; struct list_head dirty_list;
bool is_dspp_feature; bool is_dspp_feature;
bool lm_flush_override;
u32 prop_blob_sz; u32 prop_blob_sz;
struct sde_irq_callback *irq; 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_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_vlut_install_property(struct drm_crtc *crtc);
static void dspp_gamut_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_IGC] = dspp_igc_install_property; \
func[SDE_DSPP_HIST] = dspp_hist_install_property; \ func[SDE_DSPP_HIST] = dspp_hist_install_property; \
func[SDE_DSPP_DITHER] = dspp_dither_install_property; \ func[SDE_DSPP_DITHER] = dspp_dither_install_property; \
func[SDE_DSPP_RC] = dspp_rc_install_property; \
} while (0) } while (0)
typedef void (*lm_prop_install_func_t)(struct drm_crtc *crtc); 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) \ #define setup_lm_prop_install_funcs(func) \
(func[SDE_MIXER_GC] = lm_gc_install_property) (func[SDE_MIXER_GC] = lm_gc_install_property)
enum { enum sde_cp_crtc_features {
/* Append new DSPP features before SDE_CP_CRTC_DSPP_MAX */ /* Append new DSPP features before SDE_CP_CRTC_DSPP_MAX */
/* DSPP Features start */ /* DSPP Features start */
SDE_CP_CRTC_DSPP_IGC, SDE_CP_CRTC_DSPP_IGC,
@ -158,6 +163,7 @@ enum {
SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF2, SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF2,
SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF3, SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF3,
SDE_CP_CRTC_DSPP_LTM_VLUT, SDE_CP_CRTC_DSPP_LTM_VLUT,
SDE_CP_CRTC_DSPP_RC_MASK,
SDE_CP_CRTC_DSPP_MAX, SDE_CP_CRTC_DSPP_MAX,
/* DSPP features end */ /* DSPP features end */
@ -169,12 +175,52 @@ enum {
SDE_CP_CRTC_MAX_FEATURES, 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); 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_hw_cp_cfg *hw_cfg,
struct sde_crtc *hw_crtc); 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, static int set_dspp_vlut_feature(struct sde_hw_dspp *hw_dspp,
struct sde_hw_cp_cfg *hw_cfg, struct sde_hw_cp_cfg *hw_cfg,
struct sde_crtc *hw_crtc) struct sde_crtc *hw_crtc)
@ -655,9 +701,127 @@ static int set_ltm_hist_crtl_feature(struct sde_hw_dspp *hw_dspp,
return ret; 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 { \ do { \
memset(wrappers, 0, sizeof(wrappers)); \ memset(wrappers, 0, sizeof(wrappers)); \
wrappers[SDE_CP_CRTC_DSPP_VLUT] = set_dspp_vlut_feature; \ 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_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_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_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) } while (0)
#define INIT_PROP_ATTACH(p, crtc, prop, node, feature, val) \ #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; 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) 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)) if (IS_ERR(sde_crtc->hist_blob))
sde_crtc->hist_blob = NULL; 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); mutex_init(&sde_crtc->crtc_cp_lock);
INIT_LIST_HEAD(&sde_crtc->active_list); INIT_LIST_HEAD(&sde_crtc->active_list);
INIT_LIST_HEAD(&sde_crtc->dirty_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); spin_lock_init(&sde_crtc->ltm_lock);
INIT_LIST_HEAD(&sde_crtc->ltm_buf_free); INIT_LIST_HEAD(&sde_crtc->ltm_buf_free);
INIT_LIST_HEAD(&sde_crtc->ltm_buf_busy); 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, 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); 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, static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node,
struct sde_crtc *sde_crtc) 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) || 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; ret = -EINVAL;
} else { } else {
set_feature_wrapper set_feature = feature_wrapper set_feature =
crtc_feature_wrappers[prop_node->feature]; set_crtc_feature_wrappers[prop_node->feature];
catalog = get_kms(&sde_crtc->base)->catalog; catalog = get_kms(&sde_crtc->base)->catalog;
hw_cfg.broadcast_disabled = catalog->dma_cfg.broadcast_disabled; 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); 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) void sde_cp_crtc_apply_properties(struct drm_crtc *crtc)
{ {
struct sde_crtc *sde_crtc = NULL; 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_cp_node *prop_node = NULL, *n = NULL;
struct sde_hw_ctl *ctl; struct sde_hw_ctl *ctl;
u32 num_mixers = 0, i = 0; u32 num_mixers = 0, i = 0;
int rc = 0;
bool need_flush = false;
if (!crtc || !crtc->dev) { if (!crtc || !crtc->dev) {
DRM_ERROR("invalid crtc %pK dev %pK\n", crtc, 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; num_mixers = sde_crtc->num_mixers;
if (!num_mixers) { if (!num_mixers) {
DRM_DEBUG_DRIVER("no mixers for this crtc\n"); DRM_ERROR("no mixers for this crtc\n");
return; return;
} }
mutex_lock(&sde_crtc->crtc_cp_lock); 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) && if (list_empty(&sde_crtc->dirty_list) &&
list_empty(&sde_crtc->ad_dirty)) { list_empty(&sde_crtc->ad_dirty) &&
if (list_empty(&sde_crtc->ad_active)) { list_empty(&sde_crtc->ad_active) &&
DRM_DEBUG_DRIVER("Dirty list is empty\n"); list_empty(&sde_crtc->active_list)) {
goto exit; DRM_DEBUG_DRIVER("all lists are empty\n");
} goto exit;
set_dspp_flush = true;
} }
if (!list_empty(&sde_crtc->ad_active)) rc = sde_cp_crtc_set_pu_features(crtc, &need_flush);
sde_cp_ad_set_prop(sde_crtc, AD_IPC_RESET); 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, list_for_each_entry_safe(prop_node, n, &sde_crtc->dirty_list,
dirty_list) { dirty_list) {
sde_cp_crtc_setfeature(prop_node, sde_crtc); sde_cp_crtc_setfeature(prop_node, sde_crtc);
/* Set the flush flag to true */ /* 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; set_dspp_flush = true;
else else
set_lm_flush = true; set_lm_flush = true;
} }
list_for_each_entry_safe(prop_node, n, &sde_crtc->ad_dirty, if (!list_empty(&sde_crtc->ad_active)) {
dirty_list) { sde_cp_ad_set_prop(sde_crtc, AD_IPC_RESET);
set_dspp_flush = true; 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); sde_cp_crtc_setfeature(prop_node, sde_crtc);
set_dspp_flush = true;
} }
for (i = 0; i < num_mixers; i++) { 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); SDE_CP_CRTC_MAX_FEATURES), GFP_KERNEL);
setup_dspp_prop_install_funcs(dspp_prop_install_func); setup_dspp_prop_install_funcs(dspp_prop_install_func);
setup_lm_prop_install_funcs(lm_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) if (!priv->cp_property)
goto exit; 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->dirty_list);
list_del_init(&sde_crtc->ad_active); list_del_init(&sde_crtc->ad_active);
list_del_init(&sde_crtc->ad_dirty); list_del_init(&sde_crtc->ad_dirty);
sde_crtc->cp_pu_feature_mask = 0;
mutex_unlock(&sde_crtc->crtc_cp_lock); mutex_unlock(&sde_crtc->crtc_cp_lock);
spin_lock_irqsave(&sde_crtc->spin_lock, flags); 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) static void lm_gc_install_property(struct drm_crtc *crtc)
{ {
char feature_name[256]; 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); 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);
}

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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 #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, int sde_cp_crtc_set_property(struct drm_crtc *crtc,
struct drm_property *property, uint64_t val); 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 * 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. * @crtc_drm: Pointer to crtc.
*/ */
void sde_cp_mode_switch_prop_dirty(struct drm_crtc *crtc_drm); 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 */ #endif /*_SDE_COLOR_PROCESSING_H */

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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__ #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_ab_quota = max(bw_sum_of_intfs, kms->perf.perf_tune.min_bus_vote);
bus_ib_quota = perf.max_per_pipe_ib[bus_id]; 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) { if (kms->perf.perf_tune.mode == SDE_PERF_MODE_FIXED) {
bus_ab_quota = max(kms->perf.fix_core_ab_vote, bus_ab_quota = max(kms->perf.fix_core_ab_vote,
bus_ab_quota); bus_ab_quota);

View file

@ -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 * Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com> * Author: Rob Clark <robdclark@gmail.com>
* *
@ -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_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), SDE_EVT32_VERBOSE(DRMID(crtc), DRMID(conn),
conn_roi.x, conn_roi.y, conn_roi.x, conn_roi.y,
conn_roi.w, conn_roi.h); 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 */ /* disable clk & bw control until clk & bw properties are set */
cstate->bw_control = false; cstate->bw_control = false;
cstate->bw_split_vote = false; cstate->bw_split_vote = false;
sde_cp_crtc_disable(crtc);
mutex_unlock(&sde_crtc->crtc_lock); mutex_unlock(&sde_crtc->crtc_lock);
} }
@ -4150,7 +4154,7 @@ static void sde_crtc_enable(struct drm_crtc *crtc,
} }
sde_crtc->enabled = true; sde_crtc->enabled = true;
sde_cp_crtc_enable(crtc);
/* update color processing on resume */ /* update color processing on resume */
event.type = DRM_EVENT_CRTC_POWER; event.type = DRM_EVENT_CRTC_POWER;
event.length = sizeof(u32); event.length = sizeof(u32);
@ -4903,6 +4907,12 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
goto end; 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: end:
kfree(pstates); kfree(pstates);
kfree(multirect_plane); 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_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 * sde_crtc_install_properties - install all drm properties for crtc
* @crtc: Pointer to drm crtc structure * @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_src_split", catalog->has_src_split);
sde_kms_info_add_keyint(info, "has_hdr", catalog->has_hdr); _sde_crtc_install_cp_properties(info, catalog);
sde_kms_info_add_keyint(info, "has_hdr_plus", catalog->has_hdr_plus);
if (catalog->perf.max_bw_low) if (catalog->perf.max_bw_low)
sde_kms_info_add_keyint(info, "max_bandwidth_low", sde_kms_info_add_keyint(info, "max_bandwidth_low",
catalog->perf.max_bw_low * 1000LL); catalog->perf.max_bw_low * 1000LL);

View file

@ -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 * Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com> * Author: Rob Clark <robdclark@gmail.com>
* *
@ -276,6 +276,8 @@ struct sde_crtc_misr_info {
* @cur_perf : current performance committed to clock/bandwidth driver * @cur_perf : current performance committed to clock/bandwidth driver
* @plane_mask_old: keeps track of the planes used in the previous commit * @plane_mask_old: keeps track of the planes used in the previous commit
* @frame_trigger_mode: frame trigger mode * @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_buffer_cnt : number of ltm buffers
* @ltm_buffers : struct stores ltm buffer related data * @ltm_buffers : struct stores ltm buffer related data
* @ltm_buf_free : list of LTM buffers that are available * @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 * @ltm_lock : Spinlock to protect ltm buffer_cnt, hist_en and ltm lists
* @needs_hw_reset : Initiate a hw ctl reset * @needs_hw_reset : Initiate a hw ctl reset
* @comp_ratio : Compression ratio * @comp_ratio : Compression ratio
* @dspp_blob_info : blob containing dspp hw capability information
*/ */
struct sde_crtc { struct sde_crtc {
struct drm_crtc base; struct drm_crtc base;
@ -358,6 +361,9 @@ struct sde_crtc {
struct drm_property_blob *hist_blob; struct drm_property_blob *hist_blob;
enum frame_trigger_mode_type frame_trigger_mode; 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; u32 ltm_buffer_cnt;
struct sde_ltm_buffer *ltm_buffers[LTM_BUFFER_SIZE]; struct sde_ltm_buffer *ltm_buffers[LTM_BUFFER_SIZE];
struct list_head ltm_buf_free; struct list_head ltm_buf_free;
@ -369,6 +375,8 @@ struct sde_crtc {
bool needs_hw_reset; bool needs_hw_reset;
int comp_ratio; int comp_ratio;
struct drm_property_blob *dspp_blob_info;
}; };
#define to_sde_crtc(x) container_of(x, struct sde_crtc, base) #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. * @lm_roi : Current LM ROI, possibly sub-rectangle of mode.
* Origin top left of CRTC. * Origin top left of CRTC.
* @user_roi_list : List of user's requested ROIs as from set property * @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 * @property_values: Current crtc property values
* @input_fence_timeout_ns : Cached input fence timeout, in ns * @input_fence_timeout_ns : Cached input fence timeout, in ns
* @num_dim_layers: Number of dim layers * @num_dim_layers: Number of dim layers

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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__ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
@ -383,6 +383,14 @@ enum {
LTM_PROP_MAX, LTM_PROP_MAX,
}; };
enum {
RC_OFF,
RC_LEN,
RC_VERSION,
RC_MEM_TOTAL_SIZE,
RC_PROP_MAX,
};
enum { enum {
MIXER_OFF, MIXER_OFF,
MIXER_LEN, MIXER_LEN,
@ -692,6 +700,13 @@ static struct sde_prop_type ltm_prop[] = {
{LTM_VERSION, "qcom,sde-dspp-ltm-version", false, PROP_TYPE_U32}, {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[] = { static struct sde_prop_type ds_top_prop[] = {
{DS_TOP_OFF, "qcom,sde-dest-scaler-top-off", false, PROP_TYPE_U32}, {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}, {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 rc, prop_count[DSPP_PROP_MAX], i;
int ad_prop_count[AD_PROP_MAX]; 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 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]; bool blocks_prop_exists[DSPP_BLOCKS_PROP_MAX];
struct sde_prop_value *ad_prop_value = NULL, *ltm_prop_value = NULL; 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]; int blocks_prop_count[DSPP_BLOCKS_PROP_MAX];
struct sde_prop_value *prop_value = NULL, *blocks_prop_value = NULL; 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_cfg *dspp;
struct sde_dspp_sub_blks *sblk; struct sde_dspp_sub_blks *sblk;
struct device_node *snp = NULL; struct device_node *snp = NULL;
@ -2426,6 +2442,22 @@ static int sde_dspp_parse_dt(struct device_node *np,
if (rc) if (rc)
goto end; 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 */ /* get DSPP feature dt properties if they exist */
snp = of_get_child_by_name(np, dspp_prop[DSPP_BLOCKS].prop_name); snp = of_get_child_by_name(np, dspp_prop[DSPP_BLOCKS].prop_name);
if (snp) { if (snp) {
@ -2489,6 +2521,22 @@ static int sde_dspp_parse_dt(struct device_node *np,
set_bit(SDE_DSPP_LTM, &dspp->features); 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: end:
@ -2496,6 +2544,8 @@ static int sde_dspp_parse_dt(struct device_node *np,
kfree(ad_prop_value); kfree(ad_prop_value);
kfree(ltm_prop_value); kfree(ltm_prop_value);
kfree(blocks_prop_value); kfree(blocks_prop_value);
kfree(rc_prop_value);
return rc; 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; sde_cfg->allow_gdsc_toggle = true;
clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs); clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs);
clear_bit(MDSS_INTR_AD4_1_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 { } else {
SDE_ERROR("unsupported chipset id:%X\n", hw_rev); SDE_ERROR("unsupported chipset id:%X\n", hw_rev);
sde_cfg->perf.min_prefill_lines = 0xffff; sde_cfg->perf.min_prefill_lines = 0xffff;

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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 #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_630 SDE_HW_VER(6, 3, 0) /* bengal */
#define SDE_HW_VER_640 SDE_HW_VER(6, 4, 0) /* lagoon */ #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_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_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) #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_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_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_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 #define SDE_HW_BLK_NAME_LEN 16
@ -313,6 +315,7 @@ enum {
* @SDE_DSPP_VLUT PA VLUT block * @SDE_DSPP_VLUT PA VLUT block
* @SDE_DSPP_AD AD block * @SDE_DSPP_AD AD block
* @SDE_DSPP_LTM LTM block * @SDE_DSPP_LTM LTM block
* @SDE_DSPP_RC RC block
* @SDE_DSPP_MAX maximum value * @SDE_DSPP_MAX maximum value
*/ */
enum { enum {
@ -328,6 +331,7 @@ enum {
SDE_DSPP_VLUT, SDE_DSPP_VLUT,
SDE_DSPP_AD, SDE_DSPP_AD,
SDE_DSPP_LTM, SDE_DSPP_LTM,
SDE_DSPP_RC,
SDE_DSPP_MAX SDE_DSPP_MAX
}; };
@ -662,6 +666,20 @@ struct sde_lm_sub_blks {
struct sde_pp_blk gc; 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_dspp_sub_blks {
struct sde_pp_blk igc; struct sde_pp_blk igc;
struct sde_pp_blk pcc; struct sde_pp_blk pcc;
@ -675,6 +693,7 @@ struct sde_dspp_sub_blks {
struct sde_pp_blk ad; struct sde_pp_blk ad;
struct sde_pp_blk ltm; struct sde_pp_blk ltm;
struct sde_pp_blk vlut; struct sde_pp_blk vlut;
struct sde_dspp_rc rc;
}; };
struct sde_pingpong_sub_blks { struct sde_pingpong_sub_blks {
@ -1269,6 +1288,7 @@ struct sde_limit_cfg {
* @has_base_layer Supports staging layer as base layer * @has_base_layer Supports staging layer as base layer
* @allow_gdsc_toggle Flag to check if gdsc toggle is needed after crtc is * @allow_gdsc_toggle Flag to check if gdsc toggle is needed after crtc is
* disabled when external vote is present * disabled when external vote is present
* @rc_lm_flush_override Support Rounded Corner using layer mixer flush
* @sc_cfg: system cache configuration * @sc_cfg: system cache configuration
* @uidle_cfg Settings for uidle feature * @uidle_cfg Settings for uidle feature
* @sui_misr_supported indicate if secure-ui-misr is supported * @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 * @has_vig_p010 indicates if vig pipe supports p010 format
* @inline_rot_formats formats supported by the inline rotator feature * @inline_rot_formats formats supported by the inline rotator feature
* @mdss_irqs bitmap with the irqs supported by the target * @mdss_irqs bitmap with the irqs supported by the target
* @rc_count number of rounded corner hardware instances
*/ */
struct sde_mdss_cfg { struct sde_mdss_cfg {
u32 hwversion; u32 hwversion;
@ -1327,6 +1348,7 @@ struct sde_mdss_cfg {
bool update_tcsr_disp_glitch; bool update_tcsr_disp_glitch;
bool has_base_layer; bool has_base_layer;
bool allow_gdsc_toggle; bool allow_gdsc_toggle;
bool rc_lm_flush_override;
struct sde_sc_cfg sc_cfg; struct sde_sc_cfg sc_cfg;
@ -1392,6 +1414,7 @@ struct sde_mdss_cfg {
u32 ad_count; u32 ad_count;
u32 ltm_count; u32 ltm_count;
u32 rc_count;
u32 merge_3d_count; u32 merge_3d_count;
struct sde_merge_3d_cfg merge_3d[MAX_BLOCKS]; 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_WB(s) ((s)->wb)
#define BLK_AD(s) ((s)->ad) #define BLK_AD(s) ((s)->ad)
#define BLK_LTM(s) ((s)->ltm) #define BLK_LTM(s) ((s)->ltm)
#define BLK_RC(s) ((s)->rc)
/** /**
* sde_hw_set_preference: populate the individual hw lm preferences, * sde_hw_set_preference: populate the individual hw lm preferences,

View file

@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only // 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 <drm/msm_drm_pp.h> #include <drm/msm_drm_pp.h>
#include "sde_hw_mdss.h" #include "sde_hw_mdss.h"
#include "sde_hwio.h" #include "sde_hwio.h"
@ -10,6 +11,7 @@
#include "sde_hw_color_processing.h" #include "sde_hw_color_processing.h"
#include "sde_dbg.h" #include "sde_dbg.h"
#include "sde_ad4.h" #include "sde_ad4.h"
#include "sde_hw_rc.h"
#include "sde_kms.h" #include "sde_kms.h"
static struct sde_dspp_cfg *_dspp_offset(enum sde_dspp dspp, 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 (*dspp_blocks[SDE_DSPP_MAX])(struct sde_hw_dspp *c);
static void _init_dspp_ops(void) 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_VLUT] = dspp_vlut;
dspp_blocks[SDE_DSPP_AD] = dspp_ad; dspp_blocks[SDE_DSPP_AD] = dspp_ad;
dspp_blocks[SDE_DSPP_LTM] = dspp_ltm; 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) 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_hw_dspp *c;
struct sde_dspp_cfg *cfg; struct sde_dspp_cfg *cfg;
int rc; int rc;
char buf[256];
if (!addr || !m) if (!addr || !m)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
@ -317,6 +352,13 @@ struct sde_hw_dspp *sde_hw_dspp_init(enum sde_dspp idx,
c->hw.xin_id); 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; return c;
blk_init_error: blk_init_error:

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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 #ifndef _SDE_HW_DSPP_H
@ -209,6 +209,46 @@ struct sde_hw_dspp_ops {
* @status: Pointer to u32 where ltm status value is dumped. * @status: Pointer to u32 where ltm status value is dumped.
*/ */
void (*ltm_read_intr_status)(struct sde_hw_dspp *ctx, u32 *status); 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);
}; };
/** /**

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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 #ifndef _SDE_HW_MDSS_H
@ -171,6 +171,7 @@ enum sde_stage {
SDE_STAGE_10, SDE_STAGE_10,
SDE_STAGE_MAX SDE_STAGE_MAX
}; };
enum sde_dspp { enum sde_dspp {
DSPP_0 = 1, DSPP_0 = 1,
DSPP_1, DSPP_1,
@ -185,6 +186,12 @@ enum sde_ltm {
LTM_MAX LTM_MAX
}; };
enum sde_rc {
RC_0 = DSPP_0,
RC_1,
RC_MAX
};
enum sde_ds { enum sde_ds {
DS_TOP, DS_TOP,
DS_0, DS_0,

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more