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_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
CONFIG_SECURITY=y
CONFIG_HARDENED_USERCOPY=y
CONFIG_HARDENED_USERCOPY_PAGESPAN=y

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

View file

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

View file

@ -13,13 +13,15 @@
//settings macro
#define QUALCOMM //[MTK|QUALCOMM|SPRD]
#define REE //[TEE|REE] //select platform
#define TEE //[TEE|REE] //select platform
#define MALOGD_LEVEL KERN_EMERG //[KERN_DEBUG|KERN_EMERG] usually, the debug level is used for the release version
#define MA_CHR_FILE_NAME "madev0" //do not neeed modify usually
#define MA_CHR_DEV_NAME "madev" //do not neeed modify usually
#define USE_PLATFORM_DRIVE
#define MA_EINT_NAME "afs121_irq"
@ -158,20 +160,26 @@ struct fprint_dev {
//function define
//extern the settings.h function
#ifdef USE_PLATFORM_DRIVE
extern int mas_qcm_platform_init(struct platform_device *spi);
extern int mas_qcm_platform_uninit(struct platform_device *spi);
extern void mas_set_wakeup(struct platform_device *spi);
#else
extern int mas_qcm_platform_init(struct spi_device *spi);
extern int mas_qcm_platform_uninit(struct spi_device *spi);
extern int mas_fingerprint_power(bool flags);
extern void mas_select_transfer(struct spi_device *spi, int len);
extern int mas_finger_get_gpio_info(struct platform_device *pdev);
extern int mas_finger_set_gpio_info(int cmd);
extern void mas_enable_spi_clock(struct spi_device *spi);
extern void mas_disable_spi_clock(struct spi_device *spi);
extern unsigned int mas_get_irq(void);
extern int mas_get_platform(void);
extern int mas_remove_platform(void);
extern void ma_spi_change(struct spi_device *spi, unsigned int speed, int flag);
extern void mas_set_wakeup(struct spi_device *spi);
#endif
extern int mas_fingerprint_power(bool flags);
extern int mas_finger_get_gpio_info(struct platform_device *pdev);
extern int mas_finger_set_gpio_info(int cmd);
extern unsigned int mas_get_irq(void);
extern int mas_get_platform(void);
extern int mas_remove_platform(void);\
extern int mas_get_interrupt_gpio(unsigned int index);
//end

View file

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

View file

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

View file

@ -143,14 +143,14 @@ static struct input_dev *aw9523b_input_dev = NULL;
static struct i2c_client *g_client = NULL;
static const unsigned short key_array[Y_NUM][X_NUM] = {
{ 0xFFFF, KEY_H, KEY_B, KEY_7, KEY_UP, KEY_ENTER, KEY_Y, KEY_COMMA },
{ KEY_3, KEY_S, KEY_Z, KEY_M, KEY_I, KEY_9, KEY_W, KEY_J },
{ KEY_LEFT, KEY_G, KEY_V, KEY_6, KEY_RIGHT, KEY_DELETE, KEY_T, KEY_DOT },
{ KEY_SYM, KEY_A, KEY_RIGHTBRACE, KEY_HOMEPAGE, KEY_P, KEY_MINUS, KEY_Q, KEY_L },
{ KEY_BACKSPACE, KEY_D, KEY_X, KEY_K, KEY_SEMICOLON, KEY_EQUAL, KEY_E, KEY_APOSTROPHE },
{ KEY_CAPSLOCK, KEY_BACKSLASH, KEY_LEFTBRACE, KEY_DOWN, KEY_O, KEY_0, KEY_GRAVE, KEY_K },
{ KEY_SPACE, KEY_F, KEY_C, KEY_N, KEY_U, KEY_8, KEY_R, KEY_5 },
{ KEY_ESC, KEY_1, 0xFFFF, 0xFFFF, KEY_2, KEY_4, KEY_TAB, 0xFFFF }
{ 0xFFFF, KEY_J, KEY_N, KEY_7, KEY_UP, KEY_ENTER, KEY_U, KEY_DOT },
{ KEY_3, KEY_D, KEY_X, KEY_COMMA, KEY_O, KEY_9, KEY_E, KEY_K },
{ KEY_LEFT, KEY_H, KEY_B, KEY_6, KEY_RIGHT, KEY_DELETE, KEY_Y, KEY_SLASH },
{ KEY_SYM, KEY_S, KEY_Z, KEY_HOMEPAGE, KEY_LEFTBRACE, KEY_MINUS, KEY_W, KEY_SEMICOLON },
{ KEY_BACKSPACE, KEY_F, KEY_C, 0xFFFF, KEY_RIGHTBRACE,KEY_EQUAL, KEY_R, KEY_APOSTROPHE },
{ KEY_CAPSLOCK, KEY_A, KEY_GRAVE, KEY_DOWN, KEY_P, KEY_0, KEY_Q, KEY_L },
{ KEY_SPACE, KEY_G, KEY_V, KEY_M, KEY_I, KEY_8, KEY_T, KEY_5 },
{ KEY_ESC, KEY_1, 0xFFFF, 0xFFFF, KEY_2, KEY_4, KEY_TAB, 0xFFFF }
};
// This macro sets the interval between polls of the key matrix for ghosted keys (in milliseconds).
@ -1034,12 +1034,9 @@ static int aw9523b_check_dt(struct device_node *np)
{
int i;
int count;
struct device_node *node;
struct drm_panel *panel;
//需要在屏dts初始化后才能找到panel的字段
count = of_count_phandle_with_args(np, "panel", NULL);

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_READ (0xB1)
#define X_NUM (8) //列
#define Y_NUM (8) //行
#define X_NUM (8) //列
#define Y_NUM (8) //行
//i2c tranfer ,repeat try times
#define AW9523_I2C_MAX_LOOP (50)

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

View file

@ -62,7 +62,7 @@ static void scm_disable_sdi(void);
* There is no API from TZ to re-enable the registers.
* So the SDI cannot be re-enabled when it already by-passed.
*/
static int download_mode = 0;
static int download_mode = 1;
static struct kobject dload_kobj;
static int in_panic;

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

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);
/* config 0x154A to 0x17 */
if (stat & (SNK_RP_STD_DAM_BIT | SNK_RP_1P5_DAM_BIT | SNK_RP_3P0_DAM_BIT)){
smblib_masked_write(chg, TYPE_C_DEBUG_ACCESS_SINK_REG,
TYPEC_DEBUG_ACCESS_SINK_MASK, 0x17);
}
switch (stat & DETECTED_SRC_TYPE_MASK) {
case SNK_RP_STD_BIT:
case SNK_RP_STD_DAM_BIT:
@ -5628,10 +5622,6 @@ void smblib_usb_plugin_locked(struct smb_charger *chg)
smblib_err(chg, "Couldn't disable DPDM rc=%d\n", rc);
smblib_update_usb_type(chg);
if(chg->use_extcon)
smblib_notify_device_mode(chg,false);
vote(chg->usb_icl_votable, USB_PSY_VOTER,false, 0);//remove USB_PSY voting when plugin detach
}
if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB)
@ -5779,7 +5769,6 @@ static void update_sw_icl_max(struct smb_charger *chg, int pst)
/* TypeC rp med or high, use rp value */
typec_mode = smblib_get_prop_typec_mode(chg);
if (typec_rp_med_high(chg, typec_mode)) {
rp_ua = get_rp_based_dcp_current(chg, typec_mode);
vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, rp_ua);
@ -5834,6 +5823,7 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
return;
apsd_result = smblib_update_usb_type(chg);
update_sw_icl_max(chg, apsd_result->pst);
switch (apsd_result->bit) {
@ -6400,6 +6390,7 @@ static void smblib_handle_rp_change(struct smb_charger *chg, int typec_mode)
== FORCE_FLOAT_SDP_CFG_BIT)
return;
}
update_sw_icl_max(chg, apsd->pst);
smblib_dbg(chg, PR_MISC, "CC change old_mode=%d new_mode=%d\n",

View file

@ -3589,6 +3589,13 @@ static int msm_geni_serial_probe(struct platform_device *pdev)
if (!uart_console(uport))
spin_lock_init(&dev_port->rx_lock);
/*
* Earlyconsole to kernel console will switch happen after
* uart_add_one_port. Hence marking is_earlycon to false here.
*/
if (is_console)
is_earlycon = false;
IPC_LOG_MSG(dev_port->ipc_log_misc, "%s: port:%s irq:%d\n", __func__,
uport->name, uport->irq);

View file

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

View file

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

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 */
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_CDM_H_
@ -83,6 +83,7 @@
#define CAM_CDM_RESET_HW_STATUS 0x4
#define CAM_CDM_ERROR_HW_STATUS 0x5
#define CAM_CDM_FLUSH_HW_STATUS 0x6
#define CAM_CDM_RESET_ERR_STATUS 0x7
/* Curent BL command masks and shifts */
#define CAM_CDM_CURRENT_BL_LEN 0xFFFFF
@ -276,6 +277,7 @@ struct cam_cdm_common_reg_data {
* wait, etc.
* @core_en: offset to pause/enable CDM
* @fe_cfg: offset to configure CDM fetch engine
* @irq_context_status offset to read back irq context status
* @bl_fifo_rb: offset to set BL_FIFO read back
* @bl_fifo_base_rb: offset to read back base address on offset set by
* bl_fifo_rb
@ -319,6 +321,7 @@ struct cam_cdm_common_regs {
uint32_t core_cfg;
uint32_t core_en;
uint32_t fe_cfg;
uint32_t irq_context_status;
uint32_t bl_fifo_rb;
uint32_t bl_fifo_base_rb;
uint32_t bl_fifo_len_rb;
@ -374,6 +377,7 @@ enum cam_cdm_hw_process_intf_cmd {
CAM_CDM_HW_INTF_CMD_FLUSH_HW,
CAM_CDM_HW_INTF_CMD_HANDLE_ERROR,
CAM_CDM_HW_INTF_CMD_HANG_DETECT,
CAM_CDM_HW_INTF_DUMP_DBG_REGS,
CAM_CDM_HW_INTF_CMD_INVALID,
};
@ -415,6 +419,7 @@ enum cam_cdm_hw_version {
CAM_CDM_VERSION_1_1 = 0x10010000,
CAM_CDM_VERSION_1_2 = 0x10020000,
CAM_CDM_VERSION_2_0 = 0x20000000,
CAM_CDM_VERSION_2_1 = 0x20010000,
CAM_CDM_VERSION_MAX,
};

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/delay.h>
@ -49,6 +49,7 @@ bool cam_cdm_set_cam_hw_version(
case CAM_CDM110_VERSION:
case CAM_CDM120_VERSION:
case CAM_CDM200_VERSION:
case CAM_CDM210_VERSION:
cam_version->major = (ver & 0xF0000000);
cam_version->minor = (ver & 0xFFF0000);
cam_version->incr = (ver & 0xFFFF);
@ -81,6 +82,7 @@ struct cam_cdm_utils_ops *cam_cdm_get_ops(
case CAM_CDM110_VERSION:
case CAM_CDM120_VERSION:
case CAM_CDM200_VERSION:
case CAM_CDM210_VERSION:
return &CDM170_ops;
default:
CAM_ERR(CAM_CDM, "CDM Version=%x not supported in util",
@ -178,10 +180,12 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
(struct cam_cdm_bl_cb_request_entry *)data;
client_idx = CAM_CDM_GET_CLIENT_IDX(node->client_hdl);
mutex_lock(&cdm_hw->hw_mutex);
client = core->clients[client_idx];
if ((!client) || (client->handle != node->client_hdl)) {
CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client,
node->client_hdl);
mutex_unlock(&cdm_hw->hw_mutex);
return;
}
cam_cdm_get_client_refcount(client);
@ -200,6 +204,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
}
mutex_unlock(&client->lock);
cam_cdm_put_client_refcount(client);
mutex_unlock(&cdm_hw->hw_mutex);
return;
} else if (status == CAM_CDM_CB_STATUS_HW_RESET_DONE ||
status == CAM_CDM_CB_STATUS_HW_FLUSH ||
@ -215,7 +220,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
if ((!client) || (client->handle != node->client_hdl)) {
CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client,
node->client_hdl);
return;
return;
}
cam_cdm_get_client_refcount(client);
mutex_lock(&client->lock);
@ -237,6 +242,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
for (i = 0; i < CAM_PER_CDM_MAX_REGISTERED_CLIENTS; i++) {
if (core->clients[i] != NULL) {
mutex_lock(&cdm_hw->hw_mutex);
client = core->clients[i];
cam_cdm_get_client_refcount(client);
mutex_lock(&client->lock);
@ -259,6 +265,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
}
mutex_unlock(&client->lock);
cam_cdm_put_client_refcount(client);
mutex_unlock(&cdm_hw->hw_mutex);
}
}
}
@ -318,35 +325,34 @@ int cam_cdm_stream_ops_internal(void *hw_priv,
return -EINVAL;
core = (struct cam_cdm *)cdm_hw->core_info;
mutex_lock(&cdm_hw->hw_mutex);
client_idx = CAM_CDM_GET_CLIENT_IDX(*handle);
client = core->clients[client_idx];
if (!client) {
CAM_ERR(CAM_CDM, "Invalid client %pK hdl=%x", client, *handle);
mutex_unlock(&cdm_hw->hw_mutex);
return -EINVAL;
}
cam_cdm_get_client_refcount(client);
if (*handle != client->handle) {
CAM_ERR(CAM_CDM, "client id given handle=%x invalid", *handle);
cam_cdm_put_client_refcount(client);
return -EINVAL;
rc = -EINVAL;
goto end;
}
if (operation == true) {
if (true == client->stream_on) {
CAM_ERR(CAM_CDM,
"Invalid CDM client is already streamed ON");
cam_cdm_put_client_refcount(client);
return rc;
goto end;
}
} else {
if (client->stream_on == false) {
CAM_ERR(CAM_CDM,
"Invalid CDM client is already streamed Off");
cam_cdm_put_client_refcount(client);
return rc;
goto end;
}
}
mutex_lock(&cdm_hw->hw_mutex);
if (operation == true) {
if (!cdm_hw->open_count) {
struct cam_ahb_vote ahb_vote;
@ -817,6 +823,22 @@ int cam_cdm_process_cmd(void *hw_priv,
rc = cam_hw_cdm_hang_detect(cdm_hw, *handle);
break;
}
case CAM_CDM_HW_INTF_DUMP_DBG_REGS:
{
uint32_t *handle = cmd_args;
if (sizeof(uint32_t) != arg_size) {
CAM_ERR(CAM_CDM,
"Invalid CDM cmd %d size=%x for handle=0x%x",
cmd, arg_size, *handle);
return -EINVAL;
}
mutex_lock(&cdm_hw->hw_mutex);
cam_hw_cdm_dump_core_debug_registers(cdm_hw, true);
mutex_unlock(&cdm_hw->hw_mutex);
break;
}
default:
CAM_ERR(CAM_CDM, "CDM HW intf command not valid =%d", cmd);
break;

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_CDM_CORE_COMMON_H_
@ -12,6 +12,7 @@
#define CAM_CDM110_VERSION 0x10010000
#define CAM_CDM120_VERSION 0x10020000
#define CAM_CDM200_VERSION 0x20000000
#define CAM_CDM210_VERSION 0x20010000
#define CAM_CDM_AHB_BURST_LEN_1 (BIT(1) - 1)
#define CAM_CDM_AHB_BURST_LEN_4 (BIT(2) - 1)
@ -55,5 +56,7 @@ struct cam_cdm_bl_cb_request_entry *cam_cdm_find_request_by_bl_tag(
uint32_t tag, struct list_head *bl_list);
void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
enum cam_cdm_cb_status status, void *data);
void cam_hw_cdm_dump_core_debug_registers(
struct cam_hw_info *cdm_hw, bool pause_core);
#endif /* _CAM_CDM_CORE_COMMON_H_ */

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/delay.h>
@ -22,6 +22,7 @@
#include "cam_cdm_hw_reg_1_1.h"
#include "cam_cdm_hw_reg_1_2.h"
#include "cam_cdm_hw_reg_2_0.h"
#include "cam_cdm_hw_reg_2_1.h"
#include "cam_trace.h"
#include "cam_req_mgr_workq.h"
@ -60,6 +61,19 @@ static const struct of_device_id msm_cam_hw_cdm_dt_match[] = {
.compatible = CAM_HW_CDM_OPE_NAME_2_0,
.data = &cam_cdm_2_0_reg_offset,
},
{
.compatible = CAM_HW_CDM_CPAS_NAME_2_1,
.data = &cam_cdm_2_1_reg_offset,
},
{
.compatible = CAM_HW_CDM_OPE_NAME_2_1,
.data = &cam_cdm_2_1_reg_offset,
},
{
.compatible = CAM_HW_CDM_IFE_NAME_2_1,
.data = &cam_cdm_2_1_reg_offset,
},
{},
};
static enum cam_cdm_id cam_hw_cdm_get_id_by_name(char *name)
@ -85,6 +99,15 @@ static enum cam_cdm_id cam_hw_cdm_get_id_by_name(char *name)
if (strnstr(name, CAM_HW_CDM_OPE_NAME_2_0,
strlen(CAM_HW_CDM_CPAS_NAME_2_0)))
return CAM_CDM_OPE;
if (strnstr(name, CAM_HW_CDM_CPAS_NAME_2_1,
strlen(CAM_HW_CDM_CPAS_NAME_2_1)))
return CAM_CDM_CPAS;
if (strnstr(name, CAM_HW_CDM_OPE_NAME_2_1,
strlen(CAM_HW_CDM_OPE_NAME_2_1)))
return CAM_CDM_OPE;
if (strnstr(name, CAM_HW_CDM_IFE_NAME_2_1,
strlen(CAM_HW_CDM_IFE_NAME_2_1)))
return CAM_CDM_IFE;
return CAM_CDM_MAX;
}
@ -147,14 +170,14 @@ static int cam_hw_cdm_pause_core(struct cam_hw_info *cdm_hw, bool pause)
return rc;
}
int cam_hw_cdm_enable_core_dbg(struct cam_hw_info *cdm_hw)
int cam_hw_cdm_enable_core_dbg(struct cam_hw_info *cdm_hw, uint32_t value)
{
int rc = 0;
struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info;
if (cam_cdm_write_hw_reg(cdm_hw,
core->offsets->cmn_reg->core_debug,
0x10100)) {
value)) {
CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug");
rc = -EIO;
}
@ -241,24 +264,7 @@ int cam_hw_cdm_bl_fifo_pending_bl_rb_in_fifo(
return rc;
}
int cam_hw_cdm_enable_core_dbg_per_fifo(
struct cam_hw_info *cdm_hw,
uint32_t fifo_idx)
{
int rc = 0;
struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info;
if (cam_cdm_write_hw_reg(cdm_hw,
core->offsets->cmn_reg->core_debug,
(0x10100 | fifo_idx << 20))) {
CAM_ERR(CAM_CDM, "Failed to Write CDM HW core debug");
rc = -EIO;
}
return rc;
}
void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw)
static void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw)
{
struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info;
int i, j;
@ -267,13 +273,7 @@ void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw)
for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) {
cam_hw_cdm_bl_fifo_pending_bl_rb_in_fifo(cdm_hw,
i, &num_pending_req);
if (cam_hw_cdm_enable_core_dbg_per_fifo(cdm_hw, i)) {
CAM_ERR(CAM_CDM,
"Problem in selecting the fifo for readback");
continue;
}
for (j = 0 ; j < num_pending_req ; j++) {
for (j = 0; j < num_pending_req ; j++) {
cam_cdm_write_hw_reg(cdm_hw,
core->offsets->cmn_reg->bl_fifo_rb, j);
cam_cdm_read_hw_reg(cdm_hw,
@ -294,89 +294,152 @@ void cam_hw_cdm_dump_bl_fifo_data(struct cam_hw_info *cdm_hw)
}
}
void cam_hw_cdm_dump_core_debug_registers(
struct cam_hw_info *cdm_hw)
void cam_hw_cdm_dump_core_debug_registers(struct cam_hw_info *cdm_hw,
bool pause_core)
{
uint32_t dump_reg, core_dbg;
uint32_t dump_reg[4], core_dbg = 0x100;
int i;
bool is_core_paused_already;
struct cam_cdm *core = (struct cam_cdm *)cdm_hw->core_info;
const struct cam_cdm_icl_regs *inv_cmd_log =
core->offsets->cmn_reg->icl_reg;
cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en, &dump_reg);
CAM_INFO(CAM_CDM, "CDM HW core status=%x", dump_reg);
cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->core_en,
&dump_reg[0]);
if (pause_core) {
cam_hw_cdm_pause_core(cdm_hw, true);
usleep_range(1000, 1010);
}
cam_hw_cdm_enable_core_dbg(cdm_hw, core_dbg);
cam_cdm_read_hw_reg(cdm_hw, core->offsets->cmn_reg->usr_data,
&dump_reg);
CAM_INFO(CAM_CDM, "CDM HW core userdata=0x%x", dump_reg);
usleep_range(1000, 1010);
&dump_reg[1]);
cam_cdm_read_hw_reg(cdm_hw,
core->offsets->cmn_reg->debug_status,
&dump_reg);
CAM_INFO(CAM_CDM, "CDM HW Debug status reg=%x", dump_reg);
cam_cdm_read_hw_reg(cdm_hw,
core->offsets->cmn_reg->core_debug,
&core_dbg);
&dump_reg[2]);
CAM_INFO(CAM_CDM, "Core stat 0x%x udata 0x%x dbg_stat 0x%x",
dump_reg[0], dump_reg[1], dump_reg[2]);
if (core_dbg & 0x100) {
cam_cdm_read_hw_reg(cdm_hw,
core->offsets->cmn_reg->last_ahb_addr,
&dump_reg);
CAM_INFO(CAM_CDM, "AHB dump reglastaddr=%x", dump_reg);
&dump_reg[0]);
cam_cdm_read_hw_reg(cdm_hw,
core->offsets->cmn_reg->last_ahb_data,
&dump_reg);
CAM_INFO(CAM_CDM, "AHB dump reglastdata=%x", dump_reg);
&dump_reg[1]);
CAM_INFO(CAM_CDM, "AHB dump lastaddr=0x%x lastdata=0x%x",
dump_reg[0], dump_reg[1]);
} else {
CAM_INFO(CAM_CDM, "CDM HW AHB dump not enable");
}
cam_hw_cdm_dump_bl_fifo_data(cdm_hw);
if (inv_cmd_log) {
if (inv_cmd_log->misc_regs) {
cam_cdm_read_hw_reg(cdm_hw,
inv_cmd_log->misc_regs->icl_status,
&dump_reg[0]);
cam_cdm_read_hw_reg(cdm_hw,
inv_cmd_log->misc_regs->icl_inv_bl_addr,
&dump_reg[1]);
CAM_INFO(CAM_CDM,
"Last Inv Cmd Log(ICL)Status: 0x%x bl_addr: 0x%x",
dump_reg[0], dump_reg[1]);
}
if (inv_cmd_log->data_regs) {
cam_cdm_read_hw_reg(cdm_hw,
inv_cmd_log->data_regs->icl_inv_data,
&dump_reg[0]);
CAM_INFO(CAM_CDM, "First word of Last Inv cmd: 0x%x",
dump_reg[0]);
cam_cdm_read_hw_reg(cdm_hw,
inv_cmd_log->data_regs->icl_last_data_0,
&dump_reg[0]);
cam_cdm_read_hw_reg(cdm_hw,
inv_cmd_log->data_regs->icl_last_data_1,
&dump_reg[1]);
cam_cdm_read_hw_reg(cdm_hw,
inv_cmd_log->data_regs->icl_last_data_2,
&dump_reg[2]);
CAM_INFO(CAM_CDM, "Last good cmd word 0x%x 0x%x 0x%x",
dump_reg[0], dump_reg[1], dump_reg[2]);
}
}
if (core_dbg & 0x10000) {
cam_cdm_read_hw_reg(cdm_hw,
core->offsets->cmn_reg->core_en, &dump_reg[0]);
is_core_paused_already = (bool)(dump_reg[0] & 0x20);
if (!is_core_paused_already) {
cam_hw_cdm_pause_core(cdm_hw, true);
usleep_range(1000, 1010);
}
cam_hw_cdm_dump_bl_fifo_data(cdm_hw);
if (!is_core_paused_already)
cam_hw_cdm_pause_core(cdm_hw, false);
}
CAM_INFO(CAM_CDM, "CDM HW default dump");
cam_cdm_read_hw_reg(cdm_hw,
core->offsets->cmn_reg->core_cfg, &dump_reg);
CAM_INFO(CAM_CDM, "CDM HW core cfg=%x", dump_reg);
core->offsets->cmn_reg->core_cfg, &dump_reg[0]);
CAM_INFO(CAM_CDM, "CDM HW core cfg=0x%x", dump_reg[0]);
for (i = 0; i <
core->offsets->reg_data->num_bl_fifo_irq;
i++) {
cam_cdm_read_hw_reg(cdm_hw,
core->offsets->irq_reg[i]->irq_status, &dump_reg);
CAM_INFO(CAM_CDM, "CDM HW irq status%d=%x", i, dump_reg);
core->offsets->irq_reg[i]->irq_status, &dump_reg[0]);
cam_cdm_read_hw_reg(cdm_hw,
core->offsets->irq_reg[i]->irq_set, &dump_reg);
CAM_INFO(CAM_CDM, "CDM HW irq set%d=%x", i, dump_reg);
core->offsets->irq_reg[i]->irq_set, &dump_reg[1]);
cam_cdm_read_hw_reg(cdm_hw,
core->offsets->irq_reg[i]->irq_mask, &dump_reg);
CAM_INFO(CAM_CDM, "CDM HW irq mask%d=%x", i, dump_reg);
core->offsets->irq_reg[i]->irq_mask, &dump_reg[2]);
cam_cdm_read_hw_reg(cdm_hw,
core->offsets->irq_reg[i]->irq_clear, &dump_reg);
CAM_INFO(CAM_CDM, "CDM HW irq clear%d=%x", i, dump_reg);
core->offsets->irq_reg[i]->irq_clear, &dump_reg[3]);
CAM_INFO(CAM_CDM,
"cnt %d irq status 0x%x set 0x%x mask 0x%x clear 0x%x",
i, dump_reg[0], dump_reg[1], dump_reg[2], dump_reg[3]);
}
cam_cdm_read_hw_reg(cdm_hw,
core->offsets->cmn_reg->current_bl_base, &dump_reg);
CAM_INFO(CAM_CDM, "CDM HW current BL base=%x", dump_reg);
core->offsets->cmn_reg->current_bl_base, &dump_reg[0]);
cam_cdm_read_hw_reg(cdm_hw,
core->offsets->cmn_reg->current_used_ahb_base, &dump_reg[1]);
CAM_INFO(CAM_CDM, "curr BL base 0x%x AHB base 0x%x",
dump_reg[0], dump_reg[1]);
cam_cdm_read_hw_reg(cdm_hw,
core->offsets->cmn_reg->current_bl_len, &dump_reg);
core->offsets->cmn_reg->wait_status, &dump_reg[0]);
cam_cdm_read_hw_reg(cdm_hw,
core->offsets->cmn_reg->comp_wait[0]->comp_wait_status,
&dump_reg[1]);
cam_cdm_read_hw_reg(cdm_hw,
core->offsets->cmn_reg->comp_wait[1]->comp_wait_status,
&dump_reg[2]);
CAM_INFO(CAM_CDM, "wait status 0x%x comp wait status 0x%x: 0x%x",
dump_reg[0], dump_reg[1], dump_reg[2]);
cam_cdm_read_hw_reg(cdm_hw,
core->offsets->cmn_reg->current_bl_len, &dump_reg[0]);
CAM_INFO(CAM_CDM,
"CDM HW current BL len=%d ARB %d FIFO %d tag=%d, ",
(dump_reg & CAM_CDM_CURRENT_BL_LEN),
(dump_reg & CAM_CDM_CURRENT_BL_ARB) >>
(dump_reg[0] & CAM_CDM_CURRENT_BL_LEN),
(dump_reg[0] & CAM_CDM_CURRENT_BL_ARB) >>
CAM_CDM_CURRENT_BL_ARB_SHIFT,
(dump_reg & CAM_CDM_CURRENT_BL_FIFO) >>
(dump_reg[0] & CAM_CDM_CURRENT_BL_FIFO) >>
CAM_CDM_CURRENT_BL_FIFO_SHIFT,
(dump_reg & CAM_CDM_CURRENT_BL_TAG) >>
(dump_reg[0] & CAM_CDM_CURRENT_BL_TAG) >>
CAM_CDM_CURRENT_BL_TAG_SHIFT);
cam_cdm_read_hw_reg(cdm_hw,
core->offsets->cmn_reg->current_used_ahb_base, &dump_reg);
CAM_INFO(CAM_CDM, "CDM HW current AHB base=%x", dump_reg);
cam_hw_cdm_disable_core_dbg(cdm_hw);
if (pause_core)
cam_hw_cdm_pause_core(cdm_hw, false);
}
enum cam_cdm_arbitration cam_cdm_get_arbitration_type(
@ -1084,11 +1147,15 @@ static void cam_hw_cdm_reset_cleanup(
int i;
struct cam_cdm_bl_cb_request_entry *node, *tnode;
bool flush_hw = false;
bool reset_err = false;
if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status) ||
test_bit(CAM_CDM_FLUSH_HW_STATUS, &core->cdm_status))
flush_hw = true;
if (test_bit(CAM_CDM_ERROR_HW_STATUS, &core->cdm_status))
reset_err = true;
for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++) {
list_for_each_entry_safe(node, tnode,
&core->bl_fifo[i].bl_request_list, entry) {
@ -1097,12 +1164,19 @@ static void cam_hw_cdm_reset_cleanup(
CAM_DBG(CAM_CDM,
"Notifying client %d for tag %d",
node->client_hdl, node->bl_tag);
if (flush_hw)
if (flush_hw) {
enum cam_cdm_cb_status status;
status = reset_err ?
CAM_CDM_CB_STATUS_HW_ERROR :
CAM_CDM_CB_STATUS_HW_RESUBMIT;
cam_cdm_notify_clients(cdm_hw,
(node->client_hdl == handle) ?
CAM_CDM_CB_STATUS_HW_FLUSH :
CAM_CDM_CB_STATUS_HW_RESUBMIT,
status,
(void *)node);
}
else
cam_cdm_notify_clients(cdm_hw,
CAM_CDM_CB_STATUS_HW_RESET_DONE,
@ -1245,7 +1319,7 @@ static void cam_hw_cdm_work(struct work_struct *work)
* to dump debug info
*/
cam_hw_cdm_pause_core(cdm_hw, true);
cam_hw_cdm_dump_core_debug_registers(cdm_hw);
cam_hw_cdm_dump_core_debug_registers(cdm_hw, true);
if (payload->irq_status &
CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK) {
@ -1284,6 +1358,8 @@ static void cam_hw_cdm_work(struct work_struct *work)
CAM_CDM_IRQ_STATUS_ERROR_INV_CMD_MASK))
clear_bit(CAM_CDM_ERROR_HW_STATUS,
&core->cdm_status);
} else {
CAM_ERR(CAM_CDM, "NULL payload");
}
kfree(payload);
payload = NULL;
@ -1306,16 +1382,8 @@ static void cam_hw_cdm_iommu_fault_handler(struct iommu_domain *domain,
for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++)
mutex_lock(&core->bl_fifo[i].fifo_lock);
if (cdm_hw->hw_state == CAM_HW_STATE_POWER_UP) {
/*
* First pause CDM, If it fails still proceed
* to dump debug info
*/
cam_hw_cdm_pause_core(cdm_hw, true);
cam_hw_cdm_dump_core_debug_registers(cdm_hw);
/* Resume CDM back */
cam_hw_cdm_pause_core(cdm_hw, false);
}
else
cam_hw_cdm_dump_core_debug_registers(cdm_hw, true);
} else
CAM_INFO(CAM_CDM, "CDM hw is power in off state");
for (i = 0; i < core->offsets->reg_data->num_bl_fifo; i++)
mutex_unlock(&core->bl_fifo[i].fifo_lock);
@ -1338,17 +1406,28 @@ irqreturn_t cam_hw_cdm_irq(int irq_num, void *data)
struct cam_cdm_work_payload *payload[CAM_CDM_BL_FIFO_MAX] = {0};
uint32_t user_data = 0;
uint32_t irq_status[CAM_CDM_BL_FIFO_MAX] = {0};
uint32_t irq_context_summary = 0xF;
bool work_status;
int i;
CAM_DBG(CAM_CDM, "Got irq");
CAM_DBG(CAM_CDM, "Got irq hw_version 0x%x", cdm_core->hw_version);
spin_lock(&cdm_hw->hw_lock);
if (cdm_hw->hw_state == CAM_HW_STATE_POWER_DOWN) {
CAM_DBG(CAM_CDM, "CDM is in power down state");
spin_unlock(&cdm_hw->hw_lock);
return IRQ_HANDLED;
}
if (cdm_core->hw_version >= CAM_CDM_VERSION_2_1) {
if (cam_cdm_read_hw_reg(cdm_hw,
cdm_core->offsets->cmn_reg->irq_context_status,
&irq_context_summary)) {
CAM_ERR(CAM_CDM, "Failed to read CDM HW IRQ status");
}
}
for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo_irq; i++) {
if (!(BIT(i) & irq_context_summary))
continue;
if (cam_cdm_read_hw_reg(cdm_hw,
cdm_core->offsets->irq_reg[i]->irq_status,
&irq_status[i])) {
@ -1613,7 +1692,7 @@ int cam_hw_cdm_handle_error_info(
current_fifo, current_tag);
/* dump cdm registers for further debug */
cam_hw_cdm_dump_core_debug_registers(cdm_hw);
cam_hw_cdm_dump_core_debug_registers(cdm_hw, false);
for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++) {
reset_val = reset_val |
@ -1639,7 +1718,7 @@ int cam_hw_cdm_handle_error_info(
if (time_left <= 0) {
rc = -ETIMEDOUT;
CAM_ERR(CAM_CDM, "CDM HW reset Wait failed rc=%d", rc);
goto end;
set_bit(CAM_CDM_RESET_ERR_STATUS, &cdm_core->cdm_status);
}
rc = cam_hw_cdm_set_cdm_core_cfg(cdm_hw);
@ -1678,6 +1757,7 @@ int cam_hw_cdm_handle_error_info(
end:
clear_bit(CAM_CDM_FLUSH_HW_STATUS, &cdm_core->cdm_status);
clear_bit(CAM_CDM_RESET_HW_STATUS, &cdm_core->cdm_status);
clear_bit(CAM_CDM_RESET_ERR_STATUS, &cdm_core->cdm_status);
for (i = 0; i < cdm_core->offsets->reg_data->num_bl_fifo; i++)
mutex_unlock(&cdm_core->bl_fifo[i].fifo_lock);

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
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/delay.h>
@ -506,6 +506,32 @@ int cam_cdm_detect_hang_error(uint32_t handle)
}
EXPORT_SYMBOL(cam_cdm_detect_hang_error);
int cam_cdm_dump_debug_registers(uint32_t handle)
{
uint32_t hw_index;
int rc = -EINVAL;
struct cam_hw_intf *hw;
if (get_cdm_mgr_refcount()) {
CAM_ERR(CAM_CDM, "CDM intf mgr get refcount failed");
rc = -EPERM;
return rc;
}
hw_index = CAM_CDM_GET_HW_IDX(handle);
if (hw_index < CAM_CDM_INTF_MGR_MAX_SUPPORTED_CDM) {
hw = cdm_mgr.nodes[hw_index].device;
if (hw && hw->hw_ops.process_cmd)
rc = hw->hw_ops.process_cmd(hw->hw_priv,
CAM_CDM_HW_INTF_DUMP_DBG_REGS,
&handle,
sizeof(handle));
}
put_cdm_mgr_refcount();
return rc;
}
int cam_cdm_intf_register_hw_cdm(struct cam_hw_intf *hw,
struct cam_cdm_private_dt_data *data, enum cam_cdm_type type,
uint32_t *index)

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_CDM_API_H_
@ -296,4 +296,13 @@ struct cam_cdm_utils_ops *cam_cdm_publish_ops(void);
* @return 0 on success
*/
int cam_cdm_detect_hang_error(uint32_t handle);
/**
* @brief : API to dump the CDM Debug registers
*
* @handle : Input handle of the CDM to dump the registers
*
* @return 0 on success
*/
int cam_cdm_dump_debug_registers(uint32_t handle);
#endif /* _CAM_CDM_API_H_ */

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_CDM_SOC_H_
@ -13,6 +13,9 @@
#define CAM_HW_CDM_IFE_NAME_1_2 "qcom,cam-ife-cdm1_2"
#define CAM_HW_CDM_CPAS_NAME_2_0 "qcom,cam-cpas-cdm2_0"
#define CAM_HW_CDM_OPE_NAME_2_0 "qcom,cam-ope-cdm2_0"
#define CAM_HW_CDM_CPAS_NAME_2_1 "qcom,cam-cpas-cdm2_1"
#define CAM_HW_CDM_OPE_NAME_2_1 "qcom,cam-ope-cdm2_1"
#define CAM_HW_CDM_IFE_NAME_2_1 "qcom,cam-ife-cdm2_1"
int cam_hw_cdm_soc_get_dt_properties(struct cam_hw_info *cdm_hw,
const struct of_device_id *table);

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
*/
#include <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);
}
soc_private->custom_id = 0;
rc = of_property_read_u32(of_node,
"custom-id",
&soc_private->custom_id);
if (rc) {
CAM_DBG(CAM_CPAS,
"failed to read camnoc-axi-min-ib-bw rc:%d", rc);

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_CPAS_SOC_H_
@ -109,6 +109,8 @@ struct cam_cpas_feature_info {
* @feature_info: fuse based feature info for hw supported features
* @cx_ipeak_gpu_limit: Flag for Cx Ipeak GPU mitigation
* @gpu_pwr_limit: Handle for Cx Ipeak GPU Mitigation
* @custom_id: Custom id to differentiate between target if
* cpas version is same
*
*/
struct cam_cpas_private_soc {
@ -129,6 +131,7 @@ struct cam_cpas_private_soc {
struct cam_cpas_feature_info feature_info[CAM_CPAS_MAX_FUSE_FEATURE];
uint32_t cx_ipeak_gpu_limit;
struct kgsl_pwr_limit *gpu_pwr_limit;
uint32_t custom_id;
};
void cam_cpas_util_debug_parse_data(struct cam_cpas_private_soc *soc_private);

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/delay.h>
@ -24,6 +24,7 @@
#include "cpastop_v480_100.h"
#include "cpastop_v540_100.h"
#include "cpastop_v520_100.h"
#include "cpastop_v545_110_518.h"
#include "cam_req_mgr_workq.h"
struct cam_camnoc_info *camnoc_info;
@ -133,6 +134,14 @@ static int cam_cpastop_get_hw_info(struct cam_hw_info *cpas_hw,
(hw_caps->camera_version.minor == 2) &&
(hw_caps->camera_version.incr == 0)) {
soc_info->hw_version = CAM_CPAS_TITAN_520_V100;
} else if ((hw_caps->camera_version.major == 5) &&
(hw_caps->camera_version.minor == 4) &&
(hw_caps->camera_version.incr == 5)) {
if ((hw_caps->cpas_version.major == 1) &&
(hw_caps->cpas_version.minor == 1) &&
(hw_caps->cpas_version.incr == 0)) {
soc_info->hw_version = CAM_CPAS_TITAN_545_V110;
}
}
CAM_DBG(CAM_CPAS, "CPAS HW VERSION %x", soc_info->hw_version);
@ -605,6 +614,7 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw,
{
int rc = 0;
struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info;
struct cam_cpas_private_soc *soc_private;
CAM_DBG(CAM_CPAS,
"hw_version=0x%x Camera Version %d.%d.%d, cpas version %d.%d.%d",
@ -647,6 +657,12 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw,
case CAM_CPAS_TITAN_520_V100:
camnoc_info = &cam520_cpas100_camnoc_info;
break;
case CAM_CPAS_TITAN_545_V110:
soc_private = (struct cam_cpas_private_soc *)
soc_info->soc_private;
if (soc_private->custom_id == CAM_CPAS_TITAN_SOC_ID_518)
camnoc_info = &cam545_cpas110_socid518_camnoc_info;
break;
default:
CAM_ERR(CAM_CPAS, "Camera Version not supported %d.%d.%d",
hw_caps->camera_version.major,

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_CPASTOP_HW_H_
@ -107,6 +107,8 @@ enum cam_camnoc_hw_irq_type {
* @CAM_CAMNOC_FD: Indicates FD HW connection to camnoc
* @CAM_CAMNOC_ICP: Indicates ICP HW connection to camnoc
* @CAM_CAMNOC_TFE: Indicates TFE HW connection to camnoc
* @CAM_CAMNOC_TFE_1 : Indicates TFE1 HW connection to camnoc
* @CAM_CAMNOC_TFE_2 : Indicates TFE2 HW connection to camnoc
* @CAM_CAMNOC_OPE: Indicates OPE HW connection to camnoc
*/
enum cam_camnoc_port_type {
@ -131,6 +133,8 @@ enum cam_camnoc_port_type {
CAM_CAMNOC_FD,
CAM_CAMNOC_ICP,
CAM_CAMNOC_TFE,
CAM_CAMNOC_TFE_1,
CAM_CAMNOC_TFE_2,
CAM_CAMNOC_OPE,
};

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 */
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_CPAS_API_H_
@ -48,9 +48,19 @@ enum cam_cpas_hw_version {
CAM_CPAS_TITAN_480_V100 = 0x480100,
CAM_CPAS_TITAN_540_V100 = 0x540100,
CAM_CPAS_TITAN_520_V100 = 0x520100,
CAM_CPAS_TITAN_545_V110 = 0x545110,
CAM_CPAS_TITAN_MAX
};
/**
* enum cam_cpas_hw_soc_id - Enum for Titan soc id
*/
enum cam_cpas_hw_soc_id {
CAM_CPAS_TITAN_SOC_ID_507 = 507,
CAM_CPAS_TITAN_SOC_ID_518 = 518,
CAM_CPAS_TITAN_SOC_ID_MAX
};
/**
* enum cam_camnoc_irq_type - Enum for camnoc irq types
*

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/debugfs.h>
@ -3066,6 +3066,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_applied(
ctx_isp->frame_id,
ctx->ctx_id);
ctx->ctx_crm_intf->notify_err(&notify);
atomic_set(&ctx_isp->process_bubble, 1);
} else {
req_isp->bubble_report = 0;
}
@ -3123,6 +3124,44 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state(
ctx_isp->boot_timestamp = sof_event_data->boot_time;
CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
if (atomic_read(&ctx_isp->process_bubble)) {
if (list_empty(&ctx->active_req_list)) {
CAM_ERR(CAM_ISP, "No available active req in bubble");
atomic_set(&ctx_isp->process_bubble, 0);
return -EINVAL;
}
if (ctx_isp->last_sof_timestamp ==
ctx_isp->sof_timestamp_val) {
CAM_DBG(CAM_ISP,
"Tasklet delay detected! Bubble frame: %lld check skipped, sof_timestamp: %lld, ctx_id: %d",
ctx_isp->frame_id,
ctx_isp->sof_timestamp_val,
ctx->ctx_id);
goto end;
}
req = list_first_entry(&ctx->active_req_list,
struct cam_ctx_request, list);
req_isp = (struct cam_isp_ctx_req *) req->req_priv;
if (req_isp->bubble_detected) {
req_isp->num_acked = 0;
req_isp->bubble_detected = false;
list_del_init(&req->list);
list_add(&req->list, &ctx->pending_req_list);
atomic_set(&ctx_isp->process_bubble, 0);
ctx_isp->active_req_cnt--;
CAM_DBG(CAM_REQ,
"Move active req: %lld to pending list(cnt = %d) [bubble re-apply],ctx %u",
req->request_id,
ctx_isp->active_req_cnt, ctx->ctx_id);
goto end;
}
}
/*
* Signal all active requests with error and move the all the active
* requests to free list
@ -3144,6 +3183,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state(
ctx_isp->active_req_cnt--;
}
end:
/* notify reqmgr with sof signal */
if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) {
notify.link_hdl = ctx->link_hdl;
@ -3174,6 +3214,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state(
__cam_isp_ctx_substate_val_to_type(
ctx_isp->substate_activated));
ctx_isp->last_sof_timestamp = ctx_isp->sof_timestamp_val;
return 0;
}
@ -3426,6 +3467,7 @@ static int __cam_isp_ctx_release_hw_in_top_state(struct cam_context *ctx,
ctx_isp->hw_acquired = false;
ctx_isp->init_received = false;
ctx_isp->req_info.last_bufdone_req_id = 0;
ctx_isp->last_sof_timestamp = 0;
atomic64_set(&ctx_isp->state_monitor_head, -1);
@ -3490,6 +3532,7 @@ static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
ctx_isp->init_received = false;
ctx_isp->rdi_only_context = false;
ctx_isp->req_info.last_bufdone_req_id = 0;
ctx_isp->last_sof_timestamp = 0;
atomic64_set(&ctx_isp->state_monitor_head, -1);
for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++)
@ -3830,6 +3873,7 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
ctx_isp->hw_acquired = true;
ctx_isp->split_acquire = false;
ctx->ctxt_to_hw_map = param.ctxt_to_hw_map;
ctx_isp->last_sof_timestamp = 0;
atomic64_set(&ctx_isp->state_monitor_head, -1);
for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++)
@ -3987,6 +4031,7 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx,
ctx_isp->hw_ctx = param.ctxt_to_hw_map;
ctx_isp->hw_acquired = true;
ctx->ctxt_to_hw_map = param.ctxt_to_hw_map;
ctx_isp->last_sof_timestamp = 0;
atomic64_set(&ctx_isp->state_monitor_head, -1);
@ -4132,6 +4177,7 @@ static int __cam_isp_ctx_acquire_hw_v2(struct cam_context *ctx,
ctx_isp->hw_ctx = param.ctxt_to_hw_map;
ctx_isp->hw_acquired = true;
ctx->ctxt_to_hw_map = param.ctxt_to_hw_map;
ctx_isp->last_sof_timestamp = 0;
trace_cam_context_state("ISP", ctx);
CAM_DBG(CAM_ISP,
@ -4390,9 +4436,11 @@ static int __cam_isp_ctx_start_dev_in_ready(struct cam_context *ctx,
/* HW failure. user need to clean up the resource */
CAM_ERR(CAM_ISP, "Start HW failed");
ctx->state = CAM_CTX_READY;
trace_cam_context_state("ISP", ctx);
if (rc == -ETIMEDOUT)
if ((rc == -ETIMEDOUT) &&
(isp_ctx_debug.enable_cdm_cmd_buff_dump))
rc = cam_isp_ctx_dump_req(req_isp, 0, 0, NULL, false);
trace_cam_context_state("ISP", ctx);
list_del_init(&req->list);
list_add(&req->list, &ctx->pending_req_list);
goto end;
@ -4953,8 +5001,15 @@ static int cam_isp_context_debug_register(void)
goto err;
}
return 0;
if (!debugfs_create_u32("enable_cdm_cmd_buffer_dump",
0644,
isp_ctx_debug.dentry,
&isp_ctx_debug.enable_cdm_cmd_buff_dump)) {
CAM_ERR(CAM_ISP, "failed to create enable_cdm_cmd_buffer_dump");
goto err;
}
return 0;
err:
debugfs_remove_recursive(isp_ctx_debug.dentry);
return -ENOMEM;

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_ISP_CONTEXT_H_
@ -110,13 +110,15 @@ enum cam_isp_state_change_trigger {
/**
* struct cam_isp_ctx_debug - Contains debug parameters
*
* @dentry: Debugfs entry
* @enable_state_monitor_dump: Enable isp state monitor dump
* @dentry: Debugfs entry
* @enable_state_monitor_dump: Enable isp state monitor dump
* @enable_cdm_cmd_buff_dump: Enable CDM Command buffer dump
*
*/
struct cam_isp_ctx_debug {
struct dentry *dentry;
uint32_t enable_state_monitor_dump;
uint32_t enable_cdm_cmd_buff_dump;
};
/**
@ -232,6 +234,7 @@ struct cam_isp_context_event_record {
* @req_isp: ISP private request object storage
* @hw_ctx: HW object returned by the acquire device command
* @sof_timestamp_val: Captured time stamp value at sof hw event
* @last_sof_timestamp: Time stamp value for last SOF event
* @boot_timestamp: Boot time stamp for a given req_id
* @active_req_cnt: Counter for the active request
* @reported_req_id: Last reported request id
@ -268,6 +271,7 @@ struct cam_isp_context {
void *hw_ctx;
uint64_t sof_timestamp_val;
uint64_t last_sof_timestamp;
uint64_t boot_timestamp;
int32_t active_req_cnt;
int64_t reported_req_id;

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
*/
#include <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));
}
/* set tpg debug information for top tpg */
for (i = 0; i < CAM_TOP_TPG_HW_NUM_MAX; i++) {
if (g_tfe_hw_mgr.tpg_devices[i]) {
rc = g_tfe_hw_mgr.tpg_devices[i]->hw_ops.process_cmd(
g_tfe_hw_mgr.tpg_devices[i]->hw_priv,
CAM_ISP_HW_CMD_TPG_SET_PATTERN,
&g_tfe_hw_mgr.debug_cfg.set_tpg_pattern,
sizeof(g_tfe_hw_mgr.debug_cfg.set_tpg_pattern));
}
}
camif_debug = g_tfe_hw_mgr.debug_cfg.camif_debug;
list_for_each_entry(hw_mgr_res, &ctx->res_list_tfe_in, list) {
for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
@ -5450,6 +5461,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(cam_tfe_camif_debug,
static int cam_tfe_hw_mgr_debug_register(void)
{
g_tfe_hw_mgr.debug_cfg.set_tpg_pattern = CAM_TOP_TPG_DEFAULT_PATTERN;
g_tfe_hw_mgr.debug_cfg.dentry = debugfs_create_dir("camera_tfe",
NULL);
@ -5482,6 +5494,14 @@ static int cam_tfe_hw_mgr_debug_register(void)
goto err;
}
if (!debugfs_create_u32("set_tpg_pattern",
0644,
g_tfe_hw_mgr.debug_cfg.dentry,
&g_tfe_hw_mgr.debug_cfg.set_tpg_pattern)) {
CAM_ERR(CAM_ISP, "failed to create set_tpg_pattern");
goto err;
}
if (!debugfs_create_u32("enable_reg_dump",
0644,
g_tfe_hw_mgr.debug_cfg.dentry,

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_TFE_HW_MGR_H_
@ -30,6 +30,7 @@
* @enable_recovery: enable recovery
* @enable_csid_recovery: enable csid recovery
* @camif_debug: enable sensor diagnosis status
* @set_tpg_pattern: tpg pattern information
* @enable_reg_dump: enable reg dump on error;
* @per_req_reg_dump: Enable per request reg dump
*
@ -40,6 +41,7 @@ struct cam_tfe_hw_mgr_debug {
uint32_t enable_recovery;
uint32_t enable_csid_recovery;
uint32_t camif_debug;
uint32_t set_tpg_pattern;
uint32_t enable_reg_dump;
uint32_t per_req_reg_dump;
};

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#include <media/cam_defs.h>
@ -140,6 +140,14 @@ static int cam_isp_update_dual_config(
}
hw_mgr_res = &res_list_isp_out[i];
if (!hw_mgr_res) {
CAM_ERR(CAM_ISP,
"Invalid isp out resource i %d num_out_res %d",
i, dual_config->num_ports);
rc = -EINVAL;
goto end;
}
for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) {
if (!hw_mgr_res->hw_res[j])
continue;

View file

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

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_ISP_HW_H_
@ -114,6 +114,7 @@ enum cam_isp_hw_cmd_type {
CAM_ISP_HW_CMD_TPG_PHY_CLOCK_UPDATE,
CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP,
CAM_ISP_HW_CMD_DUMP_HW,
CAM_ISP_HW_CMD_TPG_SET_PATTERN,
CAM_ISP_HW_CMD_MAX,
};

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_TOP_TPG_HW_INTF_H_
@ -13,7 +13,8 @@
#define CAM_TOP_TPG_HW_NUM_MAX 2
/* Max supported number of DT for TPG */
#define CAM_TOP_TPG_MAX_SUPPORTED_DT 4
/* TPG default pattern should be color bar */
#define CAM_TOP_TPG_DEFAULT_PATTERN 0x8
/**
* enum cam_top_tpg_id - top tpg hw instance id
*/

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/irq_controller
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/include
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/
ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_TFE_CSID_530_H_
@ -134,6 +134,7 @@ static struct cam_tfe_csid_csi2_rx_reg_offset
.csid_csi2_rx_irq_set_addr = 0x2c,
/*CSI2 rx control */
.phy_sel_base = 1,
.csid_csi2_rx_cfg0_addr = 0x100,
.csid_csi2_rx_cfg1_addr = 0x104,
.csid_csi2_rx_capture_ctrl_addr = 0x108,

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/iopoll.h>
@ -10,6 +10,7 @@
#include <media/cam_req_mgr.h>
#include "cam_tfe_csid_core.h"
#include "cam_csid_ppi_core.h"
#include "cam_isp_hw.h"
#include "cam_soc_util.h"
#include "cam_io_util.h"
@ -738,6 +739,8 @@ static int cam_tfe_csid_enable_csi2(
{
const struct cam_tfe_csid_reg_offset *csid_reg;
struct cam_hw_soc_info *soc_info;
struct cam_csid_ppi_cfg ppi_lane_cfg;
uint32_t ppi_index = 0, rc;
uint32_t val = 0;
csid_reg = csid_hw->csid_info->csid_reg;
@ -801,6 +804,30 @@ static int cam_tfe_csid_enable_csi2(
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr);
/*
* There is one to one mapping for ppi index with phy index
* we do not always update phy sel equal to phy number,for some
* targets "phy_sel = phy_num + 1", and for some targets it is
* "phy_sel = phy_num", ppi_index should be updated accordingly
*/
ppi_index = csid_hw->csi2_rx_cfg.phy_sel -
csid_reg->csi2_reg->phy_sel_base;
if (csid_hw->ppi_hw_intf[ppi_index] && csid_hw->ppi_enable) {
ppi_lane_cfg.lane_type = csid_hw->csi2_rx_cfg.lane_type;
ppi_lane_cfg.lane_num = csid_hw->csi2_rx_cfg.lane_num;
ppi_lane_cfg.lane_cfg = csid_hw->csi2_rx_cfg.lane_cfg;
CAM_DBG(CAM_ISP, "ppi_index to init %d", ppi_index);
rc = csid_hw->ppi_hw_intf[ppi_index]->hw_ops.init(
csid_hw->ppi_hw_intf[ppi_index]->hw_priv,
&ppi_lane_cfg,
sizeof(struct cam_csid_ppi_cfg));
if (rc < 0) {
CAM_ERR(CAM_ISP, "PPI:%d Init Failed", ppi_index);
return rc;
}
}
return 0;
}
@ -810,6 +837,7 @@ static int cam_tfe_csid_disable_csi2(
{
const struct cam_tfe_csid_reg_offset *csid_reg;
struct cam_hw_soc_info *soc_info;
uint32_t ppi_index = 0, rc;
csid_reg = csid_hw->csid_info->csid_reg;
soc_info = &csid_hw->hw_info->soc_info;
@ -826,6 +854,20 @@ static int cam_tfe_csid_disable_csi2(
cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
csid_reg->csi2_reg->csid_csi2_rx_cfg1_addr);
ppi_index = csid_hw->csi2_rx_cfg.phy_sel -
csid_reg->csi2_reg->phy_sel_base;
if (csid_hw->ppi_hw_intf[ppi_index] && csid_hw->ppi_enable) {
/* De-Initialize the PPI bridge */
CAM_DBG(CAM_ISP, "ppi_index to de-init %d\n", ppi_index);
rc = csid_hw->ppi_hw_intf[ppi_index]->hw_ops.deinit(
csid_hw->ppi_hw_intf[ppi_index]->hw_priv,
NULL, 0);
if (rc < 0) {
CAM_ERR(CAM_ISP, "PPI:%d De-Init Failed", ppi_index);
return rc;
}
}
return 0;
}
@ -2700,13 +2742,15 @@ irqreturn_t cam_tfe_csid_irq(int irq_num, void *data)
unsigned long flags;
uint32_t i, val;
csid_hw = (struct cam_tfe_csid_hw *)data;
if (!data) {
CAM_ERR(CAM_ISP, "CSID: Invalid arguments");
return IRQ_HANDLED;
}
csid_hw = (struct cam_tfe_csid_hw *)data;
CAM_DBG(CAM_ISP, "CSID %d IRQ Handling", csid_hw->hw_intf->hw_idx);
csid_reg = csid_hw->csid_info->csid_reg;
soc_info = &csid_hw->hw_info->soc_info;
csi2_reg = csid_reg->csi2_reg;
@ -3207,6 +3251,24 @@ int cam_tfe_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf,
tfe_csid_hw->error_irq_count = 0;
tfe_csid_hw->prev_boot_timestamp = 0;
/* Check if ppi bridge is present or not? */
tfe_csid_hw->ppi_enable = of_property_read_bool(
csid_hw_info->soc_info.pdev->dev.of_node,
"ppi-enable");
if (!tfe_csid_hw->ppi_enable)
return 0;
/* Initialize the PPI bridge */
for (i = 0; i < CAM_CSID_PPI_HW_MAX; i++) {
rc = cam_csid_ppi_hw_init(&tfe_csid_hw->ppi_hw_intf[i], i);
if (rc < 0) {
CAM_INFO(CAM_ISP, "PPI init failed for PPI %d", i);
rc = 0;
break;
}
}
return 0;
err:
if (rc) {

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_TFE_CSID_HW_H_
@ -9,6 +9,7 @@
#include "cam_hw.h"
#include "cam_tfe_csid_hw_intf.h"
#include "cam_tfe_csid_soc.h"
#include "cam_csid_ppi_core.h"
#define CAM_TFE_CSID_CID_MAX 4
@ -184,6 +185,7 @@ struct cam_tfe_csid_csi2_rx_reg_offset {
uint32_t csid_csi2_rx_total_crc_err_addr;
/*configurations */
uint32_t phy_sel_base;
uint32_t csi2_rst_srb_all;
uint32_t csi2_rst_done_shift_val;
uint32_t csi2_irq_mask_all;
@ -407,6 +409,9 @@ struct cam_csid_evt_payload {
* @event_cb_priv: Context data
* @prev_boot_timestamp previous frame bootime stamp
* @prev_qtimer_ts previous frame qtimer csid timestamp
* @ppi_hw_intf interface to ppi hardware
* @ppi_enabled flag to specify if the hardware has ppi bridge
* or not
*
*/
struct cam_tfe_csid_hw {
@ -439,6 +444,8 @@ struct cam_tfe_csid_hw {
void *event_cb_priv;
uint64_t prev_boot_timestamp;
uint64_t prev_qtimer_ts;
struct cam_hw_intf *ppi_hw_intf[CAM_CSID_PPI_HW_MAX];
bool ppi_enable;
};
int cam_tfe_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf,

View file

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

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
*/
#include <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;
struct cam_top_tpg_cfg *tpg_data;
uint32_t i, val;
uint32_t in_format = 0;
if (!hw_priv || !start_args ||
(arg_size != sizeof(struct cam_isp_resource_node))) {
@ -456,6 +457,56 @@ static int cam_top_tpg_start(void *hw_priv, void *start_args,
cam_io_w_mb(0x2581F4,
soc_info->reg_map[0].mem_base + tpg_reg->tpg_vc_cfg1);
/* configure tpg pattern */
in_format = tpg_data->dt_cfg[0].encode_format & 0xF;
val = in_format << tpg_reg->tpg_dt_encode_format_shift;
switch (tpg_hw->tpg_pattern) {
case 0x0:
val = val | tpg_hw->tpg_pattern;
break;
case 0x1:
val = val | tpg_hw->tpg_pattern;
break;
case 0x2:
val = val | tpg_hw->tpg_pattern;
break;
case 0x3:
val = val | tpg_hw->tpg_pattern;
break;
case 0x4:
val = val | tpg_hw->tpg_pattern;
break;
case 0x5:
val = val | tpg_hw->tpg_pattern;
break;
case 0x6:
val = val | tpg_hw->tpg_pattern;
break;
case 0x7:
val = val | tpg_hw->tpg_pattern;
break;
case 0x8:
/* unicolor bar selection */
val = 0x1 | (1 << tpg_reg->top_unicolor_bar_shift);
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
tpg_reg->tpg_color_bar_cfg);
val = (in_format << tpg_reg->tpg_dt_encode_format_shift) |
tpg_hw->tpg_pattern;
break;
default:
/* frame with split color bar */
val = 1 << tpg_reg->tpg_split_en_shift;
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
tpg_reg->tpg_color_bar_cfg);
val = (in_format << tpg_reg->tpg_dt_encode_format_shift) |
CAM_TOP_TPG_DEFAULT_PATTERN;
break;
}
cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
tpg_reg->tpg_dt_0_cfg_2);
val = (1 << tpg_reg->tpg_split_en_shift);
cam_io_w_mb(tpg_data->pix_pattern, soc_info->reg_map[0].mem_base +
tpg_reg->tpg_common_gen_cfg);
@ -469,8 +520,14 @@ static int cam_top_tpg_start(void *hw_priv, void *start_args,
soc_info->reg_map[0].mem_base + tpg_reg->tpg_vbi_cfg);
/* Set the TOP tpg mux sel*/
cam_io_w_mb((1 << tpg_hw->hw_intf->hw_idx),
val = cam_io_r_mb(soc_info->reg_map[1].mem_base +
tpg_reg->top_mux_reg_offset);
val |= (1 << tpg_hw->hw_intf->hw_idx);
cam_io_w_mb(val,
soc_info->reg_map[1].mem_base + tpg_reg->top_mux_reg_offset);
CAM_DBG(CAM_ISP, "TPG:%d Set top Mux: 0x%x",
tpg_hw->hw_intf->hw_idx, val);
val = ((tpg_data->num_active_lanes - 1) <<
tpg_reg->tpg_num_active_lines_shift) |
@ -498,6 +555,7 @@ static int cam_top_tpg_stop(void *hw_priv,
struct cam_isp_resource_node *tpg_res;
const struct cam_top_tpg_reg_offset *tpg_reg;
struct cam_top_tpg_cfg *tpg_data;
uint32_t val;
if (!hw_priv || !stop_args ||
(arg_size != sizeof(struct cam_isp_resource_node))) {
@ -524,6 +582,16 @@ static int cam_top_tpg_stop(void *hw_priv,
cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
tpg_reg->tpg_ctrl);
/* Reset the TOP tpg mux sel*/
val = cam_io_r_mb(soc_info->reg_map[1].mem_base +
tpg_reg->top_mux_reg_offset);
val &= ~(1 << tpg_hw->hw_intf->hw_idx);
cam_io_w_mb(val,
soc_info->reg_map[1].mem_base + tpg_reg->top_mux_reg_offset);
CAM_DBG(CAM_ISP, "TPG:%d Reset Top Mux: 0x%x",
tpg_hw->hw_intf->hw_idx, val);
tpg_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
CAM_DBG(CAM_ISP, "TPG:%d stopped", tpg_hw->hw_intf->hw_idx);
@ -563,6 +631,19 @@ static int cam_top_tpg_set_phy_clock(
return 0;
}
static int cam_top_tpg_set_top_tpg_pattern(struct cam_top_tpg_hw *tpg_hw,
void *cmd_args)
{
uint32_t *top_tpg_pattern;
top_tpg_pattern = (uint32_t *) cmd_args;
tpg_hw->tpg_pattern = *top_tpg_pattern;
CAM_DBG(CAM_ISP, "TPG:%d set tpg debug value:%d",
tpg_hw->hw_intf->hw_idx, tpg_hw->tpg_pattern);
return 0;
}
static int cam_top_tpg_process_cmd(void *hw_priv,
uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
{
@ -582,6 +663,9 @@ static int cam_top_tpg_process_cmd(void *hw_priv,
case CAM_ISP_HW_CMD_TPG_PHY_CLOCK_UPDATE:
rc = cam_top_tpg_set_phy_clock(tpg_hw, cmd_args);
break;
case CAM_ISP_HW_CMD_TPG_SET_PATTERN:
rc = cam_top_tpg_set_top_tpg_pattern(tpg_hw, cmd_args);
break;
default:
CAM_ERR(CAM_ISP, "TPG:%d unsupported cmd:%d",
tpg_hw->hw_intf->hw_idx, cmd_type);

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_TOP_TPG_HW_H_
@ -60,6 +60,7 @@ struct cam_top_tpg_reg_offset {
uint32_t tpg_payload_mode_color;
uint32_t tpg_split_en_shift;
uint32_t top_mux_reg_offset;
uint32_t top_unicolor_bar_shift;
};
/**
@ -129,7 +130,7 @@ struct cam_top_tpg_cfg {
* @hw_info: tpg hw device information
* @tpg_info: tpg hw specific information
* @tpg_res: tpg resource
* @tpg_cfg: tpg configuration
* @tpg_pattern: tpg pattern configuration
* @clk_rate clock rate
* @lock_state lock state
* @tpg_complete tpg completion
@ -140,6 +141,7 @@ struct cam_top_tpg_hw {
struct cam_hw_info *hw_info;
struct cam_top_tpg_hw_info *tpg_info;
struct cam_isp_resource_node tpg_res;
uint32_t tpg_pattern;
uint64_t clk_rate;
spinlock_t lock_state;
struct completion tpg_complete;

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_TOP_TPG_V1_H_
@ -48,6 +48,7 @@ static struct cam_top_tpg_reg_offset cam_top_tpg_v1_reg_offset = {
.tpg_payload_mode_color = 0x8,
.tpg_split_en_shift = 5,
.top_mux_reg_offset = 0x1C,
.top_unicolor_bar_shift = 2,
};
#endif /*_CAM_TOP_TPG_V1_H_ */

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#include <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 ||
!packet->num_io_configs) {
CAM_ERR(CAM_JPEG, "wrong number of cmd/patch info: %u %u",
packet->num_cmd_buf,
packet->num_patches);
!packet->num_io_configs ||
(packet->num_io_configs > CAM_JPEG_IMAGE_MAX)) {
CAM_ERR(CAM_JPEG,
"wrong number of cmd/patch/io_configs info: %u %u %u",
packet->num_cmd_buf, packet->num_patches,
packet->num_io_configs);
return -EINVAL;
}

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/uaccess.h>
@ -695,15 +695,14 @@ static int32_t cam_ope_process_request_timer(void *priv, void *data)
}
CAM_ERR(CAM_OPE,
"pending requests means, issue is with HW for ctx %d",
ctx_data->ctx_id);
CAM_ERR(CAM_OPE, "ctx: %d, lrt: %llu, lct: %llu",
"pending req at HW, ctx %d lrt %llu lct %llu",
ctx_data->ctx_id, ctx_data->last_req_time,
ope_hw_mgr->last_callback_time);
hw_mgr->ope_dev_intf[i]->hw_ops.process_cmd(
hw_mgr->ope_dev_intf[i]->hw_priv,
OPE_HW_DUMP_DEBUG,
NULL, 0);
task = cam_req_mgr_workq_get_task(ope_hw_mgr->msg_work);
if (!task) {
CAM_ERR(CAM_OPE, "no empty task");
@ -1601,6 +1600,7 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata,
struct timespec64 ts;
bool flag = false;
bool dump_flag = true;
int i;
if (!userdata) {
CAM_ERR(CAM_OPE, "Invalid ctx from CDM callback");
@ -1660,9 +1660,17 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata,
ope_req->request_id, ctx->ctx_id);
CAM_INFO(CAM_OPE, "Rst of CDM and OPE for error reqid = %lld",
ope_req->request_id);
if (status != CAM_CDM_CB_STATUS_HW_FLUSH) {
cam_ope_dump_req_data(ope_req);
dump_flag = false;
CAM_INFO(CAM_OPE, "bach_size: %d",
ctx->req_list[cookie]->num_batch);
for (i = 0; i < ctx->req_list[cookie]->num_batch; i++)
CAM_INFO(CAM_OPE, "i: %d num_stripes: %d",
i,
ctx->req_list[cookie]->num_stripes[i]);
}
rc = cam_ope_mgr_reset_hw();
flag = true;
@ -1753,7 +1761,7 @@ static int cam_ope_mgr_create_kmd_buf(struct cam_ope_hw_mgr *hw_mgr,
static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr,
struct cam_packet *packet,
struct cam_hw_prepare_update_args *prep_args,
struct cam_hw_prepare_update_args *prep_arg,
struct cam_ope_ctx *ctx_data, uint32_t req_idx)
{
@ -1764,8 +1772,8 @@ static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr,
struct cam_ope_request *ope_request;
ope_request = ctx_data->req_list[req_idx];
prep_args->num_out_map_entries = 0;
prep_args->num_in_map_entries = 0;
prep_arg->num_out_map_entries = 0;
prep_arg->num_in_map_entries = 0;
ope_request = ctx_data->req_list[req_idx];
CAM_DBG(CAM_OPE, "E: req_idx = %u %x", req_idx, packet);
@ -1775,8 +1783,16 @@ static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr,
io_buf = ope_request->io_buf[i][l];
if (io_buf->direction == CAM_BUF_INPUT) {
if (io_buf->fence != -1) {
sync_in_obj[j++] = io_buf->fence;
prep_args->num_in_map_entries++;
if (j < CAM_MAX_IN_RES) {
sync_in_obj[j++] =
io_buf->fence;
prep_arg->num_in_map_entries++;
} else {
CAM_ERR(CAM_OPE,
"reached max in_res %d %d",
io_buf->resource_type,
ope_request->request_id);
}
} else {
CAM_ERR(CAM_OPE, "Invalid fence %d %d",
io_buf->resource_type,
@ -1784,10 +1800,10 @@ static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr,
}
} else {
if (io_buf->fence != -1) {
prep_args->out_map_entries[k].sync_id =
prep_arg->out_map_entries[k].sync_id =
io_buf->fence;
k++;
prep_args->num_out_map_entries++;
prep_arg->num_out_map_entries++;
} else {
if (io_buf->resource_type
!= OPE_OUT_RES_STATS_LTM) {
@ -1808,38 +1824,38 @@ static int cam_ope_mgr_process_io_cfg(struct cam_ope_hw_mgr *hw_mgr,
}
}
if (prep_args->num_in_map_entries > 1 &&
prep_args->num_in_map_entries <= CAM_MAX_IN_RES)
prep_args->num_in_map_entries =
if (prep_arg->num_in_map_entries > 1 &&
prep_arg->num_in_map_entries <= CAM_MAX_IN_RES)
prep_arg->num_in_map_entries =
cam_common_util_remove_duplicate_arr(
sync_in_obj, prep_args->num_in_map_entries);
sync_in_obj, prep_arg->num_in_map_entries);
if (prep_args->num_in_map_entries > 1 &&
prep_args->num_in_map_entries <= CAM_MAX_IN_RES) {
if (prep_arg->num_in_map_entries > 1 &&
prep_arg->num_in_map_entries <= CAM_MAX_IN_RES) {
rc = cam_sync_merge(&sync_in_obj[0],
prep_args->num_in_map_entries, &merged_sync_in_obj);
prep_arg->num_in_map_entries, &merged_sync_in_obj);
if (rc) {
prep_args->num_out_map_entries = 0;
prep_args->num_in_map_entries = 0;
prep_arg->num_out_map_entries = 0;
prep_arg->num_in_map_entries = 0;
return rc;
}
ope_request->in_resource = merged_sync_in_obj;
prep_args->in_map_entries[0].sync_id = merged_sync_in_obj;
prep_args->num_in_map_entries = 1;
prep_arg->in_map_entries[0].sync_id = merged_sync_in_obj;
prep_arg->num_in_map_entries = 1;
CAM_DBG(CAM_REQ, "ctx_id: %u req_id: %llu Merged Sync obj: %d",
ctx_data->ctx_id, packet->header.request_id,
merged_sync_in_obj);
} else if (prep_args->num_in_map_entries == 1) {
prep_args->in_map_entries[0].sync_id = sync_in_obj[0];
prep_args->num_in_map_entries = 1;
} else if (prep_arg->num_in_map_entries == 1) {
prep_arg->in_map_entries[0].sync_id = sync_in_obj[0];
prep_arg->num_in_map_entries = 1;
ope_request->in_resource = 0;
CAM_DBG(CAM_OPE, "fence = %d", sync_in_obj[0]);
} else {
CAM_DBG(CAM_OPE, "Invalid count of input fences, count: %d",
prep_args->num_in_map_entries);
prep_args->num_in_map_entries = 0;
prep_arg->num_in_map_entries);
prep_arg->num_in_map_entries = 0;
ope_request->in_resource = 0;
rc = -EINVAL;
}
@ -2740,6 +2756,10 @@ static int cam_ope_mgr_acquire_hw(void *hw_priv, void *hw_acquire_args)
ctx->ctxt_event_cb = args->event_cb;
cam_ope_ctx_clk_info_init(ctx);
ctx->ctx_state = OPE_CTX_STATE_ACQUIRED;
kzfree(cdm_acquire);
cdm_acquire = NULL;
kzfree(bw_update);
bw_update = NULL;
mutex_unlock(&ctx->ctx_mutex);
mutex_unlock(&hw_mgr->hw_mgr_mutex);

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
*/
#include <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;
int num_dmi = 0;
struct cam_cdm_utils_ops *cdm_ops;
uint32_t reg_val_pair[2];
struct cam_hw_info *ope_dev;
struct cam_ope_device_core_info *core_info;
struct ope_hw *ope_hw;
struct cam_ope_top_reg *top_reg;
if (s_idx >= OPE_MAX_CMD_BUFS ||
batch_idx >= OPE_MAX_BATCH_SIZE) {
@ -868,10 +873,21 @@ static uint32_t *ope_create_stripe_cmd(struct cam_ope_hw_mgr *hw_mgr,
}
CAM_DBG(CAM_OPE, "Stripe:%d Indirect:X", stripe_idx);
}
if (hw_mgr->frame_dump_enable)
dump_stripe_cmd(frm_proc, stripe_idx, i, k,
iova_addr, kmd_buf, buf_len);
}
ope_dev = hw_mgr->ope_dev_intf[0]->hw_priv;
core_info = (struct cam_ope_device_core_info *)ope_dev->core_info;
ope_hw = core_info->ope_hw_info->ope_hw;
top_reg = ope_hw->top_reg;
reg_val_pair[0] = top_reg->offset + top_reg->scratch_reg;
reg_val_pair[1] = stripe_idx;
kmd_buf = cdm_ops->cdm_write_regrandom(kmd_buf, 1, reg_val_pair);
return kmd_buf;
}

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
*/
#include <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) {
case OPE_HW_VER_1_0_0:
case OPE_HW_VER_1_1_0:
core_info->ope_hw_info->ope_hw = &ope_hw_100;
break;
default:

View file

@ -1,12 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
*/
#ifndef CAM_OPE_HW_H
#define CAM_OPE_HW_H
#define OPE_HW_VER_1_0_0 0x10000000
#define OPE_HW_VER_1_1_0 0x10010000
#define OPE_DEV_OPE 0
#define OPE_DEV_MAX 1
@ -72,6 +73,7 @@ struct cam_ope_top_reg {
uint32_t violation_status;
uint32_t throttle_cnt_cfg;
uint32_t debug_cfg;
uint32_t scratch_reg;
uint32_t num_debug_registers;
struct cam_ope_debug_register *debug_regs;
};

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
*/
#ifndef CAM_OPE_HW_100_H
@ -70,6 +70,9 @@ static struct cam_ope_debug_register ope_debug_regs[OPE_MAX_DEBUG_REGISTER] = {
{
.offset = 0xD0,
},
{
.offset = 0xD4,
},
};
static struct cam_ope_top_reg ope_top_reg = {
@ -87,7 +90,8 @@ static struct cam_ope_top_reg ope_top_reg = {
.violation_status = 0x28,
.throttle_cnt_cfg = 0x2C,
.debug_cfg = 0xDC,
.num_debug_registers = 9,
.scratch_reg = 0x1F0,
.num_debug_registers = 10,
.debug_regs = ope_debug_regs,
};

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
*/
#include <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)
{
uint32_t i, val;
uint32_t i, val[3];
struct cam_ope_top_reg *top_reg;
top_reg = ope_hw_info->top_reg;
for (i = 0; i < top_reg->num_debug_registers; i++) {
val = cam_io_r_mb(top_reg->base +
for (i = 0; i < top_reg->num_debug_registers; i = i+3) {
val[0] = cam_io_r_mb(top_reg->base +
top_reg->debug_regs[i].offset);
CAM_INFO(CAM_OPE, "Debug_status_%d val: 0x%x", i, val);
val[1] = ((i+1) < top_reg->num_debug_registers) ?
cam_io_r_mb(top_reg->base +
top_reg->debug_regs[i+1].offset) : 0;
val[2] = ((i+2) < top_reg->num_debug_registers) ?
cam_io_r_mb(top_reg->base +
top_reg->debug_regs[i+2].offset) : 0;
CAM_INFO(CAM_OPE, "status[%d-%d] : 0x%x 0x%x 0x%x",
i, i+2, val[0], val[1], val[2]);
}
CAM_INFO(CAM_OPE, "scrath reg: 0x%x, stripe_idx: %d",
top_reg->offset + top_reg->scratch_reg,
cam_io_r_mb(top_reg->base + top_reg->scratch_reg));
return 0;
}

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#define pr_fmt(fmt) "CAM-REQ-MGR_UTIL %s:%d " fmt, __func__, __LINE__
@ -114,7 +114,7 @@ static int32_t cam_get_free_handle_index(void)
idx = find_first_zero_bit(hdl_tbl->bitmap, hdl_tbl->bits);
if (idx >= CAM_REQ_MGR_MAX_HANDLES_V2 || idx < 0) {
CAM_DBG(CAM_CRM, "idx: %d", idx);
CAM_ERR(CAM_CRM, "No free index found idx: %d", idx);
return -ENOSR;
}
@ -123,20 +123,6 @@ static int32_t cam_get_free_handle_index(void)
return idx;
}
void cam_dump_tbl_info(void)
{
int i;
for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES_V2; i++)
CAM_INFO(CAM_CRM,
"i: %d session_hdl=0x%x hdl_value=0x%x type=%d state=%d dev_id=0x%llx",
i, hdl_tbl->hdl[i].session_hdl,
hdl_tbl->hdl[i].hdl_value,
hdl_tbl->hdl[i].type,
hdl_tbl->hdl[i].state,
hdl_tbl->hdl[i].dev_id);
}
int32_t cam_create_session_hdl(void *priv)
{
int idx;
@ -153,7 +139,6 @@ int32_t cam_create_session_hdl(void *priv)
idx = cam_get_free_handle_index();
if (idx < 0) {
CAM_ERR(CAM_CRM, "Unable to create session handle");
cam_dump_tbl_info();
spin_unlock_bh(&hdl_tbl_lock);
return idx;
}
@ -189,7 +174,6 @@ int32_t cam_create_device_hdl(struct cam_create_dev_hdl *hdl_data)
if (idx < 0) {
CAM_ERR(CAM_CRM,
"Unable to create device handle(idx= %d)", idx);
cam_dump_tbl_info();
spin_unlock_bh(&hdl_tbl_lock);
return idx;
}

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_CSIPHY_1_2_1_HWREG_H_
@ -13,10 +13,10 @@ struct csiphy_reg_parms_t csiphy_v1_2_1 = {
.mipi_csiphy_interrupt_clear0_addr = 0x858,
.mipi_csiphy_glbl_irq_cmd_addr = 0x828,
.csiphy_interrupt_status_size = 11,
.csiphy_common_array_size = 6,
.csiphy_common_array_size = 7,
.csiphy_reset_array_size = 5,
.csiphy_2ph_config_array_size = 20,
.csiphy_3ph_config_array_size = 34,
.csiphy_3ph_config_array_size = 33,
.csiphy_2ph_clock_lane = 0x1,
.csiphy_2ph_combo_ck_ln = 0x10,
};
@ -26,6 +26,7 @@ struct csiphy_reg_t csiphy_common_reg_1_2_1[] = {
{0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x081C, 0x02, 0x00, CSIPHY_2PH_REGS},
{0x081C, 0x52, 0x00, CSIPHY_3PH_REGS},
{0x0800, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x02, 0x00, CSIPHY_2PH_REGS},
{0x0800, 0x0E, 0x00, CSIPHY_3PH_REGS},
};
@ -34,7 +35,7 @@ struct csiphy_reg_t csiphy_reset_reg_1_2_1[] = {
{0x0814, 0x00, 0x05, CSIPHY_LANE_ENABLE},
{0x0818, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x081C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x01, 0x01, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
};
@ -59,7 +60,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0900, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0908, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0904, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0904, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0904, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0034, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS},
@ -70,7 +71,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0000, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0014, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0024, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
@ -81,7 +82,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0C80, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0C88, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0C84, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0C84, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0C84, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0734, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS},
@ -92,7 +93,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x070c, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0714, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0724, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
@ -103,7 +104,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0A00, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A04, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0234, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS},
@ -114,7 +115,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0200, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0214, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0224, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
@ -125,7 +126,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0B00, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B04, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0434, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS},
@ -136,7 +137,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0400, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x040c, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0414, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0424, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
@ -147,7 +148,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0C00, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0C08, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0C04, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0C04, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0C04, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0634, 0x07, 0x00, CSIPHY_DEFAULT_PARAMS},
@ -158,7 +159,7 @@ csiphy_reg_t csiphy_2ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0600, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x060c, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0614, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0628, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0624, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0800, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
@ -184,7 +185,7 @@ struct csiphy_reg_t
{0x0000, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x000c, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0014, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0024, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS},
@ -206,7 +207,7 @@ struct csiphy_reg_t
{0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x070c, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0714, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0724, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS},
@ -228,7 +229,7 @@ struct csiphy_reg_t
{0x0200, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x020c, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0214, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0224, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS},
@ -250,7 +251,7 @@ struct csiphy_reg_t
{0x0400, 0x8D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x040C, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0414, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0428, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0424, 0x00, 0x00, CSIPHY_DNP_PARAMS},
{0x0800, 0x00, 0x00, CSIPHY_DNP_PARAMS},
@ -272,9 +273,9 @@ struct csiphy_reg_t
{0x0600, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x060C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0638, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0614, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0628, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0624, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0624, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
},
@ -289,10 +290,11 @@ csiphy_reg_t csiphy_3ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0990, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0994, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0998, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x098C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0168, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x098C, 0xAF, 0x01, CSIPHY_DEFAULT_PARAMS},
{0x015C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0104, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x010C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
{0x010C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
{0x0108, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE},
{0x0114, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0150, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@ -307,28 +309,27 @@ csiphy_reg_t csiphy_3ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x012C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0160, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x01CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x01DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x09C0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x09C4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x09C8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0984, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0988, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0980, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x09AC, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x09B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
},
{
{0x0A90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A98, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A98, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A8C, 0xBF, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0368, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A8C, 0xAF, 0x01, CSIPHY_DEFAULT_PARAMS},
{0x035C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0304, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x030C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
{0x030C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
{0x0308, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE},
{0x0314, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0350, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@ -343,16 +344,14 @@ csiphy_reg_t csiphy_3ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x032C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0360, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x03CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x03DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0AC0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0AC4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0AC8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0A80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0AAC, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0AB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
},
{
{0x0B90, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@ -361,10 +360,11 @@ csiphy_reg_t csiphy_3ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x0B90, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B94, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B98, 0x1A, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B8C, 0xAF, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0568, 0xAC, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B8C, 0xAF, 0x01, CSIPHY_DEFAULT_PARAMS},
{0x055C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0504, 0x06, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x050C, 0x07, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
{0x050C, 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
{0x0508, 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE},
{0x0514, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0550, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
@ -379,16 +379,14 @@ csiphy_reg_t csiphy_3ph_v1_2_1_reg[MAX_LANES][MAX_SETTINGS_PER_LANE] = {
{0x052C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0560, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x05CC, 0x41, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x05DC, 0x50, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0BC0, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0BC4, 0x7D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0BC8, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B84, 0x20, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B88, 0x05, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0B80, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0BAC, 0x35, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0BB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0800, 0x0E, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0884, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
},
};
@ -398,82 +396,55 @@ struct data_rate_settings_t data_rate_delta_table_1_2_1 = {
{
/* (2.5 * 10**3 * 2.28) rounded value*/
.bandwidth = 5700000000,
.data_rate_reg_array_size = 12,
.data_rate_reg_array_size = 9,
.csiphy_data_rate_regs = {
{0x15C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x35C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x55C, 0x66, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
{0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
{0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x144, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x344, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x544, 0x22, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x16C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x36C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x56C, 0xAD, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x164, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x364, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x564, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x144, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x344, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x544, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
}
},
{
/* (3.5 * 10**3 * 2.28) rounded value */
.bandwidth = 7980000000,
.data_rate_reg_array_size = 24,
.data_rate_reg_array_size = 12,
.csiphy_data_rate_regs = {
{0x15C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x35C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x55C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x9B4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
{0xAB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
{0xBB4, 0x03, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x9B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0xAB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0xBB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x544, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x13C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x33C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x53C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x140, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x340, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x540, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x9B4, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS},
{0xAB4, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS},
{0xBB4, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS},
{0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x16C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x36C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x56C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS},
},
},
{
/* (4.5 * 10**3 * 2.28) rounded value */
.bandwidth = 10260000000,
.data_rate_reg_array_size = 24,
.data_rate_reg_array_size = 12,
.csiphy_data_rate_regs = {
{0x15C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x35C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x55C, 0x46, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x9B4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0xAB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0xBB4, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x9B0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0xAB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0xBB0, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x144, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x344, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x544, 0xA2, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x13C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x33C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x53C, 0x10, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x140, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x340, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x540, 0x81, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x168, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x368, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x568, 0xA0, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x16C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x36C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x56C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x9B4, 0x02, 0x01, CSIPHY_DEFAULT_PARAMS},
{0xAB4, 0x02, 0x01, CSIPHY_DEFAULT_PARAMS},
{0xBB4, 0x02, 0x01, CSIPHY_DEFAULT_PARAMS},
{0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS},
},
}
}

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#include <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",
i, curr);
cam_res_mgr_led_trigger_event(
flash_ctrl->torch_trigger[i], curr);
}
@ -509,6 +508,8 @@ static int cam_flash_ops(struct cam_flash_ctrl *flash_ctrl,
int cam_flash_off(struct cam_flash_ctrl *flash_ctrl)
{
int rc = 0;
if (!flash_ctrl) {
CAM_ERR(CAM_FLASH, "Flash control Null");
return -EINVAL;
@ -519,6 +520,18 @@ int cam_flash_off(struct cam_flash_ctrl *flash_ctrl)
(enum led_brightness)LED_SWITCH_OFF);
flash_ctrl->flash_state = CAM_FLASH_STATE_START;
if ((flash_ctrl->i2c_data.streamoff_settings.is_settings_valid) &&
(flash_ctrl->i2c_data.streamoff_settings.request_id == 0)) {
flash_ctrl->apply_streamoff = true;
rc = cam_flash_i2c_apply_setting(flash_ctrl, 0);
if (rc < 0) {
CAM_ERR(CAM_SENSOR,
"cannot apply streamoff settings");
}
flash_ctrl->flash_state = CAM_FLASH_STATE_CONFIG;
}
return 0;
}
@ -621,6 +634,21 @@ static int cam_flash_i2c_delete_req(struct cam_flash_ctrl *fctrl,
CAM_DBG(CAM_FLASH, "top: %llu, del_req_id:%llu",
top, del_req_id);
for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
if ((del_req_id >
fctrl->i2c_data.per_frame[i].request_id) && (
fctrl->i2c_data.per_frame[i].is_settings_valid
== 1)) {
fctrl->i2c_data.per_frame[i].request_id = 0;
rc = delete_request(
&(fctrl->i2c_data.per_frame[i]));
if (rc < 0)
CAM_ERR(CAM_SENSOR,
"Delete request Fail:%lld rc:%d",
del_req_id, rc);
}
}
}
cam_flash_i2c_flush_nrt(fctrl);
@ -720,10 +748,27 @@ int cam_flash_i2c_apply_setting(struct cam_flash_ctrl *fctrl,
struct i2c_settings_list *i2c_list;
struct i2c_settings_array *i2c_set = NULL;
int frame_offset = 0, rc = 0;
CAM_DBG(CAM_FLASH, "req_id=%llu", req_id);
if (req_id == 0) {
/* NonRealTime Init settings*/
if (fctrl->i2c_data.init_settings.is_settings_valid == true) {
if (fctrl->apply_streamoff == true) {
fctrl->apply_streamoff = false;
i2c_set = &fctrl->i2c_data.streamoff_settings;
list_for_each_entry(i2c_list,
&(i2c_set->list_head),
list) {
rc = cam_sensor_util_i2c_apply_setting
(&(fctrl->io_master_info), i2c_list);
if (rc) {
CAM_ERR(CAM_FLASH,
"Failed to apply stream on settings: %d",
rc);
return rc;
}
break;
}
} else if (fctrl->i2c_data.init_settings.is_settings_valid ==
true) {
list_for_each_entry(i2c_list,
&(fctrl->i2c_data.init_settings.list_head),
list) {
@ -1202,7 +1247,8 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
rc = fctrl->func_tbl.apply_setting(fctrl, 0);
if (rc) {
CAM_ERR(CAM_FLASH, "cannot apply settings rc = %d", rc);
CAM_ERR(CAM_FLASH,
"cannot apply settings rc = %d", rc);
return rc;
}
@ -1218,6 +1264,7 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
i2c_reg_settings =
&fctrl->i2c_data.per_frame[frm_offset];
if (i2c_reg_settings->is_settings_valid == true) {
CAM_DBG(CAM_FLASH, "settings already valid");
i2c_reg_settings->request_id = 0;
i2c_reg_settings->is_settings_valid = false;
goto update_req_mgr;
@ -1234,6 +1281,18 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
"Failed in parsing i2c packets");
return rc;
}
if ((fctrl->flash_state == CAM_FLASH_STATE_ACQUIRE) ||
(fctrl->flash_state == CAM_FLASH_STATE_CONFIG)) {
fctrl->flash_state = CAM_FLASH_STATE_CONFIG;
rc = fctrl->func_tbl.apply_setting(fctrl, 1);
if (rc) {
CAM_ERR(CAM_FLASH,
"cannot apply fire settings rc = %d",
rc);
return rc;
}
return rc;
}
break;
}
case CAM_FLASH_PACKET_OPCODE_NON_REALTIME_SET_OPS: {
@ -1272,21 +1331,48 @@ int cam_flash_i2c_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg)
return rc;
}
case CAM_PKT_NOP_OPCODE: {
frm_offset = csl_packet->header.request_id %
MAX_PER_FRAME_ARRAY;
if ((fctrl->flash_state == CAM_FLASH_STATE_INIT) ||
(fctrl->flash_state == CAM_FLASH_STATE_ACQUIRE)) {
CAM_WARN(CAM_FLASH,
"Rxed NOP packets without linking");
frm_offset = csl_packet->header.request_id %
MAX_PER_FRAME_ARRAY;
fctrl->i2c_data.per_frame[frm_offset].is_settings_valid
= false;
return 0;
}
i2c_reg_settings =
&fctrl->i2c_data.per_frame[frm_offset];
i2c_reg_settings->is_settings_valid = true;
i2c_reg_settings->request_id =
csl_packet->header.request_id;
CAM_DBG(CAM_FLASH, "NOP Packet is Received: req_id: %u",
csl_packet->header.request_id);
goto update_req_mgr;
}
case CAM_FLASH_PACKET_OPCODE_STREAM_OFF: {
if (fctrl->streamoff_count > 0)
return rc;
CAM_DBG(CAM_FLASH, "Received Stream off Settings");
i2c_data = &(fctrl->i2c_data);
fctrl->streamoff_count = fctrl->streamoff_count + 1;
i2c_reg_settings = &i2c_data->streamoff_settings;
i2c_reg_settings->request_id = 0;
i2c_reg_settings->is_settings_valid = 1;
offset = (uint32_t *)((uint8_t *)&csl_packet->payload +
csl_packet->cmd_buf_offset);
cmd_desc = (struct cam_cmd_buf_desc *)(offset);
rc = cam_sensor_i2c_command_parser(&fctrl->io_master_info,
i2c_reg_settings,
cmd_desc, 1, NULL);
if (rc) {
CAM_ERR(CAM_FLASH,
"Failed in parsing i2c Stream off packets");
return rc;
}
break;
}
default:
CAM_ERR(CAM_FLASH, "Wrong Opcode : %d",
(csl_packet->header.op_code & 0xFFFFFF));
@ -1827,6 +1913,16 @@ int cam_flash_release_dev(struct cam_flash_ctrl *fctrl)
{
int rc = 0;
if (fctrl->i2c_data.streamoff_settings.is_settings_valid == true) {
fctrl->i2c_data.streamoff_settings.is_settings_valid = false;
rc = delete_request(&fctrl->i2c_data.streamoff_settings);
if (rc) {
CAM_WARN(CAM_FLASH,
"Failed to delete Stream off i2c_setting: %d",
rc);
}
}
if (fctrl->bridge_intf.device_hdl != 1) {
rc = cam_destroy_device_hdl(fctrl->bridge_intf.device_hdl);
if (rc)
@ -1837,6 +1933,7 @@ int cam_flash_release_dev(struct cam_flash_ctrl *fctrl)
fctrl->bridge_intf.link_hdl = -1;
fctrl->bridge_intf.session_hdl = -1;
fctrl->last_flush_req = 0;
fctrl->streamoff_count = 0;
}
return rc;

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/module.h>
@ -71,6 +71,7 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
flash_acq_dev.device_handle;
fctrl->bridge_intf.session_hdl =
flash_acq_dev.session_handle;
fctrl->apply_streamoff = false;
rc = copy_to_user(u64_to_user_ptr(cmd->handle),
&flash_acq_dev,
@ -123,6 +124,7 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
if (fctrl->func_tbl.power_ops(fctrl, false))
CAM_WARN(CAM_FLASH, "Power Down Failed");
fctrl->streamoff_count = 0;
fctrl->flash_state = CAM_FLASH_STATE_INIT;
break;
}
@ -130,7 +132,8 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
struct cam_flash_query_cap_info flash_cap = {0};
CAM_DBG(CAM_FLASH, "CAM_QUERY_CAP");
flash_cap.slot_info = fctrl->soc_info.index;
flash_cap.slot_info = fctrl->soc_info.index;
flash_cap.flash_type = soc_private->flash_type;
for (i = 0; i < fctrl->flash_num_sources; i++) {
flash_cap.max_current_flash[i] =
soc_private->flash_max_current[i];
@ -161,6 +164,7 @@ static int32_t cam_flash_driver_cmd(struct cam_flash_ctrl *fctrl,
goto release_mutex;
}
fctrl->apply_streamoff = false;
fctrl->flash_state = CAM_FLASH_STATE_START;
break;
}
@ -401,8 +405,9 @@ static int cam_flash_init_subdev(struct cam_flash_ctrl *fctrl)
static int32_t cam_flash_platform_probe(struct platform_device *pdev)
{
int32_t rc = 0, i = 0;
struct cam_flash_ctrl *fctrl = NULL;
struct device_node *of_parent = NULL;
struct cam_flash_ctrl *fctrl = NULL;
struct device_node *of_parent = NULL;
struct cam_hw_soc_info *soc_info = NULL;
CAM_DBG(CAM_FLASH, "Enter");
if (!pdev->dev.of_node) {
@ -418,6 +423,7 @@ static int32_t cam_flash_platform_probe(struct platform_device *pdev)
fctrl->soc_info.pdev = pdev;
fctrl->soc_info.dev = &pdev->dev;
fctrl->soc_info.dev_name = pdev->name;
fctrl->of_node = pdev->dev.of_node;
platform_set_drvdata(pdev, fctrl);
@ -458,6 +464,25 @@ static int32_t cam_flash_platform_probe(struct platform_device *pdev)
fctrl->io_master_info.cci_client->cci_device = fctrl->cci_num;
CAM_DBG(CAM_FLASH, "cci-index %d", fctrl->cci_num, rc);
soc_info = &fctrl->soc_info;
if (!soc_info->gpio_data) {
CAM_DBG(CAM_FLASH, "No GPIO found");
} else {
if (!soc_info->gpio_data->cam_gpio_common_tbl_size) {
CAM_ERR(CAM_FLASH, "Invalid gpio table size");
rc = -EINVAL;
goto free_cci_resource;
}
rc = cam_sensor_util_init_gpio_pin_tbl(soc_info,
&fctrl->power_info.gpio_num_info);
if ((rc < 0) || (!fctrl->power_info.gpio_num_info)) {
CAM_ERR(CAM_FLASH, "No/Error Flash GPIOs");
rc = -EINVAL;
goto free_cci_resource;
}
}
fctrl->i2c_data.per_frame =
kzalloc(sizeof(struct i2c_settings_array) *
MAX_PER_FRAME_ARRAY, GFP_KERNEL);
@ -469,6 +494,7 @@ static int32_t cam_flash_platform_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&(fctrl->i2c_data.init_settings.list_head));
INIT_LIST_HEAD(&(fctrl->i2c_data.config_settings.list_head));
INIT_LIST_HEAD(&(fctrl->i2c_data.streamoff_settings.list_head));
for (i = 0; i < MAX_PER_FRAME_ARRAY; i++)
INIT_LIST_HEAD(
&(fctrl->i2c_data.per_frame[i].list_head));
@ -526,13 +552,17 @@ static int32_t cam_flash_i2c_driver_probe(struct i2c_client *client,
{
int32_t rc = 0, i = 0;
struct cam_flash_ctrl *fctrl;
struct cam_hw_soc_info *soc_info = NULL;
if (client == NULL || id == NULL) {
CAM_ERR(CAM_FLASH, "Invalid Args client: %pK id: %pK",
client, id);
if (client == NULL) {
CAM_ERR(CAM_FLASH, "Invalid Args client: %pK", client);
return -EINVAL;
}
if (id == NULL) {
CAM_DBG(CAM_FLASH, "device id is Null");
}
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
CAM_ERR(CAM_FLASH, "%s :: i2c_check_functionality failed",
client->name);
@ -541,22 +571,51 @@ static int32_t cam_flash_i2c_driver_probe(struct i2c_client *client,
/* Create sensor control structure */
fctrl = kzalloc(sizeof(*fctrl), GFP_KERNEL);
if (!fctrl)
if (!fctrl) {
CAM_ERR(CAM_FLASH, "Failed to allocate memory for fctrl");
return -ENOMEM;
}
i2c_set_clientdata(client, fctrl);
fctrl->io_master_info.client = client;
fctrl->of_node = client->dev.of_node;
fctrl->soc_info.dev = &client->dev;
fctrl->soc_info.dev_name = client->name;
fctrl->io_master_info.master_type = I2C_MASTER;
rc = cam_flash_init_default_params(fctrl);
if (rc) {
CAM_ERR(CAM_FLASH,
"failed: cam_flash_init_default_params rc %d", rc);
goto free_ctrl;
}
rc = cam_flash_get_dt_data(fctrl, &fctrl->soc_info);
if (rc) {
CAM_ERR(CAM_FLASH, "failed: cam_sensor_parse_dt rc %d", rc);
goto free_ctrl;
}
soc_info = &fctrl->soc_info;
if (!soc_info->gpio_data) {
CAM_DBG(CAM_FLASH, "No GPIO found");
} else {
if (!soc_info->gpio_data->cam_gpio_common_tbl_size) {
CAM_ERR(CAM_FLASH, "Invalid gpio table size");
rc = -EINVAL;
goto free_ctrl;
}
rc = cam_sensor_util_init_gpio_pin_tbl(soc_info,
&fctrl->power_info.gpio_num_info);
if ((rc < 0) || (!fctrl->power_info.gpio_num_info)) {
CAM_ERR(CAM_FLASH, "No/Error Flash GPIOs");
rc = -EINVAL;
goto free_ctrl;
}
}
rc = cam_flash_init_subdev(fctrl);
if (rc)
goto free_ctrl;
@ -571,6 +630,7 @@ static int32_t cam_flash_i2c_driver_probe(struct i2c_client *client,
INIT_LIST_HEAD(&(fctrl->i2c_data.init_settings.list_head));
INIT_LIST_HEAD(&(fctrl->i2c_data.config_settings.list_head));
INIT_LIST_HEAD(&(fctrl->i2c_data.streamoff_settings.list_head));
for (i = 0; i < MAX_PER_FRAME_ARRAY; i++)
INIT_LIST_HEAD(&(fctrl->i2c_data.per_frame[i].list_head));
@ -624,6 +684,7 @@ static struct i2c_driver cam_flash_i2c_driver = {
.remove = cam_flash_i2c_driver_remove,
.driver = {
.name = FLASH_DRIVER_I2C,
.of_match_table = cam_flash_dt_match,
},
};
@ -632,14 +693,13 @@ static int32_t __init cam_flash_init_module(void)
int32_t rc = 0;
rc = platform_driver_register(&cam_flash_platform_driver);
if (rc == 0) {
CAM_DBG(CAM_FLASH, "platform probe success");
return 0;
}
if (rc < 0)
CAM_ERR(CAM_FLASH, "platform probe failed rc: %d", rc);
rc = i2c_add_driver(&cam_flash_i2c_driver);
if (rc)
if (rc < 0)
CAM_ERR(CAM_FLASH, "i2c_add_driver failed rc: %d", rc);
return rc;
}

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2019, 2021 The Linux Foundation. All rights reserved.
*/
#ifndef _CAM_FLASH_DEV_H_
@ -24,6 +24,7 @@
#include "cam_subdev.h"
#include "cam_mem_mgr.h"
#include "cam_sensor_cmn_header.h"
#include "cam_sensor_util.h"
#include "cam_soc_util.h"
#include "cam_debug_util.h"
#include "cam_sensor_io.h"
@ -39,6 +40,7 @@
#define CAM_FLASH_PACKET_OPCODE_INIT 0
#define CAM_FLASH_PACKET_OPCODE_SET_OPS 1
#define CAM_FLASH_PACKET_OPCODE_NON_REALTIME_SET_OPS 2
#define CAM_FLASH_PACKET_OPCODE_STREAM_OFF 3
struct cam_flash_ctrl;
@ -130,6 +132,7 @@ struct cam_flash_frame_setting {
* @torch_op_current : Torch operational current
* @torch_max_current : Max supported current for LED in torch mode
* @is_wled_flash : Detection between WLED/LED flash
* @flash_type : Flash type
*/
struct cam_flash_private_soc {
@ -142,6 +145,7 @@ struct cam_flash_private_soc {
uint32_t torch_op_current[CAM_FLASH_MAX_LED_TRIGGERS];
uint32_t torch_max_current[CAM_FLASH_MAX_LED_TRIGGERS];
bool is_wled_flash;
uint32_t flash_type;
};
struct cam_flash_func_tbl {
@ -179,6 +183,8 @@ struct cam_flash_func_tbl {
* @io_master_info : Information about the communication master
* @i2c_data : I2C register settings
* @last_flush_req : last request to flush
* @streamoff_count : Count to hold the number of times stream off called
* @apply_streamoff : variable to store when to apply stream off
*/
struct cam_flash_ctrl {
char device_name[CAM_CTX_DEV_NAME_MAX_LENGTH];
@ -207,6 +213,8 @@ struct cam_flash_ctrl {
struct camera_io_master io_master_info;
struct i2c_data_settings i2c_data;
uint32_t last_flush_req;
uint32_t streamoff_count;
int32_t apply_streamoff;
};
int cam_flash_pmic_pkt_parser(struct cam_flash_ctrl *fctrl, void *arg);

View file

@ -1,12 +1,13 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2018, 2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2018, 2020, 2021 The Linux Foundation. All rights reserved.
*/
#include <linux/of.h>
#include <linux/of_gpio.h>
#include "cam_flash_soc.h"
#include "cam_res_mgr_api.h"
#include <dt-bindings/msm/msm-camera.h>
static int32_t cam_get_source_node_info(
struct device_node *of_node,
@ -22,6 +23,13 @@ static int32_t cam_get_source_node_info(
soc_private->is_wled_flash =
of_property_read_bool(of_node, "wled-flash-support");
rc = of_property_read_u32(of_node,
"flash-type", &soc_private->flash_type);
if (rc) {
CAM_ERR(CAM_FLASH, "flash-type read failed rc=%d", rc);
soc_private->flash_type = CAM_FLASH_TYPE_PMIC;
}
switch_src_node = of_parse_phandle(of_node, "switch-source", 0);
if (!switch_src_node) {
CAM_WARN(CAM_FLASH, "switch_src_node NULL");
@ -232,7 +240,14 @@ int cam_flash_get_dt_data(struct cam_flash_ctrl *fctrl,
rc = -ENOMEM;
goto release_soc_res;
}
of_node = fctrl->pdev->dev.of_node;
if (fctrl->of_node == NULL) {
CAM_ERR(CAM_FLASH, "device node is NULL");
rc = -EINVAL;
goto free_soc_private;
}
of_node = fctrl->of_node;
rc = cam_soc_util_get_dt_properties(soc_info);
if (rc) {

View file

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

View file

@ -1134,6 +1134,7 @@ int cam_sensor_power_up(struct cam_sensor_ctrl_t *s_ctrl)
//add by hzt 2021-9-4 for control external gpio
power_info->imx582_avdd18_gpio=s_ctrl->imx582_avdd18_gpio;
//add by hzt 2021-9-4 for control external gpio
power_info->imx582_avdd28_gpio=s_ctrl->imx582_avdd28_gpio;
rc = cam_sensor_core_power_up(power_info, soc_info);
if (rc < 0) {

View file

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

View file

@ -260,6 +260,7 @@ int32_t cam_sensor_parse_dt(struct cam_sensor_ctrl_t *s_ctrl)
//add by hzt 2021-9-4 for control external gpio
s_ctrl->imx582_avdd28_gpio = of_get_named_gpio(s_ctrl->of_node, "imx582_avdd28,pwr-gpio", 0);
/* Initialize mutex */

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#include "cam_sensor_cmn_header.h"
@ -32,9 +32,14 @@ static int32_t cam_qup_i2c_rxdata(
},
};
rc = i2c_transfer(dev_client->adapter, msgs, 2);
if (rc < 0)
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "failed 0x%x", saddr);
return rc;
return rc;
}
/* Returns negative errno */
/* else the number of messages executed. */
/* So positive values are not errors. */
return 0;
}
@ -53,9 +58,14 @@ static int32_t cam_qup_i2c_txdata(
},
};
rc = i2c_transfer(dev_client->client->adapter, msg, 1);
if (rc < 0)
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "failed 0x%x", saddr);
return rc;
return rc;
}
/* Returns negative errno, */
/* else the number of messages executed. */
/* So positive values are not errors. */
return 0;
}
int32_t cam_qup_i2c_read(struct i2c_client *client,

View file

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

View file

@ -1774,6 +1774,7 @@ int msm_cam_sensor_handle_reg_gpio(int seq_type,
//add by hzt 2021-9-4 for control external gpio
//s_ctrl.imx582_avdd18_gpio = of_get_named_gpio(s_ctrl->of_node, "imx582_avdd18,pwr-gpio", 0);
//s_ctrl.imx582_avdd28_gpio = of_get_named_gpio(s_ctrl->of_node, "imx582_avdd28,pwr-gpio", 0);
//add by hzt 2021-9-4 control external gpio
@ -2068,6 +2069,15 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl,
//gpio_set_value_cansleep(ctrl->imx582_avdd18_gpio, 1);
gpio_direction_output(ctrl->imx582_avdd18_gpio,1);
gpio_free(ctrl->imx582_avdd18_gpio);
CAM_DBG(CAM_SENSOR, "before to request imx582_avdd28_gpio:%d,,\n",ctrl->imx582_avdd28_gpio);
ret = gpio_request(ctrl->imx582_avdd28_gpio, "imx582_avdd28_gpio");
if (ret < 0) {
CAM_DBG(CAM_SENSOR, "Failed to request imx582_avdd28_gpio:%d,,\n",ctrl->imx582_avdd28_gpio);
}
//gpio_set_value_cansleep(ctrl->imx582_avdd28_gpio, 1);
gpio_direction_output(ctrl->imx582_avdd28_gpio,1);
gpio_free(ctrl->imx582_avdd28_gpio);
}
//add by hzt 2021-9-4 control external gpio
@ -2357,7 +2367,6 @@ int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl,
//add by hzt 2021-9-4 for control external gpio
if(pd->seq_val==SENSOR_VANA)
{
CAM_DBG(CAM_SENSOR, "before to request imx582_avdd18_gpio:%d,,\n",ctrl->imx582_avdd18_gpio);
ret = gpio_request(ctrl->imx582_avdd18_gpio, "imx582_avdd18_gpio");
if (ret < 0) {
@ -2366,6 +2375,15 @@ int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl,
//gpio_set_value_cansleep(ctrl->imx582_avdd18_gpio, 0);
gpio_direction_output(ctrl->imx582_avdd18_gpio,0);
gpio_free(ctrl->imx582_avdd18_gpio);
CAM_DBG(CAM_SENSOR, "before to request imx582_avdd28_gpio:%d,,\n",ctrl->imx582_avdd28_gpio);
ret = gpio_request(ctrl->imx582_avdd28_gpio, "imx582_avdd28_gpio");
if (ret < 0) {
CAM_DBG(CAM_SENSOR, "Failed to request imx582_avdd28_gpio:%d,,\n",ctrl->imx582_avdd28_gpio);
}
//gpio_set_value_cansleep(ctrl->imx582_avdd28_gpio, 0);
gpio_direction_output(ctrl->imx582_avdd28_gpio,0);
gpio_free(ctrl->imx582_avdd28_gpio);
}
//add by hzt 2021-9-4 control external gpio

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2014-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/module.h>
@ -203,6 +203,8 @@ struct cam_dma_buff_info {
struct cam_sec_buff_info {
struct dma_buf *buf;
struct dma_buf_attachment *attach;
struct sg_table *table;
enum dma_data_direction dir;
int ref_count;
dma_addr_t paddr;
@ -2674,6 +2676,8 @@ static int cam_smmu_map_stage2_buffer_and_add_to_list(int idx, int ion_fd,
mapping_info->dir = dma_dir;
mapping_info->ref_count = 1;
mapping_info->buf = dmabuf;
mapping_info->attach = attach;
mapping_info->table = table;
CAM_DBG(CAM_SMMU, "idx=%d, ion_fd=%d, dev=%pK, paddr=%pK, len=%u",
idx, ion_fd,
@ -2774,11 +2778,28 @@ static int cam_smmu_secure_unmap_buf_and_remove_from_list(
struct cam_sec_buff_info *mapping_info,
int idx)
{
if (!mapping_info) {
CAM_ERR(CAM_SMMU, "Error: List doesn't exist");
if ((!mapping_info->buf) || (!mapping_info->table) ||
(!mapping_info->attach)) {
CAM_ERR(CAM_SMMU,
"Error: Invalid params dev = %pK, table = %pK",
(void *)iommu_cb_set.cb_info[idx].dev,
(void *)mapping_info->table);
CAM_ERR(CAM_SMMU, "Error:dma_buf = %pK, attach = %pK\n",
(void *)mapping_info->buf,
(void *)mapping_info->attach);
return -EINVAL;
}
/* skip cache operations */
mapping_info->attach->dma_map_attrs |= DMA_ATTR_SKIP_CPU_SYNC;
/* iommu buffer clean up */
dma_buf_unmap_attachment(mapping_info->attach,
mapping_info->table, mapping_info->dir);
dma_buf_detach(mapping_info->buf, mapping_info->attach);
dma_buf_put(mapping_info->buf);
mapping_info->buf = NULL;
list_del_init(&mapping_info->list);
CAM_DBG(CAM_SMMU, "unmap fd: %d, idx : %d", mapping_info->ion_fd, idx);

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#include <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),
k_ioctl->size))
return -EFAULT;
sync_create.name[SYNC_DEBUG_NAME_LEN] = '\0';
result = cam_sync_create(&sync_create.sync_obj,
sync_create.name);

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2019, 2021 The Linux Foundation. All rights reserved.
*/
#ifndef __UAPI_CAM_SENSOR_H__
@ -474,6 +474,7 @@ struct cam_flash_query_curr {
* @max_current_flash : max supported current for flash
* @max_duration_flash : max flash turn on duration
* @max_current_torch : max supported current for torch
* @flash_type : Indicates about the flash type -I2C,GPIO,PMIC
*
*/
struct cam_flash_query_cap_info {
@ -481,6 +482,7 @@ struct cam_flash_query_cap_info {
uint32_t max_current_flash[CAM_FLASH_MAX_LED_TRIGGERS];
uint32_t max_duration_flash[CAM_FLASH_MAX_LED_TRIGGERS];
uint32_t max_current_torch[CAM_FLASH_MAX_LED_TRIGGERS];
uint32_t flash_type;
} __attribute__ ((packed));
#endif

View file

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

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#include <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);
}
static int dp_display_get_display_type(struct dp_display *dp_display,
const char **display_type)
{
struct dp_display_private *dp;
if (!dp_display || !display_type) {
pr_err("invalid input\n");
return -EINVAL;
}
dp = container_of(dp_display, struct dp_display_private, dp_display);
*display_type = dp->parser->display_type;
if (!strcmp(*display_type, "primary"))
dp_display->is_primary = true;
return 0;
}
static int dp_display_setup_colospace(struct dp_display *dp_display,
void *panel,
u32 colorspace)
@ -3100,6 +3121,7 @@ static int dp_display_probe(struct platform_device *pdev)
g_dp_display->post_open = NULL;
g_dp_display->post_init = dp_display_post_init;
g_dp_display->config_hdr = dp_display_config_hdr;
g_dp_display->get_display_type = dp_display_get_display_type;
g_dp_display->mst_install = dp_display_mst_install;
g_dp_display->mst_uninstall = dp_display_mst_uninstall;
g_dp_display->mst_connector_install = dp_display_mst_connector_install;

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _DP_DISPLAY_H_
@ -72,6 +72,7 @@ struct dp_display {
u32 max_pclk_khz;
u32 no_mst_encoder;
void *dp_mst_prv_info;
bool is_primary;
int (*enable)(struct dp_display *dp_display, void *panel);
int (*post_enable)(struct dp_display *dp_display, void *panel);
@ -126,6 +127,8 @@ struct dp_display {
struct drm_connector *connector, char *pps_cmd);
void (*wakeup_phy_layer)(struct dp_display *dp_display,
bool wakeup);
int (*get_display_type)(struct dp_display *dp_display,
const char **display_type);
};
#ifdef CONFIG_DRM_MSM_DP

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved.
*/
#include <drm/drm_atomic_helper.h>
@ -580,6 +580,19 @@ int dp_connector_get_modes(struct drm_connector *connector,
return rc;
}
int dp_connnector_set_info_blob(struct drm_connector *connector,
void *info, void *display, struct msm_mode_info *mode_info)
{
struct dp_display *dp_display = display;
const char *display_type = NULL;
dp_display->get_display_type(dp_display, &display_type);
sde_kms_info_add_keystr(info,
"display type", display_type);
return 0;
}
int dp_drm_bridge_init(void *data, struct drm_encoder *encoder)
{
int rc = 0;

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved.
*/
#ifndef _DP_DRM_H_
@ -177,6 +177,18 @@ int dp_mst_init(struct dp_display *dp_display);
* @display: Pointer to private display structure
*/
void dp_mst_deinit(struct dp_display *dp_display);
/**
* dp_conn_set_info_blob - callback to perform info blob initialization
* @connector: Pointer to drm connector structure
* @info: Pointer to sde connector info structure
* @display: Pointer to private display handle
* @mode_info: Pointer to mode info structure
* Returns: Zero on success
*/
int dp_connnector_set_info_blob(struct drm_connector *connector,
void *info, void *display, struct msm_mode_info *mode_info);
#else
static inline int dp_connector_config_hdr(struct drm_connector *connector,
void *display, struct sde_connector_state *c_state)
@ -278,6 +290,13 @@ static inline int dp_mst_deinit(struct dp_display *dp_display)
{
return 0;
}
int dp_connnector_set_info_blob(struct drm_connector *connector,
void *info, void *display, struct msm_mode_info *mode_info)
{
return 0;
}
#endif
#endif /* _DP_DRM_H_ */

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/of_gpio.h>
@ -166,6 +166,10 @@ static int dp_parser_misc(struct dp_parser *parser)
if (rc)
parser->max_lclk_khz = DP_MAX_LINK_CLK_KHZ;
parser->display_type = of_get_property(of_node, "label", NULL);
if (!parser->display_type)
parser->display_type = "unknown";
return 0;
}

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _DP_PARSER_H_
@ -198,6 +198,7 @@ static inline char *dp_phy_aux_config_type_to_string(u32 cfg_type)
* @max_dp_dsc_input_width_pixs: Maximum input width for DSC block
* @has_widebus: widebus (2PPC) feature eanble status
*@mst_fixed_port: mst port_num reserved for fixed topology
* @display_type: display type as defined in device tree.
* @parse: function to be called by client to parse device tree.
* @get_io: function to be called by client to get io data.
* @get_io_buf: function to be called by client to get io buffers.
@ -230,6 +231,8 @@ struct dp_parser {
bool lphw_hpd;
u32 mst_fixed_port[MAX_DP_MST_STREAMS];
const char *display_type;
int (*parse)(struct dp_parser *parser);
struct dp_io_data *(*get_io)(struct dp_parser *parser, char *name);
void (*get_io_buf)(struct dp_parser *parser, char *name);

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
*/
#include <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
static int dsi_panel_power_on(struct dsi_panel *panel)
{
int rc = 0;
@ -662,12 +661,29 @@ static int dsi_panel_wled_register(struct dsi_panel *panel,
return 0;
}
static int dsi_panel_dcs_set_display_brightness_c2(struct mipi_dsi_device *dsi,
u32 bl_lvl)
{
u16 brightness = (u16)bl_lvl;
u8 first_byte = brightness & 0xff;
u8 second_byte = brightness >> 8;
u8 payload[8] = {second_byte, first_byte,
second_byte, first_byte,
second_byte, first_byte,
second_byte, first_byte};
return mipi_dsi_dcs_write(dsi, 0xC2, payload, sizeof(payload));
}
static int dsi_panel_update_backlight(struct dsi_panel *panel,
u32 bl_lvl)
{
int rc = 0;
static int old_bkl = 0;
struct mipi_dsi_device *dsi;
struct dsi_backlight_config *bl;
//DSI_ERR("----------update dcs backlight:%d,by eric.wang------\n", bl_lvl);
if(bl_lvl==0&&old_bkl>0){
set_lcd_vcc_3v3_gpio(0);
@ -682,11 +698,16 @@ static int dsi_panel_update_backlight(struct dsi_panel *panel,
}
dsi = &panel->mipi_device;
bl = &panel->bl_config;
if (panel->bl_config.bl_inverted_dbv)
bl_lvl = (((bl_lvl & 0xff) << 8) | (bl_lvl >> 8));
rc = mipi_dsi_dcs_set_display_brightness(dsi, bl_lvl);
if (panel->bl_config.bl_dcs_subtype == 0xc2)
rc = dsi_panel_dcs_set_display_brightness_c2(dsi, bl_lvl);
else
rc = mipi_dsi_dcs_set_display_brightness(dsi, bl_lvl);
if (rc < 0)
DSI_ERR("failed to update dcs backlight:%d\n", bl_lvl);
@ -1907,7 +1928,7 @@ static int dsi_panel_create_cmd_packets(const char *data,
cmd[i].msg.type = data[0];
cmd[i].last_command = (data[1] == 1);
cmd[i].msg.channel = data[2];
cmd[i].msg.flags |= (data[3] == 1 ? MIPI_DSI_MSG_REQ_ACK : 0);
cmd[i].msg.flags |= data[3];
cmd[i].msg.ctrl = 0;
cmd[i].post_wait_ms = cmd[i].msg.wait_ms = data[4];
cmd[i].msg.tx_len = ((data[5] << 8) | (data[6]));
@ -2417,6 +2438,16 @@ static int dsi_panel_parse_bl_config(struct dsi_panel *panel)
panel->bl_config.brightness_max_level = val;
}
rc = utils->read_u32(utils->data, "qcom,mdss-dsi-bl-ctrl-dcs-subtype",
&val);
if (rc) {
DSI_DEBUG("[%s] bl-ctrl-dcs-subtype, defautling to zero\n",
panel->name);
panel->bl_config.bl_dcs_subtype = 0;
} else {
panel->bl_config.bl_dcs_subtype = val;
}
panel->bl_config.bl_inverted_dbv = utils->read_bool(utils->data,
"qcom,mdss-dsi-bl-inverted-dbv");

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _DSI_PANEL_H_
@ -122,6 +122,7 @@ struct dsi_backlight_config {
u32 bl_scale;
u32 bl_scale_sv;
bool bl_inverted_dbv;
u32 bl_dcs_subtype;
int en_gpio;
/* PWM params */

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
* Author: Rob Clark <robdclark@gmail.com>
*
@ -61,6 +61,8 @@
#define MSM_VERSION_MINOR 3
#define MSM_VERSION_PATCHLEVEL 0
static DEFINE_MUTEX(msm_release_lock);
static void msm_fb_output_poll_changed(struct drm_device *dev)
{
struct msm_drm_private *priv = NULL;
@ -1460,14 +1462,27 @@ void msm_mode_object_event_notify(struct drm_mode_object *obj,
static int msm_release(struct inode *inode, struct file *filp)
{
struct drm_file *file_priv = filp->private_data;
struct drm_minor *minor = file_priv->minor;
struct drm_device *dev = minor->dev;
struct msm_drm_private *priv = dev->dev_private;
struct drm_file *file_priv;
struct drm_minor *minor;
struct drm_device *dev;
struct msm_drm_private *priv;
struct msm_drm_event *node, *temp, *tmp_node;
u32 count;
unsigned long flags;
LIST_HEAD(tmp_head);
int ret = 0;
mutex_lock(&msm_release_lock);
file_priv = filp->private_data;
if (!file_priv) {
ret = -EINVAL;
goto end;
}
minor = file_priv->minor;
dev = minor->dev;
priv = dev->dev_private;
spin_lock_irqsave(&dev->event_lock, flags);
list_for_each_entry_safe(node, temp, &priv->client_event_list,
@ -1504,7 +1519,11 @@ static int msm_release(struct inode *inode, struct file *filp)
*/
msm_preclose(dev, file_priv);
return drm_release(inode, filp);
ret = drm_release(inode, filp);
filp->private_data = NULL;
end:
mutex_unlock(&msm_release_lock);
return ret;
}
/**

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
* 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_CIR,
CRTC_PROP_DEST_SCALER_LUT_SEP,
CRTC_PROP_DSPP_INFO,
/* # of blob properties */
CRTC_PROP_BLOBCOUNT,

View file

@ -1,11 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
*/
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/dma-buf.h>
#include <linux/string.h>
#include <drm/msm_drm_pp.h>
#include "sde_color_processing.h"
#include "sde_kms.h"
@ -29,6 +30,7 @@ struct sde_cp_node {
struct list_head active_list;
struct list_head dirty_list;
bool is_dspp_feature;
bool lm_flush_override;
u32 prop_blob_sz;
struct sde_irq_callback *irq;
};
@ -55,6 +57,8 @@ static void dspp_ad_install_property(struct drm_crtc *crtc);
static void dspp_ltm_install_property(struct drm_crtc *crtc);
static void dspp_rc_install_property(struct drm_crtc *crtc);
static void dspp_vlut_install_property(struct drm_crtc *crtc);
static void dspp_gamut_install_property(struct drm_crtc *crtc);
@ -111,6 +115,7 @@ do { \
func[SDE_DSPP_IGC] = dspp_igc_install_property; \
func[SDE_DSPP_HIST] = dspp_hist_install_property; \
func[SDE_DSPP_DITHER] = dspp_dither_install_property; \
func[SDE_DSPP_RC] = dspp_rc_install_property; \
} while (0)
typedef void (*lm_prop_install_func_t)(struct drm_crtc *crtc);
@ -122,7 +127,7 @@ static void lm_gc_install_property(struct drm_crtc *crtc);
#define setup_lm_prop_install_funcs(func) \
(func[SDE_MIXER_GC] = lm_gc_install_property)
enum {
enum sde_cp_crtc_features {
/* Append new DSPP features before SDE_CP_CRTC_DSPP_MAX */
/* DSPP Features start */
SDE_CP_CRTC_DSPP_IGC,
@ -158,6 +163,7 @@ enum {
SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF2,
SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF3,
SDE_CP_CRTC_DSPP_LTM_VLUT,
SDE_CP_CRTC_DSPP_RC_MASK,
SDE_CP_CRTC_DSPP_MAX,
/* DSPP features end */
@ -169,12 +175,52 @@ enum {
SDE_CP_CRTC_MAX_FEATURES,
};
enum sde_cp_crtc_pu_features {
SDE_CP_CRTC_DSPP_RC_PU,
SDE_CP_CRTC_MAX_PU_FEATURES,
};
typedef void (*dspp_cap_update_func_t)(struct sde_crtc *crtc,
struct sde_kms_info *info);
enum sde_dspp_caps_features {
SDE_CP_RC_CAPS,
SDE_CP_CAPS_MAX,
};
static void rc_caps_update(struct sde_crtc *crtc, struct sde_kms_info *info);
static dspp_cap_update_func_t dspp_cap_update_func[SDE_CP_CAPS_MAX];
#define setup_dspp_caps_funcs(func) \
(func[SDE_CP_RC_CAPS] = rc_caps_update)
static void _sde_cp_crtc_enable_hist_irq(struct sde_crtc *sde_crtc);
typedef int (*set_feature_wrapper)(struct sde_hw_dspp *hw_dspp,
typedef int (*feature_wrapper)(struct sde_hw_dspp *hw_dspp,
struct sde_hw_cp_cfg *hw_cfg,
struct sde_crtc *hw_crtc);
static struct sde_kms *get_kms(struct drm_crtc *crtc)
{
struct msm_drm_private *priv = crtc->dev->dev_private;
return to_sde_kms(priv->kms);
}
static void update_pu_feature_enable(struct sde_crtc *sde_crtc,
u32 feature, bool enable)
{
if (!sde_crtc || feature > SDE_CP_CRTC_MAX_PU_FEATURES) {
DRM_ERROR("invalid args feature %d\n", feature);
return;
}
if (enable)
sde_crtc->cp_pu_feature_mask |= BIT(feature);
else
sde_crtc->cp_pu_feature_mask &= ~BIT(feature);
}
static int set_dspp_vlut_feature(struct sde_hw_dspp *hw_dspp,
struct sde_hw_cp_cfg *hw_cfg,
struct sde_crtc *hw_crtc)
@ -655,9 +701,127 @@ static int set_ltm_hist_crtl_feature(struct sde_hw_dspp *hw_dspp,
return ret;
}
set_feature_wrapper crtc_feature_wrappers[SDE_CP_CRTC_MAX_FEATURES];
static int check_rc_mask_feature(struct sde_hw_dspp *hw_dspp,
struct sde_hw_cp_cfg *hw_cfg,
struct sde_crtc *sde_crtc)
{
int ret = 0;
#define setup_crtc_feature_wrappers(wrappers) \
if (!hw_dspp || !hw_cfg || !sde_crtc) {
DRM_ERROR("invalid arguments");
return -EINVAL;
}
if (!hw_dspp->ops.validate_rc_mask) {
DRM_ERROR("invalid rc ops");
return -EINVAL;
}
ret = hw_dspp->ops.validate_rc_mask(hw_dspp, hw_cfg);
if (ret)
DRM_ERROR("failed to validate rc mask %d", ret);
return ret;
}
static int set_rc_mask_feature(struct sde_hw_dspp *hw_dspp,
struct sde_hw_cp_cfg *hw_cfg,
struct sde_crtc *sde_crtc)
{
int ret = 0;
if (!hw_dspp || !hw_cfg || !sde_crtc) {
DRM_ERROR("invalid arguments\n");
return -EINVAL;
}
if (!hw_dspp->ops.setup_rc_mask || !hw_dspp->ops.setup_rc_data) {
DRM_ERROR("invalid rc ops\n");
return -EINVAL;
}
DRM_DEBUG_DRIVER("dspp %d setup mask for rc instance %u\n",
hw_dspp->idx, hw_dspp->cap->sblk->rc.idx);
ret = hw_dspp->ops.setup_rc_mask(hw_dspp, hw_cfg);
if (ret) {
DRM_ERROR("failed to setup rc mask, ret %d\n", ret);
goto exit;
}
/* rc data should be programmed once if dspp are in multi-pipe mode */
if (hw_dspp->cap->sblk->rc.idx % hw_cfg->num_of_mixers == 0) {
ret = hw_dspp->ops.setup_rc_data(hw_dspp, hw_cfg);
if (ret) {
DRM_ERROR("failed to setup rc data, ret %d\n", ret);
goto exit;
}
}
update_pu_feature_enable(sde_crtc, SDE_CP_CRTC_DSPP_RC_PU,
hw_cfg->payload != NULL);
exit:
return ret;
}
static int set_rc_pu_feature(struct sde_hw_dspp *hw_dspp,
struct sde_hw_cp_cfg *hw_cfg,
struct sde_crtc *sde_crtc)
{
int ret = 0;
if (!hw_dspp || !hw_cfg || !sde_crtc) {
DRM_ERROR("invalid arguments\n");
return -EINVAL;
}
if (!hw_dspp->ops.setup_rc_pu_roi) {
DRM_ERROR("invalid rc ops\n");
return -EINVAL;
}
DRM_DEBUG_DRIVER("dspp %d setup pu roi for rc instance %u\n",
hw_dspp->idx, hw_dspp->cap->sblk->rc.idx);
ret = hw_dspp->ops.setup_rc_pu_roi(hw_dspp, hw_cfg);
if (ret < 0)
DRM_ERROR("failed to setup rc pu roi, ret %d\n", ret);
return ret;
}
static int check_rc_pu_feature(struct sde_hw_dspp *hw_dspp,
struct sde_hw_cp_cfg *hw_cfg,
struct sde_crtc *sde_crtc)
{
int ret = 0;
if (!hw_dspp || !hw_cfg || !sde_crtc) {
DRM_ERROR("invalid arguments\n");
return -EINVAL;
}
if (!hw_dspp->ops.validate_rc_pu_roi) {
SDE_ERROR("invalid rc ops");
return -EINVAL;
}
ret = hw_dspp->ops.validate_rc_pu_roi(hw_dspp, hw_cfg);
if (ret)
SDE_ERROR("failed to validate rc pu roi, ret %d", ret);
return ret;
}
feature_wrapper check_crtc_feature_wrappers[SDE_CP_CRTC_MAX_FEATURES];
#define setup_check_crtc_feature_wrappers(wrappers) \
do { \
memset(wrappers, 0, sizeof(wrappers)); \
wrappers[SDE_CP_CRTC_DSPP_RC_MASK] = check_rc_mask_feature; \
} while (0)
feature_wrapper set_crtc_feature_wrappers[SDE_CP_CRTC_MAX_FEATURES];
#define setup_set_crtc_feature_wrappers(wrappers) \
do { \
memset(wrappers, 0, sizeof(wrappers)); \
wrappers[SDE_CP_CRTC_DSPP_VLUT] = set_dspp_vlut_feature; \
@ -697,6 +861,21 @@ do { \
wrappers[SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF2] = set_ltm_queue_buf_feature; \
wrappers[SDE_CP_CRTC_DSPP_LTM_QUEUE_BUF3] = set_ltm_queue_buf_feature; \
wrappers[SDE_CP_CRTC_DSPP_LTM_HIST_CTL] = set_ltm_hist_crtl_feature; \
wrappers[SDE_CP_CRTC_DSPP_RC_MASK] = set_rc_mask_feature; \
} while (0)
feature_wrapper set_crtc_pu_feature_wrappers[SDE_CP_CRTC_MAX_PU_FEATURES];
#define setup_set_crtc_pu_feature_wrappers(wrappers) \
do { \
memset(wrappers, 0, sizeof(wrappers)); \
wrappers[SDE_CP_CRTC_DSPP_RC_PU] = set_rc_pu_feature; \
} while (0)
feature_wrapper check_crtc_pu_feature_wrappers[SDE_CP_CRTC_MAX_PU_FEATURES];
#define setup_check_crtc_pu_feature_wrappers(wrappers) \
do { \
memset(wrappers, 0, sizeof(wrappers)); \
wrappers[SDE_CP_CRTC_DSPP_RC_PU] = check_rc_pu_feature; \
} while (0)
#define INIT_PROP_ATTACH(p, crtc, prop, node, feature, val) \
@ -886,12 +1065,6 @@ static int sde_cp_enable_crtc_property(struct drm_crtc *crtc,
return ret;
}
static struct sde_kms *get_kms(struct drm_crtc *crtc)
{
struct msm_drm_private *priv = crtc->dev->dev_private;
return to_sde_kms(priv->kms);
}
static void sde_cp_crtc_prop_attach(struct sde_cp_prop_attach *prop_attach)
{
@ -938,6 +1111,9 @@ void sde_cp_crtc_init(struct drm_crtc *crtc)
if (IS_ERR(sde_crtc->hist_blob))
sde_crtc->hist_blob = NULL;
msm_property_install_blob(&sde_crtc->property_info,
"dspp_caps", DRM_MODE_PROP_IMMUTABLE, CRTC_PROP_DSPP_INFO);
mutex_init(&sde_crtc->crtc_cp_lock);
INIT_LIST_HEAD(&sde_crtc->active_list);
INIT_LIST_HEAD(&sde_crtc->dirty_list);
@ -948,6 +1124,7 @@ void sde_cp_crtc_init(struct drm_crtc *crtc)
spin_lock_init(&sde_crtc->ltm_lock);
INIT_LIST_HEAD(&sde_crtc->ltm_buf_free);
INIT_LIST_HEAD(&sde_crtc->ltm_buf_busy);
sde_cp_crtc_disable(crtc);
}
static void sde_cp_crtc_install_immutable_property(struct drm_crtc *crtc,
@ -1182,6 +1359,70 @@ static void _sde_cp_crtc_enable_hist_irq(struct sde_crtc *sde_crtc)
spin_unlock_irqrestore(&node->state_lock, flags);
}
static int sde_cp_crtc_checkfeature(struct sde_cp_node *prop_node,
struct sde_crtc *sde_crtc, struct sde_crtc_state *sde_crtc_state)
{
struct sde_hw_cp_cfg hw_cfg;
struct sde_hw_mixer *hw_lm;
struct sde_hw_dspp *hw_dspp;
u32 num_mixers;
int i = 0, ret = 0;
bool feature_enabled = false;
feature_wrapper check_feature = NULL;
if (!prop_node || !sde_crtc || !sde_crtc_state) {
DRM_ERROR("invalid arguments");
return -EINVAL;
}
num_mixers = sde_crtc->num_mixers;
if (prop_node->feature >= SDE_CP_CRTC_MAX_FEATURES) {
DRM_ERROR("invalid feature %d\n", prop_node->feature);
return -EINVAL;
}
check_feature = check_crtc_feature_wrappers[prop_node->feature];
if (check_feature == NULL)
return 0;
memset(&hw_cfg, 0, sizeof(hw_cfg));
sde_cp_get_hw_payload(prop_node, &hw_cfg, &feature_enabled);
hw_cfg.num_of_mixers = sde_crtc->num_mixers;
hw_cfg.last_feature = 0;
for (i = 0; i < num_mixers; i++) {
hw_dspp = sde_crtc->mixers[i].hw_dspp;
if (!hw_dspp || i >= DSPP_MAX)
continue;
hw_cfg.dspp[i] = hw_dspp;
}
for (i = 0; i < num_mixers && !ret; i++) {
hw_lm = sde_crtc->mixers[i].hw_lm;
hw_dspp = sde_crtc->mixers[i].hw_dspp;
if (!hw_lm) {
ret = -EINVAL;
continue;
}
hw_cfg.ctl = sde_crtc->mixers[i].hw_ctl;
hw_cfg.mixer_info = hw_lm;
/* use incoming state information */
hw_cfg.displayh = num_mixers *
sde_crtc_state->lm_roi[i].w;
hw_cfg.displayv = sde_crtc_state->lm_roi[i].h;
DRM_DEBUG_DRIVER("check cp feature %d on mixer %d\n",
prop_node->feature, hw_lm->idx - LM_0);
ret = check_feature(hw_dspp, &hw_cfg, sde_crtc);
if (ret)
break;
}
return ret;
}
static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node,
struct sde_crtc *sde_crtc)
{
@ -1206,11 +1447,11 @@ static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node,
}
if ((prop_node->feature >= SDE_CP_CRTC_MAX_FEATURES) ||
crtc_feature_wrappers[prop_node->feature] == NULL) {
set_crtc_feature_wrappers[prop_node->feature] == NULL) {
ret = -EINVAL;
} else {
set_feature_wrapper set_feature =
crtc_feature_wrappers[prop_node->feature];
feature_wrapper set_feature =
set_crtc_feature_wrappers[prop_node->feature];
catalog = get_kms(&sde_crtc->base)->catalog;
hw_cfg.broadcast_disabled = catalog->dma_cfg.broadcast_disabled;
@ -1252,6 +1493,257 @@ static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node,
list_del_init(&prop_node->dirty_list);
}
static int sde_cp_crtc_check_pu_features(struct drm_crtc *crtc)
{
int ret = 0, i = 0, j = 0;
struct sde_crtc *sde_crtc;
struct sde_crtc_state *sde_crtc_state;
struct sde_hw_cp_cfg hw_cfg;
struct sde_hw_dspp *hw_dspp;
if (!crtc) {
DRM_ERROR("invalid crtc %pK\n", crtc);
return -EINVAL;
}
sde_crtc = to_sde_crtc(crtc);
if (!sde_crtc) {
DRM_ERROR("invalid sde_crtc %pK\n", sde_crtc);
return -EINVAL;
}
sde_crtc_state = to_sde_crtc_state(crtc->state);
if (!sde_crtc_state) {
DRM_ERROR("invalid sde_crtc_state %pK\n", sde_crtc_state);
return -EINVAL;
}
for (i = 0; i < sde_crtc->num_mixers; i++) {
if (!sde_crtc->mixers[i].hw_lm) {
DRM_ERROR("invalid lm in mixer %d\n", i);
return -EINVAL;
}
if (!sde_crtc->mixers[i].hw_ctl) {
DRM_ERROR("invalid ctl in mixer %d\n", i);
return -EINVAL;
}
}
/* early return when not a partial update frame */
if (sde_crtc_state->user_roi_list.num_rects == 0) {
DRM_DEBUG_DRIVER("no partial update required\n");
return 0;
}
memset(&hw_cfg, 0, sizeof(hw_cfg));
hw_cfg.num_of_mixers = sde_crtc->num_mixers;
hw_cfg.payload = &sde_crtc_state->user_roi_list;
hw_cfg.len = sizeof(sde_crtc_state->user_roi_list);
for (i = 0; i < hw_cfg.num_of_mixers; i++)
hw_cfg.dspp[i] = sde_crtc->mixers[i].hw_dspp;
for (i = 0; i < SDE_CP_CRTC_MAX_PU_FEATURES; i++) {
feature_wrapper check_pu_feature =
check_crtc_pu_feature_wrappers[i];
if (!check_pu_feature ||
!(sde_crtc->cp_pu_feature_mask & BIT(i)))
continue;
for (j = 0; j < hw_cfg.num_of_mixers; j++) {
hw_dspp = sde_crtc->mixers[j].hw_dspp;
/* use incoming state information */
hw_cfg.mixer_info = sde_crtc->mixers[j].hw_lm;
hw_cfg.ctl = sde_crtc->mixers[j].hw_ctl;
hw_cfg.displayh = hw_cfg.num_of_mixers *
sde_crtc_state->lm_roi[j].w;
hw_cfg.displayv = sde_crtc_state->lm_roi[j].h;
ret = check_pu_feature(hw_dspp, &hw_cfg, sde_crtc);
if (ret) {
DRM_ERROR("failed pu feature %d in mixer %d\n",
i, j);
return -EAGAIN;
}
}
}
return ret;
}
int sde_cp_crtc_check_properties(struct drm_crtc *crtc,
struct drm_crtc_state *state)
{
struct sde_crtc *sde_crtc = NULL;
struct sde_crtc_state *sde_crtc_state = NULL;
struct sde_cp_node *prop_node = NULL, *n = NULL;
int ret = 0;
if (!crtc || !crtc->dev || !state) {
DRM_ERROR("invalid crtc %pK dev %pK state %pK\n", crtc,
(crtc ? crtc->dev : NULL), state);
return -EINVAL;
}
sde_crtc = to_sde_crtc(crtc);
if (!sde_crtc) {
DRM_ERROR("invalid sde_crtc %pK\n", sde_crtc);
return -EINVAL;
}
sde_crtc_state = to_sde_crtc_state(state);
if (!sde_crtc_state) {
DRM_ERROR("invalid sde_crtc_state %pK\n", sde_crtc_state);
return -EINVAL;
}
mutex_lock(&sde_crtc->crtc_cp_lock);
ret = sde_cp_crtc_check_pu_features(crtc);
if (ret) {
DRM_ERROR("failed check pu features, ret %d\n", ret);
goto exit;
}
if (list_empty(&sde_crtc->dirty_list)) {
DRM_DEBUG_DRIVER("Dirty list is empty\n");
goto exit;
}
list_for_each_entry_safe(prop_node, n, &sde_crtc->dirty_list,
dirty_list) {
ret = sde_cp_crtc_checkfeature(prop_node, sde_crtc,
sde_crtc_state);
if (ret) {
DRM_ERROR("failed check on prop_node %u\n",
prop_node->property_id);
/* remove invalid feature from dirty list */
list_del_init(&prop_node->dirty_list);
goto exit;
}
}
exit:
mutex_unlock(&sde_crtc->crtc_cp_lock);
return ret;
}
static int sde_cp_crtc_set_pu_features(struct drm_crtc *crtc, bool *need_flush)
{
int ret = 0, i = 0, j = 0;
struct sde_crtc *sde_crtc;
struct sde_crtc_state *sde_crtc_state;
struct sde_hw_cp_cfg hw_cfg;
struct sde_hw_dspp *hw_dspp;
struct sde_hw_mixer *hw_lm;
struct sde_mdss_cfg *catalog;
struct sde_rect user_rect, cached_rect;
if (!need_flush) {
DRM_ERROR("invalid need_flush %pK\n", need_flush);
return -EINVAL;
}
if (!crtc) {
DRM_ERROR("invalid crtc %pK\n", crtc);
return -EINVAL;
}
sde_crtc = to_sde_crtc(crtc);
if (!sde_crtc) {
DRM_ERROR("invalid sde_crtc %pK\n", sde_crtc);
return -EINVAL;
}
sde_crtc_state = to_sde_crtc_state(crtc->state);
if (!sde_crtc_state) {
DRM_ERROR("invalid sde_crtc_state %pK\n", sde_crtc_state);
return -EINVAL;
}
for (i = 0; i < sde_crtc->num_mixers; i++) {
if (!sde_crtc->mixers[i].hw_lm) {
DRM_ERROR("invalid lm in mixer %d\n", i);
return -EINVAL;
}
if (!sde_crtc->mixers[i].hw_ctl) {
DRM_ERROR("invalid ctl in mixer %d\n", i);
return -EINVAL;
}
}
/* early return if not a partial update frame or no change in rois */
if ((sde_crtc_state->user_roi_list.num_rects == 0) &&
(sde_crtc->cached_user_roi_list.num_rects == 0)) {
DRM_DEBUG_DRIVER("no partial update required\n");
return 0;
} else if (sde_crtc_state->user_roi_list.num_rects == 0) {
DRM_DEBUG_DRIVER("transition from PU to full update\n");
memset(&sde_crtc->cached_user_roi_list, 0,
sizeof(struct msm_roi_list));
} else {
sde_kms_rect_merge_rectangles(&sde_crtc_state->user_roi_list,
&user_rect);
sde_kms_rect_merge_rectangles(
&sde_crtc->cached_user_roi_list,
&cached_rect);
if (sde_kms_rect_is_equal(&user_rect, &cached_rect)) {
DRM_DEBUG_DRIVER("no change in list of ROIs\n");
return 0;
}
}
catalog = get_kms(&sde_crtc->base)->catalog;
memset(&hw_cfg, 0, sizeof(hw_cfg));
hw_cfg.num_of_mixers = sde_crtc->num_mixers;
hw_cfg.broadcast_disabled = catalog->dma_cfg.broadcast_disabled;
hw_cfg.payload = (sde_crtc_state->user_roi_list.num_rects) ?
&sde_crtc_state->user_roi_list : NULL;
hw_cfg.len = sizeof(sde_crtc_state->user_roi_list);
for (i = 0; i < hw_cfg.num_of_mixers; i++)
hw_cfg.dspp[i] = sde_crtc->mixers[i].hw_dspp;
for (i = 0; i < SDE_CP_CRTC_MAX_PU_FEATURES; i++) {
feature_wrapper set_pu_feature =
set_crtc_pu_feature_wrappers[i];
if (!set_pu_feature ||
!(sde_crtc->cp_pu_feature_mask & BIT(i)))
continue;
for (j = 0; j < hw_cfg.num_of_mixers; j++) {
hw_lm = sde_crtc->mixers[j].hw_lm;
hw_dspp = sde_crtc->mixers[j].hw_dspp;
hw_cfg.mixer_info = hw_lm;
hw_cfg.ctl = sde_crtc->mixers[j].hw_ctl;
hw_cfg.displayh = hw_cfg.num_of_mixers *
hw_lm->cfg.out_width;
hw_cfg.displayv = hw_lm->cfg.out_height;
ret = set_pu_feature(hw_dspp, &hw_cfg, sde_crtc);
/* feature does not need flush when ret > 0 */
if (ret < 0) {
DRM_ERROR("failed pu feature %d in mixer %d\n",
i, j);
return ret;
} else if (ret == 0) {
*need_flush = true;
}
}
}
if (sde_crtc_state->user_roi_list.num_rects != 0) {
memcpy(&sde_crtc->cached_user_roi_list,
&sde_crtc_state->user_roi_list,
sizeof(struct msm_roi_list));
}
return 0;
}
void sde_cp_crtc_apply_properties(struct drm_crtc *crtc)
{
struct sde_crtc *sde_crtc = NULL;
@ -1259,6 +1751,8 @@ void sde_cp_crtc_apply_properties(struct drm_crtc *crtc)
struct sde_cp_node *prop_node = NULL, *n = NULL;
struct sde_hw_ctl *ctl;
u32 num_mixers = 0, i = 0;
int rc = 0;
bool need_flush = false;
if (!crtc || !crtc->dev) {
DRM_ERROR("invalid crtc %pK dev %pK\n", crtc,
@ -1274,42 +1768,49 @@ void sde_cp_crtc_apply_properties(struct drm_crtc *crtc)
num_mixers = sde_crtc->num_mixers;
if (!num_mixers) {
DRM_DEBUG_DRIVER("no mixers for this crtc\n");
DRM_ERROR("no mixers for this crtc\n");
return;
}
mutex_lock(&sde_crtc->crtc_cp_lock);
/* Check if dirty lists are empty and ad features are disabled for
* early return. If ad properties are active then we need to issue
* dspp flush.
**/
if (list_empty(&sde_crtc->dirty_list) &&
list_empty(&sde_crtc->ad_dirty)) {
if (list_empty(&sde_crtc->ad_active)) {
DRM_DEBUG_DRIVER("Dirty list is empty\n");
goto exit;
}
set_dspp_flush = true;
list_empty(&sde_crtc->ad_dirty) &&
list_empty(&sde_crtc->ad_active) &&
list_empty(&sde_crtc->active_list)) {
DRM_DEBUG_DRIVER("all lists are empty\n");
goto exit;
}
if (!list_empty(&sde_crtc->ad_active))
sde_cp_ad_set_prop(sde_crtc, AD_IPC_RESET);
rc = sde_cp_crtc_set_pu_features(crtc, &need_flush);
if (rc) {
DRM_ERROR("failed set pu features, skip cp updates\n");
goto exit;
} else if (need_flush) {
set_dspp_flush = true;
set_lm_flush = true;
}
list_for_each_entry_safe(prop_node, n, &sde_crtc->dirty_list,
dirty_list) {
dirty_list) {
sde_cp_crtc_setfeature(prop_node, sde_crtc);
/* Set the flush flag to true */
if (prop_node->is_dspp_feature)
if (prop_node->is_dspp_feature &&
!prop_node->lm_flush_override)
set_dspp_flush = true;
else
set_lm_flush = true;
}
list_for_each_entry_safe(prop_node, n, &sde_crtc->ad_dirty,
dirty_list) {
if (!list_empty(&sde_crtc->ad_active)) {
sde_cp_ad_set_prop(sde_crtc, AD_IPC_RESET);
set_dspp_flush = true;
}
list_for_each_entry_safe(prop_node, n, &sde_crtc->ad_dirty,
dirty_list) {
sde_cp_crtc_setfeature(prop_node, sde_crtc);
set_dspp_flush = true;
}
for (i = 0; i < num_mixers; i++) {
@ -1381,7 +1882,13 @@ void sde_cp_crtc_install_properties(struct drm_crtc *crtc)
SDE_CP_CRTC_MAX_FEATURES), GFP_KERNEL);
setup_dspp_prop_install_funcs(dspp_prop_install_func);
setup_lm_prop_install_funcs(lm_prop_install_func);
setup_crtc_feature_wrappers(crtc_feature_wrappers);
setup_set_crtc_feature_wrappers(set_crtc_feature_wrappers);
setup_check_crtc_feature_wrappers(check_crtc_feature_wrappers);
setup_set_crtc_pu_feature_wrappers(
set_crtc_pu_feature_wrappers);
setup_check_crtc_pu_feature_wrappers(
check_crtc_pu_feature_wrappers);
setup_dspp_caps_funcs(dspp_cap_update_func);
}
if (!priv->cp_property)
goto exit;
@ -1659,6 +2166,7 @@ void sde_cp_crtc_clear(struct drm_crtc *crtc)
list_del_init(&sde_crtc->dirty_list);
list_del_init(&sde_crtc->ad_active);
list_del_init(&sde_crtc->ad_dirty);
sde_crtc->cp_pu_feature_mask = 0;
mutex_unlock(&sde_crtc->crtc_cp_lock);
spin_lock_irqsave(&sde_crtc->spin_lock, flags);
@ -1944,6 +2452,57 @@ static void dspp_ltm_install_property(struct drm_crtc *crtc)
}
}
static void dspp_rc_install_property(struct drm_crtc *crtc)
{
char feature_name[256];
struct sde_kms *kms = NULL;
struct sde_mdss_cfg *catalog = NULL;
struct sde_cp_node *prop_node = NULL;
struct sde_crtc *sde_crtc = NULL;
u32 version;
if (!crtc) {
DRM_ERROR("invalid arguments");
return;
}
sde_crtc = to_sde_crtc(crtc);
if (!sde_crtc) {
DRM_ERROR("invalid sde_crtc %pK\n", sde_crtc);
return;
}
kms = get_kms(crtc);
catalog = kms->catalog;
version = catalog->dspp[0].sblk->rc.version >> 16;
switch (version) {
case 1:
snprintf(feature_name, ARRAY_SIZE(feature_name), "%s%d",
"SDE_DSPP_RC_MASK_V", version);
sde_cp_crtc_install_blob_property(crtc, feature_name,
SDE_CP_CRTC_DSPP_RC_MASK,
sizeof(struct drm_msm_rc_mask_cfg));
/* Override flush mechanism to use layer mixer flush bits */
if (!catalog->rc_lm_flush_override)
break;
DRM_DEBUG("rc using lm flush override\n");
list_for_each_entry(prop_node, &sde_crtc->feature_list,
feature_list) {
if (prop_node->feature == SDE_CP_CRTC_DSPP_RC_MASK) {
prop_node->lm_flush_override = true;
break;
}
}
break;
default:
DRM_ERROR("version %d not supported\n", version);
break;
}
}
static void lm_gc_install_property(struct drm_crtc *crtc)
{
char feature_name[256];
@ -3373,3 +3932,72 @@ void sde_cp_mode_switch_prop_dirty(struct drm_crtc *crtc_drm)
}
mutex_unlock(&crtc->crtc_cp_lock);
}
static void rc_caps_update(struct sde_crtc *crtc, struct sde_kms_info *info)
{
struct sde_mdss_cfg *catalog = get_kms(&crtc->base)->catalog;
u32 i, num_mixers = crtc->num_mixers;
char blk_name[256];
if (!catalog->rc_count || num_mixers > catalog->rc_count)
return;
for (i = 0; i < num_mixers; i++) {
struct sde_hw_dspp *dspp = crtc->mixers[i].hw_dspp;
if (!dspp || (dspp->idx - DSPP_0) >= catalog->rc_count)
continue;
snprintf(blk_name, sizeof(blk_name), "rc%u",
(dspp->idx - DSPP_0));
sde_kms_info_add_keyint(info, blk_name, 1);
}
}
void sde_cp_crtc_enable(struct drm_crtc *drm_crtc)
{
struct sde_crtc *crtc;
struct sde_kms_info *info = NULL;
u32 i, num_mixers;
if (!drm_crtc) {
DRM_ERROR("invalid crtc handle");
return;
}
crtc = to_sde_crtc(drm_crtc);
num_mixers = crtc->num_mixers;
if (!num_mixers)
return;
mutex_lock(&crtc->crtc_cp_lock);
info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
if (info) {
for (i = 0; i < ARRAY_SIZE(dspp_cap_update_func); i++)
dspp_cap_update_func[i](crtc, info);
msm_property_set_blob(&crtc->property_info,
&crtc->dspp_blob_info,
info->data, SDE_KMS_INFO_DATALEN(info),
CRTC_PROP_DSPP_INFO);
}
kfree(info);
mutex_unlock(&crtc->crtc_cp_lock);
}
void sde_cp_crtc_disable(struct drm_crtc *drm_crtc)
{
struct sde_kms_info *info = NULL;
struct sde_crtc *crtc;
if (!drm_crtc) {
DRM_ERROR("invalid crtc handle");
return;
}
crtc = to_sde_crtc(drm_crtc);
mutex_lock(&crtc->crtc_cp_lock);
info = kzalloc(sizeof(struct sde_kms_info), GFP_KERNEL);
if (info)
msm_property_set_blob(&crtc->property_info,
&crtc->dspp_blob_info,
info->data, SDE_KMS_INFO_DATALEN(info),
CRTC_PROP_DSPP_INFO);
mutex_unlock(&crtc->crtc_cp_lock);
kfree(info);
}

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2019, 2021, The Linux Foundation. All rights reserved.
*/
#ifndef _SDE_COLOR_PROCESSING_H
@ -93,6 +93,15 @@ void sde_cp_crtc_destroy_properties(struct drm_crtc *crtc);
*/
int sde_cp_crtc_set_property(struct drm_crtc *crtc,
struct drm_property *property, uint64_t val);
/**
* sde_cp_crtc_check_properties: Verify color processing properties for a crtc.
* Should be called during atomic check call.
* @crtc: Pointer to crtc.
* @state: Pointer to crtc state.
* @returns: 0 on success, non-zero otherwise
*/
int sde_cp_crtc_check_properties(struct drm_crtc *crtc,
struct drm_crtc_state *state);
/**
* sde_cp_crtc_apply_properties: Enable/disable properties
@ -196,4 +205,18 @@ int sde_cp_ltm_off_event_handler(struct drm_crtc *crtc_drm, bool en,
* @crtc_drm: Pointer to crtc.
*/
void sde_cp_mode_switch_prop_dirty(struct drm_crtc *crtc_drm);
/**
* sde_cp_crtc_enable(): enable color processing info in the crtc.
* Should be called during crtc enable.
* @crtc: Pointer to drm_crtc.
*/
void sde_cp_crtc_enable(struct drm_crtc *crtc);
/**
* sde_cp_crtc_disable(): disable color processing info in the crtc.
* Should be called during crtc disable.
* @crtc: Pointer to drm_crtc.
*/
void sde_cp_crtc_disable(struct drm_crtc *crtc);
#endif /*_SDE_COLOR_PROCESSING_H */

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
*/
#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
@ -676,6 +676,10 @@ static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms,
bus_ab_quota = max(bw_sum_of_intfs, kms->perf.perf_tune.min_bus_vote);
bus_ib_quota = perf.max_per_pipe_ib[bus_id];
if (!kms->perf.sde_rsc_available)
bus_ib_quota = max(SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA,
bus_ib_quota);
if (kms->perf.perf_tune.mode == SDE_PERF_MODE_FIXED) {
bus_ab_quota = max(kms->perf.fix_core_ab_vote,
bus_ab_quota);

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
* 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_DEBUG("conn_roi x:%u, y:%u, w:%u, h:%u\n",
conn_roi.x, conn_roi.y,
conn_roi.w, conn_roi.h);
SDE_EVT32_VERBOSE(DRMID(crtc), DRMID(conn),
conn_roi.x, conn_roi.y,
conn_roi.w, conn_roi.h);
@ -4079,6 +4082,7 @@ static void sde_crtc_disable(struct drm_crtc *crtc)
/* disable clk & bw control until clk & bw properties are set */
cstate->bw_control = false;
cstate->bw_split_vote = false;
sde_cp_crtc_disable(crtc);
mutex_unlock(&sde_crtc->crtc_lock);
}
@ -4150,7 +4154,7 @@ static void sde_crtc_enable(struct drm_crtc *crtc,
}
sde_crtc->enabled = true;
sde_cp_crtc_enable(crtc);
/* update color processing on resume */
event.type = DRM_EVENT_CRTC_POWER;
event.length = sizeof(u32);
@ -4903,6 +4907,12 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
goto end;
}
rc = sde_cp_crtc_check_properties(crtc, state);
if (rc) {
SDE_ERROR("crtc%d failed cp properties check %d\n",
crtc->base.id, rc);
goto end;
}
end:
kfree(pstates);
kfree(multirect_plane);
@ -4989,6 +4999,26 @@ static void sde_kms_add_ubwc_info(struct sde_kms_info *info,
sde_kms_info_add_keystr(info, "DDR version", "DDR5");
}
/**
* _sde_crtc_install_cp_properties - install color properties for crtc
* @info: Pointer to kms info structure
* @catalog: Pointer to catalog structure
*/
static void _sde_crtc_install_cp_properties(struct sde_kms_info *info,
struct sde_mdss_cfg *catalog)
{
if (!info || !catalog) {
SDE_ERROR("invalid info or catalog\n");
return;
}
sde_kms_info_add_keyint(info, "has_hdr", catalog->has_hdr);
sde_kms_info_add_keyint(info, "has_hdr_plus", catalog->has_hdr_plus);
if (catalog->dspp_count && catalog->rc_count)
sde_kms_info_add_keyint(info, "rc_mem_size",
catalog->dspp[0].sblk->rc.mem_total_size);
}
/**
* sde_crtc_install_properties - install all drm properties for crtc
* @crtc: Pointer to drm crtc structure
@ -5189,8 +5219,7 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc,
}
sde_kms_info_add_keyint(info, "has_src_split", catalog->has_src_split);
sde_kms_info_add_keyint(info, "has_hdr", catalog->has_hdr);
sde_kms_info_add_keyint(info, "has_hdr_plus", catalog->has_hdr_plus);
_sde_crtc_install_cp_properties(info, catalog);
if (catalog->perf.max_bw_low)
sde_kms_info_add_keyint(info, "max_bandwidth_low",
catalog->perf.max_bw_low * 1000LL);

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

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/
#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
@ -383,6 +383,14 @@ enum {
LTM_PROP_MAX,
};
enum {
RC_OFF,
RC_LEN,
RC_VERSION,
RC_MEM_TOTAL_SIZE,
RC_PROP_MAX,
};
enum {
MIXER_OFF,
MIXER_LEN,
@ -692,6 +700,13 @@ static struct sde_prop_type ltm_prop[] = {
{LTM_VERSION, "qcom,sde-dspp-ltm-version", false, PROP_TYPE_U32},
};
static struct sde_prop_type rc_prop[] = {
{RC_OFF, "qcom,sde-dspp-rc-off", false, PROP_TYPE_U32_ARRAY},
{RC_LEN, "qcom,sde-dspp-rc-size", false, PROP_TYPE_U32},
{RC_VERSION, "qcom,sde-dspp-rc-version", false, PROP_TYPE_U32},
{RC_MEM_TOTAL_SIZE, "qcom,sde-dspp-rc-mem-size", false, PROP_TYPE_U32},
};
static struct sde_prop_type ds_top_prop[] = {
{DS_TOP_OFF, "qcom,sde-dest-scaler-top-off", false, PROP_TYPE_U32},
{DS_TOP_LEN, "qcom,sde-dest-scaler-top-size", false, PROP_TYPE_U32},
@ -2357,14 +2372,15 @@ static int sde_dspp_parse_dt(struct device_node *np,
{
int rc, prop_count[DSPP_PROP_MAX], i;
int ad_prop_count[AD_PROP_MAX];
int ltm_prop_count[LTM_PROP_MAX];
int ltm_prop_count[LTM_PROP_MAX], rc_prop_count[RC_PROP_MAX];
bool prop_exists[DSPP_PROP_MAX], ad_prop_exists[AD_PROP_MAX];
bool ltm_prop_exists[LTM_PROP_MAX];
bool ltm_prop_exists[LTM_PROP_MAX], rc_prop_exists[RC_PROP_MAX];
bool blocks_prop_exists[DSPP_BLOCKS_PROP_MAX];
struct sde_prop_value *ad_prop_value = NULL, *ltm_prop_value = NULL;
struct sde_prop_value *rc_prop_value = NULL;
int blocks_prop_count[DSPP_BLOCKS_PROP_MAX];
struct sde_prop_value *prop_value = NULL, *blocks_prop_value = NULL;
u32 off_count, ad_off_count, ltm_off_count;
u32 off_count, ad_off_count, ltm_off_count, rc_off_count;
struct sde_dspp_cfg *dspp;
struct sde_dspp_sub_blks *sblk;
struct device_node *snp = NULL;
@ -2426,6 +2442,22 @@ static int sde_dspp_parse_dt(struct device_node *np,
if (rc)
goto end;
/* Parse RC dtsi entries */
rc_prop_value = kcalloc(RC_PROP_MAX,
sizeof(struct sde_prop_value), GFP_KERNEL);
if (!rc_prop_value) {
rc = -ENOMEM;
goto end;
}
rc = _validate_dt_entry(np, rc_prop, ARRAY_SIZE(rc_prop),
rc_prop_count, &rc_off_count);
if (rc)
goto end;
rc = _read_dt_entry(np, rc_prop, ARRAY_SIZE(rc_prop), rc_prop_count,
rc_prop_exists, rc_prop_value);
if (rc)
goto end;
/* get DSPP feature dt properties if they exist */
snp = of_get_child_by_name(np, dspp_prop[DSPP_BLOCKS].prop_name);
if (snp) {
@ -2489,6 +2521,22 @@ static int sde_dspp_parse_dt(struct device_node *np,
set_bit(SDE_DSPP_LTM, &dspp->features);
}
sblk->rc.id = SDE_DSPP_RC;
sde_cfg->rc_count = rc_off_count;
if (rc_prop_value && (i < rc_off_count) &&
rc_prop_exists[RC_OFF]) {
sblk->rc.base = PROP_VALUE_ACCESS(rc_prop_value,
RC_OFF, i);
sblk->rc.len = PROP_VALUE_ACCESS(rc_prop_value,
RC_LEN, 0);
sblk->rc.version = PROP_VALUE_ACCESS(rc_prop_value,
RC_VERSION, 0);
sblk->rc.mem_total_size = PROP_VALUE_ACCESS(
rc_prop_value, RC_MEM_TOTAL_SIZE,
0);
sblk->rc.idx = i;
set_bit(SDE_DSPP_RC, &dspp->features);
}
}
end:
@ -2496,6 +2544,8 @@ static int sde_dspp_parse_dt(struct device_node *np,
kfree(ad_prop_value);
kfree(ltm_prop_value);
kfree(blocks_prop_value);
kfree(rc_prop_value);
return rc;
}
@ -4383,6 +4433,23 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
sde_cfg->allow_gdsc_toggle = true;
clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs);
clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs);
} else if (IS_KHAJE_TARGET(hw_rev)) {
sde_cfg->has_cwb_support = false;
sde_cfg->has_qsync = true;
sde_cfg->perf.min_prefill_lines = 24;
sde_cfg->vbif_qos_nlvl = 8;
sde_cfg->ts_prefill_rev = 2;
sde_cfg->ctl_rev = SDE_CTL_CFG_VERSION_1_0_0;
sde_cfg->delay_prg_fetch_start = true;
sde_cfg->sui_ns_allowed = true;
sde_cfg->sui_misr_supported = true;
sde_cfg->sui_block_xin_mask = 0xC01;
sde_cfg->has_hdr = false;
sde_cfg->has_sui_blendstage = true;
sde_cfg->allow_gdsc_toggle = true;
clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs);
clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs);
sde_cfg->rc_lm_flush_override = true;
} else {
SDE_ERROR("unsupported chipset id:%X\n", hw_rev);
sde_cfg->perf.min_prefill_lines = 0xffff;

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/
#ifndef _SDE_HW_CATALOG_H
@ -56,6 +56,7 @@
#define SDE_HW_VER_630 SDE_HW_VER(6, 3, 0) /* bengal */
#define SDE_HW_VER_640 SDE_HW_VER(6, 4, 0) /* lagoon */
#define SDE_HW_VER_650 SDE_HW_VER(6, 5, 0) /* scuba */
#define SDE_HW_VER_6100 SDE_HW_VER(6, 10, 0) /* khaje */
#define IS_MSM8996_TARGET(rev) IS_SDE_MAJOR_MINOR_SAME((rev), SDE_HW_VER_170)
#define IS_MSM8998_TARGET(rev) IS_SDE_MAJOR_MINOR_SAME((rev), SDE_HW_VER_300)
@ -71,6 +72,7 @@
#define IS_BENGAL_TARGET(rev) IS_SDE_MAJOR_MINOR_SAME((rev), SDE_HW_VER_630)
#define IS_LAGOON_TARGET(rev) IS_SDE_MAJOR_MINOR_SAME((rev), SDE_HW_VER_640)
#define IS_SCUBA_TARGET(rev) IS_SDE_MAJOR_MINOR_SAME((rev), SDE_HW_VER_650)
#define IS_KHAJE_TARGET(rev) IS_SDE_MAJOR_MINOR_SAME((rev), SDE_HW_VER_6100)
#define SDE_HW_BLK_NAME_LEN 16
@ -313,6 +315,7 @@ enum {
* @SDE_DSPP_VLUT PA VLUT block
* @SDE_DSPP_AD AD block
* @SDE_DSPP_LTM LTM block
* @SDE_DSPP_RC RC block
* @SDE_DSPP_MAX maximum value
*/
enum {
@ -328,6 +331,7 @@ enum {
SDE_DSPP_VLUT,
SDE_DSPP_AD,
SDE_DSPP_LTM,
SDE_DSPP_RC,
SDE_DSPP_MAX
};
@ -662,6 +666,20 @@ struct sde_lm_sub_blks {
struct sde_pp_blk gc;
};
/**
* struct sde_dspp_rc: Pixel processing rounded corner sub-blk information
* @info: HW register and features supported by this sub-blk.
* @version: HW Algorithm version.
* @idx: HW block instance id.
* @mem_total_size: data memory size.
*/
struct sde_dspp_rc {
SDE_HW_SUBBLK_INFO;
u32 version;
u32 idx;
u32 mem_total_size;
};
struct sde_dspp_sub_blks {
struct sde_pp_blk igc;
struct sde_pp_blk pcc;
@ -675,6 +693,7 @@ struct sde_dspp_sub_blks {
struct sde_pp_blk ad;
struct sde_pp_blk ltm;
struct sde_pp_blk vlut;
struct sde_dspp_rc rc;
};
struct sde_pingpong_sub_blks {
@ -1269,6 +1288,7 @@ struct sde_limit_cfg {
* @has_base_layer Supports staging layer as base layer
* @allow_gdsc_toggle Flag to check if gdsc toggle is needed after crtc is
* disabled when external vote is present
* @rc_lm_flush_override Support Rounded Corner using layer mixer flush
* @sc_cfg: system cache configuration
* @uidle_cfg Settings for uidle feature
* @sui_misr_supported indicate if secure-ui-misr is supported
@ -1285,6 +1305,7 @@ struct sde_limit_cfg {
* @has_vig_p010 indicates if vig pipe supports p010 format
* @inline_rot_formats formats supported by the inline rotator feature
* @mdss_irqs bitmap with the irqs supported by the target
* @rc_count number of rounded corner hardware instances
*/
struct sde_mdss_cfg {
u32 hwversion;
@ -1327,6 +1348,7 @@ struct sde_mdss_cfg {
bool update_tcsr_disp_glitch;
bool has_base_layer;
bool allow_gdsc_toggle;
bool rc_lm_flush_override;
struct sde_sc_cfg sc_cfg;
@ -1392,6 +1414,7 @@ struct sde_mdss_cfg {
u32 ad_count;
u32 ltm_count;
u32 rc_count;
u32 merge_3d_count;
struct sde_merge_3d_cfg merge_3d[MAX_BLOCKS];
@ -1439,6 +1462,7 @@ struct sde_mdss_hw_cfg_handler {
#define BLK_WB(s) ((s)->wb)
#define BLK_AD(s) ((s)->ad)
#define BLK_LTM(s) ((s)->ltm)
#define BLK_RC(s) ((s)->rc)
/**
* sde_hw_set_preference: populate the individual hw lm preferences,

View file

@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2019, 2021, The Linux Foundation. All rights reserved.
*/
#include <drm/msm_drm_pp.h>
#include "sde_hw_mdss.h"
#include "sde_hwio.h"
@ -10,6 +11,7 @@
#include "sde_hw_color_processing.h"
#include "sde_dbg.h"
#include "sde_ad4.h"
#include "sde_hw_rc.h"
#include "sde_kms.h"
static struct sde_dspp_cfg *_dspp_offset(enum sde_dspp dspp,
@ -229,6 +231,37 @@ static void dspp_ltm(struct sde_hw_dspp *c)
}
}
static void dspp_rc(struct sde_hw_dspp *c)
{
int ret = 0;
if (!c) {
SDE_ERROR("invalid arguments\n");
return;
}
if (c->cap->sblk->rc.version == SDE_COLOR_PROCESS_VER(0x1, 0x0)) {
ret = sde_hw_rc_init(c);
if (ret) {
SDE_ERROR("rc init failed, ret %d\n", ret);
return;
}
ret = reg_dmav1_init_dspp_op_v4(SDE_DSPP_RC, c->idx);
if (!ret)
c->ops.setup_rc_data =
sde_hw_rc_setup_data_dma;
else
c->ops.setup_rc_data =
sde_hw_rc_setup_data_ahb;
c->ops.validate_rc_mask = sde_hw_rc_check_mask;
c->ops.setup_rc_mask = sde_hw_rc_setup_mask;
c->ops.validate_rc_pu_roi = sde_hw_rc_check_pu_roi;
c->ops.setup_rc_pu_roi = sde_hw_rc_setup_pu_roi;
}
}
static void (*dspp_blocks[SDE_DSPP_MAX])(struct sde_hw_dspp *c);
static void _init_dspp_ops(void)
@ -245,6 +278,7 @@ static void _init_dspp_ops(void)
dspp_blocks[SDE_DSPP_VLUT] = dspp_vlut;
dspp_blocks[SDE_DSPP_AD] = dspp_ad;
dspp_blocks[SDE_DSPP_LTM] = dspp_ltm;
dspp_blocks[SDE_DSPP_RC] = dspp_rc;
}
static void _setup_dspp_ops(struct sde_hw_dspp *c, unsigned long features)
@ -274,6 +308,7 @@ struct sde_hw_dspp *sde_hw_dspp_init(enum sde_dspp idx,
struct sde_hw_dspp *c;
struct sde_dspp_cfg *cfg;
int rc;
char buf[256];
if (!addr || !m)
return ERR_PTR(-EINVAL);
@ -317,6 +352,13 @@ struct sde_hw_dspp *sde_hw_dspp_init(enum sde_dspp idx,
c->hw.xin_id);
}
if ((cfg->sblk->rc.id == SDE_DSPP_RC) && cfg->sblk->rc.base) {
snprintf(buf, ARRAY_SIZE(buf), "%s_%d", "rc", c->idx - DSPP_0);
sde_dbg_reg_register_dump_range(SDE_DBG_NAME, buf,
c->hw.blk_off + cfg->sblk->rc.base,
c->hw.blk_off + cfg->sblk->rc.base +
cfg->sblk->rc.len, c->hw.xin_id);
}
return c;
blk_init_error:

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2019, 2021, The Linux Foundation. All rights reserved.
*/
#ifndef _SDE_HW_DSPP_H
@ -209,6 +209,46 @@ struct sde_hw_dspp_ops {
* @status: Pointer to u32 where ltm status value is dumped.
*/
void (*ltm_read_intr_status)(struct sde_hw_dspp *ctx, u32 *status);
/**
* validate_rc_mask - Validate RC mask configuration
* @ctx: Pointer to dspp context.
* @cfg: Pointer to configuration.
* Return: 0 on success, non-zero otherwise.
*/
int (*validate_rc_mask)(struct sde_hw_dspp *ctx, void *cfg);
/**
* setup_rc_mask - Setup RC mask configuration
* @ctx: Pointer to dspp context.
* @cfg: Pointer to configuration.
* Return: 0 on success, non-zero otherwise.
*/
int (*setup_rc_mask)(struct sde_hw_dspp *ctx, void *cfg);
/**
* validate_rc_pu_roi - Validate RC regions in during partial update.
* @ctx: Pointer to dspp context.
* @cfg: Pointer to configuration.
* Return: 0 on success, non-zero otherwise.
*/
int (*validate_rc_pu_roi)(struct sde_hw_dspp *ctx, void *cfg);
/**
* setup_rc_pu_roi - Setup RC regions in during partial update.
* @ctx: Pointer to dspp context.
* @cfg: Pointer to configuration.
* Return: 0 on success, non-zero otherwise.
*/
int (*setup_rc_pu_roi)(struct sde_hw_dspp *ctx, void *cfg);
/**
* setup_rc_data - Program RC mask data
* @ctx: Pointer to dspp context.
* @cfg: Pointer to configuration.
* Return: 0 on success, non-zero otherwise.
*/
int (*setup_rc_data)(struct sde_hw_dspp *ctx, void *cfg);
};
/**

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2019, 2021, The Linux Foundation. All rights reserved.
*/
#ifndef _SDE_HW_MDSS_H
@ -171,6 +171,7 @@ enum sde_stage {
SDE_STAGE_10,
SDE_STAGE_MAX
};
enum sde_dspp {
DSPP_0 = 1,
DSPP_1,
@ -185,6 +186,12 @@ enum sde_ltm {
LTM_MAX
};
enum sde_rc {
RC_0 = DSPP_0,
RC_1,
RC_MAX
};
enum sde_ds {
DS_TOP,
DS_0,

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