mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-11 23:24:22 -04:00
Merge "msm: camera: sensor: Notify completion in error case" into camera-kernel.lnx.4.0
This commit is contained in:
commit
5a3fb45a2a
4 changed files with 113 additions and 21 deletions
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
@ -42,6 +42,9 @@ static void cam_cci_flush_queue(struct cci_device *cci_dev,
|
|||
void __iomem *base = soc_info->reg_map[0].mem_base;
|
||||
|
||||
cam_io_w_mb(1 << master, base + CCI_HALT_REQ_ADDR);
|
||||
if (!cci_dev->cci_master_info[master].status)
|
||||
reinit_completion(&cci_dev->cci_master_info[master]
|
||||
.reset_complete);
|
||||
rc = wait_for_completion_timeout(
|
||||
&cci_dev->cci_master_info[master].reset_complete, CCI_TIMEOUT);
|
||||
if (rc < 0) {
|
||||
|
|
@ -51,6 +54,7 @@ static void cam_cci_flush_queue(struct cci_device *cci_dev,
|
|||
|
||||
/* Set reset pending flag to true */
|
||||
cci_dev->cci_master_info[master].reset_pending = true;
|
||||
cci_dev->cci_master_info[master].status = 0;
|
||||
|
||||
/* Set proper mask to RESET CMD address based on MASTER */
|
||||
if (master == MASTER_0)
|
||||
|
|
@ -66,6 +70,7 @@ static void cam_cci_flush_queue(struct cci_device *cci_dev,
|
|||
CCI_TIMEOUT);
|
||||
if (rc <= 0)
|
||||
CAM_ERR(CAM_CCI, "wait failed %d", rc);
|
||||
cci_dev->cci_master_info[master].status = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -127,8 +132,10 @@ static int32_t cam_cci_validate_queue(struct cci_device *cci_dev,
|
|||
return rc;
|
||||
}
|
||||
rc = cci_dev->cci_master_info[master].status;
|
||||
if (rc < 0)
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_CCI, "Failed rc %d", rc);
|
||||
cci_dev->cci_master_info[master].status = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
|
@ -246,14 +253,16 @@ static uint32_t cam_cci_wait(struct cci_device *cci_dev,
|
|||
cam_cci_dump_registers(cci_dev, master, queue);
|
||||
#endif
|
||||
CAM_ERR(CAM_CCI, "wait for queue: %d", queue);
|
||||
if (rc == 0)
|
||||
if (rc == 0) {
|
||||
rc = -ETIMEDOUT;
|
||||
cam_cci_flush_queue(cci_dev, master);
|
||||
return rc;
|
||||
cam_cci_flush_queue(cci_dev, master);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
rc = cci_dev->cci_master_info[master].status;
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_CCI, "failed rc %d", rc);
|
||||
cci_dev->cci_master_info[master].status = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -851,7 +860,8 @@ static int32_t cam_cci_data_queue(struct cci_device *cci_dev,
|
|||
|
||||
rc = cam_cci_transfer_end(cci_dev, master, queue);
|
||||
if (rc < 0) {
|
||||
CAM_ERR(CAM_CCI, "failed rc %d", rc);
|
||||
CAM_ERR(CAM_CCI, "Slave: 0x%x failed rc %d",
|
||||
(c_ctrl->cci_info->sid << 1), rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -918,6 +928,7 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
|
|||
mutex_unlock(&cci_dev->cci_master_info[master].mutex);
|
||||
|
||||
mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
|
||||
reinit_completion(&cci_dev->cci_master_info[master].report_q[queue]);
|
||||
/*
|
||||
* Call validate queue to make sure queue is empty before starting.
|
||||
* If this call fails, don't proceed with i2c_read call. This is to
|
||||
|
|
@ -1024,6 +1035,14 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
|
|||
goto rel_mutex_q;
|
||||
}
|
||||
|
||||
if (cci_dev->cci_master_info[master].status) {
|
||||
CAM_ERR(CAM_CCI, "Error with Salve: 0x%x",
|
||||
(c_ctrl->cci_info->sid << 1));
|
||||
rc = -EINVAL;
|
||||
cci_dev->cci_master_info[master].status = 0;
|
||||
goto rel_mutex_q;
|
||||
}
|
||||
|
||||
read_words = cam_io_r_mb(base +
|
||||
CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100);
|
||||
if (read_words <= 0) {
|
||||
|
|
@ -1104,6 +1123,14 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
|
|||
cam_cci_flush_queue(cci_dev, master);
|
||||
goto rel_mutex_q;
|
||||
}
|
||||
|
||||
if (cci_dev->cci_master_info[master].status) {
|
||||
CAM_ERR(CAM_CCI, "Error with Slave 0x%x",
|
||||
(c_ctrl->cci_info->sid << 1));
|
||||
rc = -EINVAL;
|
||||
cci_dev->cci_master_info[master].status = 0;
|
||||
goto rel_mutex_q;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1183,6 +1210,7 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
|
|||
mutex_unlock(&cci_dev->cci_master_info[master].mutex);
|
||||
|
||||
mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
|
||||
reinit_completion(&cci_dev->cci_master_info[master].report_q[queue]);
|
||||
/*
|
||||
* Call validate queue to make sure queue is empty before starting.
|
||||
* If this call fails, don't proceed with i2c_read call. This is to
|
||||
|
|
@ -1290,6 +1318,14 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
|
|||
rc = 0;
|
||||
}
|
||||
|
||||
if (cci_dev->cci_master_info[master].status) {
|
||||
CAM_ERR(CAM_CCI, "ERROR with Slave 0x%x:",
|
||||
(c_ctrl->cci_info->sid << 1));
|
||||
rc = -EINVAL;
|
||||
cci_dev->cci_master_info[master].status = 0;
|
||||
goto rel_mutex_q;
|
||||
}
|
||||
|
||||
read_words = cam_io_r_mb(base +
|
||||
CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100);
|
||||
exp_words = ((read_cfg->num_byte / 4) + 1);
|
||||
|
|
@ -1384,6 +1420,8 @@ static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd,
|
|||
goto ERROR;
|
||||
}
|
||||
mutex_unlock(&cci_dev->cci_master_info[master].mutex);
|
||||
|
||||
reinit_completion(&cci_dev->cci_master_info[master].report_q[queue]);
|
||||
/*
|
||||
* Call validate queue to make sure queue is empty before starting.
|
||||
* If this call fails, don't proceed with i2c_write call. This is to
|
||||
|
|
@ -1546,6 +1584,7 @@ static int32_t cam_cci_read_bytes(struct v4l2_subdev *sd,
|
|||
* THRESHOLD irq's, we reinit the threshold wait before
|
||||
* we load the burst read cmd.
|
||||
*/
|
||||
reinit_completion(&cci_dev->cci_master_info[master].rd_done);
|
||||
reinit_completion(&cci_dev->cci_master_info[master].th_complete);
|
||||
|
||||
CAM_DBG(CAM_CCI, "Bytes to read %u", read_bytes);
|
||||
|
|
@ -1687,7 +1726,29 @@ int32_t cam_cci_core_cfg(struct v4l2_subdev *sd,
|
|||
{
|
||||
int32_t rc = 0;
|
||||
struct cci_device *cci_dev = v4l2_get_subdevdata(sd);
|
||||
CAM_DBG(CAM_CCI, "cmd %d", cci_ctrl->cmd);
|
||||
enum cci_i2c_master_t master = MASTER_MAX;
|
||||
|
||||
if (!cci_dev) {
|
||||
CAM_ERR(CAM_CCI, "CCI_DEV IS NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!cci_ctrl) {
|
||||
CAM_ERR(CAM_CCI, "CCI_CTRL IS NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
master = cci_ctrl->cci_info->cci_i2c_master;
|
||||
if (master >= MASTER_MAX) {
|
||||
CAM_ERR(CAM_CCI, "INVALID MASTER: %d", master);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cci_dev->cci_master_info[master].status < 0) {
|
||||
CAM_WARN(CAM_CCI, "CCI hardware is resetting");
|
||||
return -EAGAIN;
|
||||
}
|
||||
CAM_DBG(CAM_CCI, "master = %d, cmd = %d", master, cci_ctrl->cmd);
|
||||
|
||||
switch (cci_ctrl->cmd) {
|
||||
case MSM_CCI_INIT:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "cam_cci_dev.h"
|
||||
|
|
@ -82,7 +82,9 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
|
|||
false;
|
||||
if (!cci_master_info->status)
|
||||
complete(&cci_master_info->reset_complete);
|
||||
cci_master_info->status = 0;
|
||||
|
||||
complete_all(&cci_master_info->rd_done);
|
||||
complete_all(&cci_master_info->th_complete);
|
||||
}
|
||||
if (cci_dev->cci_master_info[MASTER_1].reset_pending == true) {
|
||||
cci_master_info = &cci_dev->cci_master_info[MASTER_1];
|
||||
|
|
@ -90,7 +92,9 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
|
|||
false;
|
||||
if (!cci_master_info->status)
|
||||
complete(&cci_master_info->reset_complete);
|
||||
cci_master_info->status = 0;
|
||||
|
||||
complete_all(&cci_master_info->rd_done);
|
||||
complete_all(&cci_master_info->th_complete);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -223,9 +227,18 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
|
|||
}
|
||||
if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK) {
|
||||
cci_dev->cci_master_info[MASTER_0].status = -EINVAL;
|
||||
if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK)
|
||||
CAM_ERR(CAM_CCI, "Base:%pK, M0 NACK ERROR: 0x%x",
|
||||
if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0_NACK_ERROR_BMSK) {
|
||||
CAM_ERR(CAM_CCI, "Base:%pK, M0_Q0 NACK ERROR: 0x%x",
|
||||
base, irq_status0);
|
||||
complete_all(&cci_dev->cci_master_info[MASTER_0]
|
||||
.report_q[QUEUE_0]);
|
||||
}
|
||||
if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q1_NACK_ERROR_BMSK) {
|
||||
CAM_ERR(CAM_CCI, "Base:%pK, M0_Q1 NACK ERROR: 0x%x",
|
||||
base, irq_status0);
|
||||
complete_all(&cci_dev->cci_master_info[MASTER_0]
|
||||
.report_q[QUEUE_1]);
|
||||
}
|
||||
if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK)
|
||||
CAM_ERR(CAM_CCI,
|
||||
"Base:%pK, M0 QUEUE_OVER/UNDER_FLOW OR CMD ERR: 0x%x",
|
||||
|
|
@ -234,22 +247,35 @@ irqreturn_t cam_cci_irq(int irq_num, void *data)
|
|||
CAM_ERR(CAM_CCI,
|
||||
"Base: %pK, M0 RD_OVER/UNDER_FLOW ERROR: 0x%x",
|
||||
base, irq_status0);
|
||||
cam_io_w_mb(CCI_M0_HALT_REQ_RMSK, base + CCI_HALT_REQ_ADDR);
|
||||
|
||||
cci_dev->cci_master_info[MASTER_0].reset_pending = true;
|
||||
cam_io_w_mb(CCI_M0_RESET_RMSK, base + CCI_RESET_CMD_ADDR);
|
||||
}
|
||||
if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK) {
|
||||
cci_dev->cci_master_info[MASTER_1].status = -EINVAL;
|
||||
if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK)
|
||||
CAM_ERR(CAM_CCI, "Base:%pK, M1 NACK ERROR: 0x%x",
|
||||
if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_Q0_NACK_ERROR_BMSK) {
|
||||
CAM_ERR(CAM_CCI, "Base:%pK, M1_Q0 NACK ERROR: 0x%x",
|
||||
base, irq_status0);
|
||||
if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK)
|
||||
complete_all(&cci_dev->cci_master_info[MASTER_1]
|
||||
.report_q[QUEUE_0]);
|
||||
}
|
||||
if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_Q1_NACK_ERROR_BMSK) {
|
||||
CAM_ERR(CAM_CCI, "Base:%pK, M1_Q1 NACK ERROR: 0x%x",
|
||||
base, irq_status0);
|
||||
complete_all(&cci_dev->cci_master_info[MASTER_1]
|
||||
.report_q[QUEUE_1]);
|
||||
}
|
||||
if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_Q0Q1_ERROR_BMSK)
|
||||
CAM_ERR(CAM_CCI,
|
||||
"Base:%pK, M1 QUEUE_OVER_UNDER_FLOW OR CMD ERROR:0x%x",
|
||||
base, irq_status0);
|
||||
if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M0_RD_ERROR_BMSK)
|
||||
if (irq_status0 & CCI_IRQ_STATUS_0_I2C_M1_RD_ERROR_BMSK)
|
||||
CAM_ERR(CAM_CCI,
|
||||
"Base:%pK, M1 RD_OVER/UNDER_FLOW ERROR: 0x%x",
|
||||
base, irq_status0);
|
||||
cam_io_w_mb(CCI_M1_HALT_REQ_RMSK, base + CCI_HALT_REQ_ADDR);
|
||||
|
||||
cci_dev->cci_master_info[MASTER_1].reset_pending = true;
|
||||
cam_io_w_mb(CCI_M1_RESET_RMSK, base + CCI_RESET_CMD_ADDR);
|
||||
}
|
||||
|
||||
cam_io_w_mb(irq_status0, base + CCI_IRQ_CLEAR_0_ADDR);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2012-2015, 2017-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2012-2015, 2017-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_CCI_HWREG_
|
||||
|
|
@ -54,8 +54,10 @@
|
|||
#define CCI_IRQ_STATUS_0_I2C_M0_Q0_REPORT_BMSK 0x10
|
||||
#define CCI_IRQ_STATUS_0_I2C_M0_ERROR_BMSK 0x18000EE6
|
||||
#define CCI_IRQ_STATUS_0_I2C_M1_ERROR_BMSK 0x60EE6000
|
||||
#define CCI_IRQ_STATUS_0_I2C_M0_NACK_ERROR_BMSK 0x18000000
|
||||
#define CCI_IRQ_STATUS_0_I2C_M1_NACK_ERROR_BMSK 0x60000000
|
||||
#define CCI_IRQ_STATUS_0_I2C_M0_Q0_NACK_ERROR_BMSK 0x8000000
|
||||
#define CCI_IRQ_STATUS_0_I2C_M0_Q1_NACK_ERROR_BMSK 0x10000000
|
||||
#define CCI_IRQ_STATUS_0_I2C_M1_Q0_NACK_ERROR_BMSK 0x20000000
|
||||
#define CCI_IRQ_STATUS_0_I2C_M1_Q1_NACK_ERROR_BMSK 0x40000000
|
||||
#define CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_ERROR_BMSK 0xEE0
|
||||
#define CCI_IRQ_STATUS_0_I2C_M1_Q0Q1_ERROR_BMSK 0xEE0000
|
||||
#define CCI_IRQ_STATUS_0_I2C_M0_RD_ERROR_BMSK 0x6
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ int cam_cci_init(struct v4l2_subdev *sd,
|
|||
&cci_dev->cci_master_info[master].report_q[i]);
|
||||
/* Set reset pending flag to true */
|
||||
cci_dev->cci_master_info[master].reset_pending = true;
|
||||
cci_dev->cci_master_info[master].status = 0;
|
||||
/* Set proper mask to RESET CMD address */
|
||||
if (master == MASTER_0)
|
||||
cam_io_w_mb(CCI_M0_RESET_RMSK,
|
||||
|
|
@ -68,6 +69,7 @@ int cam_cci_init(struct v4l2_subdev *sd,
|
|||
CCI_TIMEOUT);
|
||||
if (rc <= 0)
|
||||
CAM_ERR(CAM_CCI, "wait failed %d", rc);
|
||||
cci_dev->cci_master_info[master].status = 0;
|
||||
mutex_unlock(&cci_dev->cci_master_info[master].mutex);
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -142,6 +144,7 @@ int cam_cci_init(struct v4l2_subdev *sd,
|
|||
}
|
||||
|
||||
cci_dev->cci_master_info[master].reset_pending = true;
|
||||
cci_dev->cci_master_info[master].status = 0;
|
||||
cam_io_w_mb(CCI_RESET_CMD_RMSK, base +
|
||||
CCI_RESET_CMD_ADDR);
|
||||
cam_io_w_mb(0x1, base + CCI_RESET_CMD_ADDR);
|
||||
|
|
|
|||
Loading…
Reference in a new issue