mirror of
https://github.com/LineageOS/android_kernel_samsung_msm8226.git
synced 2026-09-28 00:00:22 +02:00
msm: camera: Add support for ISP statistics collection
Add suppport to configure statistics modules Add support for statistics buffer handling Handle statistics module interrupt and generate event to notify userspace. Change-Id: I58f610f9509d259dcae7cb55e35ce7e3c4ab03d4 Signed-off-by: Kevin Chan <ktchan@codeaurora.org> [smuckle@codeaurora.org: backported from msm-3.7] Signed-off-by: Steve Muckle <smuckle@codeaurora.org>
This commit is contained in:
@@ -34,6 +34,9 @@
|
||||
#define MAX_INIT_FRAME_DROP 31
|
||||
#define ISP_SUB(a) ((a > 0) ? a-1 : 0)
|
||||
|
||||
#define VFE_PING_FLAG 0xFFFFFFFF
|
||||
#define VFE_PONG_FLAG 0x0
|
||||
|
||||
struct vfe_device;
|
||||
struct msm_vfe_axi_stream;
|
||||
struct msm_vfe_stats_stream;
|
||||
@@ -133,14 +136,12 @@ struct msm_vfe_core_ops {
|
||||
int (*get_platform_data) (struct vfe_device *vfe_dev);
|
||||
};
|
||||
struct msm_vfe_stats_ops {
|
||||
int (*get_stats_idx) (enum msm_isp_stats_type stats_type);
|
||||
void (*cfg_framedrop) (struct vfe_device *vfe_dev,
|
||||
struct msm_vfe_stats_stream *stream_info);
|
||||
void (*clear_framedrop) (struct vfe_device *vfe_dev,
|
||||
struct msm_vfe_stats_stream *stream_info);
|
||||
void (*cfg_comp_mask) (struct vfe_device *vfe_dev,
|
||||
struct msm_vfe_stats_stream *stream_info);
|
||||
void (*clear_comp_mask) (struct vfe_device *vfe_dev,
|
||||
struct msm_vfe_stats_stream *stream_info);
|
||||
void (*cfg_comp_mask) (struct vfe_device *vfe_dev);
|
||||
void (*cfg_wm_irq_mask) (struct vfe_device *vfe_dev,
|
||||
struct msm_vfe_stats_stream *stream_info);
|
||||
void (*clear_wm_irq_mask) (struct vfe_device *vfe_dev,
|
||||
@@ -153,20 +154,17 @@ struct msm_vfe_stats_ops {
|
||||
|
||||
void (*cfg_ub) (struct vfe_device *vfe_dev);
|
||||
|
||||
void (*stats_enable) (struct vfe_device *vfe_dev,
|
||||
void (*enable_module) (struct vfe_device *vfe_dev,
|
||||
uint32_t stats_mask, uint8_t enable);
|
||||
|
||||
void (*update_ping_pong_addr) (struct vfe_device *vfe_dev,
|
||||
enum msm_isp_stats_type stats_type, uint32_t pingpong_status,
|
||||
unsigned long paddr);
|
||||
struct msm_vfe_stats_stream *stream_info,
|
||||
uint32_t pingpong_status, unsigned long paddr);
|
||||
|
||||
uint32_t (*get_frame_id) (struct vfe_device *vfe_dev);
|
||||
uint32_t (*get_wm_mask) (uint32_t irq_status0, uint32_t irq_status1);
|
||||
uint32_t (*get_comp_mask) (uint32_t irq_status0, uint32_t irq_status1);
|
||||
uint32_t (*get_pingpong_status) (struct vfe_device *vfe_dev);
|
||||
uint32_t (*get_active_pingpong_idx) (uint32_t pingpong_status,
|
||||
enum msm_isp_stats_type stats_type);
|
||||
|
||||
};
|
||||
|
||||
struct msm_vfe_ops {
|
||||
@@ -179,6 +177,7 @@ struct msm_vfe_ops {
|
||||
struct msm_vfe_hardware_info {
|
||||
struct msm_vfe_ops vfe_ops;
|
||||
struct msm_vfe_axi_hardware_info *axi_hw_info;
|
||||
struct msm_vfe_stats_hardware_info *stats_hw_info;
|
||||
struct v4l2_subdev_internal_ops *subdev_internal_ops;
|
||||
struct v4l2_subdev_ops *subdev_ops;
|
||||
};
|
||||
@@ -189,7 +188,6 @@ struct msm_vfe_axi_hardware_info {
|
||||
uint8_t num_rdi_master;
|
||||
uint8_t num_comp_mask;
|
||||
uint32_t min_wm_ub;
|
||||
uint8_t num_stats_comp_mask;
|
||||
};
|
||||
|
||||
enum msm_vfe_axi_state {
|
||||
@@ -243,6 +241,7 @@ struct msm_vfe_axi_composite_info {
|
||||
uint32_t stream_handle;
|
||||
uint32_t stream_composite_mask;
|
||||
};
|
||||
|
||||
struct msm_vfe_src_info {
|
||||
unsigned long frame_id;
|
||||
uint8_t active;
|
||||
@@ -251,40 +250,12 @@ struct msm_vfe_src_info {
|
||||
enum msm_vfe_inputmux input_mux;
|
||||
};
|
||||
|
||||
enum msm_vfe_stats_state {
|
||||
STATE_AVALIABLE,
|
||||
STATE_INACTIVE,
|
||||
STATE_ACTIVE,
|
||||
STATE_START_PENDING,
|
||||
STATE_STOP_PENDING,
|
||||
STATE_STOPPING,
|
||||
};
|
||||
struct msm_vfe_stats_stream {
|
||||
uint32_t frame_id;
|
||||
uint8_t enable;
|
||||
enum msm_isp_stats_type stats_type;
|
||||
int8_t comp_mask_index;
|
||||
struct msm_isp_buffer *buf[2];
|
||||
uint32_t session_id;
|
||||
uint32_t stream_id;
|
||||
uint32_t bufq_handle;
|
||||
uint32_t stream_handle;
|
||||
uint32_t framedrop_pattern;
|
||||
uint8_t comp_flag;
|
||||
uint8_t comp_idx;
|
||||
enum msm_vfe_stats_state state;
|
||||
};
|
||||
|
||||
struct msm_vfe_stats_composite_info {
|
||||
uint32_t stats_mask;
|
||||
uint8_t comp_flag;
|
||||
};
|
||||
|
||||
enum msm_wm_ub_cfg_type {
|
||||
MSM_WM_UB_CFG_DEFAULT,
|
||||
MSM_WM_UB_EQUAL_SLICING,
|
||||
MSM_WM_UB_CFG_MAX_NUM
|
||||
};
|
||||
|
||||
struct msm_vfe_axi_shared_data {
|
||||
struct msm_vfe_axi_hardware_info *hw_info;
|
||||
struct msm_vfe_axi_stream stream_info[MAX_NUM_STREAM];
|
||||
@@ -305,14 +276,44 @@ struct msm_vfe_axi_shared_data {
|
||||
unsigned long event_mask;
|
||||
};
|
||||
|
||||
struct msm_vfe_stats_hardware_info {
|
||||
uint32_t stats_capability_mask;
|
||||
uint32_t stats_ping_pong_offset;
|
||||
uint8_t num_stats_type;
|
||||
uint8_t num_stats_comp_mask;
|
||||
};
|
||||
|
||||
enum msm_vfe_stats_state {
|
||||
STATS_AVALIABLE,
|
||||
STATS_INACTIVE,
|
||||
STATS_ACTIVE,
|
||||
STATS_START_PENDING,
|
||||
STATS_STOP_PENDING,
|
||||
STATS_STOPPING,
|
||||
};
|
||||
|
||||
struct msm_vfe_stats_stream {
|
||||
uint32_t session_id;
|
||||
uint32_t stream_id;
|
||||
uint32_t stream_handle;
|
||||
enum msm_isp_stats_type stats_type;
|
||||
enum msm_vfe_stats_state state;
|
||||
uint32_t framedrop_pattern;
|
||||
uint32_t irq_subsample_pattern;
|
||||
|
||||
struct msm_isp_buffer *buf[2];
|
||||
uint32_t bufq_handle;
|
||||
};
|
||||
|
||||
struct msm_vfe_stats_shared_data {
|
||||
struct msm_vfe_stats_stream stream_info[MSM_ISP_STATS_MAX];
|
||||
struct msm_vfe_stats_composite_info
|
||||
composite_info[MAX_NUM_STATS_COMP_MASK];
|
||||
enum msm_vfe_stats_pipeline_policy stats_pipeline_policy;
|
||||
uint32_t comp_framedrop_pattern;
|
||||
uint32_t comp_irq_subsample_pattern;
|
||||
uint8_t num_active_stream;
|
||||
uint8_t num_used_composite_mask;
|
||||
uint16_t stream_handle_cnt;
|
||||
};
|
||||
|
||||
struct msm_vfe_tasklet_queue_cmd {
|
||||
struct list_head list;
|
||||
uint32_t vfeInterruptStatus0;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#endif
|
||||
|
||||
#define VFE40_BURST_LEN 4
|
||||
#define VFE40_UB_SIZE 1024
|
||||
#define VFE40_EQUAL_SLICE_UB 117
|
||||
#define VFE40_WM_BASE(idx) (0x6C + 0x24 * idx)
|
||||
#define VFE40_RDI_BASE(idx) (0x2E8 + 0x4 * idx)
|
||||
@@ -41,6 +42,13 @@
|
||||
#define VFE40_PING_PONG_BASE(wm, ping_pong) \
|
||||
(VFE40_WM_BASE(wm) + 0x4 * (1 + (~(ping_pong >> wm) & 0x1)))
|
||||
|
||||
#define VFE40_NUM_STATS_TYPE 8
|
||||
#define VFE40_STATS_PING_PONG_OFFSET 8
|
||||
#define VFE40_STATS_BASE(idx) (0x168 + 0x18 * idx)
|
||||
#define VFE40_STATS_PING_PONG_BASE(idx, ping_pong) \
|
||||
(VFE40_STATS_BASE(idx) + 0x4 * \
|
||||
(~(ping_pong >> (idx + VFE40_STATS_PING_PONG_OFFSET)) & 0x1))
|
||||
|
||||
#define VFE40_VBIF_CLKON 0x4
|
||||
#define VFE40_VBIF_IN_RD_LIM_CONF0 0xB0
|
||||
#define VFE40_VBIF_IN_RD_LIM_CONF1 0xB4
|
||||
@@ -907,64 +915,160 @@ static uint32_t msm_vfe40_get_pingpong_status(
|
||||
return msm_camera_io_r(vfe_dev->vfe_base + 0x268);
|
||||
}
|
||||
|
||||
static void msm_vfe40_stats_cfg_comp_mask(
|
||||
struct vfe_device *vfe_dev,
|
||||
struct msm_vfe_stats_stream *stream_info)
|
||||
static int msm_vfe40_get_stats_idx(enum msm_isp_stats_type stats_type)
|
||||
{
|
||||
|
||||
switch (stats_type) {
|
||||
case MSM_ISP_STATS_BE:
|
||||
return 0;
|
||||
case MSM_ISP_STATS_BG:
|
||||
return 1;
|
||||
case MSM_ISP_STATS_BF:
|
||||
return 2;
|
||||
case MSM_ISP_STATS_AWB:
|
||||
return 3;
|
||||
case MSM_ISP_STATS_RS:
|
||||
return 4;
|
||||
case MSM_ISP_STATS_CS:
|
||||
return 5;
|
||||
case MSM_ISP_STATS_IHIST:
|
||||
return 6;
|
||||
case MSM_ISP_STATS_BHIST:
|
||||
return 7;
|
||||
default:
|
||||
pr_err("%s: Invalid stats type\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static void msm_vfe40_stats_clear_comp_mask(
|
||||
struct vfe_device *vfe_dev,
|
||||
struct msm_vfe_stats_stream *stream_info)
|
||||
static void msm_vfe40_stats_cfg_comp_mask(struct vfe_device *vfe_dev)
|
||||
{
|
||||
|
||||
if (vfe_dev->stats_data.stats_pipeline_policy == STATS_COMP_ALL)
|
||||
msm_camera_io_w(0x00FF0000, vfe_dev->vfe_base + 0x44);
|
||||
else
|
||||
msm_camera_io_w(0x00000000, vfe_dev->vfe_base + 0x44);
|
||||
}
|
||||
|
||||
static void msm_vfe40_stats_cfg_wm_irq_mask(
|
||||
struct vfe_device *vfe_dev,
|
||||
struct msm_vfe_stats_stream *stream_info)
|
||||
{
|
||||
|
||||
uint32_t irq_mask;
|
||||
irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x28);
|
||||
irq_mask |= 1 << (STATS_IDX(stream_info->stream_handle) + 16);
|
||||
msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x28);
|
||||
}
|
||||
|
||||
static void msm_vfe40_stats_clear_wm_irq_mask(
|
||||
struct vfe_device *vfe_dev,
|
||||
struct msm_vfe_stats_stream *stream_info)
|
||||
{
|
||||
|
||||
uint32_t irq_mask;
|
||||
irq_mask = msm_camera_io_r(vfe_dev->vfe_base + 0x28);
|
||||
irq_mask &= ~(1 << (STATS_IDX(stream_info->stream_handle) + 16));
|
||||
msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x28);
|
||||
}
|
||||
|
||||
static void msm_vfe40_stats_cfg_wm_reg(
|
||||
struct vfe_device *vfe_dev,
|
||||
struct msm_vfe_stats_stream *stream_info)
|
||||
{
|
||||
int stats_idx = STATS_IDX(stream_info->stream_handle);
|
||||
uint32_t stats_base = VFE40_STATS_BASE(stats_idx);
|
||||
|
||||
/*WR_ADDR_CFG*/
|
||||
msm_camera_io_w(0x7C, vfe_dev->vfe_base + stats_base + 0x8);
|
||||
/*WR_IRQ_FRAMEDROP_PATTERN*/
|
||||
msm_camera_io_w(0xFFFFFFFF,
|
||||
vfe_dev->vfe_base + stats_base + 0x10);
|
||||
/*WR_IRQ_SUBSAMPLE_PATTERN*/
|
||||
msm_camera_io_w(0xFFFFFFFF,
|
||||
vfe_dev->vfe_base + stats_base + 0x14);
|
||||
}
|
||||
|
||||
static void msm_vfe40_stats_clear_wm_reg(
|
||||
struct vfe_device *vfe_dev,
|
||||
struct msm_vfe_stats_stream *stream_info)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
int stats_idx = STATS_IDX(stream_info->stream_handle);
|
||||
uint32_t stats_base = VFE40_STATS_BASE(stats_idx);
|
||||
|
||||
/*WR_ADDR_CFG*/
|
||||
msm_camera_io_w(val, vfe_dev->vfe_base + stats_base + 0x8);
|
||||
/*WR_IRQ_FRAMEDROP_PATTERN*/
|
||||
msm_camera_io_w(val, vfe_dev->vfe_base + stats_base + 0x10);
|
||||
/*WR_IRQ_SUBSAMPLE_PATTERN*/
|
||||
msm_camera_io_w(val, vfe_dev->vfe_base + stats_base + 0x14);
|
||||
}
|
||||
|
||||
static void msm_vfe40_stats_cfg_ub(struct vfe_device *vfe_dev)
|
||||
{
|
||||
int i;
|
||||
uint32_t ub_offset = VFE40_UB_SIZE;
|
||||
uint32_t ub_size[VFE40_NUM_STATS_TYPE] = {
|
||||
64, /*MSM_ISP_STATS_BE*/
|
||||
64, /*MSM_ISP_STATS_BG*/
|
||||
64, /*MSM_ISP_STATS_BF*/
|
||||
16, /*MSM_ISP_STATS_AWB*/
|
||||
8, /*MSM_ISP_STATS_RS*/
|
||||
16, /*MSM_ISP_STATS_CS*/
|
||||
16, /*MSM_ISP_STATS_IHIST*/
|
||||
16, /*MSM_ISP_STATS_BHIST*/
|
||||
};
|
||||
|
||||
for (i = 0; i < VFE40_NUM_STATS_TYPE; i++) {
|
||||
ub_offset -= ub_size[i];
|
||||
msm_camera_io_w(VFE40_BURST_LEN << 30 |
|
||||
ub_offset << 16 | (ub_size[i] - 1),
|
||||
vfe_dev->vfe_base + VFE40_STATS_BASE(i) + 0xC);
|
||||
}
|
||||
}
|
||||
|
||||
static void msm_vfe40_stats_enable(struct vfe_device *vfe_dev,
|
||||
static void msm_vfe40_stats_enable_module(struct vfe_device *vfe_dev,
|
||||
uint32_t stats_mask, uint8_t enable)
|
||||
{
|
||||
int i;
|
||||
uint32_t module_cfg, module_cfg_mask = 0;
|
||||
|
||||
for (i = 0; i < VFE40_NUM_STATS_TYPE; i++) {
|
||||
if ((stats_mask >> i) & 0x1) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
module_cfg_mask |= 1 << (5 + i);
|
||||
break;
|
||||
case 6:
|
||||
module_cfg_mask |= 1 << 15;
|
||||
break;
|
||||
case 7:
|
||||
module_cfg_mask |= 1 << 18;
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Invalid stats mask\n", __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module_cfg = msm_camera_io_r(vfe_dev->vfe_base + 0x18);
|
||||
if (enable)
|
||||
module_cfg |= module_cfg_mask;
|
||||
else
|
||||
module_cfg &= ~module_cfg_mask;
|
||||
msm_camera_io_w(module_cfg, vfe_dev->vfe_base + 0x18);
|
||||
}
|
||||
|
||||
static void msm_vfe40_stats_update_ping_pong_addr(
|
||||
struct vfe_device *vfe_dev,
|
||||
enum msm_isp_stats_type stats_type,
|
||||
uint32_t pingpong_status,
|
||||
unsigned long paddr)
|
||||
struct vfe_device *vfe_dev, struct msm_vfe_stats_stream *stream_info,
|
||||
uint32_t pingpong_status, unsigned long paddr)
|
||||
{
|
||||
int stats_idx = STATS_IDX(stream_info->stream_handle);
|
||||
msm_camera_io_w(paddr, vfe_dev->vfe_base +
|
||||
VFE40_STATS_PING_PONG_BASE(stats_idx, pingpong_status));
|
||||
}
|
||||
|
||||
static uint32_t msm_vfe40_stats_get_wm_mask(
|
||||
@@ -976,7 +1080,7 @@ static uint32_t msm_vfe40_stats_get_wm_mask(
|
||||
static uint32_t msm_vfe40_stats_get_comp_mask(
|
||||
uint32_t irq_status0, uint32_t irq_status1)
|
||||
{
|
||||
return (irq_status0 >> 29) & 0x2;
|
||||
return (irq_status0 >> 29) & 0x3;
|
||||
}
|
||||
|
||||
static uint32_t msm_vfe40_stats_get_frame_id(
|
||||
@@ -985,55 +1089,6 @@ static uint32_t msm_vfe40_stats_get_frame_id(
|
||||
return vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id;
|
||||
}
|
||||
|
||||
static uint32_t msm_vfe40_stats_get_active_pingpong_idx(
|
||||
uint32_t pingpong_status,
|
||||
enum msm_isp_stats_type stats_type)
|
||||
{
|
||||
int pingpong_bit = 0;
|
||||
switch (stats_type) {
|
||||
case MSM_ISP_STATS_AWB:
|
||||
if (pingpong_status & (1 << 11))
|
||||
pingpong_bit = 1; /* pong is active */
|
||||
break;
|
||||
case MSM_ISP_STATS_RS:
|
||||
if (pingpong_status & (1 << 12))
|
||||
pingpong_bit = 1; /* pong is active */
|
||||
break;
|
||||
case MSM_ISP_STATS_CS:
|
||||
if (pingpong_status & (1 << 13))
|
||||
pingpong_bit = 1; /* pong is active */
|
||||
break;
|
||||
case MSM_ISP_STATS_IHIST:
|
||||
if (pingpong_status & (1 << 14))
|
||||
pingpong_bit = 1; /* pong is active */
|
||||
break;
|
||||
case MSM_ISP_STATS_BG:
|
||||
if (pingpong_status & (1 << 9))
|
||||
pingpong_bit = 1; /* pong is active */
|
||||
break;
|
||||
case MSM_ISP_STATS_BF:
|
||||
if (pingpong_status & (1 << 10))
|
||||
pingpong_bit = 1; /* pong is active */
|
||||
break;
|
||||
case MSM_ISP_STATS_BE:
|
||||
if (pingpong_status & (1 << 8))
|
||||
pingpong_bit = 1; /* pong is active */
|
||||
break;
|
||||
case MSM_ISP_STATS_BHIST:
|
||||
if (pingpong_status & (1 << 15))
|
||||
pingpong_bit = 1; /* pong is active */
|
||||
break;
|
||||
case MSM_ISP_STATS_SKIN:
|
||||
case MSM_ISP_STATS_AEC:
|
||||
case MSM_ISP_STATS_AF:
|
||||
default:
|
||||
pr_err("%s: not supported stats type = %d\n",
|
||||
__func__, stats_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
return pingpong_bit;
|
||||
}
|
||||
|
||||
static int msm_vfe40_get_platform_data(struct vfe_device *vfe_dev)
|
||||
{
|
||||
int rc = 0;
|
||||
@@ -1085,12 +1140,22 @@ vfe_no_resource:
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct msm_vfe_axi_hardware_info msm_vfe40_axi_hw_info = {
|
||||
static struct msm_vfe_axi_hardware_info msm_vfe40_axi_hw_info = {
|
||||
.num_wm = 7,
|
||||
.num_comp_mask = 4,
|
||||
.num_rdi = 3,
|
||||
.num_rdi_master = 3,
|
||||
.min_wm_ub = 64,
|
||||
};
|
||||
|
||||
static struct msm_vfe_stats_hardware_info msm_vfe40_stats_hw_info = {
|
||||
.stats_capability_mask =
|
||||
1 << MSM_ISP_STATS_BE | 1 << MSM_ISP_STATS_BF |
|
||||
1 << MSM_ISP_STATS_BG | 1 << MSM_ISP_STATS_BHIST |
|
||||
1 << MSM_ISP_STATS_AWB | 1 << MSM_ISP_STATS_IHIST |
|
||||
1 << MSM_ISP_STATS_RS | 1 << MSM_ISP_STATS_CS,
|
||||
.stats_ping_pong_offset = VFE40_STATS_PING_PONG_OFFSET,
|
||||
.num_stats_type = VFE40_NUM_STATS_TYPE,
|
||||
.num_stats_comp_mask = 2,
|
||||
};
|
||||
|
||||
@@ -1156,25 +1221,24 @@ struct msm_vfe_hardware_info vfe40_hw_info = {
|
||||
.get_platform_data = msm_vfe40_get_platform_data,
|
||||
},
|
||||
.stats_ops = {
|
||||
.get_stats_idx = msm_vfe40_get_stats_idx,
|
||||
.cfg_comp_mask = msm_vfe40_stats_cfg_comp_mask,
|
||||
.clear_comp_mask = msm_vfe40_stats_clear_comp_mask,
|
||||
.cfg_wm_irq_mask = msm_vfe40_stats_cfg_wm_irq_mask,
|
||||
.clear_wm_irq_mask = msm_vfe40_stats_clear_wm_irq_mask,
|
||||
.cfg_wm_reg = msm_vfe40_stats_cfg_wm_reg,
|
||||
.clear_wm_reg = msm_vfe40_stats_clear_wm_reg,
|
||||
.cfg_ub = msm_vfe40_stats_cfg_ub,
|
||||
.stats_enable = msm_vfe40_stats_enable,
|
||||
.enable_module = msm_vfe40_stats_enable_module,
|
||||
.update_ping_pong_addr =
|
||||
msm_vfe40_stats_update_ping_pong_addr,
|
||||
.get_comp_mask = msm_vfe40_stats_get_comp_mask,
|
||||
.get_wm_mask = msm_vfe40_stats_get_wm_mask,
|
||||
.get_frame_id = msm_vfe40_stats_get_frame_id,
|
||||
.get_pingpong_status = msm_vfe40_get_pingpong_status,
|
||||
.get_active_pingpong_idx =
|
||||
msm_vfe40_stats_get_active_pingpong_idx,
|
||||
},
|
||||
},
|
||||
.axi_hw_info = &msm_vfe40_axi_hw_info,
|
||||
.stats_hw_info = &msm_vfe40_stats_hw_info,
|
||||
.subdev_ops = &msm_vfe40_subdev_ops,
|
||||
.subdev_internal_ops = &msm_vfe40_internal_ops,
|
||||
};
|
||||
|
||||
@@ -644,8 +644,6 @@ void msm_isp_axi_stream_update(struct vfe_device *vfe_dev)
|
||||
complete(&vfe_dev->stream_config_complete);
|
||||
}
|
||||
}
|
||||
#define VFE_PING_FLAG 0xFFFFFFFF
|
||||
#define VFE_PONG_FLAG 0x0
|
||||
|
||||
int msm_isp_cfg_ping_pong_address(struct vfe_device *vfe_dev,
|
||||
struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status,
|
||||
|
||||
@@ -13,251 +13,331 @@
|
||||
#include <media/v4l2-subdev.h>
|
||||
#include "msm_isp_util.h"
|
||||
#include "msm_isp_stats_util.h"
|
||||
#define VFE_PING_ACTIVE_FLAG 0xFFFFFFFF
|
||||
#define VFE_PONG_ACTIVE_FLAG 0x0
|
||||
|
||||
int msm_isp_stats_cfg_ping_pong_address(struct vfe_device *vfe_dev,
|
||||
static int msm_isp_stats_cfg_ping_pong_address(struct vfe_device *vfe_dev,
|
||||
struct msm_vfe_stats_stream *stream_info, uint32_t pingpong_status,
|
||||
struct msm_isp_buffer *out_buf)
|
||||
struct msm_isp_buffer **done_buf)
|
||||
{
|
||||
int rc = -1;
|
||||
struct msm_isp_buffer *buf;
|
||||
int active_bit = 0;
|
||||
int buf_idx;
|
||||
uint32_t pingpong_bit = 0;
|
||||
uint32_t bufq_handle = stream_info->bufq_handle;
|
||||
uint32_t stats_pingpong_offset =
|
||||
STATS_IDX(stream_info->stream_handle) +
|
||||
vfe_dev->hw_info->stats_hw_info->stats_ping_pong_offset;
|
||||
|
||||
out_buf = NULL;
|
||||
active_bit = vfe_dev->hw_info->vfe_ops.stats_ops.
|
||||
get_active_pingpong_idx(pingpong_status,
|
||||
stream_info->stats_type);
|
||||
buf_idx = active_bit^0x1;
|
||||
|
||||
pingpong_bit = (~(pingpong_status >> stats_pingpong_offset) & 0x1);
|
||||
rc = vfe_dev->buf_mgr->ops->get_buf(
|
||||
vfe_dev->buf_mgr, bufq_handle, &buf);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: No free buffer, stats_type = %d\n",
|
||||
__func__, stream_info->stats_type);
|
||||
pr_err("%s: No free buffer, stats_stream = %d\n",
|
||||
__func__, stream_info->stream_handle);
|
||||
return rc;
|
||||
}
|
||||
vfe_dev->hw_info->vfe_ops.stats_ops.update_ping_pong_addr(
|
||||
vfe_dev, stream_info->stats_type,
|
||||
pingpong_status, buf->mapped_info[buf_idx].paddr);
|
||||
|
||||
if (stream_info->buf[buf_idx])
|
||||
out_buf = stream_info->buf[buf_idx];
|
||||
stream_info->buf[buf_idx] = buf;
|
||||
if (buf->num_planes != 1) {
|
||||
pr_err("%s: Invalid buffer\n", __func__);
|
||||
rc = -EINVAL;
|
||||
goto buf_error;
|
||||
}
|
||||
|
||||
vfe_dev->hw_info->vfe_ops.stats_ops.update_ping_pong_addr(
|
||||
vfe_dev, stream_info,
|
||||
pingpong_status, buf->mapped_info[0].paddr);
|
||||
|
||||
if (stream_info->buf[pingpong_bit] && done_buf)
|
||||
*done_buf = stream_info->buf[pingpong_bit];
|
||||
|
||||
stream_info->buf[pingpong_bit] = buf;
|
||||
return 0;
|
||||
buf_error:
|
||||
vfe_dev->buf_mgr->ops->put_buf(vfe_dev->buf_mgr,
|
||||
buf->bufq_handle, buf->buf_idx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void msm_isp_process_stats_irq(struct vfe_device *vfe_dev,
|
||||
uint32_t irq_status0, uint32_t irq_status1,
|
||||
struct timeval *tv)
|
||||
{
|
||||
uint32_t frame_id;
|
||||
uint32_t stats_comp_mask = 0, stats_mask = 0;
|
||||
ISP_DBG("%s: status: 0x%x\n", __func__, irq_status0);
|
||||
int i;
|
||||
struct msm_isp_event_data buf_event;
|
||||
struct msm_isp_stats_event *stats_event = &buf_event.u.stats;
|
||||
struct msm_isp_buffer *done_buf;
|
||||
struct msm_vfe_stats_stream *stream_info = NULL;
|
||||
uint32_t pingpong_status;
|
||||
uint32_t stats_comp_mask = 0, stats_irq_mask = 0;
|
||||
stats_comp_mask = vfe_dev->hw_info->vfe_ops.stats_ops.
|
||||
get_comp_mask(irq_status0, irq_status1);
|
||||
stats_mask = vfe_dev->hw_info->vfe_ops.stats_ops.
|
||||
stats_irq_mask = vfe_dev->hw_info->vfe_ops.stats_ops.
|
||||
get_wm_mask(irq_status0, irq_status1);
|
||||
if (!(stats_comp_mask || stats_mask))
|
||||
if (!(stats_comp_mask || stats_irq_mask))
|
||||
return;
|
||||
frame_id = vfe_dev->hw_info->vfe_ops.stats_ops.get_frame_id(vfe_dev);
|
||||
/* TD: process comp/non comp stats */
|
||||
}
|
||||
ISP_DBG("%s: status: 0x%x\n", __func__, irq_status0);
|
||||
|
||||
static int msm_isp_stats_reserve_comp_mask(
|
||||
struct vfe_device *vfe_dev,
|
||||
struct msm_vfe_stats_shared_data *stats_data,
|
||||
struct msm_vfe_stats_stream *stream_info)
|
||||
{
|
||||
int i;
|
||||
uint8_t num_stats_comp;
|
||||
int8_t comp_idx = -1;
|
||||
if (stream_info->comp_flag == 0)
|
||||
return 0;
|
||||
if (vfe_dev->stats_data.stats_pipeline_policy == STATS_COMP_ALL) {
|
||||
if (!stats_comp_mask)
|
||||
return;
|
||||
stats_irq_mask = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
num_stats_comp = vfe_dev->axi_data.hw_info->num_stats_comp_mask;
|
||||
for (i = 0; i < num_stats_comp; i++) {
|
||||
if (!stats_data->composite_info[i].stats_mask == 0 &&
|
||||
comp_idx < 0)
|
||||
comp_idx = i;
|
||||
if (stats_data->composite_info[i].comp_flag ==
|
||||
stream_info->comp_flag) {
|
||||
comp_idx = i;
|
||||
break;
|
||||
memset(&buf_event, 0, sizeof(struct msm_isp_event_data));
|
||||
pingpong_status = vfe_dev->hw_info->
|
||||
vfe_ops.stats_ops.get_pingpong_status(vfe_dev);
|
||||
|
||||
for (i = 0; i < vfe_dev->hw_info->stats_hw_info->num_stats_type; i++) {
|
||||
if (!(stats_irq_mask & (1 << i)))
|
||||
continue;
|
||||
stream_info = &vfe_dev->stats_data.stream_info[i];
|
||||
done_buf = NULL;
|
||||
msm_isp_stats_cfg_ping_pong_address(vfe_dev,
|
||||
stream_info, pingpong_status, &done_buf);
|
||||
if (done_buf) {
|
||||
stats_event->stats_mask |= 1 << stream_info->stats_type;
|
||||
stats_event->stats_buf_idxs[stream_info->stats_type] =
|
||||
done_buf->buf_idx;
|
||||
}
|
||||
}
|
||||
if (comp_idx < 0) {
|
||||
pr_err("%s: no more stats comp idx\n", __func__);
|
||||
return -EACCES;
|
||||
}
|
||||
stats_data->composite_info[comp_idx].stats_mask |=
|
||||
(1 << stream_info->stats_type);
|
||||
if (stats_data->composite_info[comp_idx].comp_flag == 0)
|
||||
stats_data->composite_info[comp_idx].comp_flag =
|
||||
stream_info->comp_flag;
|
||||
stream_info->comp_idx = comp_idx;
|
||||
return 0;
|
||||
|
||||
buf_event.timestamp = *tv;
|
||||
msm_isp_send_event(vfe_dev, ISP_EVENT_STATS_NOTIFY, &buf_event);
|
||||
}
|
||||
|
||||
static int msm_isp_stats_unreserve_comp_mask(
|
||||
struct vfe_device *vfe_dev,
|
||||
struct msm_vfe_stats_shared_data *stats_data,
|
||||
struct msm_vfe_stats_stream *stream_info)
|
||||
int msm_isp_stats_create_stream(struct vfe_device *vfe_dev,
|
||||
struct msm_vfe_stats_stream_request_cmd *stream_req_cmd)
|
||||
{
|
||||
uint8_t comp_idx = stream_info->comp_idx;
|
||||
int rc = -1;
|
||||
struct msm_vfe_stats_stream *stream_info = NULL;
|
||||
struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
|
||||
uint32_t stats_idx;
|
||||
|
||||
if (stream_info->comp_flag == 0)
|
||||
return 0;
|
||||
stats_data->composite_info[comp_idx].stats_mask &=
|
||||
~(1 << stream_info->stats_type);
|
||||
if (stats_data->composite_info[comp_idx].stats_mask == 0)
|
||||
memset(&stats_data->composite_info[comp_idx], 0,
|
||||
sizeof(struct msm_vfe_stats_composite_info));
|
||||
if (!(vfe_dev->hw_info->stats_hw_info->stats_capability_mask &
|
||||
(1 << stream_req_cmd->stats_type))) {
|
||||
pr_err("%s: Stats type not supported\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
stats_idx = vfe_dev->hw_info->vfe_ops.stats_ops.
|
||||
get_stats_idx(stream_req_cmd->stats_type);
|
||||
|
||||
stream_info = &stats_data->stream_info[stats_idx];
|
||||
if (stream_info->state != STATS_AVALIABLE) {
|
||||
pr_err("%s: Stats already requested\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (stats_data->stats_pipeline_policy != STATS_COMP_ALL) {
|
||||
if (stream_req_cmd->framedrop_pattern >= MAX_SKIP) {
|
||||
pr_err("%s: Invalid framedrop pattern\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (stream_req_cmd->irq_subsample_pattern >= MAX_SKIP) {
|
||||
pr_err("%s: Invalid irq subsample pattern\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
if (stats_data->comp_framedrop_pattern >= MAX_SKIP) {
|
||||
pr_err("%s: Invalid comp framedrop pattern\n",
|
||||
__func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (stats_data->comp_irq_subsample_pattern >= MAX_SKIP) {
|
||||
pr_err("%s: Invalid comp irq subsample pattern\n",
|
||||
__func__);
|
||||
return rc;
|
||||
}
|
||||
stream_req_cmd->framedrop_pattern =
|
||||
vfe_dev->stats_data.comp_framedrop_pattern;
|
||||
stream_req_cmd->irq_subsample_pattern =
|
||||
vfe_dev->stats_data.comp_irq_subsample_pattern;
|
||||
}
|
||||
|
||||
stream_info->session_id = stream_req_cmd->session_id;
|
||||
stream_info->stream_id = stream_req_cmd->stream_id;
|
||||
stream_info->stats_type = stream_req_cmd->stats_type;
|
||||
stream_info->framedrop_pattern = stream_req_cmd->framedrop_pattern;
|
||||
stream_info->irq_subsample_pattern =
|
||||
stream_req_cmd->irq_subsample_pattern;
|
||||
stream_info->state = STATS_INACTIVE;
|
||||
|
||||
if ((vfe_dev->stats_data.stream_handle_cnt << 8) == 0)
|
||||
vfe_dev->stats_data.stream_handle_cnt++;
|
||||
|
||||
stream_req_cmd->stream_handle =
|
||||
(++vfe_dev->stats_data.stream_handle_cnt) << 8 | stats_idx;
|
||||
|
||||
stream_info->stream_handle = stream_req_cmd->stream_handle;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_isp_request_stats_stream(struct vfe_device *vfe_dev, void *arg)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_vfe_stats_stream_request_cmd *stream_cfg_cmd = arg;
|
||||
struct msm_vfe_stats_stream_request_cmd *stream_req_cmd = arg;
|
||||
struct msm_vfe_stats_stream *stream_info = NULL;
|
||||
struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
|
||||
uint32_t stats_idx;
|
||||
|
||||
if (stream_cfg_cmd->stats_type < MSM_ISP_STATS_AEC ||
|
||||
stream_cfg_cmd->stats_type >= MSM_ISP_STATS_MAX) {
|
||||
pr_err("%s: invalid stats type %d received\n",
|
||||
__func__, stream_cfg_cmd->stats_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
stream_info = &stats_data->stream_info[stream_cfg_cmd->stats_type];
|
||||
if (stream_info->stream_handle != 0) {
|
||||
pr_err("%s: stats type %d has been used already\n",
|
||||
__func__, stream_cfg_cmd->stats_type);
|
||||
return -EBUSY;
|
||||
rc = msm_isp_stats_create_stream(vfe_dev, stream_req_cmd);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: create stream failed\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
stats_data->stream_handle_cnt++;
|
||||
if (stats_data->stream_handle_cnt == 0)
|
||||
stats_data->stream_handle_cnt++;
|
||||
stream_info->stream_handle =
|
||||
stats_data->stream_handle_cnt << 16 |
|
||||
stream_cfg_cmd->stats_type;
|
||||
stream_info->enable = 0;
|
||||
stream_info->stats_type = stream_cfg_cmd->stats_type;
|
||||
stream_info->comp_flag = stream_cfg_cmd->comp_flag;
|
||||
stream_info->session_id = stream_cfg_cmd->session_id;
|
||||
stream_info->stream_id = stream_cfg_cmd->stream_id;
|
||||
stream_info->framedrop_pattern = stream_cfg_cmd->framedrop_pattern;
|
||||
stream_cfg_cmd->stream_handle = stream_info->stream_handle;
|
||||
msm_isp_stats_reserve_comp_mask(vfe_dev, stats_data, stream_info);
|
||||
if (stream_info->comp_flag)
|
||||
vfe_dev->hw_info->vfe_ops.stats_ops.
|
||||
cfg_comp_mask(vfe_dev, stream_info);
|
||||
else
|
||||
stats_idx = STATS_IDX(stream_req_cmd->stream_handle);
|
||||
stream_info = &stats_data->stream_info[stats_idx];
|
||||
|
||||
switch (stream_info->framedrop_pattern) {
|
||||
case NO_SKIP:
|
||||
stream_info->framedrop_pattern = VFE_NO_DROP;
|
||||
break;
|
||||
case EVERY_2FRAME:
|
||||
stream_info->framedrop_pattern = VFE_DROP_EVERY_2FRAME;
|
||||
break;
|
||||
case EVERY_4FRAME:
|
||||
stream_info->framedrop_pattern = VFE_DROP_EVERY_4FRAME;
|
||||
break;
|
||||
case EVERY_8FRAME:
|
||||
stream_info->framedrop_pattern = VFE_DROP_EVERY_8FRAME;
|
||||
break;
|
||||
case EVERY_16FRAME:
|
||||
stream_info->framedrop_pattern = VFE_DROP_EVERY_16FRAME;
|
||||
break;
|
||||
case EVERY_32FRAME:
|
||||
stream_info->framedrop_pattern = VFE_DROP_EVERY_32FRAME;
|
||||
break;
|
||||
default:
|
||||
stream_info->framedrop_pattern = VFE_NO_DROP;
|
||||
break;
|
||||
}
|
||||
|
||||
if (stats_data->stats_pipeline_policy == STATS_COMP_NONE)
|
||||
vfe_dev->hw_info->vfe_ops.stats_ops.
|
||||
cfg_wm_irq_mask(vfe_dev, stream_info);
|
||||
vfe_dev->hw_info->vfe_ops.stats_ops.
|
||||
cfg_wm_reg(vfe_dev, stream_info);
|
||||
|
||||
vfe_dev->hw_info->vfe_ops.stats_ops.cfg_wm_reg(vfe_dev, stream_info);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_isp_release_stats_stream(struct vfe_device *vfe_dev, void *arg)
|
||||
{
|
||||
int rc = 0;
|
||||
int rc = -1;
|
||||
struct msm_vfe_stats_stream_cfg_cmd stream_cfg_cmd;
|
||||
struct msm_vfe_stats_stream_release_cmd *stream_release_cmd = arg;
|
||||
struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
|
||||
int stats_idx = STATS_IDX(stream_release_cmd->stream_handle);
|
||||
struct msm_vfe_stats_stream *stream_info =
|
||||
&stats_data->stream_info[
|
||||
(stream_release_cmd->stream_handle & 0xFF)];
|
||||
&stats_data->stream_info[stats_idx];
|
||||
|
||||
if (stream_info == NULL ||
|
||||
stream_info->stream_handle !=
|
||||
stream_release_cmd->stream_handle) {
|
||||
pr_err("%s: handle mismatch(0x%x, 0x%x\n",
|
||||
__func__, stream_info->stream_handle,
|
||||
stream_release_cmd->stream_handle);
|
||||
rc = -EINVAL;
|
||||
if (stream_info->state == STATS_AVALIABLE) {
|
||||
pr_err("%s: stream already release\n", __func__);
|
||||
return rc;
|
||||
} else if (stream_info->state != STATS_INACTIVE) {
|
||||
stream_cfg_cmd.enable = 0;
|
||||
stream_cfg_cmd.num_streams = 1;
|
||||
stream_cfg_cmd.stream_handle[0] =
|
||||
stream_release_cmd->stream_handle;
|
||||
rc = msm_isp_cfg_stats_stream(vfe_dev, &stream_cfg_cmd);
|
||||
}
|
||||
if (stream_info->enable) {
|
||||
struct msm_vfe_stats_stream_cfg_cmd stop_cmd;
|
||||
memset(&stop_cmd, 0, sizeof(stop_cmd));
|
||||
stop_cmd.num_streams = 1;
|
||||
stop_cmd.stream_handle[0] = stream_release_cmd->stream_handle;
|
||||
stop_cmd.enable = 0;
|
||||
rc = msm_isp_cfg_stats_stream(vfe_dev, (void *)&stop_cmd);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: cannot stop stats type %d\n",
|
||||
__func__, stream_info->stats_type);
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
if (stream_info->bufq_handle) {
|
||||
vfe_dev->buf_mgr->ops->release_buf(vfe_dev->buf_mgr,
|
||||
stream_info->bufq_handle);
|
||||
stream_info->bufq_handle = 0;
|
||||
}
|
||||
vfe_dev->hw_info->vfe_ops.stats_ops.
|
||||
clear_wm_reg(vfe_dev, stream_info);
|
||||
if (stream_info->comp_flag) {
|
||||
msm_isp_stats_unreserve_comp_mask(vfe_dev,
|
||||
stats_data, stream_info);
|
||||
|
||||
if (stats_data->stats_pipeline_policy == STATS_COMP_NONE)
|
||||
vfe_dev->hw_info->vfe_ops.stats_ops.
|
||||
clear_comp_mask(vfe_dev, stream_info);
|
||||
} else {
|
||||
vfe_dev->hw_info->vfe_ops.stats_ops.
|
||||
clear_wm_irq_mask(vfe_dev, stream_info);
|
||||
}
|
||||
vfe_dev->hw_info->vfe_ops.stats_ops.
|
||||
clear_framedrop(vfe_dev, stream_info);
|
||||
clear_wm_irq_mask(vfe_dev, stream_info);
|
||||
|
||||
vfe_dev->hw_info->vfe_ops.stats_ops.clear_wm_reg(vfe_dev, stream_info);
|
||||
memset(stream_info, 0, sizeof(struct msm_vfe_stats_stream));
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_isp_cfg_stats_stream(struct vfe_device *vfe_dev, void *arg)
|
||||
{
|
||||
int i, rc = 0;
|
||||
uint32_t pingpong_status = 0;
|
||||
struct msm_isp_buffer *buf = NULL;
|
||||
struct msm_vfe_stats_stream_cfg_cmd *stream_cfg_cmd = arg;
|
||||
struct msm_vfe_stats_stream *stream_info;
|
||||
struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
|
||||
int idx;
|
||||
uint32_t stats_mask = 0;
|
||||
uint8_t enable = stream_cfg_cmd->enable;
|
||||
|
||||
if (stats_data->num_active_stream == 0)
|
||||
vfe_dev->hw_info->vfe_ops.stats_ops.cfg_ub(vfe_dev);
|
||||
|
||||
for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
|
||||
idx = stream_cfg_cmd->stream_handle[i] & 0xF;
|
||||
idx = STATS_IDX(stream_cfg_cmd->stream_handle[i]);
|
||||
stream_info = &stats_data->stream_info[idx];
|
||||
if (stream_info->stream_handle !=
|
||||
stream_cfg_cmd->stream_handle[i]) {
|
||||
pr_err("%s: invalid stream handle -0x%x received\n",
|
||||
pr_err("%s: Invalid stream handle: 0x%x received\n",
|
||||
__func__, stream_cfg_cmd->stream_handle[i]);
|
||||
continue;
|
||||
}
|
||||
if (enable) {
|
||||
|
||||
if (stream_cfg_cmd->enable) {
|
||||
stream_info->bufq_handle =
|
||||
vfe_dev->buf_mgr->ops->get_bufq_handle(
|
||||
vfe_dev->buf_mgr, stream_info->session_id,
|
||||
stream_info->stream_id);
|
||||
if (stream_info->bufq_handle == 0) {
|
||||
pr_err("%s: no buf configured for stats type = %d\n",
|
||||
pr_err("%s: no buf configured for stream: 0x%x\n",
|
||||
__func__,
|
||||
stream_info->stats_type);
|
||||
stream_info->stream_handle);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
msm_isp_stats_cfg_ping_pong_address(vfe_dev,
|
||||
stream_info, VFE_PING_FLAG, NULL);
|
||||
msm_isp_stats_cfg_ping_pong_address(vfe_dev,
|
||||
stream_info, VFE_PONG_FLAG, NULL);
|
||||
stream_info->state = STATS_START_PENDING;
|
||||
stats_data->num_active_stream++;
|
||||
} else {
|
||||
stream_info->state = STATS_STOP_PENDING;
|
||||
stats_data->num_active_stream--;
|
||||
}
|
||||
/* config ping address */
|
||||
pingpong_status = VFE_PONG_ACTIVE_FLAG;
|
||||
stats_mask |= (1 << stream_info->stats_type);
|
||||
msm_isp_stats_cfg_ping_pong_address(vfe_dev,
|
||||
stream_info, pingpong_status, buf);
|
||||
pingpong_status = VFE_PING_ACTIVE_FLAG;
|
||||
msm_isp_stats_cfg_ping_pong_address(vfe_dev,
|
||||
stream_info, pingpong_status, buf);
|
||||
stats_mask |= 1 << idx;
|
||||
}
|
||||
vfe_dev->hw_info->vfe_ops.stats_ops.
|
||||
stats_enable(vfe_dev, stats_mask, enable);
|
||||
enable_module(vfe_dev, stats_mask, stream_cfg_cmd->enable);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_isp_cfg_stats_comp_policy(struct vfe_device *vfe_dev, void *arg)
|
||||
{
|
||||
int rc = -1;
|
||||
struct msm_vfe_stats_comp_policy_cfg *policy_cfg_cmd = arg;
|
||||
struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
|
||||
|
||||
if (stats_data->num_active_stream != 0) {
|
||||
pr_err("%s: Cannot update policy when there are active streams\n",
|
||||
__func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (policy_cfg_cmd->stats_pipeline_policy >= MAX_STATS_POLICY) {
|
||||
pr_err("%s: Invalid stats composite policy\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (policy_cfg_cmd->comp_framedrop_pattern >= MAX_SKIP) {
|
||||
pr_err("%s: Invalid comp framedrop pattern\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (policy_cfg_cmd->comp_irq_subsample_pattern >= MAX_SKIP) {
|
||||
pr_err("%s: Invalid comp irq subsample pattern\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
stats_data->stats_pipeline_policy =
|
||||
policy_cfg_cmd->stats_pipeline_policy;
|
||||
stats_data->comp_framedrop_pattern =
|
||||
policy_cfg_cmd->comp_framedrop_pattern;
|
||||
stats_data->comp_irq_subsample_pattern =
|
||||
policy_cfg_cmd->comp_irq_subsample_pattern;
|
||||
|
||||
vfe_dev->hw_info->vfe_ops.stats_ops.cfg_comp_mask(vfe_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#define __MSM_ISP_STATS_UTIL_H__
|
||||
|
||||
#include "msm_isp.h"
|
||||
#define STATS_IDX(idx) (idx & 0xFF)
|
||||
|
||||
void msm_isp_process_stats_irq(struct vfe_device *vfe_dev,
|
||||
uint32_t irq_status0, uint32_t irq_status1,
|
||||
@@ -20,4 +21,5 @@ void msm_isp_process_stats_irq(struct vfe_device *vfe_dev,
|
||||
int msm_isp_cfg_stats_stream(struct vfe_device *vfe_dev, void *arg);
|
||||
int msm_isp_release_stats_stream(struct vfe_device *vfe_dev, void *arg);
|
||||
int msm_isp_request_stats_stream(struct vfe_device *vfe_dev, void *arg);
|
||||
int msm_isp_cfg_stats_comp_policy(struct vfe_device *vfe_dev, void *arg);
|
||||
#endif /* __MSM_ISP_STATS_UTIL_H__ */
|
||||
|
||||
@@ -142,6 +142,9 @@ long msm_isp_ioctl(struct v4l2_subdev *sd,
|
||||
case VIDIOC_MSM_ISP_CFG_STATS_STREAM:
|
||||
msm_isp_cfg_stats_stream(vfe_dev, arg);
|
||||
break;
|
||||
case VIDIOC_MSM_ISP_CFG_STATS_COMP_POLICY:
|
||||
msm_isp_cfg_stats_comp_policy(vfe_dev, arg);
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&vfe_dev->mutex);
|
||||
@@ -425,6 +428,8 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
vfe_dev->buf_mgr->ops->buf_mgr_init(vfe_dev->buf_mgr, "msm_isp", 14);
|
||||
|
||||
memset(&vfe_dev->axi_data, 0, sizeof(struct msm_vfe_axi_shared_data));
|
||||
memset(&vfe_dev->stats_data, 0,
|
||||
sizeof(struct msm_vfe_stats_shared_data));
|
||||
vfe_dev->axi_data.hw_info = vfe_dev->hw_info->axi_hw_info;
|
||||
|
||||
ISP_DBG("%s: HW Version: 0x%x\n",
|
||||
|
||||
@@ -142,6 +142,12 @@ struct msm_vfe_axi_stream_cfg_cmd {
|
||||
enum msm_vfe_axi_stream_cmd cmd;
|
||||
};
|
||||
|
||||
enum msm_vfe_stats_pipeline_policy {
|
||||
STATS_COMP_ALL,
|
||||
STATS_COMP_NONE,
|
||||
MAX_STATS_POLICY,
|
||||
};
|
||||
|
||||
enum msm_isp_stats_type {
|
||||
MSM_ISP_STATS_AEC, /* legacy based AEC */
|
||||
MSM_ISP_STATS_AF, /* legacy based AF */
|
||||
@@ -161,10 +167,12 @@ struct msm_vfe_stats_stream_request_cmd {
|
||||
uint32_t session_id;
|
||||
uint32_t stream_id;
|
||||
enum msm_isp_stats_type stats_type;
|
||||
uint8_t comp_flag;
|
||||
uint32_t framedrop_pattern;
|
||||
uint32_t irq_subsample_pattern;
|
||||
uint32_t stream_handle;
|
||||
uint8_t comp_flag;
|
||||
};
|
||||
|
||||
struct msm_vfe_stats_stream_release_cmd {
|
||||
uint32_t stream_handle;
|
||||
};
|
||||
@@ -173,6 +181,13 @@ struct msm_vfe_stats_stream_cfg_cmd {
|
||||
uint32_t stream_handle[MSM_ISP_STATS_MAX];
|
||||
uint8_t enable;
|
||||
};
|
||||
|
||||
struct msm_vfe_stats_comp_policy_cfg {
|
||||
enum msm_vfe_stats_pipeline_policy stats_pipeline_policy;
|
||||
uint32_t comp_framedrop_pattern;
|
||||
uint32_t comp_irq_subsample_pattern;
|
||||
};
|
||||
|
||||
enum msm_vfe_reg_cfg_type {
|
||||
VFE_WRITE,
|
||||
VFE_WRITE_MB,
|
||||
@@ -320,4 +335,8 @@ struct msm_isp_event_data {
|
||||
_IOWR('V', BASE_VIDIOC_PRIVATE+11, \
|
||||
struct msm_vfe_stats_stream_release_cmd)
|
||||
|
||||
#define VIDIOC_MSM_ISP_CFG_STATS_COMP_POLICY \
|
||||
_IOWR('V', BASE_VIDIOC_PRIVATE+12, \
|
||||
struct msm_vfe_stats_comp_policy_cfg)
|
||||
|
||||
#endif /* __MSMB_ISP__ */
|
||||
|
||||
Reference in New Issue
Block a user