msm: camera: isp: Add support for BUS IRQ controller
Initialize BUS IRQ controller. Remove hard code subscribe of IRQ mask
and add independent subscribe/unsubscribe for each WM/composite_group.
Change-Id: I02983ae9811c33ec353b2d1caecbd5c84f7177ae
Signed-off-by: Harsh Shah <harshs@codeaurora.org>
Signed-off-by: Soundrapandian Jeyaprakash <jsoundra@codeaurora.org>
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
index 9203ee6..07a7612 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
@@ -17,8 +17,10 @@
#include "cam_io_util.h"
#include "cam_cdm_util.h"
#include "cam_hw_intf.h"
+#include "cam_ife_hw_mgr.h"
#include "cam_vfe_hw_intf.h"
#include "cam_irq_controller.h"
+#include "cam_tasklet_util.h"
#include "cam_vfe_bus.h"
#include "cam_vfe_bus_ver2.h"
#include "cam_vfe_core.h"
@@ -26,28 +28,25 @@
#undef CDBG
#define CDBG(fmt, args...) pr_debug(fmt, ##args)
-#define FRAME_BASED_EN 0
+static const char drv_name[] = "vfe_bus";
+
+#define CAM_VFE_BUS_IRQ_REG0 0
+#define CAM_VFE_BUS_IRQ_REG1 1
+#define CAM_VFE_BUS_IRQ_REG2 2
+#define CAM_VFE_BUS_IRQ_MAX 3
+
+#define CAM_VFE_BUS_VER2_PAYLOAD_MAX 256
#define MAX_BUF_UPDATE_REG_NUM \
(sizeof(struct cam_vfe_bus_ver2_reg_offset_bus_client)/4)
#define MAX_REG_VAL_PAIR_SIZE \
- (MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES)
+ (MAX_BUF_UPDATE_REG_NUM * 2 * CAM_PACKET_MAX_PLANES)
#define CAM_VFE_ADD_REG_VAL_PAIR(buf_array, index, offset, val) \
- do { \
- buf_array[index++] = offset; \
- buf_array[index++] = val; \
- } while (0)
-
-static uint32_t irq_reg_offset[CAM_IFE_BUS_IRQ_REGISTERS_MAX] = {
- 0x0000205C,
- 0x00002060,
- 0x00002064,
- 0x0000206C,
- 0x00002070,
- 0x00002074,
- 0x00002078,
-};
+ do { \
+ buf_array[index++] = offset; \
+ buf_array[index++] = val; \
+ } while (0)
enum cam_vfe_bus_packer_format {
PACKER_FMT_PLAIN_128 = 0x0,
@@ -70,23 +69,29 @@
};
struct cam_vfe_bus_ver2_common_data {
+ uint32_t core_index;
void __iomem *mem_base;
struct cam_hw_intf *hw_intf;
void *bus_irq_controller;
void *vfe_irq_controller;
struct cam_vfe_bus_ver2_reg_offset_common *common_reg;
uint32_t io_buf_update[
- MAX_REG_VAL_PAIR_SIZE];
+ MAX_REG_VAL_PAIR_SIZE];
+
+ struct cam_vfe_bus_irq_evt_payload evt_payload[
+ CAM_VFE_BUS_VER2_PAYLOAD_MAX];
+ struct list_head free_payload_list;
};
struct cam_vfe_bus_ver2_wm_resource_data {
uint32_t index;
struct cam_vfe_bus_ver2_common_data *common_data;
struct cam_vfe_bus_ver2_reg_offset_bus_client *hw_regs;
+ void *ctx;
uint32_t irq_enabled;
-
uint32_t init_cfg_done;
+
uint32_t offset;
uint32_t width;
uint32_t height;
@@ -127,6 +132,8 @@
uint32_t dual_slave_core;
uint32_t intra_client_mask;
uint32_t composite_mask;
+
+ void *ctx;
};
struct cam_vfe_bus_ver2_vfe_out_data {
@@ -147,7 +154,6 @@
struct cam_cdm_utils_ops *cdm_util_ops;
};
-
struct cam_vfe_bus_ver2_priv {
struct cam_vfe_bus_ver2_common_data common_data;
@@ -159,12 +165,59 @@
struct list_head free_dual_comp_grp;
struct list_head used_comp_grp;
- struct cam_vfe_bus_irq_evt_payload evt_payload[128];
- struct list_head free_payload_list;
+ uint32_t irq_handle;
};
+static int cam_vfe_bus_get_evt_payload(
+ struct cam_vfe_bus_ver2_common_data *common_data,
+ struct cam_vfe_bus_irq_evt_payload **evt_payload)
+{
+ if (list_empty(&common_data->free_payload_list)) {
+ *evt_payload = NULL;
+ pr_err("No free payload\n");
+ return -ENODEV;
+ }
+
+ *evt_payload = list_first_entry(&common_data->free_payload_list,
+ struct cam_vfe_bus_irq_evt_payload, list);
+ list_del_init(&(*evt_payload)->list);
+ return 0;
+}
+
static int cam_vfe_bus_put_evt_payload(void *core_info,
- struct cam_vfe_bus_irq_evt_payload **evt_payload);
+ struct cam_vfe_bus_irq_evt_payload **evt_payload)
+{
+ struct cam_vfe_bus_ver2_common_data *common_data = NULL;
+ uint32_t *ife_irq_regs = NULL;
+ uint32_t status_reg0, status_reg1, status_reg2;
+
+ if (!core_info) {
+ pr_err("Invalid param core_info NULL");
+ return -EINVAL;
+ }
+ if (*evt_payload == NULL) {
+ pr_err("No payload to put\n");
+ return -EINVAL;
+ }
+
+ ife_irq_regs = (*evt_payload)->irq_reg_val;
+ status_reg0 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
+ status_reg1 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
+ status_reg2 = ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS2];
+
+ if (status_reg0 || status_reg1 || status_reg2) {
+ CDBG("status0 0x%x status1 0x%x status2 0x%x\n",
+ status_reg0, status_reg1, status_reg2);
+ return 0;
+ }
+
+ common_data = core_info;
+ list_add_tail(&(*evt_payload)->list,
+ &common_data->free_payload_list);
+ *evt_payload = NULL;
+
+ return 0;
+}
static int cam_vfe_bus_ver2_get_intra_client_mask(
enum cam_vfe_bus_ver2_vfe_core_id dual_slave_core,
@@ -592,6 +645,8 @@
static int cam_vfe_bus_acquire_wm(
struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
struct cam_isp_out_port_info *out_port_info,
+ void *tasklet,
+ void *ctx,
enum cam_vfe_bus_ver2_vfe_out_type vfe_out_res_id,
enum cam_vfe_bus_plane_type plane,
enum cam_isp_hw_split_id split_id,
@@ -615,10 +670,12 @@
}
wm_res_local = &ver2_bus_priv->bus_client[wm_idx];
+ wm_res_local->tasklet_info = tasklet;
wm_res_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
rsrc_data = wm_res_local->res_priv;
rsrc_data->irq_enabled = subscribe_irq;
+ rsrc_data->ctx = ctx;
rsrc_data->format = out_port_info->format;
rsrc_data->pack_fmt = cam_vfe_bus_get_packer_fmt(rsrc_data->format);
@@ -718,6 +775,8 @@
rsrc_data->ubwc_meta_offset = 0;
rsrc_data->init_cfg_done = 0;
rsrc_data->en_cfg = 0;
+
+ wm_res->tasklet_info = NULL;
wm_res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
return 0;
@@ -730,6 +789,7 @@
wm_res->res_priv;
struct cam_vfe_bus_ver2_common_data *common_data =
rsrc_data->common_data;
+ uint32_t bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_addr);
cam_io_w_mb(0, common_data->mem_base + rsrc_data->hw_regs->header_cfg);
@@ -753,6 +813,28 @@
cam_io_w(0x0,
common_data->mem_base + rsrc_data->hw_regs->framedrop_period);
+ /* Subscribe IRQ */
+ if (rsrc_data->irq_enabled) {
+ CDBG("Subscribe WM%d IRQ\n", rsrc_data->index);
+ bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG1] =
+ (1 << rsrc_data->index);
+ wm_res->irq_handle = cam_irq_controller_subscribe_irq(
+ common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1,
+ bus_irq_reg_mask, wm_res,
+ wm_res->top_half_handler,
+ cam_ife_mgr_do_tasklet_buf_done,
+ wm_res->tasklet_info, cam_tasklet_enqueue_cmd);
+ if (wm_res->irq_handle < 0) {
+ pr_err("Subscribe IRQ failed for WM %d\n",
+ rsrc_data->index);
+ return -EFAULT;
+ }
+ }
+
+ /* Enable WM */
+ cam_io_w_mb(rsrc_data->en_cfg, common_data->mem_base +
+ rsrc_data->hw_regs->cfg);
+
CDBG("WM res %d width = %d, height = %d\n", rsrc_data->index,
rsrc_data->width, rsrc_data->height);
CDBG("WM res %d pk_fmt = %d\n", rsrc_data->index,
@@ -781,12 +863,10 @@
CDBG("irq_enabled %d", rsrc_data->irq_enabled);
/* Unsubscribe IRQ */
- if (rsrc_data->irq_enabled) {
- /*
- * Currently all WM IRQ are unsubscribed in one place. Need to
- * make it dynamic.
- */
- }
+ if (rsrc_data->irq_enabled)
+ rc = cam_irq_controller_unsubscribe_irq(
+ common_data->bus_irq_controller,
+ wm_res->irq_handle);
/* Halt & Reset WM */
cam_io_w_mb(BIT(rsrc_data->index),
@@ -800,7 +880,42 @@
static int cam_vfe_bus_handle_wm_done_top_half(uint32_t evt_id,
struct cam_irq_th_payload *th_payload)
{
- return -EPERM;
+ int32_t rc;
+ int i;
+ struct cam_isp_resource_node *wm_res = NULL;
+ struct cam_vfe_bus_ver2_wm_resource_data *rsrc_data = NULL;
+ struct cam_vfe_bus_irq_evt_payload *evt_payload;
+
+ wm_res = th_payload->handler_priv;
+ if (!wm_res) {
+ pr_err_ratelimited("Error! No resource\n");
+ return -ENODEV;
+ }
+
+ rsrc_data = wm_res->res_priv;
+
+ CDBG("IRQ status_0 = %x\n", th_payload->evt_status_arr[0]);
+ CDBG("IRQ status_1 = %x\n", th_payload->evt_status_arr[1]);
+
+ rc = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
+ if (rc) {
+ pr_err_ratelimited("No tasklet_cmd is free in queue\n");
+ return rc;
+ }
+
+ cam_isp_hw_get_timestamp(&evt_payload->ts);
+
+ evt_payload->ctx = rsrc_data->ctx;
+ evt_payload->core_index = rsrc_data->common_data->core_index;
+ evt_payload->evt_id = evt_id;
+
+ for (i = 0; i < th_payload->num_registers; i++)
+ evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
+
+ th_payload->evt_payload_priv = evt_payload;
+
+ CDBG("Exit\n");
+ return rc;
}
static int cam_vfe_bus_handle_wm_done_bottom_half(void *wm_node,
@@ -825,9 +940,10 @@
~BIT(rsrc_data->index);
rc = CAM_VFE_IRQ_STATUS_SUCCESS;
}
+ CDBG("status_reg %x rc %d\n", status_reg, rc);
if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
- cam_vfe_bus_put_evt_payload(evt_payload->core_info,
+ cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
&evt_payload);
return rc;
@@ -924,6 +1040,8 @@
static int cam_vfe_bus_acquire_comp_grp(
struct cam_vfe_bus_ver2_priv *ver2_bus_priv,
struct cam_isp_out_port_info *out_port_info,
+ void *tasklet,
+ void *ctx,
uint32_t unique_id,
uint32_t is_dual,
uint32_t is_master,
@@ -965,6 +1083,7 @@
}
list_del(&comp_grp_local->list);
+ comp_grp_local->tasklet_info = tasklet;
comp_grp_local->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
rsrc_data->is_master = is_master;
@@ -987,6 +1106,7 @@
}
}
+ rsrc_data->ctx = ctx;
*comp_grp = comp_grp_local;
return rc;
@@ -1040,6 +1160,7 @@
in_rsrc_data->composite_mask = 0;
in_rsrc_data->dual_slave_core = CAM_VFE_BUS_VER2_VFE_CORE_MAX;
+ comp_grp->tasklet_info = NULL;
comp_grp->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE;
return 0;
@@ -1052,11 +1173,7 @@
comp_grp->res_priv;
struct cam_vfe_bus_ver2_common_data *common_data =
rsrc_data->common_data;
-
- /*
- * Individual Comp_Grp Subscribe IRQ can be done here once
- * dynamic IRQ enable support is added.
- */
+ uint32_t bus_irq_reg_mask[CAM_VFE_BUS_IRQ_MAX] = {0};
cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
rsrc_data->hw_regs->comp_mask);
@@ -1078,9 +1195,30 @@
cam_io_w_mb(intra_client_en, common_data->mem_base +
common_data->common_reg->dual_master_comp_cfg);
+
+ bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG2] = (1 << dual_comp_grp);
+ } else {
+ /* IRQ bits for COMP GRP start at 5. So add 5 to the shift */
+ bus_irq_reg_mask[CAM_VFE_BUS_IRQ_REG0] =
+ (1 << (rsrc_data->comp_grp_type + 5));
+ }
+
+ /* Subscribe IRQ */
+ CDBG("Subscribe COMP_GRP%d IRQ\n", rsrc_data->comp_grp_type);
+ comp_grp->irq_handle = cam_irq_controller_subscribe_irq(
+ common_data->bus_irq_controller, CAM_IRQ_PRIORITY_1,
+ bus_irq_reg_mask, comp_grp,
+ comp_grp->top_half_handler,
+ cam_ife_mgr_do_tasklet_buf_done,
+ comp_grp->tasklet_info, cam_tasklet_enqueue_cmd);
+ if (comp_grp->irq_handle < 0) {
+ pr_err("Subscribe IRQ failed for comp_grp %d\n",
+ rsrc_data->comp_grp_type);
+ return -EFAULT;
}
comp_grp->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
+
return rc;
}
@@ -1093,6 +1231,9 @@
rsrc_data->common_data;
/* Unsubscribe IRQ */
+ rc = cam_irq_controller_unsubscribe_irq(
+ common_data->bus_irq_controller,
+ comp_grp->irq_handle);
cam_io_w_mb(rsrc_data->composite_mask, common_data->mem_base +
rsrc_data->hw_regs->comp_mask);
@@ -1120,7 +1261,42 @@
static int cam_vfe_bus_handle_comp_done_top_half(uint32_t evt_id,
struct cam_irq_th_payload *th_payload)
{
- return -EPERM;
+ int32_t rc;
+ int i;
+ struct cam_isp_resource_node *comp_grp = NULL;
+ struct cam_vfe_bus_ver2_comp_grp_data *rsrc_data = NULL;
+ struct cam_vfe_bus_irq_evt_payload *evt_payload;
+
+ comp_grp = th_payload->handler_priv;
+ if (!comp_grp) {
+ pr_err_ratelimited("Error! No resource\n");
+ return -ENODEV;
+ }
+
+ rsrc_data = comp_grp->res_priv;
+
+ CDBG("IRQ status_0 = %x\n", th_payload->evt_status_arr[0]);
+ CDBG("IRQ status_1 = %x\n", th_payload->evt_status_arr[1]);
+
+ rc = cam_vfe_bus_get_evt_payload(rsrc_data->common_data, &evt_payload);
+ if (rc) {
+ pr_err_ratelimited("No tasklet_cmd is free in queue\n");
+ return rc;
+ }
+
+ cam_isp_hw_get_timestamp(&evt_payload->ts);
+
+ evt_payload->ctx = rsrc_data->ctx;
+ evt_payload->core_index = rsrc_data->common_data->core_index;
+ evt_payload->evt_id = evt_id;
+
+ for (i = 0; i < th_payload->num_registers; i++)
+ evt_payload->irq_reg_val[i] = th_payload->evt_status_arr[i];
+
+ th_payload->evt_payload_priv = evt_payload;
+
+ CDBG("Exit\n");
+ return rc;
}
static int cam_vfe_bus_handle_comp_done_bottom_half(
@@ -1136,12 +1312,13 @@
uint32_t comp_err_reg;
uint32_t comp_grp_id;
+ CDBG("comp grp type %d\n", rsrc_data->comp_grp_type);
+
if (!evt_payload)
return rc;
cam_ife_irq_regs = evt_payload->irq_reg_val;
- CDBG("comp grp type %d\n", rsrc_data->comp_grp_type);
switch (rsrc_data->comp_grp_type) {
case CAM_VFE_BUS_VER2_COMP_GRP_0:
case CAM_VFE_BUS_VER2_COMP_GRP_1:
@@ -1178,8 +1355,8 @@
rc = CAM_VFE_IRQ_STATUS_SUCCESS;
}
- CDBG("status reg = 0x%x, bit index = %d\n",
- status_reg, (comp_grp_id + 5));
+ CDBG("status reg = 0x%x, bit index = %d rc %d\n",
+ status_reg, (comp_grp_id + 5), rc);
break;
case CAM_VFE_BUS_VER2_COMP_GRP_DUAL_0:
@@ -1220,11 +1397,13 @@
break;
default:
rc = CAM_VFE_IRQ_STATUS_ERR;
+ pr_err("Error! Invalid comp_grp_type %u\n",
+ rsrc_data->comp_grp_type);
break;
}
if (rc == CAM_VFE_IRQ_STATUS_SUCCESS)
- cam_vfe_bus_put_evt_payload(evt_payload->core_info,
+ cam_vfe_bus_put_evt_payload(rsrc_data->common_data,
&evt_payload);
return rc;
@@ -1297,7 +1476,8 @@
return 0;
}
-static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args)
+static int cam_vfe_bus_acquire_vfe_out(void *bus_priv, void *acquire_args,
+ uint32_t args_size)
{
int rc = -ENODEV;
int i;
@@ -1353,30 +1533,43 @@
CAM_ISP_RES_COMP_GROUP_ID_MAX)) {
rc = cam_vfe_bus_acquire_comp_grp(ver2_bus_priv,
out_acquire_args->out_port_info,
+ acq_args->tasklet,
+ out_acquire_args->ctx,
out_acquire_args->unique_id,
out_acquire_args->is_dual,
out_acquire_args->is_master,
out_acquire_args->dual_slave_core,
&rsrc_data->comp_grp);
- if (rc < 0)
+ if (rc) {
+ pr_err("VFE%d Comp_Grp acquire failed for Out %d rc=%d\n",
+ rsrc_data->common_data->core_index,
+ vfe_out_res_id, rc);
return rc;
+ }
subscribe_irq = 0;
- } else
+ } else {
subscribe_irq = 1;
+ }
/* Reserve WM */
for (i = 0; i < num_wm; i++) {
rc = cam_vfe_bus_acquire_wm(ver2_bus_priv,
out_acquire_args->out_port_info,
+ acq_args->tasklet,
+ out_acquire_args->ctx,
vfe_out_res_id,
i,
out_acquire_args->split_id,
subscribe_irq,
&rsrc_data->wm_res[i],
&client_done_mask);
- if (rc < 0)
+ if (rc) {
+ pr_err("VFE%d WM acquire failed for Out %d rc=%d\n",
+ rsrc_data->common_data->core_index,
+ vfe_out_res_id, rc);
goto release_wm;
+ }
if (rsrc_data->comp_grp)
cam_vfe_bus_add_wm_to_comp_grp(rsrc_data->comp_grp,
@@ -1399,11 +1592,21 @@
return rc;
}
-static int cam_vfe_bus_release_vfe_out(void *bus_priv,
- struct cam_isp_resource_node *vfe_out)
+static int cam_vfe_bus_release_vfe_out(void *bus_priv, void *release_args,
+ uint32_t args_size)
{
uint32_t i;
- struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
+ struct cam_isp_resource_node *vfe_out = NULL;
+ struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
+
+ if (!bus_priv || !release_args) {
+ pr_err("Invalid input bus_priv %pK release_args %pK\n",
+ bus_priv, release_args);
+ return -EINVAL;
+ }
+
+ vfe_out = release_args;
+ rsrc_data = vfe_out->res_priv;
if (vfe_out->res_state != CAM_ISP_RESOURCE_STATE_RESERVED) {
pr_err("Error! Invalid resource state:%d\n",
@@ -1428,12 +1631,20 @@
return 0;
}
-static int cam_vfe_bus_start_vfe_out(struct cam_isp_resource_node *vfe_out)
+static int cam_vfe_bus_start_vfe_out(
+ struct cam_isp_resource_node *vfe_out)
{
int rc = 0, i;
- struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
- struct cam_vfe_bus_ver2_common_data *common_data =
- rsrc_data->common_data;
+ struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
+ struct cam_vfe_bus_ver2_common_data *common_data = NULL;
+
+ if (!vfe_out) {
+ pr_err("Invalid input\n");
+ return -EINVAL;
+ }
+
+ rsrc_data = vfe_out->res_priv;
+ common_data = rsrc_data->common_data;
CDBG("Start resource index %d\n", rsrc_data->out_type);
@@ -1443,28 +1654,12 @@
return -EACCES;
}
- /* Enable IRQ Mask */
- cam_io_w_mb(0x00001FE0, common_data->mem_base + 0x2044);
- cam_io_w_mb(0x000FFFE7, common_data->mem_base + 0x2048);
- cam_io_w_mb(0x000000FF, common_data->mem_base + 0x204c);
-
for (i = 0; i < rsrc_data->num_wm; i++)
rc = cam_vfe_bus_start_wm(rsrc_data->wm_res[i]);
if (rsrc_data->comp_grp)
rc = cam_vfe_bus_start_comp_grp(rsrc_data->comp_grp);
- /* VFE_MODULE_BUS_CGC_OVERRIDE */
- cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x0000003C);
- /* VFE_MODULE_COLOR_CGC_OVERRIDE */
- cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x00000034);
- /* VFE_MODULE_ZOOM_CGC_OVERRIDE */
- cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x38);
- /* VFE_MODULE_LENS_CGC_OVERRIDE */
- cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x0000002C);
- /* VFE_MODULE_STATS_CGC_OVERRIDE */
- cam_io_w_mb(0xFFFFFFFF, rsrc_data->common_data->mem_base + 0x00000030);
-
/* BUS_WR_INPUT_IF_ADDR_SYNC_CFG */
cam_io_w_mb(0x0, rsrc_data->common_data->mem_base + 0x0000207C);
/* BUS_WR_INPUT_IF_ADDR_SYNC_FRAME_HEADER */
@@ -1490,10 +1685,18 @@
return rc;
}
-static int cam_vfe_bus_stop_vfe_out(struct cam_isp_resource_node *vfe_out)
+static int cam_vfe_bus_stop_vfe_out(
+ struct cam_isp_resource_node *vfe_out)
{
int rc = 0, i;
- struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = vfe_out->res_priv;
+ struct cam_vfe_bus_ver2_vfe_out_data *rsrc_data = NULL;
+
+ if (!vfe_out) {
+ pr_err("Invalid input\n");
+ return -EINVAL;
+ }
+
+ rsrc_data = vfe_out->res_priv;
if (vfe_out->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE ||
vfe_out->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) {
@@ -1604,122 +1807,15 @@
return 0;
}
-static int cam_vfe_bus_get_evt_payload(
- struct cam_vfe_bus_ver2_priv *bus_priv,
- struct cam_vfe_bus_irq_evt_payload **evt_payload)
-{
- if (list_empty(&bus_priv->free_payload_list)) {
- *evt_payload = NULL;
- pr_err("No free payload\n");
- return -ENODEV;
- }
-
- *evt_payload = list_first_entry(&bus_priv->free_payload_list,
- struct cam_vfe_bus_irq_evt_payload, list);
- list_del_init(&(*evt_payload)->list);
- return 0;
-}
-
-static int cam_vfe_bus_put_evt_payload(void *core_info,
- struct cam_vfe_bus_irq_evt_payload **evt_payload)
-{
- struct cam_vfe_bus_ver2_priv *bus_priv = NULL;
- uint32_t *cam_ife_irq_regs = (*evt_payload)->irq_reg_val;
- uint32_t status_reg0, status_reg1;
-
- status_reg0 = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS0];
- status_reg1 = cam_ife_irq_regs[CAM_IFE_IRQ_BUS_REG_STATUS1];
-
- if (status_reg0 || status_reg1) {
- CDBG("status0 0x%x status1 0x%x\n", status_reg0, status_reg1);
- return 0;
- }
-
- if (!core_info) {
- pr_err("Invalid param core_info NULL");
- return -EINVAL;
- }
- if (*evt_payload == NULL) {
- pr_err("No payload to put\n");
- return -EINVAL;
- }
- bus_priv = (*evt_payload)->bus_priv;
- list_add_tail(&(*evt_payload)->list, &bus_priv->free_payload_list);
- *evt_payload = NULL;
- return 0;
-}
-
static int cam_vfe_bus_ver2_handle_irq(uint32_t evt_id,
struct cam_irq_th_payload *th_payload)
{
- int32_t rc;
- int i;
- struct cam_vfe_irq_handler_priv *handler_priv;
- struct cam_vfe_hw_core_info *core_info;
- struct cam_vfe_bus_irq_evt_payload *evt_payload;
- struct cam_vfe_bus *bus_info;
struct cam_vfe_bus_ver2_priv *bus_priv;
- struct cam_irq_controller_reg_info *reg_info;
- uint32_t irq_mask;
- int found = 0;
- handler_priv = th_payload->handler_priv;
- core_info = handler_priv->core_info;
- bus_info = core_info->vfe_bus;
- bus_priv = bus_info->bus_priv;
- reg_info = &bus_priv->common_data.common_reg->irq_reg_info;
-
- /*
- * add reset ack handling here once supported.
- * Just clear all the bus irq status registers and ignore the reset.
- */
-
+ bus_priv = th_payload->handler_priv;
CDBG("Enter\n");
- rc = cam_vfe_bus_get_evt_payload(bus_priv, &evt_payload);
- if (rc) {
- pr_err("No tasklet_cmd is free in queue\n");
- return rc;
- }
-
- cam_isp_hw_get_timestamp(&evt_payload->ts);
-
- evt_payload->core_index = handler_priv->core_index;
- evt_payload->core_info = handler_priv->core_info;
- evt_payload->bus_priv = bus_priv;
- CDBG("core_idx %d, core_info %llx\n", handler_priv->core_index,
- (uint64_t)handler_priv->core_info);
-
- for (i = 0; i < CAM_IFE_BUS_IRQ_REGISTERS_MAX; i++) {
- irq_mask = cam_io_r(handler_priv->mem_base +
- irq_reg_offset[i] - (0xC * 2));
- evt_payload->irq_reg_val[i] = irq_mask &
- cam_io_r(handler_priv->mem_base + irq_reg_offset[i]);
- if (evt_payload->irq_reg_val[i])
- found = 1;
- CDBG("irq_status%d = 0x%x\n", i, evt_payload->irq_reg_val[i]);
- }
- for (i = 0; i <= CAM_IFE_IRQ_BUS_REG_STATUS2; i++) {
- cam_io_w(evt_payload->irq_reg_val[i], handler_priv->mem_base +
- reg_info->irq_reg_set[i].clear_reg_offset);
- CDBG("Clear irq_status%d = 0x%x offset 0x%x\n", i,
- evt_payload->irq_reg_val[i],
- reg_info->irq_reg_set[i].clear_reg_offset);
- }
- cam_io_w(reg_info->global_clear_bitmask, handler_priv->mem_base +
- reg_info->global_clear_offset);
- CDBG("Global clear bitmask = 0x%x offset 0x%x\n",
- reg_info->global_clear_bitmask,
- reg_info->global_clear_offset);
-
- if (found)
- th_payload->evt_payload_priv = evt_payload;
- else {
- cam_vfe_bus_put_evt_payload(evt_payload->core_info,
- &evt_payload);
- rc = -ENOMSG;
- }
-
- return rc;
+ return cam_irq_controller_handle_irq(evt_id,
+ bus_priv->common_data.bus_irq_controller);
}
static int cam_vfe_bus_update_buf(void *priv, void *cmd_args,
@@ -1953,6 +2049,69 @@
return 0;
}
+static int cam_vfe_bus_start_hw(void *hw_priv,
+ void *start_hw_args, uint32_t arg_size)
+{
+ return cam_vfe_bus_start_vfe_out(hw_priv);
+}
+
+static int cam_vfe_bus_stop_hw(void *hw_priv,
+ void *stop_hw_args, uint32_t arg_size)
+{
+ return cam_vfe_bus_stop_vfe_out(hw_priv);
+}
+
+static int cam_vfe_bus_init_hw(void *hw_priv,
+ void *init_hw_args, uint32_t arg_size)
+{
+ struct cam_vfe_bus_ver2_priv *bus_priv = hw_priv;
+ uint32_t top_irq_reg_mask[2] = {0};
+
+ if (!bus_priv) {
+ pr_err("Error! Invalid args\n");
+ return -EINVAL;
+ }
+
+ top_irq_reg_mask[0] = (1 << 9);
+
+ bus_priv->irq_handle = cam_irq_controller_subscribe_irq(
+ bus_priv->common_data.vfe_irq_controller,
+ CAM_IRQ_PRIORITY_2,
+ top_irq_reg_mask,
+ bus_priv,
+ cam_vfe_bus_ver2_handle_irq,
+ NULL,
+ NULL,
+ NULL);
+
+ if (bus_priv->irq_handle <= 0) {
+ pr_err("Failed to subscribe BUS IRQ\n");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int cam_vfe_bus_deinit_hw(void *hw_priv,
+ void *deinit_hw_args, uint32_t arg_size)
+{
+ struct cam_vfe_bus_ver2_priv *bus_priv = hw_priv;
+ int rc;
+
+ if (!bus_priv || (bus_priv->irq_handle <= 0)) {
+ pr_err("Error! Invalid args\n");
+ return -EINVAL;
+ }
+
+ rc = cam_irq_controller_unsubscribe_irq(
+ bus_priv->common_data.vfe_irq_controller,
+ bus_priv->irq_handle);
+ if (rc)
+ pr_err("Failed to unsubscribe irq rc=%d\n", rc);
+
+ return rc;
+}
+
static int cam_vfe_bus_process_cmd(void *priv,
uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
{
@@ -1977,7 +2136,7 @@
}
int cam_vfe_bus_ver2_init(
- void __iomem *mem_base,
+ struct cam_hw_soc_info *soc_info,
struct cam_hw_intf *hw_intf,
void *bus_hw_info,
void *vfe_irq_controller,
@@ -1990,6 +2149,13 @@
CDBG("Enter\n");
+ if (!soc_info || !hw_intf || !bus_hw_info || !vfe_irq_controller) {
+ pr_err("Error! Invalid params soc_info %pK hw_intf %pK hw_info %pK controller %pK\n",
+ soc_info, hw_intf, bus_hw_info, vfe_irq_controller);
+ rc = -EINVAL;
+ goto end;
+ }
+
vfe_bus_local = kzalloc(sizeof(struct cam_vfe_bus), GFP_KERNEL);
if (!vfe_bus_local) {
CDBG("Failed to alloc for vfe_bus\n");
@@ -2006,11 +2172,21 @@
}
vfe_bus_local->bus_priv = bus_priv;
- bus_priv->common_data.mem_base = mem_base;
+ bus_priv->common_data.core_index = soc_info->index;
+ bus_priv->common_data.mem_base =
+ CAM_SOC_GET_REG_MAP_START(soc_info, VFE_CORE_BASE_IDX);
bus_priv->common_data.hw_intf = hw_intf;
bus_priv->common_data.vfe_irq_controller = vfe_irq_controller;
bus_priv->common_data.common_reg = &ver2_hw_info->common_reg;
+ rc = cam_irq_controller_init(drv_name, bus_priv->common_data.mem_base,
+ &ver2_hw_info->common_reg.irq_reg_info,
+ &bus_priv->common_data.bus_irq_controller);
+ if (rc) {
+ pr_err("Error! cam_irq_controller_init failed\n");
+ goto free_bus_priv;
+ }
+
INIT_LIST_HEAD(&bus_priv->free_comp_grp);
INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
INIT_LIST_HEAD(&bus_priv->used_comp_grp);
@@ -2042,20 +2218,22 @@
}
}
- INIT_LIST_HEAD(&bus_priv->free_payload_list);
- for (i = 0; i < 128; i++) {
- INIT_LIST_HEAD(&bus_priv->evt_payload[i].list);
- list_add_tail(&bus_priv->evt_payload[i].list,
- &bus_priv->free_payload_list);
+ INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
+ for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++) {
+ INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
+ list_add_tail(&bus_priv->common_data.evt_payload[i].list,
+ &bus_priv->common_data.free_payload_list);
}
- vfe_bus_local->acquire_resource = cam_vfe_bus_acquire_vfe_out;
- vfe_bus_local->release_resource = cam_vfe_bus_release_vfe_out;
- vfe_bus_local->start_resource = cam_vfe_bus_start_vfe_out;
- vfe_bus_local->stop_resource = cam_vfe_bus_stop_vfe_out;
- vfe_bus_local->top_half_handler = cam_vfe_bus_ver2_handle_irq;
+ vfe_bus_local->hw_ops.reserve = cam_vfe_bus_acquire_vfe_out;
+ vfe_bus_local->hw_ops.release = cam_vfe_bus_release_vfe_out;
+ vfe_bus_local->hw_ops.start = cam_vfe_bus_start_hw;
+ vfe_bus_local->hw_ops.stop = cam_vfe_bus_stop_hw;
+ vfe_bus_local->hw_ops.init = cam_vfe_bus_init_hw;
+ vfe_bus_local->hw_ops.deinit = cam_vfe_bus_deinit_hw;
+ vfe_bus_local->top_half_handler = cam_vfe_bus_ver2_handle_irq;
vfe_bus_local->bottom_half_handler = NULL;
- vfe_bus_local->process_cmd = cam_vfe_bus_process_cmd;
+ vfe_bus_local->hw_ops.process_cmd = cam_vfe_bus_process_cmd;
*vfe_bus = vfe_bus_local;
@@ -2080,6 +2258,7 @@
for (--i; i >= 0; i--)
cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
+free_bus_priv:
kfree(vfe_bus_local->bus_priv);
free_bus_local:
@@ -2109,9 +2288,9 @@
goto free_bus_local;
}
- INIT_LIST_HEAD(&bus_priv->free_payload_list);
- for (i = 0; i < 128; i++)
- INIT_LIST_HEAD(&bus_priv->evt_payload[i].list);
+ INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
+ for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++)
+ INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
for (i = 0; i < CAM_VFE_BUS_VER2_MAX_CLIENTS; i++) {
rc = cam_vfe_bus_deinit_wm_resource(&bus_priv->bus_client[i]);
@@ -2135,6 +2314,11 @@
INIT_LIST_HEAD(&bus_priv->free_dual_comp_grp);
INIT_LIST_HEAD(&bus_priv->used_comp_grp);
+ rc = cam_irq_controller_deinit(
+ &bus_priv->common_data.bus_irq_controller);
+ if (rc)
+ pr_err("Error! Deinit IRQ Controller failed rc=%d\n", rc);
+
kfree(vfe_bus_local->bus_priv);
free_bus_local: