Merge "msm: camera: Align ISP 3.2 to new driver architecture"
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index d714ffb..69d523c 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -77,8 +77,6 @@
void (*process_axi_irq) (struct vfe_device *vfe_dev,
uint32_t irq_status0, uint32_t irq_status1,
struct msm_isp_timestamp *ts);
- void (*process_error_irq) (struct vfe_device *vfe_dev,
- uint32_t irq_status0, uint32_t irq_status1);
void (*process_stats_irq) (struct vfe_device *vfe_dev,
uint32_t irq_status0, uint32_t irq_status1,
struct msm_isp_timestamp *ts);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index 8f00e80..b981653 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -17,11 +17,13 @@
#include "msm_isp32.h"
#include "msm_isp_util.h"
#include "msm_isp_axi_util.h"
+#include "msm_isp_stats_util.h"
#include "msm_isp.h"
#include "msm.h"
#include "msm_camera_io_util.h"
-#define VFE32_BURST_LEN 4
+#define VFE32_BURST_LEN 3
+#define VFE32_UB_SIZE 1024
#define VFE32_EQUAL_SLICE_UB 117
#define VFE32_WM_BASE(idx) (0x4C + 0x18 * idx)
#define VFE32_RDI_BASE(idx) (idx ? 0x734 + 0x4 * (idx - 1) : 0x06FC)
@@ -30,6 +32,13 @@
#define VFE32_PING_PONG_BASE(wm, ping_pong) \
(VFE32_WM_BASE(wm) + 0x4 * (1 + (~(ping_pong >> wm) & 0x1)))
+#define VFE32_NUM_STATS_TYPE 7
+#define VFE32_STATS_PING_PONG_OFFSET 7
+#define VFE32_STATS_BASE(idx) (0xF4 + 0xC * idx)
+#define VFE32_STATS_PING_PONG_BASE(idx, ping_pong) \
+ (VFE32_STATS_BASE(idx) + 0x4 * \
+ (~(ping_pong >> (idx + VFE32_STATS_PING_PONG_OFFSET)) & 0x1))
+
/*Temporary use fixed bus vectors in VFE */
static struct msm_bus_vectors msm_vfe32_init_vectors[] = {
{
@@ -177,17 +186,16 @@
ISP_DBG("%s: PIX0 frame id: %lu\n", __func__,
vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id);
msm_isp_sof_notify(vfe_dev, VFE_PIX_0, ts);
+ ISP_DBG("%s: SOF IRQ\n", __func__);
+ if (vfe_dev->axi_data.src_info[VFE_PIX_0].raw_stream_count > 0
+ && vfe_dev->axi_data.src_info[VFE_PIX_0].
+ pix_stream_count == 0) {
+ msm_isp_sof_notify(vfe_dev, VFE_PIX_0, ts);
+ msm_isp_update_framedrop_reg(vfe_dev);
+ }
}
}
-static void msm_vfe32_process_stats_irq(struct vfe_device *vfe_dev,
- uint32_t irq_status0, uint32_t irq_status1,
- struct msm_isp_timestamp *ts)
-{
- /* todo: add stats specific code */
- return;
-}
-
static void msm_vfe32_process_violation_status(struct vfe_device *vfe_dev)
{
uint32_t violation_status = vfe_dev->error_info.violation_status;
@@ -326,12 +334,22 @@
if (!(irq_status0 & 0x20) && !(irq_status1 & 0x1C000000))
return;
+ if (irq_status0 & BIT(5))
+ msm_isp_sof_notify(vfe_dev, VFE_PIX_0, ts);
+ if (irq_status1 & BIT(26))
+ msm_isp_sof_notify(vfe_dev, VFE_RAW_0, ts);
+ if (irq_status1 & BIT(27))
+ msm_isp_sof_notify(vfe_dev, VFE_RAW_1, ts);
+ if (irq_status1 & BIT(28))
+ msm_isp_sof_notify(vfe_dev, VFE_RAW_2, ts);
+
if (vfe_dev->axi_data.stream_update)
msm_isp_axi_stream_update(vfe_dev);
-
msm_isp_update_framedrop_reg(vfe_dev);
msm_isp_update_error_frame_count(vfe_dev);
+ vfe_dev->hw_info->vfe_ops.core_ops.
+ reg_update(vfe_dev);
return;
}
@@ -462,6 +480,46 @@
}
}
+static void msm_vfe32_cfg_io_format(struct vfe_device *vfe_dev,
+ struct msm_vfe_axi_stream_request_cmd *stream_req_cmd)
+{
+ int bpp, bpp_reg = 0;
+ uint32_t io_format_reg;
+ bpp = msm_isp_get_bit_per_pixel(stream_req_cmd->output_format);
+
+ switch (bpp) {
+ case 8:
+ bpp_reg = 0;
+ break;
+ case 10:
+ bpp_reg = 1 << 0;
+ break;
+ case 12:
+ bpp_reg = 1 << 1;
+ break;
+ }
+ io_format_reg = msm_camera_io_r(vfe_dev->vfe_base + 0x6F8);
+ switch (stream_req_cmd->stream_src) {
+ case CAMIF_RAW:
+ io_format_reg &= 0xFFFFCFFF;
+ io_format_reg |= bpp_reg << 12;
+ break;
+ case IDEAL_RAW:
+ io_format_reg &= 0xFFFFFFC8;
+ io_format_reg |= bpp_reg << 4;
+ break;
+ case PIX_ENCODER:
+ case PIX_VIEWFINDER:
+ case RDI_INTF_0:
+ case RDI_INTF_1:
+ case RDI_INTF_2:
+ default:
+ pr_err("%s: Invalid stream source\n", __func__);
+ return;
+ }
+ msm_camera_io_w(io_format_reg, vfe_dev->vfe_base + 0x6F8);
+}
+
static void msm_vfe32_cfg_camif(struct vfe_device *vfe_dev,
struct msm_vfe_pix_cfg *pix_cfg)
{
@@ -481,10 +539,10 @@
camif_cfg->pixels_per_line,
vfe_dev->vfe_base + 0x1EC);
- msm_camera_io_w(ISP_SUB(first_pixel) << 16 | ISP_SUB(last_pixel),
+ msm_camera_io_w(first_pixel << 16 | last_pixel,
vfe_dev->vfe_base + 0x1F0);
- msm_camera_io_w(ISP_SUB(first_line) << 16 | ISP_SUB(last_line),
+ msm_camera_io_w(first_line << 16 | last_line,
vfe_dev->vfe_base + 0x1F4);
val = msm_camera_io_r(vfe_dev->vfe_base + 0x6FC);
@@ -518,6 +576,9 @@
} else if (update_state == DISABLE_CAMIF) {
msm_camera_io_w_mb(0x0, vfe_dev->vfe_base + 0x1E0);
vfe_dev->axi_data.src_info[VFE_PIX_0].active = 0;
+ } else if (update_state == DISABLE_CAMIF_IMMEDIATELY) {
+ msm_camera_io_w_mb(0x2, vfe_dev->vfe_base + 0x1E0);
+ vfe_dev->axi_data.src_info[VFE_PIX_0].active = 0;
}
}
@@ -723,7 +784,28 @@
static int msm_vfe32_get_stats_idx(enum msm_isp_stats_type stats_type)
{
- return 0;
+ switch (stats_type) {
+ case MSM_ISP_STATS_AEC:
+ case MSM_ISP_STATS_BG:
+ return 0;
+ case MSM_ISP_STATS_AF:
+ case MSM_ISP_STATS_BF:
+ return 1;
+ case MSM_ISP_STATS_AWB:
+ return 2;
+ case MSM_ISP_STATS_RS:
+ return 3;
+ case MSM_ISP_STATS_CS:
+ return 4;
+ case MSM_ISP_STATS_IHIST:
+ return 5;
+ case MSM_ISP_STATS_SKIN:
+ case MSM_ISP_STATS_BHIST:
+ return 6;
+ default:
+ pr_err("%s: Invalid stats type\n", __func__);
+ return -EINVAL;
+ }
}
static void msm_vfe32_stats_cfg_comp_mask(struct vfe_device *vfe_dev)
@@ -734,60 +816,120 @@
static void msm_vfe32_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 + 0x1C);
+ irq_mask |= BIT(STATS_IDX(stream_info->stream_handle) + 13);
+ msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x1C);
return;
}
static void msm_vfe32_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 + 0x1C);
+ irq_mask &= ~(BIT(STATS_IDX(stream_info->stream_handle) + 13));
+ msm_camera_io_w(irq_mask, vfe_dev->vfe_base + 0x1C);
return;
}
static void msm_vfe32_stats_cfg_wm_reg(struct vfe_device *vfe_dev,
struct msm_vfe_stats_stream *stream_info)
{
+ /*Nothing to configure for VFE3.x*/
return;
}
static void msm_vfe32_stats_clear_wm_reg(struct vfe_device *vfe_dev,
struct msm_vfe_stats_stream *stream_info)
{
+ /*Nothing to configure for VFE3.x*/
return;
}
static void msm_vfe32_stats_cfg_ub(struct vfe_device *vfe_dev)
{
+ int i;
+ uint32_t ub_offset = VFE32_UB_SIZE;
+ uint32_t ub_size[VFE32_NUM_STATS_TYPE] = {
+ 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 < VFE32_NUM_STATS_TYPE; i++) {
+ ub_offset -= ub_size[i];
+ msm_camera_io_w(ub_offset << 16 | (ub_size[i] - 1),
+ vfe_dev->vfe_base + VFE32_STATS_BASE(i) + 0x8);
+ }
return;
}
static void msm_vfe32_stats_enable_module(struct vfe_device *vfe_dev,
uint32_t stats_mask, uint8_t enable)
{
- return;
+ int i;
+ uint32_t module_cfg, module_cfg_mask = 0;
+
+ for (i = 0; i < VFE32_NUM_STATS_TYPE; i++) {
+ if ((stats_mask >> i) & 0x1) {
+ switch (i) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ module_cfg_mask |= 1 << (5 + i);
+ break;
+ case 5:
+ module_cfg_mask |= 1 << 16;
+ break;
+ case 6:
+ module_cfg_mask |= 1 << 19;
+ break;
+ default:
+ pr_err("%s: Invalid stats mask\n", __func__);
+ return;
+ }
+ }
+ }
+
+ module_cfg = msm_camera_io_r(vfe_dev->vfe_base + 0x10);
+ if (enable)
+ module_cfg |= module_cfg_mask;
+ else
+ module_cfg &= ~module_cfg_mask;
+ msm_camera_io_w(module_cfg, vfe_dev->vfe_base + 0x10);
}
static void msm_vfe32_stats_update_ping_pong_addr(struct vfe_device *vfe_dev,
struct msm_vfe_stats_stream *stream_info, uint32_t pingpong_status,
unsigned long paddr)
{
- return;
+ int stats_idx = STATS_IDX(stream_info->stream_handle);
+ msm_camera_io_w(paddr, vfe_dev->vfe_base +
+ VFE32_STATS_PING_PONG_BASE(stats_idx, pingpong_status));
}
static uint32_t msm_vfe32_stats_get_wm_mask(uint32_t irq_status0,
uint32_t irq_status1)
{
- return 0;
+ return (irq_status0 >> 13) & 0x7F;
}
static uint32_t msm_vfe32_stats_get_comp_mask(uint32_t irq_status0,
uint32_t irq_status1)
{
- return 0;
+ return (irq_status0 >> 24) & 0x1;
}
static uint32_t msm_vfe32_stats_get_frame_id(struct vfe_device *vfe_dev)
{
- return 0;
+ return vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id;
}
static int msm_vfe32_get_platform_data(struct vfe_device *vfe_dev)
@@ -850,6 +992,18 @@
.num_rdi_master = 3,
};
+static struct msm_vfe_stats_hardware_info msm_vfe32_stats_hw_info = {
+ .stats_capability_mask =
+ 1 << MSM_ISP_STATS_AEC | 1 << MSM_ISP_STATS_BG |
+ 1 << MSM_ISP_STATS_AF | 1 << MSM_ISP_STATS_BF |
+ 1 << MSM_ISP_STATS_AWB | 1 << MSM_ISP_STATS_IHIST |
+ 1 << MSM_ISP_STATS_RS | 1 << MSM_ISP_STATS_CS |
+ 1 << MSM_ISP_STATS_SKIN | 1 << MSM_ISP_STATS_BHIST,
+ .stats_ping_pong_offset = VFE32_STATS_PING_PONG_OFFSET,
+ .num_stats_type = VFE32_NUM_STATS_TYPE,
+ .num_stats_comp_mask = 0,
+};
+
static struct v4l2_subdev_core_ops msm_vfe32_subdev_core_ops = {
.ioctl = msm_isp_ioctl,
.subscribe_event = msm_isp_subscribe_event,
@@ -875,11 +1029,12 @@
.process_halt_irq = msm_vfe32_process_halt_irq,
.process_reg_update = msm_vfe32_process_reg_update,
.process_axi_irq = msm_isp_process_axi_irq,
- .process_stats_irq = msm_vfe32_process_stats_irq,
+ .process_stats_irq = msm_isp_process_stats_irq,
},
.axi_ops = {
.reload_wm = msm_vfe32_axi_reload_wm,
.enable_wm = msm_vfe32_axi_enable_wm,
+ .cfg_io_format = msm_vfe32_cfg_io_format,
.cfg_comp_mask = msm_vfe32_axi_cfg_comp_mask,
.clear_comp_mask = msm_vfe32_axi_clear_comp_mask,
.cfg_wm_irq_mask = msm_vfe32_axi_cfg_wm_irq_mask,
@@ -930,6 +1085,7 @@
},
.dmi_reg_offset = 0x5A0,
.axi_hw_info = &msm_vfe32_axi_hw_info,
+ .stats_hw_info = &msm_vfe32_stats_hw_info,
.subdev_ops = &msm_vfe32_subdev_ops,
.subdev_internal_ops = &msm_vfe32_internal_ops,
};