Merge "video: msm: Allow PCC/GC to be disabled/select bins" into msm-3.0
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 308f984..e2200e8 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1167,7 +1167,7 @@
capabilities of the processor.
config PL310_ERRATA_588369
- bool "Clean & Invalidate maintenance operations do not invalidate clean lines"
+ bool "PL310 errata: Clean & Invalidate maintenance operations do not invalidate clean lines"
depends on CACHE_L2X0
help
The PL310 L2 cache controller implements three types of Clean &
@@ -1192,7 +1192,7 @@
entries regardless of the ASID.
config PL310_ERRATA_727915
- bool "Background Clean & Invalidate by Way operation can cause data corruption"
+ bool "PL310 errata: Background Clean & Invalidate by Way operation can cause data corruption"
depends on CACHE_L2X0
help
PL310 implements the Clean & Invalidate by Way L2 cache maintenance
@@ -1225,8 +1225,8 @@
operation is received by a CPU before the ICIALLUIS has completed,
potentially leading to corrupted entries in the cache or TLB.
-config ARM_ERRATA_753970
- bool "ARM errata: cache sync operation may be faulty"
+config PL310_ERRATA_753970
+ bool "PL310 errata: cache sync operation may be faulty"
depends on CACHE_PL310
help
This option enables the workaround for the 753970 PL310 (r3p0) erratum.
@@ -1657,6 +1657,10 @@
config ARCH_ENABLE_MEMORY_HOTREMOVE
def_bool n
+config HOLES_IN_ZONE
+ def_bool n
+ depends on SPARSEMEM
+
config FORCE_MAX_ZONEORDER
int "Maximum zone order" if ARCH_SHMOBILE
range 11 64 if ARCH_SHMOBILE
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index 64cba23..dcd2be6 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -56,6 +56,11 @@
CONFIG_USE_OF=y
CONFIG_ARM_APPENDED_DTB=y
CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
CONFIG_VFP=y
CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 1bd3c56..7fa8099 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -70,6 +70,7 @@
CONFIG_MSM_PIL_RIVA=y
CONFIG_MSM_PIL_TZAPPS=y
CONFIG_MSM_PIL_DSPS=y
+CONFIG_MSM_PIL_VIDC=y
CONFIG_MSM_PIL_GSS=y
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_MODEM_8960=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 69806d0..262aaac 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -69,6 +69,7 @@
CONFIG_MSM_PIL_RIVA=y
CONFIG_MSM_PIL_TZAPPS=y
CONFIG_MSM_PIL_DSPS=y
+CONFIG_MSM_PIL_VIDC=y
CONFIG_MSM_PIL_GSS=y
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_MODEM_8960=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index 601f235..9429250 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -206,6 +206,10 @@
CONFIG_REGULATOR_GPIO=y
CONFIG_ION=y
CONFIG_ION_MSM=y
+CONFIG_FB=y
+CONFIG_FB_MSM=y
+CONFIG_FB_MSM_MDP_NONE=y
+CONFIG_FB_MSM_EBI2_PANEL_DETECT=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_SOC=y
diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h
index fad6d09..c582364 100644
--- a/arch/arm/include/asm/hardware/cache-l2x0.h
+++ b/arch/arm/include/asm/hardware/cache-l2x0.h
@@ -45,8 +45,6 @@
#define L2X0_CLEAN_INV_LINE_PA 0x7F0
#define L2X0_CLEAN_INV_LINE_IDX 0x7F8
#define L2X0_CLEAN_INV_WAY 0x7FC
-#define L2X0_LOCKDOWN_WAY_D 0x900
-#define L2X0_LOCKDOWN_WAY_I 0x904
/*
* The lockdown registers repeat 8 times for L310, the L210 has only one
* D and one I lockdown register at 0x0900 and 0x0904.
@@ -71,6 +69,13 @@
#define L2X0_CACHE_ID_PART_L210 (1 << 6)
#define L2X0_CACHE_ID_PART_L220 (2 << 6)
#define L2X0_CACHE_ID_PART_L310 (3 << 6)
+#define L2X0_CACHE_ID_RTL_MASK 0x3f
+#define L2X0_CACHE_ID_RTL_R0P0 0x0
+#define L2X0_CACHE_ID_RTL_R1P0 0x2
+#define L2X0_CACHE_ID_RTL_R2P0 0x4
+#define L2X0_CACHE_ID_RTL_R3P0 0x5
+#define L2X0_CACHE_ID_RTL_R3P1 0x6
+#define L2X0_CACHE_ID_RTL_R3P2 0x8
#define L2X0_AUX_CTRL_MASK 0xc0000fff
#define L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT 0
@@ -99,11 +104,36 @@
#define L2X0_ADDR_FILTER_EN 1
#ifndef __ASSEMBLY__
-extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask);
extern void l2x0_suspend(void);
extern void l2x0_resume(int collapsed);
extern void l2x0_cache_sync(void);
-extern int l2x0_of_init(__u32 aux_val, __u32 aux_mask);
+extern void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask);
+#if defined(CONFIG_CACHE_L2X0) && defined(CONFIG_OF)
+extern int l2x0_of_init(u32 aux_val, u32 aux_mask);
+#else
+static inline int l2x0_of_init(u32 aux_val, u32 aux_mask)
+{
+ return -ENODEV;
+}
+#endif
+
+struct l2x0_regs {
+ unsigned long phy_base;
+ unsigned long aux_ctrl;
+ /*
+ * Whether the following registers need to be saved/restored
+ * depends on platform
+ */
+ unsigned long tag_latency;
+ unsigned long data_latency;
+ unsigned long filter_start;
+ unsigned long filter_end;
+ unsigned long prefetch_ctrl;
+ unsigned long pwr_ctrl;
+};
+
+extern struct l2x0_regs l2x0_saved_regs;
+
#endif
#endif
diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h
index d838743..53426c6 100644
--- a/arch/arm/include/asm/outercache.h
+++ b/arch/arm/include/asm/outercache.h
@@ -34,6 +34,7 @@
void (*sync)(void);
#endif
void (*set_debug)(unsigned long);
+ void (*resume)(void);
};
#ifdef CONFIG_OUTER_CACHE
@@ -74,6 +75,12 @@
outer_cache.disable();
}
+static inline void outer_resume(void)
+{
+ if (outer_cache.resume)
+ outer_cache.resume();
+}
+
#else
static inline void outer_inv_range(phys_addr_t start, phys_addr_t end)
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 927522c..69391bf 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -20,6 +20,7 @@
#include <asm/thread_info.h>
#include <asm/memory.h>
#include <asm/procinfo.h>
+#include <asm/hardware/cache-l2x0.h>
#include <linux/kbuild.h>
/*
@@ -89,6 +90,17 @@
DEFINE(S_OLD_R0, offsetof(struct pt_regs, ARM_ORIG_r0));
DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs));
BLANK();
+#ifdef CONFIG_CACHE_L2X0
+ DEFINE(L2X0_R_PHY_BASE, offsetof(struct l2x0_regs, phy_base));
+ DEFINE(L2X0_R_AUX_CTRL, offsetof(struct l2x0_regs, aux_ctrl));
+ DEFINE(L2X0_R_TAG_LATENCY, offsetof(struct l2x0_regs, tag_latency));
+ DEFINE(L2X0_R_DATA_LATENCY, offsetof(struct l2x0_regs, data_latency));
+ DEFINE(L2X0_R_FILTER_START, offsetof(struct l2x0_regs, filter_start));
+ DEFINE(L2X0_R_FILTER_END, offsetof(struct l2x0_regs, filter_end));
+ DEFINE(L2X0_R_PREFETCH_CTRL, offsetof(struct l2x0_regs, prefetch_ctrl));
+ DEFINE(L2X0_R_PWR_CTRL, offsetof(struct l2x0_regs, pwr_ctrl));
+ BLANK();
+#endif
#ifdef CONFIG_CPU_HAS_ASID
DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id));
BLANK();
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 27db4a5..9cf07fc 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -168,6 +168,7 @@
select MSM_MULTIMEDIA_USE_ION
select MULTI_IRQ_HANDLER
select MSM_PM8X60 if PM
+ select HOLES_IN_ZONE if SPARSEMEM
config ARCH_MSM8930
bool "MSM8930"
@@ -206,6 +207,7 @@
select MSM_ULTRASOUND
select MULTI_IRQ_HANDLER
select MSM_PM8X60 if PM
+ select HOLES_IN_ZONE if SPARSEMEM
config ARCH_APQ8064
bool "APQ8064"
@@ -225,6 +227,7 @@
select MSM_L2_SPM
select MSM_PM8X60 if PM
select CPU_HAS_L2_PMU
+ select HOLES_IN_ZONE if SPARSEMEM
config ARCH_MSMCOPPER
bool "MSM Copper"
@@ -1788,6 +1791,12 @@
DSPS is a sensors offloading processor used for applications such
as rotation detection, temperature, etc.
+config MSM_PIL_VIDC
+ tristate "Video Core Secure Boot Support"
+ depends on MSM_PIL
+ help
+ Support for authenticating the video core image.
+
config MSM_PIL_GSS
tristate "GSS (Coretx A5) Boot Support"
depends on MSM_PIL
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index b465da5..0cef857 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -71,6 +71,7 @@
obj-$(CONFIG_MSM_PIL_QDSP6V4) += pil-q6v4.o
obj-$(CONFIG_MSM_PIL_RIVA) += pil-riva.o
obj-$(CONFIG_MSM_PIL_TZAPPS) += pil-tzapps.o
+obj-$(CONFIG_MSM_PIL_VIDC) += pil-vidc.o
obj-$(CONFIG_MSM_PIL_MODEM) += pil-modem.o
obj-$(CONFIG_MSM_PIL_DSPS) += pil-dsps.o
obj-$(CONFIG_MSM_PIL_GSS) += pil-gss.o
@@ -198,6 +199,9 @@
obj-$(CONFIG_ARCH_MSM9615) += cpuidle.o
endif
+ifdef CONFIG_MSM_CAMERA_V4L2
+ obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60-camera.o
+endif
obj-$(CONFIG_ARCH_FSM9XXX) += devices-fsm9xxx.o
obj-$(CONFIG_ARCH_FSM9XXX) += clock-fsm9xxx.o clock-local.o acpuclock-fsm9xxx.o
obj-$(CONFIG_ARCH_FSM9XXX) += dfe-fsm9xxx.o rfic-fsm9xxx.o
diff --git a/arch/arm/mach-msm/acpuclock-7201.c b/arch/arm/mach-msm/acpuclock-7201.c
index ec71565..b6c0b26 100644
--- a/arch/arm/mach-msm/acpuclock-7201.c
+++ b/arch/arm/mach-msm/acpuclock-7201.c
@@ -468,6 +468,10 @@
reg_clksel ^= 1;
writel_relaxed(reg_clksel, A11S_CLK_SEL_ADDR);
+ /* Wait for the clock switch to complete */
+ mb();
+ udelay(50);
+
/*
* If the new clock divider is lower than the previous, then
* program the divider after switching the clock
@@ -619,8 +623,6 @@
/* Adjust the global one */
loops_per_jiffy = cur_s->lpj;
- mb();
- udelay(50);
}
/* Nothing else to do for SWFI. */
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 051e165..041e755 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -781,7 +781,7 @@
rc = rpm_vreg_set_voltage(
sc->vreg[VREG_HFPLL_A].rpm_vreg_id,
sc->vreg[VREG_HFPLL_A].rpm_vreg_voter,
- 2100000,
+ 2050000,
sc->vreg[VREG_HFPLL_A].max_vdd, 0);
if (rc)
pr_err("%s regulator enable failed (%d)\n",
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 89d7fc9..6361d6d 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -982,11 +982,13 @@
int msm_bam_dmux_is_ch_low(uint32_t id)
{
+ unsigned long flags;
int ret;
if (id >= BAM_DMUX_NUM_CHANNELS)
return -EINVAL;
+ spin_lock_irqsave(&bam_ch[id].lock, flags);
bam_ch[id].use_wm = 1;
ret = bam_ch[id].num_tx_pkts <= LOW_WATERMARK;
DBG("%s: ch %d num tx pkts=%d, LWM=%d\n", __func__,
@@ -995,6 +997,7 @@
ret = -ENODEV;
pr_err("%s: port not open: %d\n", __func__, bam_ch[id].status);
}
+ spin_unlock_irqrestore(&bam_ch[id].lock, flags);
return ret;
}
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index c7b3af5..5d1f3e8 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -602,9 +602,10 @@
msm_gpiomux_install(apq8064_cam_common_configs,
ARRAY_SIZE(apq8064_cam_common_configs));
- if (machine_is_apq8064_cdp())
+ if (machine_is_apq8064_cdp()) {
sensor_board_info_imx074.mount_angle = 0;
- else if (machine_is_apq8064_liquid())
+ sensor_board_info_mt9m114.mount_angle = 0;
+ } else if (machine_is_apq8064_liquid())
sensor_board_info_imx074.mount_angle = 180;
platform_device_register(&msm8960_device_i2c_mux_gsbi4);
diff --git a/arch/arm/mach-msm/board-8064-display.c b/arch/arm/mach-msm/board-8064-display.c
index 19d7a9e..e17990e 100644
--- a/arch/arm/mach-msm/board-8064-display.c
+++ b/arch/arm/mach-msm/board-8064-display.c
@@ -245,15 +245,15 @@
};
static int mdp_core_clk_rate_table[] = {
- 200000000,
- 200000000,
- 200000000,
+ 85330000,
+ 128000000,
+ 160000000,
200000000,
};
static struct msm_panel_common_pdata mdp_pdata = {
.gpio = MDP_VSYNC_GPIO,
- .mdp_core_clk_rate = 200000000,
+ .mdp_core_clk_rate = 85330000,
.mdp_core_clk_table = mdp_core_clk_rate_table,
.num_mdp_clk = ARRAY_SIZE(mdp_core_clk_rate_table),
.mdp_bus_scale_table = &mdp_bus_scale_pdata,
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index 7b84a68..f8aa9c0 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -198,7 +198,7 @@
.init_level = 0,
.num_levels = 4,
.set_grp_async = NULL,
- .idle_timeout = HZ/20,
+ .idle_timeout = HZ/10,
.nap_allowed = true,
.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE,
#ifdef CONFIG_MSM_BUS_SCALING
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 3f4266f..d01af99 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -479,9 +479,59 @@
}
#ifdef CONFIG_USB_EHCI_MSM_HSIC
+/* Bandwidth requests (zero) if no vote placed */
+static struct msm_bus_vectors hsic_init_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_SPS,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+/* Bus bandwidth requests in Bytes/sec */
+static struct msm_bus_vectors hsic_max_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 60000000, /* At least 480Mbps on bus. */
+ .ib = 960000000, /* MAX bursts rate */
+ },
+ {
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_SPS,
+ .ab = 0,
+ .ib = 512000000, /*vote for 64Mhz dfab clk rate*/
+ },
+};
+
+static struct msm_bus_paths hsic_bus_scale_usecases[] = {
+ {
+ ARRAY_SIZE(hsic_init_vectors),
+ hsic_init_vectors,
+ },
+ {
+ ARRAY_SIZE(hsic_max_vectors),
+ hsic_max_vectors,
+ },
+};
+
+static struct msm_bus_scale_pdata hsic_bus_scale_pdata = {
+ hsic_bus_scale_usecases,
+ ARRAY_SIZE(hsic_bus_scale_usecases),
+ .name = "hsic",
+};
+
static struct msm_hsic_host_platform_data msm_hsic_pdata = {
- .strobe = 88,
- .data = 89,
+ .strobe = 88,
+ .data = 89,
+ .bus_scale_table = &hsic_bus_scale_pdata,
};
#else
static struct msm_hsic_host_platform_data msm_hsic_pdata;
@@ -1871,6 +1921,7 @@
&msm_pil_dsps,
&msm_8960_riva,
&msm_8960_q6_lpass,
+ &msm_pil_vidc,
&msm_gss,
#ifdef CONFIG_MSM_RTB
&msm_rtb_device,
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 5493628..98f1228 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -1637,6 +1637,7 @@
&msm_8960_q6_mss_sw,
&msm_8960_riva,
&msm_pil_tzapps,
+ &msm_pil_vidc,
&msm8960_device_qup_spi_gsbi1,
&msm8960_device_qup_i2c_gsbi3,
&msm8960_device_qup_i2c_gsbi4,
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index 23e3e69..64fa69f 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -518,7 +518,7 @@
RPM_SMPS(S3, 0, 1, 1, 500000, 1150000, NULL, 100000, 4p80, NONE, NONE),
RPM_SMPS(S4, 1, 1, 0, 1800000, 1800000, NULL, 100000, 1p60, AUTO, AUTO),
RPM_SMPS(S7, 0, 1, 0, 1150000, 1150000, NULL, 100000, 3p20, NONE, NONE),
- RPM_SMPS(S8, 1, 1, 1, 2100000, 2100000, NULL, 100000, 1p60, NONE, NONE),
+ RPM_SMPS(S8, 1, 1, 1, 2050000, 2050000, NULL, 100000, 1p60, NONE, NONE),
/* ID a_on pd ss min_uV max_uV supply sys_uA init_ip */
RPM_LDO(L1, 1, 1, 0, 1050000, 1050000, "8921_s4", 0, 10000),
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index f462c7a..29fc200 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2336,6 +2336,7 @@
&msm_8960_riva,
&msm_pil_tzapps,
&msm_pil_dsps,
+ &msm_pil_vidc,
&msm8960_device_otg,
&msm8960_device_gadget_peripheral,
&msm_device_hsusb_host,
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index cf608ad..3973bd1 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -860,6 +860,155 @@
},
};
+#ifdef CONFIG_MSM_CAMERA_V4L2
+static struct msm_camera_device_platform_data msm_camera_csi_device_data[] = {
+ {
+ .csid_core = 0,
+ .is_csic = 1,
+ .is_vpe = 1,
+ .ioclk = {
+ .vfe_clk_rate = 153600000,
+ },
+ },
+ {
+ .csid_core = 0,
+ .is_vpe = 1,
+ .ioclk = {
+ .vfe_clk_rate = 153600000,
+ },
+ },
+};
+
+static struct camera_vreg_t msm_7x30_back_cam_vreg[] = {
+ {"gp2", REG_LDO, 2600000, 2600000, -1},
+ {"lvsw1", REG_VS, 0, 0, 0},
+};
+
+static uint32_t camera_off_gpio_table[] = {
+ /* parallel CAMERA interfaces */
+ /* RST */
+ GPIO_CFG(0, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT2 */
+ GPIO_CFG(2, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT3 */
+ GPIO_CFG(3, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT4 */
+ GPIO_CFG(4, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT5 */
+ GPIO_CFG(5, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT6 */
+ GPIO_CFG(6, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT7 */
+ GPIO_CFG(7, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT8 */
+ GPIO_CFG(8, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT9 */
+ GPIO_CFG(9, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT10 */
+ GPIO_CFG(10, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT11 */
+ GPIO_CFG(11, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* PCLK */
+ GPIO_CFG(12, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* HSYNC_IN */
+ GPIO_CFG(13, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* VSYNC_IN */
+ GPIO_CFG(14, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* MCLK */
+ GPIO_CFG(15, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+};
+
+static uint32_t camera_on_gpio_table[] = {
+ /* parallel CAMERA interfaces */
+ /* RST */
+ GPIO_CFG(0, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT2 */
+ GPIO_CFG(2, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT3 */
+ GPIO_CFG(3, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT4 */
+ GPIO_CFG(4, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT5 */
+ GPIO_CFG(5, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT6 */
+ GPIO_CFG(6, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT7 */
+ GPIO_CFG(7, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT8 */
+ GPIO_CFG(8, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT9 */
+ GPIO_CFG(9, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT10 */
+ GPIO_CFG(10, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT11 */
+ GPIO_CFG(11, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* PCLK */
+ GPIO_CFG(12, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* HSYNC_IN */
+ GPIO_CFG(13, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* VSYNC_IN */
+ GPIO_CFG(14, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* MCLK */
+ GPIO_CFG(15, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+};
+
+static struct gpio msm7x30_back_cam_gpio[] = {
+ {0, GPIOF_DIR_OUT, "CAM_RESET"},
+};
+
+static struct msm_gpio_set_tbl msm7x30_back_cam_gpio_set_tbl[] = {
+ {0, GPIOF_OUT_INIT_LOW, 1000},
+ {0, GPIOF_OUT_INIT_HIGH, 4000},
+};
+
+static struct msm_camera_gpio_conf msm_7x30_back_cam_gpio_conf = {
+ .cam_gpio_req_tbl = msm7x30_back_cam_gpio,
+ .cam_gpio_req_tbl_size = ARRAY_SIZE(msm7x30_back_cam_gpio),
+ .cam_gpio_set_tbl = msm7x30_back_cam_gpio_set_tbl,
+ .cam_gpio_set_tbl_size = ARRAY_SIZE(msm7x30_back_cam_gpio_set_tbl),
+ .camera_off_table = camera_off_gpio_table,
+ .camera_off_table_size = ARRAY_SIZE(camera_off_gpio_table),
+ .camera_on_table = camera_on_gpio_table,
+ .camera_on_table_size = ARRAY_SIZE(camera_on_gpio_table),
+ .gpio_no_mux = 1,
+};
+
+static struct msm_camera_sensor_flash_data flash_vx6953 = {
+ .flash_type = MSM_CAMERA_FLASH_NONE,
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_vx6953 = {
+ .mount_angle = 0,
+ .cam_vreg = msm_7x30_back_cam_vreg,
+ .num_vreg = ARRAY_SIZE(msm_7x30_back_cam_vreg),
+ .gpio_conf = &msm_7x30_back_cam_gpio_conf,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_vx6953_data = {
+ .sensor_name = "vx6953",
+ .pdata = &msm_camera_csi_device_data[0],
+ .flash_data = &flash_vx6953,
+ .sensor_platform_info = &sensor_board_info_vx6953,
+ .csi_if = 1,
+ .camera_type = BACK_CAMERA_2D,
+};
+
+void __init msm7x30_init_cam(void)
+{
+ platform_device_register(&msm_device_csic0);
+ platform_device_register(&msm_device_vfe);
+ platform_device_register(&msm_device_vpe);
+}
+
+#ifdef CONFIG_I2C
+static struct i2c_board_info msm_camera_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("vx6953", 0x20),
+ .platform_data = &msm_camera_sensor_vx6953_data,
+ },
+};
+#endif
+#else
static struct i2c_board_info msm_camera_boardinfo[] __initdata = {
#ifdef CONFIG_MT9D112
{
@@ -912,21 +1061,36 @@
static uint32_t camera_off_gpio_table[] = {
/* parallel CAMERA interfaces */
- GPIO_CFG(0, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* RST */
- GPIO_CFG(2, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT2 */
- GPIO_CFG(3, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT3 */
- GPIO_CFG(4, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT4 */
- GPIO_CFG(5, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT5 */
- GPIO_CFG(6, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT6 */
- GPIO_CFG(7, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT7 */
- GPIO_CFG(8, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT8 */
- GPIO_CFG(9, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT9 */
- GPIO_CFG(10, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT10 */
- GPIO_CFG(11, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT11 */
- GPIO_CFG(12, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* PCLK */
- GPIO_CFG(13, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* HSYNC_IN */
- GPIO_CFG(14, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* VSYNC_IN */
- GPIO_CFG(15, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), /* MCLK */
+ /* RST */
+ GPIO_CFG(0, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT2 */
+ GPIO_CFG(2, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT3 */
+ GPIO_CFG(3, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT4 */
+ GPIO_CFG(4, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT5 */
+ GPIO_CFG(5, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT6 */
+ GPIO_CFG(6, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT7 */
+ GPIO_CFG(7, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT8 */
+ GPIO_CFG(8, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT9 */
+ GPIO_CFG(9, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT10 */
+ GPIO_CFG(10, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT11 */
+ GPIO_CFG(11, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* PCLK */
+ GPIO_CFG(12, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* HSYNC_IN */
+ GPIO_CFG(13, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* VSYNC_IN */
+ GPIO_CFG(14, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* MCLK */
+ GPIO_CFG(15, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
};
static uint32_t camera_on_vcm_gpio_table[] = {
@@ -935,21 +1099,36 @@
static uint32_t camera_on_gpio_table[] = {
/* parallel CAMERA interfaces */
- GPIO_CFG(0, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* RST */
- GPIO_CFG(2, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT2 */
- GPIO_CFG(3, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT3 */
- GPIO_CFG(4, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT4 */
- GPIO_CFG(5, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT5 */
- GPIO_CFG(6, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT6 */
- GPIO_CFG(7, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT7 */
- GPIO_CFG(8, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT8 */
- GPIO_CFG(9, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT9 */
- GPIO_CFG(10, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT10 */
- GPIO_CFG(11, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT11 */
- GPIO_CFG(12, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* PCLK */
- GPIO_CFG(13, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* HSYNC_IN */
- GPIO_CFG(14, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* VSYNC_IN */
- GPIO_CFG(15, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), /* MCLK */
+ /* RST */
+ GPIO_CFG(0, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT2 */
+ GPIO_CFG(2, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT3 */
+ GPIO_CFG(3, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT4 */
+ GPIO_CFG(4, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT5 */
+ GPIO_CFG(5, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT6 */
+ GPIO_CFG(6, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT7 */
+ GPIO_CFG(7, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT8 */
+ GPIO_CFG(8, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT9 */
+ GPIO_CFG(9, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT10 */
+ GPIO_CFG(10, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* DAT11 */
+ GPIO_CFG(11, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* PCLK */
+ GPIO_CFG(12, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* HSYNC_IN */
+ GPIO_CFG(13, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* VSYNC_IN */
+ GPIO_CFG(14, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ /* MCLK */
+ GPIO_CFG(15, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
};
static uint32_t camera_off_gpio_fluid_table[] = {
@@ -1292,27 +1471,6 @@
};
#endif
-#ifdef CONFIG_MSM_GEMINI
-static struct resource msm_gemini_resources[] = {
- {
- .start = 0xA3A00000,
- .end = 0xA3A00000 + 0x0150 - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = INT_JPEG,
- .end = INT_JPEG,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device msm_gemini_device = {
- .name = "msm_gemini",
- .resource = msm_gemini_resources,
- .num_resources = ARRAY_SIZE(msm_gemini_resources),
-};
-#endif
-
#ifdef CONFIG_MSM_VPE
static struct resource msm_vpe_resources[] = {
{
@@ -1336,6 +1494,28 @@
#endif
#endif /*CONFIG_MSM_CAMERA*/
+#endif
+
+#ifdef CONFIG_MSM_GEMINI
+static struct resource msm_gemini_resources[] = {
+ {
+ .start = 0xA3A00000,
+ .end = 0xA3A00000 + 0x0150 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = INT_JPEG,
+ .end = INT_JPEG,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device msm_gemini_device = {
+ .name = "msm_gemini",
+ .resource = msm_gemini_resources,
+ .num_resources = ARRAY_SIZE(msm_gemini_resources),
+};
+#endif
#ifdef CONFIG_MSM7KV2_AUDIO
static uint32_t audio_pamp_gpio_config =
@@ -5245,6 +5425,7 @@
#endif
&msm_kgsl_3d0,
&msm_kgsl_2d0,
+#ifndef CONFIG_MSM_CAMERA_V4L2
#ifdef CONFIG_MT9T013
&msm_camera_sensor_mt9t013,
#endif
@@ -5269,13 +5450,16 @@
#ifdef CONFIG_SN12M0PZ
&msm_camera_sensor_sn12m0pz,
#endif
+#endif
&msm_device_vidc_720p,
#ifdef CONFIG_MSM_GEMINI
&msm_gemini_device,
#endif
+#ifndef CONFIG_MSM_CAMERA_V4L2
#ifdef CONFIG_MSM_VPE
&msm_vpe_device,
#endif
+#endif
#if defined(CONFIG_TSIF) || defined(CONFIG_TSIF_MODULE)
&msm_device_tsif,
#endif
@@ -6825,6 +7009,9 @@
#ifdef CONFIG_USB_EHCI_MSM_72K
msm_add_host(0, &msm_usb_host_pdata);
#endif
+#ifdef CONFIG_MSM_CAMERA_V4L2
+ msm7x30_init_cam();
+#endif
msm7x30_init_mmc();
msm7x30_init_nand();
msm_qsd_spi_init();
diff --git a/arch/arm/mach-msm/board-msm8x60-camera.c b/arch/arm/mach-msm/board-msm8x60-camera.c
new file mode 100644
index 0000000..95561e4
--- /dev/null
+++ b/arch/arm/mach-msm/board-msm8x60-camera.c
@@ -0,0 +1,471 @@
+/* Copyright (c) 2012 Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <asm/mach-types.h>
+#include <devices-msm8x60.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/mfd/pmic8901.h>
+#include <mach/board.h>
+#include <mach/board-msm8660.h>
+#include <mach/gpiomux.h>
+#include <mach/msm_bus_board.h>
+#include "devices.h"
+
+#define GPIO_EXT_CAMIF_PWR_EN1 (PM8901_MPP_BASE + PM8901_MPPS + 13)
+#ifdef CONFIG_MSM_CAMERA_FLASH
+#define VFE_CAMIF_TIMER1_GPIO 29
+#define VFE_CAMIF_TIMER2_GPIO 30
+#define VFE_CAMIF_TIMER3_GPIO_INT 31
+#define FUSION_VFE_CAMIF_TIMER1_GPIO 42
+
+static struct msm_camera_sensor_flash_src msm_flash_src = {
+ .flash_sr_type = MSM_CAMERA_FLASH_SRC_PMIC,
+ ._fsrc.pmic_src.num_of_src = 2,
+ ._fsrc.pmic_src.low_current = 100,
+ ._fsrc.pmic_src.high_current = 300,
+ ._fsrc.pmic_src.led_src_1 = PMIC8058_ID_FLASH_LED_0,
+ ._fsrc.pmic_src.led_src_2 = PMIC8058_ID_FLASH_LED_1,
+ ._fsrc.pmic_src.pmic_set_current = pm8058_set_flash_led_current,
+};
+static struct msm_camera_sensor_strobe_flash_data strobe_flash_xenon = {
+ .flash_trigger = VFE_CAMIF_TIMER2_GPIO,
+ .flash_charge = VFE_CAMIF_TIMER1_GPIO,
+ .flash_charge_done = VFE_CAMIF_TIMER3_GPIO_INT,
+ .flash_recharge_duration = 50000,
+ .irq = MSM_GPIO_TO_INT(VFE_CAMIF_TIMER3_GPIO_INT),
+};
+#endif
+
+static struct msm_bus_vectors cam_init_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+static struct msm_bus_vectors cam_preview_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 283115520,
+ .ib = 452984832,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+static struct msm_bus_vectors cam_video_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 283115520,
+ .ib = 452984832,
+ },
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 283115520,
+ .ib = 452984832,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 319610880,
+ .ib = 511377408,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+static struct msm_bus_vectors cam_snapshot_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 566231040,
+ .ib = 905969664,
+ },
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 69984000,
+ .ib = 111974400,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 320864256,
+ .ib = 513382810,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 320864256,
+ .ib = 513382810,
+ },
+};
+
+static struct msm_bus_vectors cam_zsl_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 566231040,
+ .ib = 905969664,
+ },
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 706199040,
+ .ib = 1129918464,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 320864256,
+ .ib = 513382810,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 320864256,
+ .ib = 513382810,
+ },
+};
+
+static struct msm_bus_vectors cam_stereo_video_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 212336640,
+ .ib = 339738624,
+ },
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 25090560,
+ .ib = 40144896,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 239708160,
+ .ib = 383533056,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 79902720,
+ .ib = 127844352,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+static struct msm_bus_vectors cam_stereo_snapshot_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 300902400,
+ .ib = 481443840,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 230307840,
+ .ib = 368492544,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 245113344,
+ .ib = 392181351,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_SMI,
+ .ab = 106536960,
+ .ib = 170459136,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 106536960,
+ .ib = 170459136,
+ },
+};
+
+static struct msm_bus_paths cam_bus_client_config[] = {
+ {
+ ARRAY_SIZE(cam_init_vectors),
+ cam_zsl_vectors,
+ },
+ {
+ ARRAY_SIZE(cam_preview_vectors),
+ cam_zsl_vectors,
+ },
+ {
+ ARRAY_SIZE(cam_video_vectors),
+ cam_zsl_vectors,
+ },
+ {
+ ARRAY_SIZE(cam_snapshot_vectors),
+ cam_snapshot_vectors,
+ },
+ {
+ ARRAY_SIZE(cam_zsl_vectors),
+ cam_zsl_vectors,
+ },
+ {
+ ARRAY_SIZE(cam_stereo_video_vectors),
+ cam_stereo_video_vectors,
+ },
+ {
+ ARRAY_SIZE(cam_stereo_snapshot_vectors),
+ cam_stereo_snapshot_vectors,
+ },
+};
+
+static struct msm_bus_scale_pdata cam_bus_client_pdata = {
+ cam_bus_client_config,
+ ARRAY_SIZE(cam_bus_client_config),
+ .name = "msm_camera",
+};
+
+static struct msm_camera_device_platform_data msm_camera_csi_device_data[] = {
+ {
+ .csid_core = 0,
+ .is_csic = 1,
+ .is_vpe = 1,
+ .cam_bus_scale_table = &cam_bus_client_pdata,
+ .ioclk = {
+ .vfe_clk_rate = 228570000,
+ },
+ },
+ {
+ .csid_core = 1,
+ .is_csic = 1,
+ .is_vpe = 1,
+ .cam_bus_scale_table = &cam_bus_client_pdata,
+ .ioclk = {
+ .vfe_clk_rate = 228570000,
+ },
+ },
+};
+static struct camera_vreg_t msm_8x60_back_cam_vreg[] = {
+ {"cam_vana", REG_LDO, 2850000, 2850000, -1},
+ {"cam_vio", REG_VS, 0, 0, 0},
+ {"cam_vdig", REG_LDO, 1200000, 1200000, -1},
+};
+
+static struct gpio msm8x60_common_cam_gpio[] = {
+ {32, GPIOF_DIR_IN, "CAMIF_MCLK"},
+ {47, GPIOF_DIR_IN, "CAMIF_I2C_DATA"},
+ {48, GPIOF_DIR_IN, "CAMIF_I2C_CLK"},
+ {105, GPIOF_DIR_IN, "STANDBY"},
+ {GPIO_EXT_CAMIF_PWR_EN1, GPIOF_DIR_OUT, "CAMIF_PWR_EN"},
+};
+
+static struct gpio msm8x60_back_cam_gpio[] = {
+ {106, GPIOF_DIR_OUT, "CAM_RESET"},
+};
+
+static struct msm_gpio_set_tbl msm8x60_back_cam_gpio_set_tbl[] = {
+ {GPIO_EXT_CAMIF_PWR_EN1, GPIOF_OUT_INIT_LOW, 10000},
+ {GPIO_EXT_CAMIF_PWR_EN1, GPIOF_OUT_INIT_HIGH, 5000},
+ {106, GPIOF_OUT_INIT_LOW, 1000},
+ {106, GPIOF_OUT_INIT_HIGH, 4000},
+};
+
+static struct msm_camera_gpio_conf msm_8x60_back_cam_gpio_conf = {
+ .cam_gpio_common_tbl = msm8x60_common_cam_gpio,
+ .cam_gpio_common_tbl_size = ARRAY_SIZE(msm8x60_common_cam_gpio),
+ .cam_gpio_req_tbl = msm8x60_back_cam_gpio,
+ .cam_gpio_req_tbl_size = ARRAY_SIZE(msm8x60_back_cam_gpio),
+ .cam_gpio_set_tbl = msm8x60_back_cam_gpio_set_tbl,
+ .cam_gpio_set_tbl_size = ARRAY_SIZE(msm8x60_back_cam_gpio_set_tbl),
+};
+
+
+static struct i2c_board_info imx074_actuator_i2c_info = {
+ I2C_BOARD_INFO("imx074_act", 0x11),
+};
+
+static struct msm_actuator_info imx074_actuator_info = {
+ .board_info = &imx074_actuator_i2c_info,
+ .bus_id = MSM_GSBI4_QUP_I2C_BUS_ID,
+ .vcm_pwd = 0,
+ .vcm_enable = 1,
+};
+
+static struct msm_camera_sensor_flash_data flash_imx074 = {
+ .flash_type = MSM_CAMERA_FLASH_LED,
+#ifdef CONFIG_MSM_CAMERA_FLASH
+ .flash_src = &msm_flash_src,
+#endif
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_imx074 = {
+ .mount_angle = 0,
+ .cam_vreg = msm_8x60_back_cam_vreg,
+ .num_vreg = ARRAY_SIZE(msm_8x60_back_cam_vreg),
+ .gpio_conf = &msm_8x60_back_cam_gpio_conf,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_imx074_data = {
+ .sensor_name = "imx074",
+ .pdata = &msm_camera_csi_device_data[0],
+ .flash_data = &flash_imx074,
+ .strobe_flash_data = &strobe_flash_xenon,
+ .sensor_platform_info = &sensor_board_info_imx074,
+ .csi_if = 1,
+ .camera_type = BACK_CAMERA_2D,
+ .actuator_info = &imx074_actuator_info
+};
+
+void __init msm8x60_init_cam(void)
+{
+ platform_device_register(&msm_device_csic0);
+ platform_device_register(&msm_device_csic1);
+ platform_device_register(&msm_device_vfe);
+ platform_device_register(&msm_device_vpe);
+}
+
+#ifdef CONFIG_I2C
+static struct i2c_board_info msm8x60_camera_i2c_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("imx074", 0x1A),
+ .platform_data = &msm_camera_sensor_imx074_data,
+ },
+};
+
+struct msm_camera_board_info msm8x60_camera_board_info = {
+ .board_info = msm8x60_camera_i2c_boardinfo,
+ .num_i2c_board_info = ARRAY_SIZE(msm8x60_camera_i2c_boardinfo),
+};
+#endif
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 5db8de4..9497735 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -1562,6 +1562,7 @@
#endif
#ifdef CONFIG_MSM_VPE
+#ifndef CONFIG_MSM_CAMERA_V4L2
static struct resource msm_vpe_resources[] = {
{
.start = 0x05300000,
@@ -1582,8 +1583,10 @@
.resource = msm_vpe_resources,
};
#endif
+#endif
#ifdef CONFIG_MSM_CAMERA
+#ifndef CONFIG_MSM_CAMERA_V4L2
#ifdef CONFIG_MSM_CAMERA_FLASH
#define VFE_CAMIF_TIMER1_GPIO 29
#define VFE_CAMIF_TIMER2_GPIO 30
@@ -2486,6 +2489,7 @@
#endif
};
#endif
+#endif
#ifdef CONFIG_MSM_GEMINI
static struct resource msm_gemini_resources[] = {
@@ -3868,6 +3872,7 @@
};
static struct regulator_consumer_supply vreg_consumers_PM8058_L15[] = {
REGULATOR_SUPPLY("8058_l15", NULL),
+ REGULATOR_SUPPLY("cam_vana", "1-001a"),
};
static struct regulator_consumer_supply vreg_consumers_PM8058_L16[] = {
REGULATOR_SUPPLY("8058_l16", NULL),
@@ -3898,6 +3903,7 @@
};
static struct regulator_consumer_supply vreg_consumers_PM8058_L25[] = {
REGULATOR_SUPPLY("8058_l25", NULL),
+ REGULATOR_SUPPLY("cam_vdig", "1-001a"),
};
static struct regulator_consumer_supply vreg_consumers_PM8058_S0[] = {
REGULATOR_SUPPLY("8058_s0", NULL),
@@ -3916,6 +3922,7 @@
};
static struct regulator_consumer_supply vreg_consumers_PM8058_LVS0[] = {
REGULATOR_SUPPLY("8058_lvs0", NULL),
+ REGULATOR_SUPPLY("cam_vio", "1-001a"),
};
static struct regulator_consumer_supply vreg_consumers_PM8058_LVS1[] = {
REGULATOR_SUPPLY("8058_lvs1", NULL),
@@ -4279,6 +4286,7 @@
&hdmi_msm_device,
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
#ifdef CONFIG_MSM_CAMERA
+#ifndef CONFIG_MSM_CAMERA_V4L2
#ifdef CONFIG_MT9E013
&msm_camera_sensor_mt9e013,
#endif
@@ -4298,12 +4306,15 @@
&msm_camera_sensor_qs_s5k4e1,
#endif
#endif
+#endif
#ifdef CONFIG_MSM_GEMINI
&msm_gemini_device,
#endif
#ifdef CONFIG_MSM_VPE
+#ifndef CONFIG_MSM_CAMERA_V4L2
&msm_vpe_device,
#endif
+#endif
&msm_device_vidc,
};
@@ -5223,6 +5234,7 @@
&mipi_dsi_novatek_panel_device,
#endif
#ifdef CONFIG_MSM_CAMERA
+#ifndef CONFIG_MSM_CAMERA_V4L2
#ifdef CONFIG_MT9E013
&msm_camera_sensor_mt9e013,
#endif
@@ -5242,12 +5254,15 @@
&msm_camera_sensor_vx6953,
#endif
#endif
+#endif
#ifdef CONFIG_MSM_GEMINI
&msm_gemini_device,
#endif
#ifdef CONFIG_MSM_VPE
+#ifndef CONFIG_MSM_CAMERA_V4L2
&msm_vpe_device,
#endif
+#endif
#if defined(CONFIG_MSM_RPM_LOG) || defined(CONFIG_MSM_RPM_LOG_MODULE)
&msm8660_rpm_log_device,
@@ -7245,6 +7260,7 @@
},
#endif
#ifdef CONFIG_MSM_CAMERA
+#ifndef CONFIG_MSM_CAMERA_V4L2
{
I2C_SURF | I2C_FFA | I2C_FLUID ,
MSM_GSBI4_QUP_I2C_BUS_ID,
@@ -7258,6 +7274,7 @@
ARRAY_SIZE(msm_camera_dragon_boardinfo),
},
#endif
+#endif
{
I2C_SURF | I2C_FFA | I2C_FLUID,
MSM_GSBI7_QUP_I2C_BUS_ID,
@@ -7340,6 +7357,14 @@
#ifdef CONFIG_I2C
u8 mach_mask = 0;
int i;
+#ifdef CONFIG_MSM_CAMERA_V4L2
+ struct i2c_registry msm8x60_camera_i2c_devices = {
+ I2C_SURF | I2C_FFA | I2C_FLUID,
+ MSM_GSBI4_QUP_I2C_BUS_ID,
+ msm8x60_camera_board_info.board_info,
+ msm8x60_camera_board_info.num_i2c_board_info,
+ };
+#endif
/* Build the matching 'supported_machs' bitmask */
if (machine_is_msm8x60_surf() || machine_is_msm8x60_fusion())
@@ -7364,6 +7389,12 @@
msm8x60_i2c_devices[i].info,
msm8x60_i2c_devices[i].len);
}
+#ifdef CONFIG_MSM_CAMERA_V4L2
+ if (msm8x60_camera_i2c_devices.machs & mach_mask)
+ i2c_register_board_info(msm8x60_camera_i2c_devices.bus,
+ msm8x60_camera_i2c_devices.info,
+ msm8x60_camera_i2c_devices.len);
+#endif
#endif
}
@@ -10323,8 +10354,12 @@
msm8x60_init_tlmm();
msm8x60_init_gpiomux(board_data->gpiomux_cfgs);
msm8x60_init_uart12dm();
+#ifdef CONFIG_MSM_CAMERA_V4L2
+ msm8x60_init_cam();
+#endif
msm8x60_init_mmc();
+
#if defined(CONFIG_PMIC8058_OTHC) || defined(CONFIG_PMIC8058_OTHC_MODULE)
msm8x60_init_pm8058_othc();
#endif
@@ -10335,13 +10370,13 @@
pm8058_platform_data.keypad_pdata = &dragon_keypad_data;
else
pm8058_platform_data.keypad_pdata = &ffa_keypad_data;
-
+#ifndef CONFIG_MSM_CAMERA_V4L2
/* Specify reset pin for OV9726 */
if (machine_is_msm8x60_dragon()) {
msm_camera_sensor_ov9726_data.sensor_reset = 62;
ov9726_sensor_8660_info.mount_angle = 270;
}
-
+#endif
#ifdef CONFIG_BATTERY_MSM8X60
if (machine_is_msm8x60_surf() || machine_is_msm8x60_ffa() ||
machine_is_msm8x60_fusion() || machine_is_msm8x60_dragon() ||
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 7b27c4e..07aec8a 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -59,7 +59,7 @@
#include "board-msm7627a.h"
#define PMEM_KERNEL_EBI1_SIZE 0x3A000
-#define MSM_PMEM_AUDIO_SIZE 0x5B000
+#define MSM_PMEM_AUDIO_SIZE 0x1F4000
#define BAHAMA_SLAVE_ID_FM_REG 0x02
#define FM_GPIO 83
#define BT_PCM_BCLK_MODE 0x88
@@ -510,6 +510,7 @@
/* Concurrency 6 */
(DEC0_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
0, 0, 0, 0,
/* Concurrency 7 */
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index b4b2855..48417a4 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -2870,6 +2870,7 @@
OWN(ROW2, 11, "iface_clk", usb_hs_p_clk, "msm_otg"),
OWN(APPS3, 6, "cam_m_clk", cam_m_clk, NULL),
+ OWN(APPS3, 6, "cam_clk", cam_m_clk, "4-0020"),
OWN(APPS3, 6, "camif_pad_pclk", camif_pad_p_clk, NULL),
OWN(APPS3, 6, "iface_clk", camif_pad_p_clk, "qup_i2c.4"),
OWN(APPS3, 11, "csi_clk", csi0_clk, NULL),
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 7d1bcf3..c0019a3 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -433,7 +433,7 @@
RPM_VREG_VOTER3, 1800000, 1800000, 1);
} else {
rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_S8,
- RPM_VREG_VOTER3, 2100000, 2100000, 1);
+ RPM_VREG_VOTER3, 2050000, 2100000, 1);
if (rc)
return rc;
rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_L23,
@@ -5178,6 +5178,9 @@
CLK_LOOKUP("core_clk", gfx3d_axi_clk_8064.c, "msm_iommu.10"),
CLK_LOOKUP("core_clk", vcap_axi_clk.c, "msm_iommu.11"),
+ CLK_LOOKUP("core_clk", vcodec_axi_clk.c, "pil_vidc"),
+ CLK_LOOKUP("smmu_iface_clk", smmu_p_clk.c, "pil_vidc"),
+
CLK_LOOKUP("mem_clk", ebi1_adm_clk.c, "msm_dmov"),
CLK_LOOKUP("l2_mclk", l2_m_clk, ""),
@@ -5456,6 +5459,8 @@
CLK_LOOKUP("vcodec_iommu0_clk", vcodec_axi_a_clk.c, "msm_vidc.0"),
CLK_LOOKUP("vcodec_iommu1_clk", vcodec_axi_b_clk.c, "msm_vidc.0"),
CLK_LOOKUP("smmu_iface_clk", smmu_p_clk.c, "msm_vidc.0"),
+ CLK_LOOKUP("core_clk", vcodec_axi_clk.c, "pil_vidc"),
+ CLK_LOOKUP("smmu_iface_clk", smmu_p_clk.c, "pil_vidc"),
CLK_LOOKUP("dfab_dsps_clk", dfab_dsps_clk.c, NULL),
CLK_LOOKUP("core_clk", dfab_usb_hs_clk.c, "msm_otg"),
@@ -5728,6 +5733,8 @@
CLK_LOOKUP("vcodec_iommu0_clk", vcodec_axi_a_clk.c, "msm_vidc.0"),
CLK_LOOKUP("vcodec_iommu1_clk", vcodec_axi_b_clk.c, "msm_vidc.0"),
CLK_LOOKUP("smmu_iface_clk", smmu_p_clk.c, "msm_vidc.0"),
+ CLK_LOOKUP("core_clk", vcodec_axi_clk.c, "pil_vidc"),
+ CLK_LOOKUP("smmu_iface_clk", smmu_p_clk.c, "pil_vidc"),
CLK_LOOKUP("dfab_dsps_clk", dfab_dsps_clk.c, NULL),
CLK_LOOKUP("core_clk", dfab_usb_hs_clk.c, "msm_otg"),
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index c724414..3bfb5a3 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -3612,6 +3612,7 @@
CLK_LOOKUP("csi_clk", csi0_clk.c, NULL),
CLK_LOOKUP("csi_clk", csi1_clk.c, "msm_camera_ov7692.0"),
CLK_LOOKUP("csi_clk", csi1_clk.c, "msm_camera_ov9726.0"),
+ CLK_LOOKUP("csi_clk", csi1_clk.c, "msm_csic.1"),
CLK_LOOKUP("csi_src_clk", csi_src_clk.c, NULL),
CLK_LOOKUP("dsi_byte_div_clk", dsi_byte_clk.c, NULL),
CLK_LOOKUP("dsi_esc_clk", dsi_esc_clk.c, NULL),
@@ -3649,6 +3650,7 @@
CLK_LOOKUP("csi_vfe_clk", csi0_vfe_clk.c, NULL),
CLK_LOOKUP("csi_vfe_clk", csi1_vfe_clk.c, "msm_camera_ov7692.0"),
CLK_LOOKUP("csi_vfe_clk", csi1_vfe_clk.c, "msm_camera_ov9726.0"),
+ CLK_LOOKUP("csi_vfe_clk", csi1_vfe_clk.c, "msm_csic.1"),
CLK_LOOKUP("vfe_clk", vfe_clk.c, NULL),
CLK_LOOKUP("core_clk", vfe_clk.c, "footswitch-8x60.8"),
CLK_LOOKUP("bus_clk", vfe_axi_clk.c, "footswitch-8x60.8"),
@@ -3662,6 +3664,7 @@
CLK_LOOKUP("csi_pclk", csi0_p_clk.c, NULL),
CLK_LOOKUP("csi_pclk", csi1_p_clk.c, "msm_camera_ov7692.0"),
CLK_LOOKUP("csi_pclk", csi1_p_clk.c, "msm_camera_ov9726.0"),
+ CLK_LOOKUP("csi_pclk", csi1_p_clk.c, "msm_csic.1"),
CLK_LOOKUP("dsi_m_pclk", dsi_m_p_clk.c, NULL),
CLK_LOOKUP("dsi_s_pclk", dsi_s_p_clk.c, NULL),
CLK_LOOKUP("iface_clk", gfx2d0_p_clk.c, "kgsl-2d0.0"),
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 3255248..e8e6e37 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -996,6 +996,11 @@
.dev.platform_data = "dsps",
};
+struct platform_device msm_pil_vidc = {
+ .name = "pil_vidc",
+ .id = -1,
+};
+
static struct resource smd_resource[] = {
{
.name = "a9_m2a_0",
@@ -2794,7 +2799,7 @@
.init_level = 0,
.num_levels = ARRAY_SIZE(grp3d_freq) + 1,
.set_grp_async = NULL,
- .idle_timeout = HZ/20,
+ .idle_timeout = HZ/12,
.nap_allowed = true,
.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE,
#ifdef CONFIG_MSM_BUS_SCALING
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 70f1c2c..d722e2f 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -840,6 +840,9 @@
if (cpu_is_msm8625()) {
kgsl_3d0_pdata.idle_timeout = HZ/5;
kgsl_3d0_pdata.strtstp_sleepwake = false;
+ /* 8x25 supports a higher GPU frequency */
+ kgsl_3d0_pdata.pwrlevel[0].gpu_freq = 300000000;
+ kgsl_3d0_pdata.pwrlevel[0].bus_freq = 200000000;
}
}
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 17e7364..0e15a4f 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -283,6 +283,80 @@
.resource = resources_i2c,
};
+#ifdef CONFIG_MSM_CAMERA_V4L2
+static struct resource msm_csic_resources[] = {
+ {
+ .name = "csic",
+ .start = 0xA6100000,
+ .end = 0xA6100000 + 0x00000400 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "csic",
+ .start = INT_CSI,
+ .end = INT_CSI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct resource msm_vfe_resources[] = {
+ {
+ .name = "msm_vfe",
+ .start = 0xA6000000,
+ .end = 0xA6000000 + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "msm_vfe",
+ .start = INT_VFE,
+ .end = INT_VFE,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "msm_camif",
+ .start = 0xAB000000,
+ .end = 0xAB000000 + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct resource msm_vpe_resources[] = {
+ {
+ .name = "vpe",
+ .start = 0xAD200000,
+ .end = 0xAD200000 + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "vpe",
+ .start = INT_VPE,
+ .end = INT_VPE,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm_device_csic0 = {
+ .name = "msm_csic",
+ .id = 0,
+ .resource = msm_csic_resources,
+ .num_resources = ARRAY_SIZE(msm_csic_resources),
+};
+
+struct platform_device msm_device_vfe = {
+ .name = "msm_vfe",
+ .id = 0,
+ .resource = msm_vfe_resources,
+ .num_resources = ARRAY_SIZE(msm_vfe_resources),
+};
+
+struct platform_device msm_device_vpe = {
+ .name = "msm_vpe",
+ .id = 0,
+ .resource = msm_vpe_resources,
+ .num_resources = ARRAY_SIZE(msm_vpe_resources),
+};
+#endif
+
#define MSM_QUP_PHYS 0xA8301000
#define MSM_GSBI_QUP_I2C_PHYS 0xA8300000
#define MSM_QUP_SIZE SZ_4K
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index ba7ac2a..84ba9fe 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -1378,6 +1378,98 @@
return platform_device_register(pdev);
}
+#ifdef CONFIG_MSM_CAMERA_V4L2
+static struct resource msm_csic0_resources[] = {
+ {
+ .name = "csic",
+ .start = 0x04800000,
+ .end = 0x04800000 + 0x00000400 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "csic",
+ .start = CSI_0_IRQ,
+ .end = CSI_0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource msm_csic1_resources[] = {
+ {
+ .name = "csic",
+ .start = 0x04900000,
+ .end = 0x04900000 + 0x00000400 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "csic",
+ .start = CSI_1_IRQ,
+ .end = CSI_1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct resource msm_vfe_resources[] = {
+ {
+ .name = "msm_vfe",
+ .start = 0x04500000,
+ .end = 0x04500000 + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "msm_vfe",
+ .start = VFE_IRQ,
+ .end = VFE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource msm_vpe_resources[] = {
+ {
+ .name = "vpe",
+ .start = 0x05300000,
+ .end = 0x05300000 + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "vpe",
+ .start = INT_VPE,
+ .end = INT_VPE,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm_device_csic0 = {
+ .name = "msm_csic",
+ .id = 0,
+ .resource = msm_csic0_resources,
+ .num_resources = ARRAY_SIZE(msm_csic0_resources),
+};
+
+struct platform_device msm_device_csic1 = {
+ .name = "msm_csic",
+ .id = 1,
+ .resource = msm_csic1_resources,
+ .num_resources = ARRAY_SIZE(msm_csic1_resources),
+};
+
+struct platform_device msm_device_vfe = {
+ .name = "msm_vfe",
+ .id = 0,
+ .resource = msm_vfe_resources,
+ .num_resources = ARRAY_SIZE(msm_vfe_resources),
+};
+
+struct platform_device msm_device_vpe = {
+ .name = "msm_vpe",
+ .id = 0,
+ .resource = msm_vpe_resources,
+ .num_resources = ARRAY_SIZE(msm_vpe_resources),
+};
+
+#endif
+
+
#define MIPI_DSI_HW_BASE 0x04700000
#define ROTATOR_HW_BASE 0x04E00000
#define TVENC_HW_BASE 0x04F00000
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 078e931..624debd 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -221,6 +221,7 @@
extern struct platform_device msm_pil_modem;
extern struct platform_device msm_pil_tzapps;
extern struct platform_device msm_pil_dsps;
+extern struct platform_device msm_pil_vidc;
extern struct platform_device msm_8960_q6_lpass;
extern struct platform_device msm_8960_q6_mss_fw;
extern struct platform_device msm_8960_q6_mss_sw;
@@ -355,3 +356,9 @@
extern struct platform_device msm_bus_8930_mm_fabric;
extern struct platform_device msm_bus_8930_sys_fpb;
extern struct platform_device msm_bus_8930_cpss_fpb;
+
+extern struct platform_device msm_device_csic0;
+extern struct platform_device msm_device_csic1;
+extern struct platform_device msm_device_vfe;
+extern struct platform_device msm_device_vpe;
+
diff --git a/arch/arm/mach-msm/dma.c b/arch/arm/mach-msm/dma.c
index b055f4e..087227c 100644
--- a/arch/arm/mach-msm/dma.c
+++ b/arch/arm/mach-msm/dma.c
@@ -61,17 +61,16 @@
size_t sd_size;
struct list_head ready_commands[MSM_DMOV_CHANNEL_COUNT];
struct list_head active_commands[MSM_DMOV_CHANNEL_COUNT];
- struct mutex lock;
- spinlock_t list_lock;
+ spinlock_t lock;
unsigned int irq;
struct clk *clk;
struct clk *pclk;
struct clk *ebiclk;
unsigned int clk_ctl;
- struct delayed_work work;
+ struct timer_list timer;
};
-static void msm_dmov_clock_work(struct work_struct *);
+static void msm_dmov_clock_timer(unsigned long);
static int msm_dmov_clk_toggle(int, int);
#ifdef CONFIG_ARCH_MSM8X60
@@ -164,19 +163,15 @@
{
.crci_conf = adm0_crci_conf,
.chan_conf = adm0_chan_conf,
- .lock = __MUTEX_INITIALIZER(dmov_conf[0].lock),
- .list_lock = __SPIN_LOCK_UNLOCKED(dmov_list_lock),
+ .lock = __SPIN_LOCK_UNLOCKED(dmov_lock),
.clk_ctl = CLK_DIS,
- .work = __DELAYED_WORK_INITIALIZER(dmov_conf[0].work,
- msm_dmov_clock_work),
+ .timer = TIMER_INITIALIZER(msm_dmov_clock_timer, 0, 0),
}, {
.crci_conf = adm1_crci_conf,
.chan_conf = adm1_chan_conf,
- .lock = __MUTEX_INITIALIZER(dmov_conf[1].lock),
- .list_lock = __SPIN_LOCK_UNLOCKED(dmov_list_lock),
+ .lock = __SPIN_LOCK_UNLOCKED(dmov_lock),
.clk_ctl = CLK_DIS,
- .work = __DELAYED_WORK_INITIALIZER(dmov_conf[1].work,
- msm_dmov_clock_work),
+ .timer = TIMER_INITIALIZER(msm_dmov_clock_timer, 0, 1),
}
};
#else
@@ -184,11 +179,9 @@
{
.crci_conf = NULL,
.chan_conf = NULL,
- .lock = __MUTEX_INITIALIZER(dmov_conf[0].lock),
- .list_lock = __SPIN_LOCK_UNLOCKED(dmov_list_lock),
+ .lock = __SPIN_LOCK_UNLOCKED(dmov_lock),
.clk_ctl = CLK_DIS,
- .work = __DELAYED_WORK_INITIALIZER(dmov_conf[0].work,
- msm_dmov_clock_work),
+ .timer = TIMER_INITIALIZER(msm_dmov_clock_timer, 0, 0),
}
};
#endif
@@ -264,18 +257,16 @@
return ret;
}
-static void msm_dmov_clock_work(struct work_struct *work)
+static void msm_dmov_clock_timer(unsigned long adm)
{
- struct msm_dmov_conf *conf =
- container_of(to_delayed_work(work), struct msm_dmov_conf, work);
- int adm = DMOV_IRQ_TO_ADM(conf->irq);
- mutex_lock(&conf->lock);
- if (conf->clk_ctl == CLK_TO_BE_DIS) {
- BUG_ON(conf->channel_active);
+ unsigned long irq_flags;
+ spin_lock_irqsave(&dmov_conf[adm].lock, irq_flags);
+ if (dmov_conf[adm].clk_ctl == CLK_TO_BE_DIS) {
+ BUG_ON(dmov_conf[adm].channel_active);
msm_dmov_clk_toggle(adm, 0);
- conf->clk_ctl = CLK_DIS;
+ dmov_conf[adm].clk_ctl = CLK_DIS;
}
- mutex_unlock(&conf->lock);
+ spin_unlock_irqrestore(&dmov_conf[adm].lock, irq_flags);
}
void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful)
@@ -287,83 +278,48 @@
}
EXPORT_SYMBOL(msm_dmov_stop_cmd);
-/* Caller must hold the list lock */
-static void start_ready_cmd(unsigned ch, int adm)
+void msm_dmov_enqueue_cmd_ext(unsigned id, struct msm_dmov_cmd *cmd)
{
- struct msm_dmov_cmd *cmd;
-
- if (list_empty(&dmov_conf[adm].ready_commands[ch]))
- return;
-
- cmd = list_entry(dmov_conf[adm].ready_commands[ch].next, typeof(*cmd),
- list);
- list_del(&cmd->list);
- if (cmd->exec_func)
- cmd->exec_func(cmd);
- list_add_tail(&cmd->list, &dmov_conf[adm].active_commands[ch]);
- if (!dmov_conf[adm].channel_active)
- enable_irq(dmov_conf[adm].irq);
- dmov_conf[adm].channel_active |= BIT(ch);
- PRINT_IO("msm dmov enqueue command %x\n", cmd->cmdptr);
- writel_relaxed(cmd->cmdptr, DMOV_REG(DMOV_CMD_PTR(ch), adm));
-}
-
-static void msm_dmov_enqueue_cmd_ext_work(struct work_struct *work)
-{
- struct msm_dmov_cmd *cmd =
- container_of(work, struct msm_dmov_cmd, work);
- unsigned id = cmd->id;
- unsigned status;
- unsigned long flags;
+ unsigned long irq_flags;
+ unsigned int status;
int adm = DMOV_ID_TO_ADM(id);
int ch = DMOV_ID_TO_CHAN(id);
- mutex_lock(&dmov_conf[adm].lock);
+ spin_lock_irqsave(&dmov_conf[adm].lock, irq_flags);
if (dmov_conf[adm].clk_ctl == CLK_DIS) {
status = msm_dmov_clk_toggle(adm, 1);
if (status != 0)
goto error;
} else if (dmov_conf[adm].clk_ctl == CLK_TO_BE_DIS)
- cancel_delayed_work_sync(&dmov_conf[adm].work);
+ del_timer(&dmov_conf[adm].timer);
dmov_conf[adm].clk_ctl = CLK_EN;
- spin_lock_irqsave(&dmov_conf[adm].list_lock, flags);
-
status = readl_relaxed(DMOV_REG(DMOV_STATUS(ch), adm));
if (status & DMOV_STATUS_CMD_PTR_RDY) {
PRINT_IO("msm_dmov_enqueue_cmd(%d), start command, status %x\n",
id, status);
- start_ready_cmd(ch, adm);
+ if (cmd->exec_func)
+ cmd->exec_func(cmd);
+ list_add_tail(&cmd->list, &dmov_conf[adm].active_commands[ch]);
+ if (!dmov_conf[adm].channel_active)
+ enable_irq(dmov_conf[adm].irq);
+ dmov_conf[adm].channel_active |= 1U << ch;
+ PRINT_IO("Writing %x exactly to register", cmd->cmdptr);
+ writel_relaxed(cmd->cmdptr, DMOV_REG(DMOV_CMD_PTR(ch), adm));
} else {
- if (list_empty(&dmov_conf[adm].active_commands[ch]) &&
- !list_empty(&dmov_conf[adm].ready_commands[ch]))
+ if (!dmov_conf[adm].channel_active) {
+ dmov_conf[adm].clk_ctl = CLK_TO_BE_DIS;
+ mod_timer(&dmov_conf[adm].timer, jiffies + HZ);
+ }
+ if (list_empty(&dmov_conf[adm].active_commands[ch]))
PRINT_ERROR("msm_dmov_enqueue_cmd_ext(%d), stalled, "
"status %x\n", id, status);
PRINT_IO("msm_dmov_enqueue_cmd(%d), enqueue command, status "
"%x\n", id, status);
+ list_add_tail(&cmd->list, &dmov_conf[adm].ready_commands[ch]);
}
- if (!dmov_conf[adm].channel_active) {
- dmov_conf[adm].clk_ctl = CLK_TO_BE_DIS;
- schedule_delayed_work(&dmov_conf[adm].work, HZ);
- }
- spin_unlock_irqrestore(&dmov_conf[adm].list_lock, flags);
error:
- mutex_unlock(&dmov_conf[adm].lock);
-}
-
-void msm_dmov_enqueue_cmd_ext(unsigned id, struct msm_dmov_cmd *cmd)
-{
- int adm = DMOV_ID_TO_ADM(id);
- int ch = DMOV_ID_TO_CHAN(id);
- unsigned long flags;
- cmd->id = id;
- INIT_WORK(&cmd->work, msm_dmov_enqueue_cmd_ext_work);
-
- spin_lock_irqsave(&dmov_conf[adm].list_lock, flags);
- list_add_tail(&cmd->list, &dmov_conf[adm].ready_commands[ch]);
- spin_unlock_irqrestore(&dmov_conf[adm].list_lock, flags);
-
- schedule_work(&cmd->work);
+ spin_unlock_irqrestore(&dmov_conf[adm].lock, irq_flags);
}
EXPORT_SYMBOL(msm_dmov_enqueue_cmd_ext);
@@ -381,14 +337,14 @@
unsigned long irq_flags;
int ch = DMOV_ID_TO_CHAN(id);
int adm = DMOV_ID_TO_ADM(id);
- spin_lock_irqsave(&dmov_conf[adm].list_lock, irq_flags);
+ spin_lock_irqsave(&dmov_conf[adm].lock, irq_flags);
/* XXX not checking if flush cmd sent already */
if (!list_empty(&dmov_conf[adm].active_commands[ch])) {
PRINT_IO("msm_dmov_flush(%d), send flush cmd\n", id);
writel_relaxed(DMOV_FLUSH_TYPE, DMOV_REG(DMOV_FLUSH0(ch), adm));
}
/* spin_unlock_irqrestore has the necessary barrier */
- spin_unlock_irqrestore(&dmov_conf[adm].list_lock, irq_flags);
+ spin_unlock_irqrestore(&dmov_conf[adm].lock, irq_flags);
}
EXPORT_SYMBOL(msm_dmov_flush);
@@ -450,7 +406,7 @@
errdata->flush[5] = readl_relaxed(DMOV_REG(DMOV_FLUSH5(ch), adm));
}
-static irqreturn_t msm_dmov_isr(int irq, void *dev_id)
+static irqreturn_t msm_datamover_irq_handler(int irq, void *dev_id)
{
unsigned int int_status;
unsigned int mask;
@@ -463,12 +419,11 @@
struct msm_dmov_cmd *cmd;
int adm = DMOV_IRQ_TO_ADM(irq);
- mutex_lock(&dmov_conf[adm].lock);
+ spin_lock_irqsave(&dmov_conf[adm].lock, irq_flags);
/* read and clear isr */
int_status = readl_relaxed(DMOV_REG(DMOV_ISR, adm));
PRINT_FLOW("msm_datamover_irq_handler: DMOV_ISR %x\n", int_status);
- spin_lock_irqsave(&dmov_conf[adm].list_lock, irq_flags);
while (int_status) {
mask = int_status & -int_status;
ch = fls(mask) - 1;
@@ -536,40 +491,50 @@
ch_status = readl_relaxed(DMOV_REG(DMOV_STATUS(ch),
adm));
PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status);
- if (ch_status & DMOV_STATUS_CMD_PTR_RDY) {
- start_ready_cmd(ch, adm);
+ if ((ch_status & DMOV_STATUS_CMD_PTR_RDY) &&
+ !list_empty(&dmov_conf[adm].ready_commands[ch])) {
+ cmd = list_entry(dmov_conf[adm].
+ ready_commands[ch].next, typeof(*cmd),
+ list);
+ list_del(&cmd->list);
+ if (cmd->exec_func)
+ cmd->exec_func(cmd);
+ list_add_tail(&cmd->list,
+ &dmov_conf[adm].active_commands[ch]);
PRINT_FLOW("msm_datamover_irq_handler id %d, start command\n", id);
+ writel_relaxed(cmd->cmdptr,
+ DMOV_REG(DMOV_CMD_PTR(ch), adm));
}
} while (ch_status & DMOV_STATUS_RSLT_VALID);
if (list_empty(&dmov_conf[adm].active_commands[ch]) &&
- list_empty(&dmov_conf[adm].ready_commands[ch]))
+ list_empty(&dmov_conf[adm].ready_commands[ch]))
dmov_conf[adm].channel_active &= ~(1U << ch);
PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status);
}
- spin_unlock_irqrestore(&dmov_conf[adm].list_lock, irq_flags);
if (!dmov_conf[adm].channel_active && valid) {
disable_irq_nosync(dmov_conf[adm].irq);
dmov_conf[adm].clk_ctl = CLK_TO_BE_DIS;
- schedule_delayed_work(&dmov_conf[adm].work, HZ);
+ mod_timer(&dmov_conf[adm].timer, jiffies + HZ);
}
- mutex_unlock(&dmov_conf[adm].lock);
+ spin_unlock_irqrestore(&dmov_conf[adm].lock, irq_flags);
return valid ? IRQ_HANDLED : IRQ_NONE;
}
static int msm_dmov_suspend_late(struct device *dev)
{
+ unsigned long irq_flags;
struct platform_device *pdev = to_platform_device(dev);
int adm = (pdev->id >= 0) ? pdev->id : 0;
- mutex_lock(&dmov_conf[adm].lock);
+ spin_lock_irqsave(&dmov_conf[adm].lock, irq_flags);
if (dmov_conf[adm].clk_ctl == CLK_TO_BE_DIS) {
BUG_ON(dmov_conf[adm].channel_active);
- cancel_delayed_work_sync(&dmov_conf[adm].work);
+ del_timer(&dmov_conf[adm].timer);
msm_dmov_clk_toggle(adm, 0);
dmov_conf[adm].clk_ctl = CLK_DIS;
}
- mutex_unlock(&dmov_conf[adm].lock);
+ spin_unlock_irqrestore(&dmov_conf[adm].lock, irq_flags);
return 0;
}
@@ -684,8 +649,8 @@
if (!dmov_conf[adm].base)
return -ENOMEM;
- ret = request_threaded_irq(dmov_conf[adm].irq, NULL, msm_dmov_isr,
- IRQF_ONESHOT, "msmdatamover", NULL);
+ ret = request_irq(dmov_conf[adm].irq, msm_datamover_irq_handler,
+ 0, "msmdatamover", NULL);
if (ret) {
PRINT_ERROR("Requesting ADM%d irq %d failed\n", adm,
dmov_conf[adm].irq);
diff --git a/arch/arm/mach-msm/include/mach/board-msm8660.h b/arch/arm/mach-msm/include/mach/board-msm8660.h
index b07cc62..22e378c 100644
--- a/arch/arm/mach-msm/include/mach/board-msm8660.h
+++ b/arch/arm/mach-msm/include/mach/board-msm8660.h
@@ -33,4 +33,9 @@
#define PM8901_IRQ_BASE (PM8058_IRQ_BASE + \
NR_PMIC8058_IRQS)
+#ifdef CONFIG_MSM_CAMERA_V4L2
+extern struct msm_camera_board_info msm8x60_camera_board_info;
+void msm8x60_init_cam(void);
+#endif
+
#endif
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index ba038cb..5ee9e1a 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -200,12 +200,14 @@
struct msm_camera_csiphy_params csiphy_params;
};
+#ifndef CONFIG_MSM_CAMERA_V4L2
#define VFE31_OUTPUT_MODE_PT (0x1 << 0)
#define VFE31_OUTPUT_MODE_S (0x1 << 1)
#define VFE31_OUTPUT_MODE_V (0x1 << 2)
#define VFE31_OUTPUT_MODE_P (0x1 << 3)
#define VFE31_OUTPUT_MODE_T (0x1 << 4)
#define VFE31_OUTPUT_MODE_P_ALL_CHNLS (0x1 << 5)
+#endif
#define CSI_EMBED_DATA 0x12
#define CSI_YUV422_8 0x1E
diff --git a/arch/arm/mach-msm/include/mach/dma.h b/arch/arm/mach-msm/include/mach/dma.h
index 6e58ebe..d170f5f 100644
--- a/arch/arm/mach-msm/include/mach/dma.h
+++ b/arch/arm/mach-msm/include/mach/dma.h
@@ -1,7 +1,7 @@
/* linux/include/asm-arm/arch-msm/dma.h
*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -35,8 +35,6 @@
unsigned int result,
struct msm_dmov_errdata *err);
void (*exec_func)(struct msm_dmov_cmd *cmd);
- struct work_struct work;
- unsigned id; /* For internal use */
void *user; /* Pointer for caller's reference */
};
diff --git a/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h b/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
index 57f2d37..af82fd9 100644
--- a/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
+++ b/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
@@ -57,8 +57,9 @@
#define FL_TYPE_TABLE (1 << 0)
#define FL_TYPE_SECT (2 << 0)
#define FL_SUPERSECTION (1 << 18)
-#define FL_AP_WRITE (1 << 10)
-#define FL_AP_READ (1 << 11)
+#define FL_AP0 (1 << 10)
+#define FL_AP1 (1 << 11)
+#define FL_AP2 (1 << 15)
#define FL_SHARED (1 << 16)
#define FL_BUFFERABLE (1 << 2)
#define FL_CACHEABLE (1 << 3)
@@ -73,6 +74,7 @@
#define SL_TYPE_SMALL (2 << 0)
#define SL_AP0 (1 << 4)
#define SL_AP1 (2 << 4)
+#define SL_AP2 (1 << 9)
#define SL_SHARED (1 << 10)
#define SL_BUFFERABLE (1 << 2)
#define SL_CACHEABLE (1 << 3)
diff --git a/arch/arm/mach-msm/include/mach/sps.h b/arch/arm/mach-msm/include/mach/sps.h
index 7eaf526..852c8db 100644
--- a/arch/arm/mach-msm/include/mach/sps.h
+++ b/arch/arm/mach-msm/include/mach/sps.h
@@ -652,6 +652,7 @@
* -------------------------------------------------------------------------*/
struct sps_pipe; /* Forward declaration */
+#ifdef CONFIG_SPS
/**
* Register a BAM device
*
@@ -1218,4 +1219,162 @@
*/
int sps_get_unused_desc_num(struct sps_pipe *h, u32 *desc_num);
+#else
+static inline int sps_register_bam_device(const struct sps_bam_props
+ *bam_props, u32 *dev_handle)
+{
+ return -EPERM;
+}
+
+static inline int sps_deregister_bam_device(u32 dev_handle)
+{
+ return -EPERM;
+}
+
+static inline struct sps_pipe *sps_alloc_endpoint(void)
+{
+ return NULL;
+}
+
+static inline int sps_free_endpoint(struct sps_pipe *h)
+{
+ return -EPERM;
+}
+
+static inline int sps_get_config(struct sps_pipe *h, struct sps_connect *config)
+{
+ return -EPERM;
+}
+
+static inline int sps_alloc_mem(struct sps_pipe *h, enum sps_mem mem,
+ struct sps_mem_buffer *mem_buffer)
+{
+ return -EPERM;
+}
+
+static inline int sps_free_mem(struct sps_pipe *h,
+ struct sps_mem_buffer *mem_buffer)
+{
+ return -EPERM;
+}
+
+static inline int sps_connect(struct sps_pipe *h, struct sps_connect *connect)
+{
+ return -EPERM;
+}
+
+static inline int sps_disconnect(struct sps_pipe *h)
+{
+ return -EPERM;
+}
+
+static inline int sps_register_event(struct sps_pipe *h,
+ struct sps_register_event *reg)
+{
+ return -EPERM;
+}
+
+static inline int sps_transfer_one(struct sps_pipe *h, u32 addr, u32 size,
+ void *user, u32 flags)
+{
+ return -EPERM;
+}
+
+static inline int sps_get_event(struct sps_pipe *h,
+ struct sps_event_notify *event)
+{
+ return -EPERM;
+}
+
+static inline int sps_get_iovec(struct sps_pipe *h, struct sps_iovec *iovec)
+{
+ return -EPERM;
+}
+
+static inline int sps_flow_on(struct sps_pipe *h)
+{
+ return -EPERM;
+}
+
+static inline int sps_flow_off(struct sps_pipe *h, enum sps_flow_off mode)
+{
+ return -EPERM;
+}
+
+static inline int sps_transfer(struct sps_pipe *h,
+ struct sps_transfer *transfer)
+{
+ return -EPERM;
+}
+
+static inline int sps_is_pipe_empty(struct sps_pipe *h, u32 *empty)
+{
+ return -EPERM;
+}
+
+static inline int sps_device_reset(u32 dev)
+{
+ return -EPERM;
+}
+
+static inline int sps_set_config(struct sps_pipe *h, struct sps_connect *config)
+{
+ return -EPERM;
+}
+
+static inline int sps_set_owner(struct sps_pipe *h, enum sps_owner owner,
+ struct sps_satellite *connect)
+{
+ return -EPERM;
+}
+
+static inline int sps_get_free_count(struct sps_pipe *h, u32 *count)
+{
+ return -EPERM;
+}
+
+static inline int sps_alloc_dma_chan(const struct sps_alloc_dma_chan *alloc,
+ struct sps_dma_chan *chan)
+{
+ return -EPERM;
+}
+
+static inline int sps_free_dma_chan(struct sps_dma_chan *chan)
+{
+ return -EPERM;
+}
+
+static inline u32 sps_dma_get_bam_handle(void)
+{
+ return 0;
+}
+
+static inline void sps_dma_free_bam_handle(u32 h)
+{
+}
+
+static inline int sps_timer_ctrl(struct sps_pipe *h,
+ struct sps_timer_ctrl *timer_ctrl,
+ struct sps_timer_result *timer_result)
+{
+ return -EPERM;
+}
+
+static inline int sps_phy2h(u32 phys_addr, u32 *handle)
+{
+ return -EPERM;
+}
+
+static inline int sps_setup_bam2bam_fifo(struct sps_mem_buffer *mem_buffer,
+ u32 addr, u32 size, int use_offset)
+{
+ return -EPERM;
+}
+
+static inline int sps_get_unused_desc_num(struct sps_pipe *h, u32 *desc_num)
+{
+ return -EPERM;
+}
+#endif
+
#endif /* _SPS_H_ */
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
index d495c1b..19e1684 100644
--- a/arch/arm/mach-msm/iommu.c
+++ b/arch/arm/mach-msm/iommu.c
@@ -421,6 +421,16 @@
unsigned int pgprot;
int tex;
+ if (!(prot & (IOMMU_READ | IOMMU_WRITE))) {
+ prot |= IOMMU_READ | IOMMU_WRITE;
+ WARN_ONCE(1, "No attributes in iommu mapping; assuming RW\n");
+ }
+
+ if ((prot & IOMMU_WRITE) && !(prot & IOMMU_READ)) {
+ prot |= IOMMU_READ;
+ WARN_ONCE(1, "Write-only iommu mappings unsupported; falling back to RW\n");
+ }
+
if (prot & IOMMU_CACHE)
tex = (pgprot_kernel >> 2) & 0x07;
else
@@ -434,11 +444,15 @@
pgprot |= tex & 0x01 ? FL_BUFFERABLE : 0;
pgprot |= tex & 0x02 ? FL_CACHEABLE : 0;
pgprot |= tex & 0x04 ? FL_TEX0 : 0;
+ pgprot |= FL_AP0 | FL_AP1;
+ pgprot |= prot & IOMMU_WRITE ? 0 : FL_AP2;
} else {
pgprot = SL_SHARED;
pgprot |= tex & 0x01 ? SL_BUFFERABLE : 0;
pgprot |= tex & 0x02 ? SL_CACHEABLE : 0;
pgprot |= tex & 0x04 ? SL_TEX0 : 0;
+ pgprot |= SL_AP0 | SL_AP1;
+ pgprot |= prot & IOMMU_WRITE ? 0 : SL_AP2;
}
return pgprot;
@@ -501,9 +515,8 @@
}
for (i = 0; i < 16; i++)
- *(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION |
- FL_AP_READ | FL_AP_WRITE | FL_TYPE_SECT |
- FL_SHARED | FL_NG | pgprot;
+ *(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION
+ | FL_TYPE_SECT | FL_SHARED | FL_NG | pgprot;
if (!priv->redirect)
clean_pte(fl_pte, fl_pte + 16);
}
@@ -514,8 +527,8 @@
goto fail;
}
- *fl_pte = (pa & 0xFFF00000) | FL_AP_READ | FL_AP_WRITE | FL_NG |
- FL_TYPE_SECT | FL_SHARED | pgprot;
+ *fl_pte = (pa & 0xFFF00000) | FL_NG | FL_TYPE_SECT | FL_SHARED
+ | pgprot;
if (!priv->redirect)
clean_pte(fl_pte, fl_pte + 1);
}
@@ -558,8 +571,8 @@
goto fail;
}
- *sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 | SL_NG |
- SL_SHARED | SL_TYPE_SMALL | pgprot;
+ *sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_NG | SL_SHARED
+ | SL_TYPE_SMALL | pgprot;
if (!priv->redirect)
clean_pte(sl_pte, sl_pte + 1);
}
@@ -574,8 +587,8 @@
}
for (i = 0; i < 16; i++)
- *(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_AP0 |
- SL_NG | SL_AP1 | SL_SHARED | SL_TYPE_LARGE | pgprot;
+ *(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_NG
+ | SL_SHARED | SL_TYPE_LARGE | pgprot;
if (!priv->redirect)
clean_pte(sl_pte, sl_pte + 16);
@@ -776,8 +789,7 @@
while (offset < len && sl_offset < NUM_SL_PTE) {
pa = chunk_pa + chunk_offset;
sl_table[sl_offset] = (pa & SL_BASE_MASK_SMALL) |
- pgprot | SL_AP0 | SL_AP1 | SL_NG |
- SL_SHARED | SL_TYPE_SMALL;
+ pgprot | SL_NG | SL_SHARED | SL_TYPE_SMALL;
sl_offset++;
offset += SZ_4K;
diff --git a/arch/arm/mach-msm/pil-vidc.c b/arch/arm/mach-msm/pil-vidc.c
new file mode 100644
index 0000000..ceb9bcd
--- /dev/null
+++ b/arch/arm/mach-msm/pil-vidc.c
@@ -0,0 +1,146 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/elf.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+#include "peripheral-loader.h"
+#include "scm-pas.h"
+
+struct vidc_data {
+ struct clk *smmu_iface;
+ struct clk *core;
+ struct pil_device *pil;
+};
+
+static int pil_vidc_init_image(struct pil_desc *pil, const u8 *metadata,
+ size_t size)
+{
+ return pas_init_image(PAS_VIDC, metadata, size);
+}
+
+static int pil_vidc_reset(struct pil_desc *pil)
+{
+ int ret;
+ struct vidc_data *drv = dev_get_drvdata(pil->dev);
+
+ ret = clk_prepare_enable(drv->smmu_iface);
+ if (ret)
+ goto err_smmu;
+ ret = clk_prepare_enable(drv->core);
+ if (ret)
+ goto err_core;
+ ret = pas_auth_and_reset(PAS_VIDC);
+
+ clk_disable_unprepare(drv->core);
+err_core:
+ clk_disable_unprepare(drv->smmu_iface);
+err_smmu:
+ return ret;
+}
+
+static int pil_vidc_shutdown(struct pil_desc *pil)
+{
+ return pas_shutdown(PAS_VIDC);
+}
+
+static struct pil_reset_ops pil_vidc_ops = {
+ .init_image = pil_vidc_init_image,
+ .auth_and_reset = pil_vidc_reset,
+ .shutdown = pil_vidc_shutdown,
+};
+
+static int __devinit pil_vidc_driver_probe(struct platform_device *pdev)
+{
+ struct pil_desc *desc;
+ struct vidc_data *drv;
+ int ret;
+
+ if (pas_supported(PAS_VIDC) < 0)
+ return -ENOSYS;
+
+ desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
+ if (!drv)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, drv);
+ drv->smmu_iface = clk_get(&pdev->dev, "smmu_iface_clk");
+ if (IS_ERR(drv->smmu_iface)) {
+ dev_err(&pdev->dev, "failed to get smmu interface clock\n");
+ ret = PTR_ERR(drv->smmu_iface);
+ goto err_smmu;
+ }
+ drv->core = clk_get(&pdev->dev, "core_clk");
+ if (IS_ERR(drv->core)) {
+ dev_err(&pdev->dev, "failed to get core clock\n");
+ ret = PTR_ERR(drv->core);
+ goto err_core;
+ }
+
+ desc->name = "vidc";
+ desc->dev = &pdev->dev;
+ desc->ops = &pil_vidc_ops;
+ desc->owner = THIS_MODULE;
+ drv->pil = msm_pil_register(desc);
+ if (IS_ERR(drv->pil)) {
+ ret = PTR_ERR(drv->pil);
+ goto err_register;
+ }
+ return 0;
+
+err_register:
+ clk_put(drv->core);
+err_core:
+ clk_put(drv->smmu_iface);
+err_smmu:
+ return ret;
+}
+
+static int __devexit pil_vidc_driver_exit(struct platform_device *pdev)
+{
+ struct vidc_data *drv = platform_get_drvdata(pdev);
+ msm_pil_unregister(drv->pil);
+ clk_put(drv->smmu_iface);
+ clk_put(drv->core);
+ return 0;
+}
+
+static struct platform_driver pil_vidc_driver = {
+ .probe = pil_vidc_driver_probe,
+ .remove = __devexit_p(pil_vidc_driver_exit),
+ .driver = {
+ .name = "pil_vidc",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init pil_vidc_init(void)
+{
+ return platform_driver_register(&pil_vidc_driver);
+}
+module_init(pil_vidc_init);
+
+static void __exit pil_vidc_exit(void)
+{
+ platform_driver_unregister(&pil_vidc_driver);
+}
+module_exit(pil_vidc_exit);
+
+MODULE_DESCRIPTION("Support for secure booting vidc images");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index a5e52be..4f3c7e4 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -565,7 +565,7 @@
__raw_writel(0, APPS_CLK_SLEEP_EN);
mb();
- if (cpu_is_msm8625()) {
+ if (cpu_is_msm8625() && power_collapsed) {
/*
* enable the SCU while coming out of power
* collapse.
@@ -1089,6 +1089,8 @@
unsigned long saved_acpuclk_rate;
int collapsed = 0;
int ret;
+ int val;
+ int modem_early_exit = 0;
MSM_PM_DPRINTK(MSM_PM_DEBUG_SUSPEND|MSM_PM_DEBUG_POWER_COLLAPSE,
KERN_INFO, "%s(): idle %d, delay %u, limit %u\n", __func__,
@@ -1194,8 +1196,25 @@
#endif
collapsed = msm_pm_collapse();
- if (collapsed)
- power_collapsed = 1;
+
+ /*
+ * TBD: Currently recognise the MODEM early exit
+ * path by reading the MPA5_GDFS_CNT_VAL register.
+ */
+ if (cpu_is_msm8625()) {
+ /*
+ * on system reset default value of MPA5_GDFS_CNT_VAL
+ * is = 0xFF, later power driver reprogrammed this
+ * as: 0x000300FF. Currently based on the value of
+ * MPA5_GDFS_CNT_VAL register decide whether it is
+ * a modem early exit are not.
+ */
+ val = __raw_readl(MSM_CFG_CTL_BASE + 0x38);
+ if (val != 0xFF)
+ modem_early_exit = 1;
+ else
+ power_collapsed = 1;
+ }
#ifdef CONFIG_CACHE_L2X0
l2x0_resume(collapsed);
@@ -1256,7 +1275,7 @@
}
/* Sanity check */
- if (collapsed) {
+ if (collapsed && !modem_early_exit) {
BUG_ON(!(state_grps[0].value_read & DEM_MASTER_SMSM_RSA));
} else {
BUG_ON(!(state_grps[0].value_read &
diff --git a/arch/arm/mach-msm/scm-pas.h b/arch/arm/mach-msm/scm-pas.h
index 3651ee1..2fe71a9 100644
--- a/arch/arm/mach-msm/scm-pas.h
+++ b/arch/arm/mach-msm/scm-pas.h
@@ -22,6 +22,7 @@
PAS_RIVA,
PAS_SECAPP,
PAS_GSS,
+ PAS_VIDC,
};
extern int pas_init_image(enum pas_id id, const u8 *metadata, size_t size);
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 8b2566a..01d6ac5 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -47,6 +47,14 @@
(L2X0_CACHE_ID_PART_L310 | rev);
}
+struct l2x0_regs l2x0_saved_regs;
+
+struct l2x0_of_data {
+ void (*setup)(const struct device_node *, u32 *, u32 *);
+ void (*save)(void);
+ void (*resume)(void);
+};
+
static inline void cache_wait_way(void __iomem *reg, unsigned long mask)
{
/* wait for cache operation by line or way to complete */
@@ -67,7 +75,7 @@
{
void __iomem *base = l2x0_base;
-#ifdef CONFIG_ARM_ERRATA_753970
+#ifdef CONFIG_PL310_ERRATA_753970
/* write to an unmmapped register */
writel_relaxed(0, base + L2X0_DUMMY_REG);
#else
@@ -254,27 +262,6 @@
raw_spin_unlock_irqrestore(&l2x0_lock, flags);
}
-static void l2x0_inv_range_atomic(unsigned long start, unsigned long end)
-{
- unsigned long addr;
-
- if (start & (CACHE_LINE_SIZE - 1)) {
- start &= ~(CACHE_LINE_SIZE - 1);
- writel_relaxed(start, l2x0_base + L2X0_CLEAN_INV_LINE_PA);
- start += CACHE_LINE_SIZE;
- }
-
- if (end & (CACHE_LINE_SIZE - 1)) {
- end &= ~(CACHE_LINE_SIZE - 1);
- writel_relaxed(end, l2x0_base + L2X0_CLEAN_INV_LINE_PA);
- }
-
- for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
- writel_relaxed(addr, l2x0_base + L2X0_INV_LINE_PA);
-
- mb();
-}
-
static void l2x0_clean_range(unsigned long start, unsigned long end)
{
void __iomem *base = l2x0_base;
@@ -305,17 +292,6 @@
raw_spin_unlock_irqrestore(&l2x0_lock, flags);
}
-static void l2x0_clean_range_atomic(unsigned long start, unsigned long end)
-{
- unsigned long addr;
-
- start &= ~(CACHE_LINE_SIZE - 1);
- for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
- writel_relaxed(addr, l2x0_base + L2X0_CLEAN_LINE_PA);
-
- mb();
-}
-
static void l2x0_flush_range(unsigned long start, unsigned long end)
{
void __iomem *base = l2x0_base;
@@ -370,18 +346,36 @@
raw_spin_unlock_irqrestore(&l2x0_lock, flags);
}
-void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
+static void l2x0_unlock(u32 cache_id)
{
- __u32 aux, bits;
- __u32 way_size = 0;
+ int lockregs;
+ int i;
+
+ if (cache_id == L2X0_CACHE_ID_PART_L310)
+ lockregs = 8;
+ else
+ /* L210 and unknown types */
+ lockregs = 1;
+
+ for (i = 0; i < lockregs; i++) {
+ writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE +
+ i * L2X0_LOCKDOWN_STRIDE);
+ writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_I_BASE +
+ i * L2X0_LOCKDOWN_STRIDE);
+ }
+}
+
+void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
+{
+ u32 aux;
+ u32 cache_id;
+ u32 way_size = 0;
+ int ways;
const char *type;
l2x0_base = base;
- l2x0_cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID);
-
- bits = readl_relaxed(l2x0_base + L2X0_CTRL);
- bits &= ~0x01; /* clear bit 0 */
- writel_relaxed(bits, l2x0_base + L2X0_CTRL);
+ cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID);
+ l2x0_cache_id = cache_id;
aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
@@ -389,64 +383,59 @@
aux |= aux_val;
/* Determine the number of ways */
- switch (l2x0_cache_id & L2X0_CACHE_ID_PART_MASK) {
+ switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
case L2X0_CACHE_ID_PART_L310:
if (aux & (1 << 16))
- l2x0_ways = 16;
+ ways = 16;
else
- l2x0_ways = 8;
+ ways = 8;
type = "L310";
break;
case L2X0_CACHE_ID_PART_L210:
- l2x0_ways = (aux >> 13) & 0xf;
+ ways = (aux >> 13) & 0xf;
type = "L210";
break;
default:
/* Assume unknown chips have 8 ways */
- l2x0_ways = 8;
+ ways = 8;
type = "L2x0 series";
break;
}
writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL);
- l2x0_way_mask = (1 << l2x0_ways) - 1;
+ l2x0_way_mask = (1 << ways) - 1;
/*
* L2 cache Size = Way size * Number of ways
*/
way_size = (aux & L2X0_AUX_CTRL_WAY_SIZE_MASK) >> 17;
- way_size = SZ_1K << (way_size + 3);
- l2x0_size = l2x0_ways * way_size;
+ way_size = 1 << (way_size + 3);
+ l2x0_size = ways * way_size * SZ_1K;
l2x0_sets = way_size / CACHE_LINE_SIZE;
+ l2x0_ways = ways;
- l2x0_inv_all();
+ /*
+ * Check if l2x0 controller is already enabled.
+ * If you are booting from non-secure mode
+ * accessing the below registers will fault.
+ */
+ if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+ /* Make sure that I&D is not locked down when starting */
+ l2x0_unlock(cache_id);
- /* enable L2X0 */
- bits = readl_relaxed(l2x0_base + L2X0_CTRL);
- bits |= 0x01; /* set bit 0 */
- writel_relaxed(bits, l2x0_base + L2X0_CTRL);
+ /* l2x0 controller is disabled */
+ writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL);
- switch (l2x0_cache_id & L2X0_CACHE_ID_PART_MASK) {
- case L2X0_CACHE_ID_PART_L220:
- outer_cache.inv_range = l2x0_inv_range;
- outer_cache.clean_range = l2x0_clean_range;
- outer_cache.flush_range = l2x0_flush_range;
- printk(KERN_INFO "L220 cache controller enabled\n");
- break;
- case L2X0_CACHE_ID_PART_L310:
- outer_cache.inv_range = l2x0_inv_range;
- outer_cache.clean_range = l2x0_clean_range;
- outer_cache.flush_range = l2x0_flush_range;
- printk(KERN_INFO "L310 cache controller enabled\n");
- break;
- case L2X0_CACHE_ID_PART_L210:
- default:
- outer_cache.inv_range = l2x0_inv_range_atomic;
- outer_cache.clean_range = l2x0_clean_range_atomic;
- outer_cache.flush_range = l2x0_flush_range_atomic;
- printk(KERN_INFO "L210 cache controller enabled\n");
- break;
+ l2x0_saved_regs.aux_ctrl = aux;
+
+ l2x0_inv_all();
+
+ /* enable L2X0 */
+ writel_relaxed(1, l2x0_base + L2X0_CTRL);
}
+ outer_cache.inv_range = l2x0_inv_range;
+ outer_cache.clean_range = l2x0_clean_range;
+ outer_cache.flush_range = l2x0_flush_range;
outer_cache.sync = l2x0_cache_sync;
outer_cache.flush_all = l2x0_flush_all;
@@ -457,7 +446,7 @@
mb();
printk(KERN_INFO "%s cache controller enabled\n", type);
printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n",
- l2x0_ways, l2x0_cache_id, aux, l2x0_size);
+ ways, cache_id, aux, l2x0_size);
}
void l2x0_suspend(void)
@@ -507,7 +496,7 @@
#ifdef CONFIG_OF
static void __init l2x0_of_setup(const struct device_node *np,
- __u32 *aux_val, __u32 *aux_mask)
+ u32 *aux_val, u32 *aux_mask)
{
u32 data[2] = { 0, 0 };
u32 tag = 0;
@@ -541,7 +530,7 @@
}
static void __init pl310_of_setup(const struct device_node *np,
- __u32 *aux_val, __u32 *aux_mask)
+ u32 *aux_val, u32 *aux_mask)
{
u32 data[3] = { 0, 0, 0 };
u32 tag[3] = { 0, 0, 0 };
@@ -574,33 +563,132 @@
}
}
+static void __init pl310_save(void)
+{
+ u32 l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
+ L2X0_CACHE_ID_RTL_MASK;
+
+ l2x0_saved_regs.tag_latency = readl_relaxed(l2x0_base +
+ L2X0_TAG_LATENCY_CTRL);
+ l2x0_saved_regs.data_latency = readl_relaxed(l2x0_base +
+ L2X0_DATA_LATENCY_CTRL);
+ l2x0_saved_regs.filter_end = readl_relaxed(l2x0_base +
+ L2X0_ADDR_FILTER_END);
+ l2x0_saved_regs.filter_start = readl_relaxed(l2x0_base +
+ L2X0_ADDR_FILTER_START);
+
+ if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) {
+ /*
+ * From r2p0, there is Prefetch offset/control register
+ */
+ l2x0_saved_regs.prefetch_ctrl = readl_relaxed(l2x0_base +
+ L2X0_PREFETCH_CTRL);
+ /*
+ * From r3p0, there is Power control register
+ */
+ if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0)
+ l2x0_saved_regs.pwr_ctrl = readl_relaxed(l2x0_base +
+ L2X0_POWER_CTRL);
+ }
+}
+
+static void l2x0_resume(void)
+{
+ if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+ /* restore aux ctrl and enable l2 */
+ l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID));
+
+ writel_relaxed(l2x0_saved_regs.aux_ctrl, l2x0_base +
+ L2X0_AUX_CTRL);
+
+ l2x0_inv_all();
+
+ writel_relaxed(1, l2x0_base + L2X0_CTRL);
+ }
+}
+
+static void pl310_resume(void)
+{
+ u32 l2x0_revision;
+
+ if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+ /* restore pl310 setup */
+ writel_relaxed(l2x0_saved_regs.tag_latency,
+ l2x0_base + L2X0_TAG_LATENCY_CTRL);
+ writel_relaxed(l2x0_saved_regs.data_latency,
+ l2x0_base + L2X0_DATA_LATENCY_CTRL);
+ writel_relaxed(l2x0_saved_regs.filter_end,
+ l2x0_base + L2X0_ADDR_FILTER_END);
+ writel_relaxed(l2x0_saved_regs.filter_start,
+ l2x0_base + L2X0_ADDR_FILTER_START);
+
+ l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
+ L2X0_CACHE_ID_RTL_MASK;
+
+ if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) {
+ writel_relaxed(l2x0_saved_regs.prefetch_ctrl,
+ l2x0_base + L2X0_PREFETCH_CTRL);
+ if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0)
+ writel_relaxed(l2x0_saved_regs.pwr_ctrl,
+ l2x0_base + L2X0_POWER_CTRL);
+ }
+ }
+
+ l2x0_resume();
+}
+
+static const struct l2x0_of_data pl310_data = {
+ pl310_of_setup,
+ pl310_save,
+ pl310_resume,
+};
+
+static const struct l2x0_of_data l2x0_data = {
+ l2x0_of_setup,
+ NULL,
+ l2x0_resume,
+};
+
static const struct of_device_id l2x0_ids[] __initconst = {
- { .compatible = "arm,pl310-cache", .data = pl310_of_setup },
- { .compatible = "arm,l220-cache", .data = l2x0_of_setup },
- { .compatible = "arm,l210-cache", .data = l2x0_of_setup },
+ { .compatible = "arm,pl310-cache", .data = (void *)&pl310_data },
+ { .compatible = "arm,l220-cache", .data = (void *)&l2x0_data },
+ { .compatible = "arm,l210-cache", .data = (void *)&l2x0_data },
{}
};
-int __init l2x0_of_init(__u32 aux_val, __u32 aux_mask)
+int __init l2x0_of_init(u32 aux_val, u32 aux_mask)
{
struct device_node *np;
- void (*l2_setup)(const struct device_node *np,
- __u32 *aux_val, __u32 *aux_mask);
+ struct l2x0_of_data *data;
+ struct resource res;
np = of_find_matching_node(NULL, l2x0_ids);
if (!np)
return -ENODEV;
- l2x0_base = of_iomap(np, 0);
+
+ if (of_address_to_resource(np, 0, &res))
+ return -ENODEV;
+
+ l2x0_base = ioremap(res.start, resource_size(&res));
if (!l2x0_base)
return -ENOMEM;
+ l2x0_saved_regs.phy_base = res.start;
+
+ data = of_match_node(l2x0_ids, np)->data;
+
/* L2 configuration can only be changed if the cache is disabled */
if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
- l2_setup = of_match_node(l2x0_ids, np)->data;
- if (l2_setup)
- l2_setup(np, &aux_val, &aux_mask);
+ if (data->setup)
+ data->setup(np, &aux_val, &aux_mask);
}
+
+ if (data->save)
+ data->save();
+
l2x0_init(l2x0_base, aux_val, aux_mask);
+
+ outer_cache.resume = data->resume;
return 0;
}
#endif
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 52c2ab1..d31c2ce 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1335,8 +1335,8 @@
if (result)
return result;
- /* we've allocated the shadow, when swapped out, GMEM must be saved. */
- drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW | CTXT_FLAGS_GMEM_SAVE;
+ /* set the gmem shadow flag for the context */
+ drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW;
/* blank out gmem shadow. */
kgsl_sharedmem_set(&drawctxt->context_gmem_shadow.gmemshadow, 0, 0,
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index b9c0a28..66dd56b 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -328,6 +328,11 @@
adreno_regwrite(device, REG_SCRATCH_UMSK,
GSL_RB_MEMPTRS_SCRATCH_MASK);
+ /* update the eoptimestamp field with the last retired timestamp */
+ kgsl_sharedmem_writel(&device->memstore,
+ KGSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp),
+ rb->timestamp);
+
/* load the CP ucode */
status = adreno_ringbuffer_load_pm4_ucode(device);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index d960eaf..7c451a9 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -334,7 +334,8 @@
do_gettimeofday(&(b->start));
}
-void kgsl_pwrctrl_clk(struct kgsl_device *device, int state)
+void kgsl_pwrctrl_clk(struct kgsl_device *device, int state,
+ int requested_state)
{
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
int i = 0;
@@ -346,7 +347,7 @@
if (pwr->grp_clks[i])
clk_disable(pwr->grp_clks[i]);
if ((pwr->pwrlevels[0].gpu_freq > 0) &&
- (device->requested_state != KGSL_STATE_NAP))
+ (requested_state != KGSL_STATE_NAP))
clk_set_rate(pwr->grp_clks[0],
pwr->pwrlevels[pwr->num_pwrlevels - 1].
gpu_freq);
@@ -698,8 +699,8 @@
return -EBUSY;
}
kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
- kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_OFF);
- kgsl_pwrctrl_set_state(device, device->requested_state);
+ kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_OFF, KGSL_STATE_NAP);
+ kgsl_pwrctrl_set_state(device, KGSL_STATE_NAP);
if (device->idle_wakelock.name)
wake_unlock(&device->idle_wakelock);
case KGSL_STATE_NAP:
@@ -741,7 +742,7 @@
pwr->pwrlevels[pwr->num_pwrlevels - 1].
gpu_freq);
_sleep_accounting(device);
- kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_OFF);
+ kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_OFF, KGSL_STATE_SLEEP);
kgsl_pwrctrl_set_state(device, KGSL_STATE_SLEEP);
wake_unlock(&device->idle_wakelock);
pm_qos_update_request(&device->pm_qos_req_dma,
@@ -845,7 +846,7 @@
/* fall through */
case KGSL_STATE_NAP:
/* Turn on the core clocks */
- kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON);
+ kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON, KGSL_STATE_ACTIVE);
/* Enable state before turning on irq */
kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE);
kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
@@ -871,7 +872,7 @@
{
/* Order pwrrail/clk sequence based upon platform */
kgsl_pwrctrl_pwrrail(device, KGSL_PWRFLAGS_ON);
- kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON);
+ kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON, KGSL_STATE_ACTIVE);
kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_ON);
}
EXPORT_SYMBOL(kgsl_pwrctrl_enable);
@@ -880,7 +881,7 @@
{
/* Order pwrrail/clk sequence based upon platform */
kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_OFF);
- kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_OFF);
+ kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_OFF, KGSL_STATE_SLEEP);
kgsl_pwrctrl_pwrrail(device, KGSL_PWRFLAGS_OFF);
}
EXPORT_SYMBOL(kgsl_pwrctrl_disable);
diff --git a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
index eef80d3..4b8c938 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
@@ -180,7 +180,7 @@
struct tz_priv *priv;
/* Trustzone is only valid for some SOCs */
- if (!(cpu_is_msm8x60() || cpu_is_msm8960()))
+ if (!(cpu_is_msm8x60() || cpu_is_msm8960() || cpu_is_apq8064()))
return -EINVAL;
priv = pwrscale->priv = kzalloc(sizeof(struct tz_priv), GFP_KERNEL);
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 1f142f8..63c24f1 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -486,6 +486,8 @@
flush_dcache_page(page);
sg_set_page(&memdesc->sg[i], page, PAGE_SIZE, 0);
}
+ outer_cache_range_op_sg(memdesc->sg, memdesc->sglen,
+ KGSL_CACHE_OP_FLUSH);
ret = kgsl_mmu_map(pagetable, memdesc, protflags);
diff --git a/drivers/hwmon/pm8xxx-adc.c b/drivers/hwmon/pm8xxx-adc.c
index 2f59235..6bef3d3 100644
--- a/drivers/hwmon/pm8xxx-adc.c
+++ b/drivers/hwmon/pm8xxx-adc.c
@@ -239,6 +239,7 @@
if (arb_cntrl) {
data_arb_cntrl |= PM8XXX_ADC_ARB_USRP_CNTRL1_REQ;
+ INIT_COMPLETION(adc_pmic->adc_rslt_completion);
rc = pm8xxx_writeb(adc_pmic->dev->parent,
PM8XXX_ADC_ARB_USRP_CNTRL1, data_arb_cntrl);
} else
@@ -336,7 +337,6 @@
static int32_t pm8xxx_adc_configure(
struct pm8xxx_adc_amux_properties *chan_prop)
{
- struct pm8xxx_adc *adc_pmic = pmic_adc;
u8 data_amux_chan = 0, data_arb_rsv = 0, data_dig_param = 0;
int rc;
@@ -395,9 +395,6 @@
if (rc < 0)
return rc;
- if (!pm8xxx_adc_calib_first_adc)
- enable_irq(adc_pmic->adc_irq);
-
rc = pm8xxx_adc_arb_cntrl(1, data_amux_chan);
if (rc < 0) {
pr_err("Configuring ADC Arbiter"
@@ -476,16 +473,21 @@
spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
}
+void trigger_completion(struct work_struct *work)
+{
+ struct pm8xxx_adc *adc_8xxx = pmic_adc;
+
+ complete(&adc_8xxx->adc_rslt_completion);
+}
+DECLARE_WORK(trigger_completion_work, trigger_completion);
+
static irqreturn_t pm8xxx_adc_isr(int irq, void *dev_id)
{
- struct pm8xxx_adc *adc_8xxx = dev_id;
-
- disable_irq_nosync(adc_8xxx->adc_irq);
if (pm8xxx_adc_calib_first_adc)
return IRQ_HANDLED;
- /* TODO Handle spurius interrupt condition */
- complete(&adc_8xxx->adc_rslt_completion);
+
+ schedule_work(&trigger_completion_work);
return IRQ_HANDLED;
}
@@ -1214,10 +1216,10 @@
if (rc) {
dev_err(&pdev->dev, "failed to request adc irq "
"with error %d\n", rc);
+ } else {
+ enable_irq_wake(adc_pmic->adc_irq);
}
- disable_irq_nosync(adc_pmic->adc_irq);
-
adc_pmic->btm_warm_irq = platform_get_irq(pdev, PM8XXX_ADC_IRQ_1);
if (adc_pmic->btm_warm_irq < 0)
return adc_pmic->btm_warm_irq;
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 39c158d..bda7cb2 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -274,6 +274,10 @@
#define T7_DATA_SIZE 3
#define MXT_MAX_RW_TRIES 3
#define MXT_BLOCK_SIZE 256
+#define MXT_CFG_VERSION_LEN 3
+#define MXT_CFG_VERSION_EQUAL 0
+#define MXT_CFG_VERSION_LESS 1
+#define MXT_CFG_VERSION_GREATER 2
#define MXT_DEBUGFS_DIR "atmel_mxt_ts"
#define MXT_DEBUGFS_FILE "object"
@@ -340,8 +344,10 @@
u8 t9_min_reportid;
u8 t15_max_reportid;
u8 t15_min_reportid;
- u8 curr_cfg_version;
+ u8 cfg_version[MXT_CFG_VERSION_LEN];
int cfg_version_idx;
+ int t38_start_addr;
+ bool update_cfg;
const char *fw_name;
};
@@ -1047,8 +1053,10 @@
/* Calculate index for config major version in config array.
* Major version is the first byte in object T38.
*/
- if (object->type == MXT_SPT_USERDATA_T38)
+ if (object->type == MXT_SPT_USERDATA_T38) {
+ data->t38_start_addr = object->start_address;
found_t38 = true;
+ }
if (!found_t38 && mxt_object_writable(object->type))
data->cfg_version_idx += object->size + 1;
}
@@ -1056,14 +1064,85 @@
return 0;
}
-static int mxt_search_config_array(struct mxt_data *data, bool version_match)
+static int compare_versions(const u8 *v1, const u8 *v2)
+{
+ int i;
+
+ if (!v1 || !v2)
+ return -EINVAL;
+
+ /* The major version number stays the same across different versions for
+ * a particular controller on a target. The minor and sub-minor version
+ * numbers indicate which version is newer.
+ */
+ if (v1[0] != v2[0])
+ return -EINVAL;
+
+ for (i = 1; i < MXT_CFG_VERSION_LEN; i++) {
+ if (v1[i] > v2[i])
+ return MXT_CFG_VERSION_LESS; /* v2 is older */
+
+ if (v1[i] < v2[i])
+ return MXT_CFG_VERSION_GREATER; /* v2 is newer */
+ }
+
+ return MXT_CFG_VERSION_EQUAL; /* v1 and v2 are equal */
+}
+
+static void mxt_check_config_version(struct mxt_data *data,
+ const struct mxt_config_info *cfg_info,
+ bool match_major,
+ const u8 **cfg_version_found,
+ bool *found_cfg_major_match)
+{
+ const u8 *cfg_version;
+ int result = -EINVAL;
+
+ cfg_version = cfg_info->config + data->cfg_version_idx;
+
+ if (*cfg_version_found)
+ result = compare_versions(*cfg_version_found, cfg_version);
+
+ if (match_major) {
+ if (result >= MXT_CFG_VERSION_EQUAL)
+ *found_cfg_major_match = true;
+
+ if (result == MXT_CFG_VERSION_EQUAL ||
+ result == MXT_CFG_VERSION_GREATER) {
+ data->config_info = cfg_info;
+ data->fw_name = cfg_info->fw_name;
+ *cfg_version_found = cfg_version;
+ }
+
+ if (result == MXT_CFG_VERSION_GREATER)
+ data->update_cfg = true;
+ } else if (!*cfg_version_found || result == MXT_CFG_VERSION_GREATER) {
+ data->config_info = cfg_info;
+ data->fw_name = cfg_info->fw_name;
+ data->update_cfg = true;
+ *cfg_version_found = cfg_version;
+ }
+}
+
+/* If the controller's config version has a non-zero major number, call this
+ * function with match_major = true to look for the latest config present in
+ * the pdata based on matching family id, variant id, f/w version, build, and
+ * config major number. If the controller is programmed with wrong config data
+ * previously, call this function with match_major = false to look for latest
+ * config based on based on matching family id, variant id, f/w version and
+ * build only.
+ */
+static int mxt_search_config_array(struct mxt_data *data, bool match_major)
{
const struct mxt_platform_data *pdata = data->pdata;
const struct mxt_config_info *cfg_info;
- struct mxt_info *info = &data->info;
+ const struct mxt_info *info = &data->info;
+ const u8 *cfg_version_found;
+ bool found_cfg_major_match = false;
int i;
- u8 cfg_version;
+
+ cfg_version_found = match_major ? data->cfg_version : NULL;
for (i = 0; i < pdata->config_array_size; i++) {
@@ -1077,22 +1156,17 @@
info->version == cfg_info->version &&
info->build == cfg_info->build) {
- cfg_version = cfg_info->config[data->cfg_version_idx];
- if (data->curr_cfg_version == cfg_version ||
- !version_match) {
- data->config_info = cfg_info;
- data->fw_name = pdata->config_array[i].fw_name;
- return 0;
- }
+ mxt_check_config_version(data, cfg_info, match_major,
+ &cfg_version_found, &found_cfg_major_match);
}
}
+ if (data->config_info || found_cfg_major_match)
+ return 0;
+
+ data->config_info = NULL;
data->fw_name = NULL;
- dev_info(&data->client->dev,
- "Config not found: F: %d, V: %d, FW: %d.%d.%d, CFG: %d\n",
- info->family_id, info->variant_id,
- info->version >> 4, info->version & 0xF, info->build,
- data->curr_cfg_version);
+
return -EINVAL;
}
@@ -1115,24 +1189,40 @@
return -EINVAL;
}
- error = mxt_read_reg(data->client, object->start_address,
- &data->curr_cfg_version);
+ error = __mxt_read_reg(data->client, object->start_address,
+ sizeof(data->cfg_version), data->cfg_version);
if (error) {
dev_err(dev, "Unable to read config version\n");
return error;
}
+ dev_info(dev, "Current config version on the controller is %d.%d.%d\n",
+ data->cfg_version[0], data->cfg_version[1],
+ data->cfg_version[2]);
/* It is possible that the config data on the controller is not
* versioned and the version number returns 0. In this case,
* find a match without the config version checking.
*/
error = mxt_search_config_array(data,
- data->curr_cfg_version != 0 ? true : false);
- if (error)
- return error;
+ data->cfg_version[0] != 0 ? true : false);
+ if (error) {
+ /* If a match wasn't found for a non-zero config version,
+ * it means the controller has the wrong config data. Search
+ * for a best match based on controller and firmware version,
+ * but not config version.
+ */
+ if (data->cfg_version[0])
+ error = mxt_search_config_array(data, false);
+ if (error) {
+ dev_err(dev,
+ "Unable to find matching config in pdata\n");
+ return error;
+ }
+ }
return 0;
}
+
static void mxt_reset_delay(struct mxt_data *data)
{
struct mxt_info *info = &data->info;
@@ -1152,17 +1242,104 @@
}
}
+static int mxt_backup_nv(struct mxt_data *data)
+{
+ int error;
+ u8 command_register;
+ int timeout_counter = 0;
+
+ /* Backup to memory */
+ mxt_write_object(data, MXT_GEN_COMMAND_T6,
+ MXT_COMMAND_BACKUPNV,
+ MXT_BACKUP_VALUE);
+ msleep(MXT_BACKUP_TIME);
+
+ do {
+ error = mxt_read_object(data, MXT_GEN_COMMAND_T6,
+ MXT_COMMAND_BACKUPNV,
+ &command_register);
+ if (error)
+ return error;
+
+ usleep_range(1000, 2000);
+
+ } while ((command_register != 0) && (++timeout_counter <= 100));
+
+ if (timeout_counter > 100) {
+ dev_err(&data->client->dev, "No response after backup!\n");
+ return -EIO;
+ }
+
+ /* Soft reset */
+ mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1);
+
+ mxt_reset_delay(data);
+
+ return 0;
+}
+
+static int mxt_save_objects(struct mxt_data *data)
+{
+ struct i2c_client *client = data->client;
+ struct mxt_object *t7_object;
+ struct mxt_object *t9_object;
+ struct mxt_object *t15_object;
+ int error;
+
+ /* Store T7 and T9 locally, used in suspend/resume operations */
+ t7_object = mxt_get_object(data, MXT_GEN_POWER_T7);
+ if (!t7_object) {
+ dev_err(&client->dev, "Failed to get T7 object\n");
+ return -EINVAL;
+ }
+
+ data->t7_start_addr = t7_object->start_address;
+ error = __mxt_read_reg(client, data->t7_start_addr,
+ T7_DATA_SIZE, data->t7_data);
+ if (error < 0) {
+ dev_err(&client->dev,
+ "Failed to save current power state\n");
+ return error;
+ }
+
+ error = mxt_read_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL,
+ &data->t9_ctrl);
+ if (error < 0) {
+ dev_err(&client->dev, "Failed to save current touch object\n");
+ return error;
+ }
+
+ /* Store T9, T15's min and max report ids */
+ t9_object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
+ if (!t9_object) {
+ dev_err(&client->dev, "Failed to get T9 object\n");
+ return -EINVAL;
+ }
+ data->t9_max_reportid = t9_object->max_reportid;
+ data->t9_min_reportid = t9_object->max_reportid -
+ t9_object->num_report_ids + 1;
+
+ if (data->pdata->key_codes) {
+ t15_object = mxt_get_object(data, MXT_TOUCH_KEYARRAY_T15);
+ if (!t15_object)
+ dev_dbg(&client->dev, "T15 object is not available\n");
+ else {
+ data->t15_max_reportid = t15_object->max_reportid;
+ data->t15_min_reportid = t15_object->max_reportid -
+ t15_object->num_report_ids + 1;
+ }
+ }
+
+ return 0;
+}
+
static int mxt_initialize(struct mxt_data *data)
{
struct i2c_client *client = data->client;
struct mxt_info *info = &data->info;
int error;
- int timeout_counter = 0;
u8 val;
- u8 command_register;
- struct mxt_object *t7_object;
- struct mxt_object *t9_object;
- struct mxt_object *t15_object;
+ const u8 *cfg_ver;
error = mxt_get_info(data);
if (error) {
@@ -1209,81 +1386,40 @@
dev_dbg(&client->dev, "Config info not found.\n");
/* Check register init values */
- error = mxt_check_reg_init(data);
+ if (data->config_info && data->config_info->config) {
+ if (data->update_cfg) {
+ error = mxt_check_reg_init(data);
+ if (error) {
+ dev_err(&client->dev,
+ "Failed to check reg init value\n");
+ goto free_object_table;
+ }
+
+ error = mxt_backup_nv(data);
+ if (error) {
+ dev_err(&client->dev, "Failed to back up NV\n");
+ goto free_object_table;
+ }
+
+ cfg_ver = data->config_info->config +
+ data->cfg_version_idx;
+ dev_info(&client->dev,
+ "Config updated from %d.%d.%d to %d.%d.%d\n",
+ data->cfg_version[0], data->cfg_version[1],
+ data->cfg_version[2],
+ cfg_ver[0], cfg_ver[1], cfg_ver[2]);
+
+ memcpy(data->cfg_version, cfg_ver, MXT_CFG_VERSION_LEN);
+ }
+ } else {
+ dev_info(&client->dev,
+ "No cfg data defined, skipping check reg init\n");
+ }
+
+ error = mxt_save_objects(data);
if (error)
goto free_object_table;
- /* Store T7 and T9 locally, used in suspend/resume operations */
- t7_object = mxt_get_object(data, MXT_GEN_POWER_T7);
- if (!t7_object) {
- dev_err(&client->dev, "Failed to get T7 object\n");
- error = -EINVAL;
- goto free_object_table;
- }
-
- data->t7_start_addr = t7_object->start_address;
- error = __mxt_read_reg(client, data->t7_start_addr,
- T7_DATA_SIZE, data->t7_data);
- if (error < 0) {
- dev_err(&client->dev,
- "Failed to save current power state\n");
- goto free_object_table;
- }
- error = mxt_read_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL,
- &data->t9_ctrl);
- if (error < 0) {
- dev_err(&client->dev, "Failed to save current touch object\n");
- goto free_object_table;
- }
-
- /* Store T9, T15's min and max report ids */
- t9_object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
- if (!t9_object) {
- dev_err(&client->dev, "Failed to get T9 object\n");
- error = -EINVAL;
- goto free_object_table;
- }
- data->t9_max_reportid = t9_object->max_reportid;
- data->t9_min_reportid = t9_object->max_reportid -
- t9_object->num_report_ids + 1;
-
- if (data->pdata->key_codes) {
- t15_object = mxt_get_object(data, MXT_TOUCH_KEYARRAY_T15);
- if (!t15_object)
- dev_dbg(&client->dev, "T15 object is not available\n");
- else {
- data->t15_max_reportid = t15_object->max_reportid;
- data->t15_min_reportid = t15_object->max_reportid -
- t15_object->num_report_ids + 1;
- }
- }
-
- /* Backup to memory */
- mxt_write_object(data, MXT_GEN_COMMAND_T6,
- MXT_COMMAND_BACKUPNV,
- MXT_BACKUP_VALUE);
- msleep(MXT_BACKUP_TIME);
- do {
- error = mxt_read_object(data, MXT_GEN_COMMAND_T6,
- MXT_COMMAND_BACKUPNV,
- &command_register);
- if (error)
- goto free_object_table;
- usleep_range(1000, 2000);
- } while ((command_register != 0) && (++timeout_counter <= 100));
- if (timeout_counter > 100) {
- dev_err(&client->dev, "No response after backup!\n");
- error = -EIO;
- goto free_object_table;
- }
-
-
- /* Soft reset */
- mxt_write_object(data, MXT_GEN_COMMAND_T6,
- MXT_COMMAND_RESET, 1);
-
- mxt_reset_delay(data);
-
/* Update matrix size at info struct */
error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
if (error)
@@ -1518,6 +1654,7 @@
int error;
const char *fw_name;
u8 bootldr_id;
+ u8 cfg_version[MXT_CFG_VERSION_LEN] = {0};
/* If fw_name is set, then the existing firmware has an upgrade */
if (!data->fw_name) {
@@ -1566,6 +1703,13 @@
kfree(data->object_table);
data->object_table = NULL;
data->cfg_version_idx = 0;
+ data->update_cfg = false;
+
+ error = __mxt_write_reg(data->client, data->t38_start_addr,
+ sizeof(cfg_version), cfg_version);
+ if (error)
+ dev_err(dev,
+ "Unable to zero out config version after fw upgrade\n");
mxt_initialize(data);
}
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index c8827ff..ba510a2 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -18,7 +18,6 @@
#include <linux/crypto.h>
#include <linux/workqueue.h>
#include <linux/backing-dev.h>
-#include <linux/percpu.h>
#include <asm/atomic.h>
#include <linux/scatterlist.h>
#include <asm/page.h>
@@ -44,7 +43,8 @@
unsigned int idx_in;
unsigned int idx_out;
sector_t sector;
- atomic_t pending;
+ atomic_t cc_pending;
+ struct ablkcipher_request *req;
};
/*
@@ -57,7 +57,7 @@
struct convert_context ctx;
- atomic_t pending;
+ atomic_t io_pending;
int error;
sector_t sector;
struct dm_crypt_io *base_io;
@@ -106,18 +106,7 @@
enum flags { DM_CRYPT_SUSPENDED, DM_CRYPT_KEY_VALID };
/*
- * Duplicated per-CPU state for cipher.
- */
-struct crypt_cpu {
- struct ablkcipher_request *req;
- /* ESSIV: struct crypto_cipher *essiv_tfm */
- void *iv_private;
- struct crypto_ablkcipher *tfms[0];
-};
-
-/*
* The fields in here must be read only after initialization,
- * changing state should be in crypt_cpu.
*/
struct crypt_config {
struct dm_dev *dev;
@@ -147,11 +136,9 @@
sector_t iv_offset;
unsigned int iv_size;
- /*
- * Duplicated per cpu state. Access through
- * per_cpu_ptr() only.
- */
- struct crypt_cpu __percpu *cpu;
+ /* ESSIV: struct crypto_cipher *essiv_tfm */
+ void *iv_private;
+ struct crypto_ablkcipher **tfms;
unsigned tfms_count;
/*
@@ -185,17 +172,12 @@
static void kcryptd_queue_crypt(struct dm_crypt_io *io);
static u8 *iv_of_dmreq(struct crypt_config *cc, struct dm_crypt_request *dmreq);
-static struct crypt_cpu *this_crypt_config(struct crypt_config *cc)
-{
- return this_cpu_ptr(cc->cpu);
-}
-
/*
* Use this to access cipher attributes that are the same for each CPU.
*/
static struct crypto_ablkcipher *any_tfm(struct crypt_config *cc)
{
- return __this_cpu_ptr(cc->cpu)->tfms[0];
+ return cc->tfms[0];
}
/*
@@ -260,7 +242,7 @@
struct hash_desc desc;
struct scatterlist sg;
struct crypto_cipher *essiv_tfm;
- int err, cpu;
+ int err;
sg_init_one(&sg, cc->key, cc->key_size);
desc.tfm = essiv->hash_tfm;
@@ -270,14 +252,12 @@
if (err)
return err;
- for_each_possible_cpu(cpu) {
- essiv_tfm = per_cpu_ptr(cc->cpu, cpu)->iv_private,
+ essiv_tfm = cc->iv_private;
- err = crypto_cipher_setkey(essiv_tfm, essiv->salt,
- crypto_hash_digestsize(essiv->hash_tfm));
- if (err)
- return err;
- }
+ err = crypto_cipher_setkey(essiv_tfm, essiv->salt,
+ crypto_hash_digestsize(essiv->hash_tfm));
+ if (err)
+ return err;
return 0;
}
@@ -288,16 +268,14 @@
struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv;
unsigned salt_size = crypto_hash_digestsize(essiv->hash_tfm);
struct crypto_cipher *essiv_tfm;
- int cpu, r, err = 0;
+ int r, err = 0;
memset(essiv->salt, 0, salt_size);
- for_each_possible_cpu(cpu) {
- essiv_tfm = per_cpu_ptr(cc->cpu, cpu)->iv_private;
- r = crypto_cipher_setkey(essiv_tfm, essiv->salt, salt_size);
- if (r)
- err = r;
- }
+ essiv_tfm = cc->iv_private;
+ r = crypto_cipher_setkey(essiv_tfm, essiv->salt, salt_size);
+ if (r)
+ err = r;
return err;
}
@@ -337,8 +315,6 @@
static void crypt_iv_essiv_dtr(struct crypt_config *cc)
{
- int cpu;
- struct crypt_cpu *cpu_cc;
struct crypto_cipher *essiv_tfm;
struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv;
@@ -348,15 +324,13 @@
kzfree(essiv->salt);
essiv->salt = NULL;
- for_each_possible_cpu(cpu) {
- cpu_cc = per_cpu_ptr(cc->cpu, cpu);
- essiv_tfm = cpu_cc->iv_private;
+ essiv_tfm = cc->iv_private;
- if (essiv_tfm)
- crypto_free_cipher(essiv_tfm);
+ if (essiv_tfm)
+ crypto_free_cipher(essiv_tfm);
- cpu_cc->iv_private = NULL;
- }
+ cc->iv_private = NULL;
+
}
static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti,
@@ -365,7 +339,7 @@
struct crypto_cipher *essiv_tfm = NULL;
struct crypto_hash *hash_tfm = NULL;
u8 *salt = NULL;
- int err, cpu;
+ int err;
if (!opts) {
ti->error = "Digest algorithm missing for ESSIV mode";
@@ -390,15 +364,13 @@
cc->iv_gen_private.essiv.salt = salt;
cc->iv_gen_private.essiv.hash_tfm = hash_tfm;
- for_each_possible_cpu(cpu) {
- essiv_tfm = setup_essiv_cpu(cc, ti, salt,
- crypto_hash_digestsize(hash_tfm));
- if (IS_ERR(essiv_tfm)) {
- crypt_iv_essiv_dtr(cc);
- return PTR_ERR(essiv_tfm);
- }
- per_cpu_ptr(cc->cpu, cpu)->iv_private = essiv_tfm;
+ essiv_tfm = setup_essiv_cpu(cc, ti, salt,
+ crypto_hash_digestsize(hash_tfm));
+ if (IS_ERR(essiv_tfm)) {
+ crypt_iv_essiv_dtr(cc);
+ return PTR_ERR(essiv_tfm);
}
+ cc->iv_private = essiv_tfm;
return 0;
@@ -412,7 +384,8 @@
static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv,
struct dm_crypt_request *dmreq)
{
- struct crypto_cipher *essiv_tfm = this_crypt_config(cc)->iv_private;
+
+ struct crypto_cipher *essiv_tfm = cc->iv_private;
memset(iv, 0, cc->iv_size);
*(u64 *)iv = cpu_to_le64(dmreq->iv_sector);
@@ -750,16 +723,15 @@
static void crypt_alloc_req(struct crypt_config *cc,
struct convert_context *ctx)
{
- struct crypt_cpu *this_cc = this_crypt_config(cc);
unsigned key_index = ctx->sector & (cc->tfms_count - 1);
- if (!this_cc->req)
- this_cc->req = mempool_alloc(cc->req_pool, GFP_NOIO);
+ if (!ctx->req)
+ ctx->req = mempool_alloc(cc->req_pool, GFP_NOIO);
- ablkcipher_request_set_tfm(this_cc->req, this_cc->tfms[key_index]);
- ablkcipher_request_set_callback(this_cc->req,
+ ablkcipher_request_set_tfm(ctx->req, cc->tfms[key_index]);
+ ablkcipher_request_set_callback(ctx->req,
CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP,
- kcryptd_async_done, dmreq_of_req(cc, this_cc->req));
+ kcryptd_async_done, dmreq_of_req(cc, ctx->req));
}
/*
@@ -768,19 +740,18 @@
static int crypt_convert(struct crypt_config *cc,
struct convert_context *ctx)
{
- struct crypt_cpu *this_cc = this_crypt_config(cc);
int r;
- atomic_set(&ctx->pending, 1);
+ atomic_set(&ctx->cc_pending, 1);
while(ctx->idx_in < ctx->bio_in->bi_vcnt &&
ctx->idx_out < ctx->bio_out->bi_vcnt) {
crypt_alloc_req(cc, ctx);
- atomic_inc(&ctx->pending);
+ atomic_inc(&ctx->cc_pending);
- r = crypt_convert_block(cc, ctx, this_cc->req);
+ r = crypt_convert_block(cc, ctx, ctx->req);
switch (r) {
/* async */
@@ -789,20 +760,20 @@
INIT_COMPLETION(ctx->restart);
/* fall through*/
case -EINPROGRESS:
- this_cc->req = NULL;
+ ctx->req = NULL;
ctx->sector++;
continue;
/* sync */
case 0:
- atomic_dec(&ctx->pending);
+ atomic_dec(&ctx->cc_pending);
ctx->sector++;
cond_resched();
continue;
/* error */
default:
- atomic_dec(&ctx->pending);
+ atomic_dec(&ctx->cc_pending);
return r;
}
}
@@ -853,8 +824,7 @@
* return a partially allocated bio, the caller will then try
* to allocate additional bios while submitting this partial bio
*/
- if (i == (MIN_BIO_PAGES - 1))
- gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT;
+ gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT;
len = (size > PAGE_SIZE) ? PAGE_SIZE : size;
@@ -899,14 +869,15 @@
io->sector = sector;
io->error = 0;
io->base_io = NULL;
- atomic_set(&io->pending, 0);
+ io->ctx.req = NULL;
+ atomic_set(&io->io_pending, 0);
return io;
}
static void crypt_inc_pending(struct dm_crypt_io *io)
{
- atomic_inc(&io->pending);
+ atomic_inc(&io->io_pending);
}
/*
@@ -921,9 +892,11 @@
struct dm_crypt_io *base_io = io->base_io;
int error = io->error;
- if (!atomic_dec_and_test(&io->pending))
+ if (!atomic_dec_and_test(&io->io_pending))
return;
+ if (io->ctx.req)
+ mempool_free(io->ctx.req, cc->req_pool);
mempool_free(io, cc->io_pool);
if (likely(!base_io))
@@ -1047,16 +1020,14 @@
queue_work(cc->io_queue, &io->work);
}
-static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io,
- int error, int async)
+static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async)
{
struct bio *clone = io->ctx.bio_out;
struct crypt_config *cc = io->target->private;
- if (unlikely(error < 0)) {
+ if (unlikely(io->error < 0)) {
crypt_free_buffer_pages(cc, clone);
bio_put(clone);
- io->error = -EIO;
crypt_dec_pending(io);
return;
}
@@ -1108,11 +1079,13 @@
crypt_inc_pending(io);
r = crypt_convert(cc, &io->ctx);
- crypt_finished = atomic_dec_and_test(&io->ctx.pending);
+ if (r < 0)
+ io->error = -EIO;
+ crypt_finished = atomic_dec_and_test(&io->ctx.cc_pending);
/* Encryption was already finished, submit io now */
if (crypt_finished) {
- kcryptd_crypt_write_io_submit(io, r, 0);
+ kcryptd_crypt_write_io_submit(io, 0);
/*
* If there was an error, do not try next fragments.
@@ -1163,11 +1136,8 @@
crypt_dec_pending(io);
}
-static void kcryptd_crypt_read_done(struct dm_crypt_io *io, int error)
+static void kcryptd_crypt_read_done(struct dm_crypt_io *io)
{
- if (unlikely(error < 0))
- io->error = -EIO;
-
crypt_dec_pending(io);
}
@@ -1183,8 +1153,11 @@
r = crypt_convert(cc, &io->ctx);
- if (atomic_dec_and_test(&io->ctx.pending))
- kcryptd_crypt_read_done(io, r);
+ if (r < 0)
+ io->error = -EIO;
+
+ if (atomic_dec_and_test(&io->ctx.cc_pending))
+ kcryptd_crypt_read_done(io);
crypt_dec_pending(io);
}
@@ -1205,15 +1178,18 @@
if (!error && cc->iv_gen_ops && cc->iv_gen_ops->post)
error = cc->iv_gen_ops->post(cc, iv_of_dmreq(cc, dmreq), dmreq);
+ if (error < 0)
+ io->error = -EIO;
+
mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool);
- if (!atomic_dec_and_test(&ctx->pending))
+ if (!atomic_dec_and_test(&ctx->cc_pending))
return;
if (bio_data_dir(io->base_bio) == READ)
- kcryptd_crypt_read_done(io, error);
+ kcryptd_crypt_read_done(io);
else
- kcryptd_crypt_write_io_submit(io, error, 1);
+ kcryptd_crypt_write_io_submit(io, 1);
}
static void kcryptd_crypt(struct work_struct *work)
@@ -1275,29 +1251,35 @@
}
}
-static void crypt_free_tfms(struct crypt_config *cc, int cpu)
+static void crypt_free_tfms(struct crypt_config *cc)
{
- struct crypt_cpu *cpu_cc = per_cpu_ptr(cc->cpu, cpu);
unsigned i;
+ if (!cc->tfms)
+ return;
+
for (i = 0; i < cc->tfms_count; i++)
- if (cpu_cc->tfms[i] && !IS_ERR(cpu_cc->tfms[i])) {
- crypto_free_ablkcipher(cpu_cc->tfms[i]);
- cpu_cc->tfms[i] = NULL;
+ if (cc->tfms[i] && !IS_ERR(cc->tfms[i])) {
+ crypto_free_ablkcipher(cc->tfms[i]);
+ cc->tfms[i] = NULL;
}
}
-static int crypt_alloc_tfms(struct crypt_config *cc, int cpu, char *ciphermode)
+static int crypt_alloc_tfms(struct crypt_config *cc, char *ciphermode)
{
- struct crypt_cpu *cpu_cc = per_cpu_ptr(cc->cpu, cpu);
unsigned i;
int err;
+ cc->tfms = kmalloc(cc->tfms_count * sizeof(struct crypto_ablkcipher *),
+ GFP_KERNEL);
+ if (!cc->tfms)
+ return -ENOMEM;
+
for (i = 0; i < cc->tfms_count; i++) {
- cpu_cc->tfms[i] = crypto_alloc_ablkcipher(ciphermode, 0, 0);
- if (IS_ERR(cpu_cc->tfms[i])) {
- err = PTR_ERR(cpu_cc->tfms[i]);
- crypt_free_tfms(cc, cpu);
+ cc->tfms[i] = crypto_alloc_ablkcipher(ciphermode, 0, 0);
+ if (IS_ERR(cc->tfms[i])) {
+ err = PTR_ERR(cc->tfms[i]);
+ crypt_free_tfms(cc);
return err;
}
}
@@ -1308,15 +1290,14 @@
static int crypt_setkey_allcpus(struct crypt_config *cc)
{
unsigned subkey_size = cc->key_size >> ilog2(cc->tfms_count);
- int cpu, err = 0, i, r;
+ int err = 0, i, r;
- for_each_possible_cpu(cpu) {
- for (i = 0; i < cc->tfms_count; i++) {
- r = crypto_ablkcipher_setkey(per_cpu_ptr(cc->cpu, cpu)->tfms[i],
- cc->key + (i * subkey_size), subkey_size);
- if (r)
- err = r;
- }
+ for (i = 0; i < cc->tfms_count; i++) {
+ r = crypto_ablkcipher_setkey(cc->tfms[i],
+ cc->key + (i * subkey_size),
+ subkey_size);
+ if (r)
+ err = r;
}
return err;
@@ -1360,8 +1341,6 @@
static void crypt_dtr(struct dm_target *ti)
{
struct crypt_config *cc = ti->private;
- struct crypt_cpu *cpu_cc;
- int cpu;
ti->private = NULL;
@@ -1373,13 +1352,7 @@
if (cc->crypt_queue)
destroy_workqueue(cc->crypt_queue);
- if (cc->cpu)
- for_each_possible_cpu(cpu) {
- cpu_cc = per_cpu_ptr(cc->cpu, cpu);
- if (cpu_cc->req)
- mempool_free(cpu_cc->req, cc->req_pool);
- crypt_free_tfms(cc, cpu);
- }
+ crypt_free_tfms(cc);
if (cc->bs)
bioset_free(cc->bs);
@@ -1397,9 +1370,6 @@
if (cc->dev)
dm_put_device(ti, cc->dev);
- if (cc->cpu)
- free_percpu(cc->cpu);
-
kzfree(cc->cipher);
kzfree(cc->cipher_string);
@@ -1413,7 +1383,7 @@
struct crypt_config *cc = ti->private;
char *tmp, *cipher, *chainmode, *ivmode, *ivopts, *keycount;
char *cipher_api = NULL;
- int cpu, ret = -EINVAL;
+ int ret = -EINVAL;
/* Convert to crypto api definition? */
if (strchr(cipher_in, '(')) {
@@ -1453,14 +1423,6 @@
if (tmp)
DMWARN("Ignoring unexpected additional cipher options");
- cc->cpu = __alloc_percpu(sizeof(*(cc->cpu)) +
- cc->tfms_count * sizeof(*(cc->cpu->tfms)),
- __alignof__(struct crypt_cpu));
- if (!cc->cpu) {
- ti->error = "Cannot allocate per cpu state";
- goto bad_mem;
- }
-
/*
* For compatibility with the original dm-crypt mapping format, if
* only the cipher name is supplied, use cbc-plain.
@@ -1487,12 +1449,10 @@
}
/* Allocate cipher */
- for_each_possible_cpu(cpu) {
- ret = crypt_alloc_tfms(cc, cpu, cipher_api);
- if (ret < 0) {
- ti->error = "Error allocating crypto tfm";
- goto bad;
- }
+ ret = crypt_alloc_tfms(cc, cipher_api);
+ if (ret < 0) {
+ ti->error = "Error allocating crypto tfm";
+ goto bad;
}
/* Initialize and set key */
diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile
index 45b0134..198298b 100644
--- a/drivers/media/rc/keymaps/Makefile
+++ b/drivers/media/rc/keymaps/Makefile
@@ -56,6 +56,7 @@
rc-norwood.o \
rc-npgtech.o \
rc-pctv-sedna.o \
+ rc-philips.o \
rc-pinnacle-color.o \
rc-pinnacle-grey.o \
rc-pinnacle-pctv-hd.o \
diff --git a/drivers/media/rc/keymaps/rc-philips.c b/drivers/media/rc/keymaps/rc-philips.c
new file mode 100644
index 0000000..ff2caf9
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-philips.c
@@ -0,0 +1,81 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <media/rc-map.h>
+
+static struct rc_map_table philips[] = {
+
+ { 0x00, KEY_NUMERIC_0 },
+ { 0x01, KEY_NUMERIC_1 },
+ { 0x02, KEY_NUMERIC_2 },
+ { 0x03, KEY_NUMERIC_3 },
+ { 0x04, KEY_NUMERIC_4 },
+ { 0x05, KEY_NUMERIC_5 },
+ { 0x06, KEY_NUMERIC_6 },
+ { 0x07, KEY_NUMERIC_7 },
+ { 0x08, KEY_NUMERIC_8 },
+ { 0x09, KEY_NUMERIC_9 },
+ { 0xF4, KEY_SOUND },
+ { 0xF3, KEY_SCREEN }, /* Picture */
+
+ { 0x10, KEY_VOLUMEUP },
+ { 0x11, KEY_VOLUMEDOWN },
+ { 0x0d, KEY_MUTE },
+ { 0x20, KEY_CHANNELUP },
+ { 0x21, KEY_CHANNELDOWN },
+ { 0x0A, KEY_BACK },
+ { 0x0f, KEY_INFO },
+ { 0x5c, KEY_OK },
+ { 0x58, KEY_UP },
+ { 0x59, KEY_DOWN },
+ { 0x5a, KEY_LEFT },
+ { 0x5b, KEY_RIGHT },
+ { 0xcc, KEY_PAUSE },
+ { 0x6d, KEY_PVR }, /* Demo */
+ { 0x40, KEY_EXIT },
+ { 0x6e, KEY_PROG1 }, /* Scenea */
+ { 0x6f, KEY_MODE }, /* Dual */
+ { 0x70, KEY_SLEEP },
+ { 0xf5, KEY_TUNER }, /* Format */
+
+ { 0x4f, KEY_TV },
+ { 0x3c, KEY_NEW }, /* USB */
+ { 0x38, KEY_COMPOSE }, /* Source */
+ { 0x54, KEY_MENU },
+
+ { 0x0C, KEY_POWER },
+};
+
+static struct rc_map_list rc6_philips_map = {
+ .map = {
+ .scan = philips,
+ .size = ARRAY_SIZE(philips),
+ .rc_type = RC_TYPE_RC6,
+ .name = RC_MAP_RC6_PHILIPS,
+ }
+};
+
+static int __init init_rc_map_rc6_philips(void)
+{
+ return rc_map_register(&rc6_philips_map);
+}
+
+static void __exit exit_rc_map_rc6_philips(void)
+{
+ rc_map_unregister(&rc6_philips_map);
+}
+
+module_init(init_rc_map_rc6_philips)
+module_exit(exit_rc_map_rc6_philips)
+
+MODULE_DESCRIPTION("Philips Remote Keymap ");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index ec034b1..c00f4c6 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -82,7 +82,7 @@
# This uses the CSI interface.
config VX6953
bool "Sensor VX6953 (BAYER 5M)"
- depends on MSM_CAMERA && (ARCH_MSM7X30 || ARCH_MSM8X60)
+ depends on MSM_CAMERA && (ARCH_MSM7X30 || ARCH_MSM8X60) && !MSM_CAMERA_V4L2
default y
---help---
STM 5M Bayer Sensor with EDOF
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index f817561..ca80fc1 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -20,9 +20,14 @@
else
obj-$(CONFIG_ARCH_MSM7X27A) += msm_vfe7x27a.o msm_io_7x27a.o
endif
-obj-$(CONFIG_ARCH_MSM7X30) += msm_vfe31.o msm_io_vfe31.o msm_vpe1.o
obj-$(CONFIG_ARCH_QSD8X50) += msm_vfe8x.o msm_vfe8x_proc.o msm_io8x.o
-obj-$(CONFIG_ARCH_MSM8X60) += msm_vfe31.o msm_io_8x60.o msm_vpe1.o
+ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
+ obj-$(CONFIG_ARCH_MSM8X60) += msm_io_vfe31_v4l2.o msm_vfe31_v4l2.o msm_vpe.o
+ obj-$(CONFIG_ARCH_MSM7X30) += msm_io_vfe31_v4l2.o msm_vfe31_v4l2.o msm_vpe.o msm_axi_qos.o
+else
+ obj-$(CONFIG_ARCH_MSM8X60) += msm_vfe31.o msm_io_8x60.o msm_vpe1.o
+ obj-$(CONFIG_ARCH_MSM7X30) += msm_vfe31.o msm_io_vfe31.o msm_vpe1.o
+endif
obj-$(CONFIG_ARCH_MSM8960) += msm_io_8960.o msm_vfe32.o msm_vpe.o
obj-$(CONFIG_MT9T013) += mt9t013.o mt9t013_reg.o
obj-$(CONFIG_SN12M0PZ) += sn12m0pz.o sn12m0pz_reg.o
@@ -32,9 +37,7 @@
obj-$(CONFIG_MT9P012_KM) += mt9p012_km.o mt9p012_km_reg.o
obj-$(CONFIG_S5K3E2FX) += s5k3e2fx.o
#FIXME: Merge the two ifeq causes VX6953 preview not coming up.
-ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
- obj-$(CONFIG_VX6953) += vx6953_v4l2.o vx6953_reg_v4l2.o
-else
+ifneq ($(CONFIG_MSM_CAMERA_V4L2),y)
obj-$(CONFIG_VX6953) += vx6953.o vx6953_reg.o
obj-$(CONFIG_IMX074) += imx074.o imx074_reg.o
obj-$(CONFIG_MT9E013) += mt9e013.o mt9e013_reg.o
diff --git a/drivers/media/video/msm/csi/Makefile b/drivers/media/video/msm/csi/Makefile
index 6e8eb122..e5d5966 100644
--- a/drivers/media/video/msm/csi/Makefile
+++ b/drivers/media/video/msm/csi/Makefile
@@ -2,3 +2,5 @@
EXTRA_CFLAGS += -Idrivers/media/video/msm
obj-$(CONFIG_ARCH_MSM8960) += msm_csiphy.o msm_csid.o msm_ispif.o
obj-$(CONFIG_ARCH_MSM7X27A) += msm_csic.o
+obj-$(CONFIG_ARCH_MSM8X60) += msm_csic.o
+obj-$(CONFIG_ARCH_MSM7X30) += msm_csic.o
diff --git a/drivers/media/video/msm/csi/msm_csic.c b/drivers/media/video/msm/csi/msm_csic.c
index 3a642c7..1ca4fa3 100644
--- a/drivers/media/video/msm/csi/msm_csic.c
+++ b/drivers/media/video/msm/csi/msm_csic.c
@@ -13,6 +13,7 @@
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <mach/clk.h>
#include <mach/board.h>
#include <mach/camera.h>
#include <media/msm_isp.h>
@@ -54,7 +55,7 @@
/* Data format for unpacking purpose */
#define MIPI_PROTOCOL_CONTROL_DATA_FORMAT_SHFT 0x13
/* Enable decoding of payload based on data type filed of packet hdr */
-#define MIPI_PROTOCOL_CONTROL_DECODE_ID_BMSK 0x00000
+#define MIPI_PROTOCOL_CONTROL_DECODE_ID_BMSK 0x40000
/* Enable error correction on packet headers */
#define MIPI_PROTOCOL_CONTROL_ECC_EN_BMSK 0x20000
@@ -132,7 +133,7 @@
#define MSM_AXI_QOS_SNAPSHOT 200000
#define MSM_AXI_QOS_RECORDING 200000
-#define MIPI_PWR_CNTL_ENA 0x07
+#define MIPI_PWR_CNTL_EN 0x07
#define MIPI_PWR_CNTL_DIS 0x0
static int msm_csic_config(struct csic_cfg_params *cfg_params)
@@ -210,9 +211,9 @@
break;
}
- msm_io_w(0xFFFFF3FF, csicbase + MIPI_INTERRUPT_MASK);
- /*clear IRQ bits - write 1 clears the status*/
- msm_io_w(0xFFFFF3FF, csicbase + MIPI_INTERRUPT_STATUS);
+ msm_io_w(0xF077F3C0, csicbase + MIPI_INTERRUPT_MASK);
+ /*clear IRQ bits*/
+ msm_io_w(0xF077F3C0, csicbase + MIPI_INTERRUPT_STATUS);
return rc;
}
@@ -244,7 +245,14 @@
return 0;
}
-static struct msm_cam_clk_info csic_clk_info[] = {
+static struct msm_cam_clk_info csic_8x_clk_info[] = {
+ {"csi_src_clk", 384000000},
+ {"csi_clk", -1},
+ {"csi_vfe_clk", -1},
+ {"csi_pclk", -1},
+};
+
+static struct msm_cam_clk_info csic_7x_clk_info[] = {
{"csi_clk", 400000000},
{"csi_vfe_clk", -1},
{"csi_pclk", -1},
@@ -267,12 +275,18 @@
return rc;
}
- pr_info("msm_cam_clk_enable: enable csi_pclk, csi_clk, csi_vfe_clk\n");
- rc = msm_cam_clk_enable(&csic_dev->pdev->dev, csic_clk_info,
- csic_dev->csic_clk, ARRAY_SIZE(csic_clk_info), 1);
+ csic_dev->hw_version = CSIC_8X;
+ rc = msm_cam_clk_enable(&csic_dev->pdev->dev, csic_8x_clk_info,
+ csic_dev->csic_clk, ARRAY_SIZE(csic_8x_clk_info), 1);
if (rc < 0) {
- iounmap(csic_dev->base);
- return rc;
+ csic_dev->hw_version = CSIC_7X;
+ rc = msm_cam_clk_enable(&csic_dev->pdev->dev, csic_7x_clk_info,
+ csic_dev->csic_clk, ARRAY_SIZE(csic_7x_clk_info), 1);
+ if (rc < 0) {
+ csic_dev->hw_version = 0;
+ iounmap(csic_dev->base);
+ return rc;
+ }
}
#if DBG_CSIC
@@ -282,20 +296,58 @@
return 0;
}
+static void msm_csic_disable(struct v4l2_subdev *sd)
+{
+ uint32_t val;
+ struct csic_device *csic_dev;
+ csic_dev = v4l2_get_subdevdata(sd);
+
+ val = 0x0;
+ if (csic_dev->base != NULL) {
+ CDBG("%s MIPI_PHY_D0_CONTROL2 val=0x%x\n", __func__, val);
+ msm_io_w(val, csic_dev->base + MIPI_PHY_D0_CONTROL2);
+ msm_io_w(val, csic_dev->base + MIPI_PHY_D1_CONTROL2);
+ msm_io_w(val, csic_dev->base + MIPI_PHY_D2_CONTROL2);
+ msm_io_w(val, csic_dev->base + MIPI_PHY_D3_CONTROL2);
+ CDBG("%s MIPI_PHY_CL_CONTROL val=0x%x\n", __func__, val);
+ msm_io_w(val, csic_dev->base + MIPI_PHY_CL_CONTROL);
+ msleep(20);
+ val = msm_io_r(csic_dev->base + MIPI_PHY_D1_CONTROL);
+ val &=
+ ~((0x1 << MIPI_PHY_D1_CONTROL_MIPI_CLK_PHY_SHUTDOWNB_SHFT)
+ |(0x1 << MIPI_PHY_D1_CONTROL_MIPI_DATA_PHY_SHUTDOWNB_SHFT));
+ CDBG("%s MIPI_PHY_D1_CONTROL val=0x%x\n", __func__, val);
+ msm_io_w(val, csic_dev->base + MIPI_PHY_D1_CONTROL);
+ usleep_range(5000, 6000);
+ msm_io_w(0x0, csic_dev->base + MIPI_INTERRUPT_MASK);
+ msm_io_w(0x0, csic_dev->base + MIPI_INTERRUPT_STATUS);
+ msm_io_w(MIPI_PROTOCOL_CONTROL_SW_RST_BMSK,
+ csic_dev->base + MIPI_PROTOCOL_CONTROL);
+
+ msm_io_w(0xE400, csic_dev->base + MIPI_CAMERA_CNTL);
+ }
+}
+
static int msm_csic_release(struct v4l2_subdev *sd)
{
struct csic_device *csic_dev;
csic_dev = v4l2_get_subdevdata(sd);
+ msm_csic_disable(sd);
#if DBG_CSIC
disable_irq(csic_dev->irq->start);
#endif
- pr_info("msm_cam_clk_enable: disble csi_pclk, csi_clk, csi_vfe_clk\n");
- msm_cam_clk_enable(&csic_dev->pdev->dev, csic_clk_info,
- csic_dev->csic_clk, ARRAY_SIZE(csic_clk_info), 0);
+ if (csic_dev->hw_version == CSIC_8X) {
+ msm_cam_clk_enable(&csic_dev->pdev->dev, csic_8x_clk_info,
+ csic_dev->csic_clk, ARRAY_SIZE(csic_8x_clk_info), 0);
+ } else if (csic_dev->hw_version == CSIC_7X) {
+ msm_cam_clk_enable(&csic_dev->pdev->dev, csic_7x_clk_info,
+ csic_dev->csic_clk, ARRAY_SIZE(csic_7x_clk_info), 0);
+ }
iounmap(csic_dev->base);
+ csic_dev->base = NULL;
return 0;
}
@@ -365,7 +417,7 @@
}
rc = request_irq(new_csic_dev->irq->start, msm_csic_irq,
- IRQF_TRIGGER_HIGH, "csic", new_csic_dev);
+ IRQF_TRIGGER_HIGH, "csic", new_csic_dev);
if (rc < 0) {
release_mem_region(new_csic_dev->mem->start,
resource_size(new_csic_dev->mem));
@@ -374,20 +426,6 @@
goto csic_no_resource;
}
disable_irq(new_csic_dev->irq->start);
- pr_info("msm_cam_clk_enable: enable csi_pclk\n");
- msm_cam_clk_enable(&pdev->dev, &csic_clk_info[2],
- new_csic_dev->csic_clk, 1, 1);
- new_csic_dev->base = ioremap(new_csic_dev->mem->start,
- resource_size(new_csic_dev->mem));
- if (!new_csic_dev->base) {
- rc = -ENOMEM;
- goto csic_no_resource;
- }
-
- msm_io_w(MIPI_PWR_CNTL_DIS, new_csic_dev->base + MIPI_PWR_CNTL_DIS);
- pr_info("msm_cam_clk_enable: disable csi_pclk\n");
- msm_cam_clk_enable(&pdev->dev, &csic_clk_info[2],
- new_csic_dev->csic_clk, 1, 0);
iounmap(new_csic_dev->base);
new_csic_dev->pdev = pdev;
diff --git a/drivers/media/video/msm/csi/msm_csic.h b/drivers/media/video/msm/csi/msm_csic.h
index 08dde52..177e9d1 100644
--- a/drivers/media/video/msm/csi/msm_csic.h
+++ b/drivers/media/video/msm/csi/msm_csic.h
@@ -17,6 +17,9 @@
#include <linux/io.h>
#include <media/v4l2-subdev.h>
+#define CSIC_7X 0x1
+#define CSIC_8X (0x1 << 1)
+
struct csic_device {
struct platform_device *pdev;
struct v4l2_subdev subdev;
diff --git a/drivers/media/video/msm/io/msm_io_util.c b/drivers/media/video/msm/io/msm_io_util.c
index a04d6fd..cc6bab2 100644
--- a/drivers/media/video/msm/io/msm_io_util.c
+++ b/drivers/media/video/msm/io/msm_io_util.c
@@ -111,15 +111,15 @@
curr_vreg->reg_name);
goto vreg_set_voltage_fail;
}
- if (curr_vreg->op_mode) {
+ if (curr_vreg->op_mode >= 0) {
rc = regulator_set_optimum_mode(
reg_ptr[i],
curr_vreg->op_mode);
if (rc < 0) {
- pr_err("%s: %s set optimum"
- "mode failed\n",
- __func__,
- curr_vreg->reg_name);
+ pr_err(
+ "%s: %s set optimum mode failed\n",
+ __func__,
+ curr_vreg->reg_name);
goto vreg_set_opt_mode_fail;
}
}
@@ -130,9 +130,10 @@
curr_vreg = &cam_vreg[i];
if (reg_ptr[i]) {
if (curr_vreg->type == REG_LDO) {
- if (curr_vreg->op_mode)
+ if (curr_vreg->op_mode >= 0) {
regulator_set_optimum_mode(
reg_ptr[i], 0);
+ }
regulator_set_voltage(
reg_ptr[i], 0, curr_vreg->
max_voltage);
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index d12d65e..44e260c 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -1440,6 +1440,10 @@
pr_err("%s NULL pointer passed in!\n", __func__);
return rc;
}
+ if (!g_server_dev.use_count) {
+ pr_err("%s: error, daemon not yet started.", __func__);
+ return -EINVAL;
+ }
mutex_lock(&pcam->vid_lock);
for (i = 0; i < MSM_DEV_INST_MAX; i++) {
if (pcam->dev_inst[i] == NULL)
@@ -1633,6 +1637,10 @@
pr_err("%s NULL pointer of camera device!\n", __func__);
return -EINVAL;
}
+ if (!g_server_dev.use_count) {
+ pr_err("%s: error, daemon not yet started.", __func__);
+ return -EINVAL;
+ }
mutex_lock(&pcam->vid_lock);
diff --git a/drivers/media/video/msm/msm_io_vfe31_v4l2.c b/drivers/media/video/msm/msm_io_vfe31_v4l2.c
new file mode 100644
index 0000000..03810f4
--- /dev/null
+++ b/drivers/media/video/msm/msm_io_vfe31_v4l2.c
@@ -0,0 +1,408 @@
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/regulator/consumer.h>
+#include <mach/gpio.h>
+#include <mach/board.h>
+#include <mach/camera.h>
+#include <mach/vreg.h>
+#include <mach/camera.h>
+#include <mach/clk.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+
+#include <linux/pm_qos_params.h>
+
+/* AXI rates in KHz */
+#define MSM_AXI_QOS_PREVIEW 192000
+#define MSM_AXI_QOS_SNAPSHOT 192000
+#define MSM_AXI_QOS_RECORDING 192000
+
+#define BUFF_SIZE_128 128
+
+static struct clk *camio_jpeg_clk;
+static struct clk *camio_vfe_clk;
+static struct clk *camio_jpeg_pclk;
+static struct clk *camio_vpe_clk;
+static struct clk *camio_vpe_pclk;
+static struct regulator *fs_ijpeg;
+static struct regulator *fs_vpe;
+
+static int vpe_clk_rate;
+void msm_io_w(u32 data, void __iomem *addr)
+{
+ CDBG("%s: %08x %08x\n", __func__, (int) (addr), (data));
+ writel_relaxed((data), (addr));
+}
+
+void msm_io_w_mb(u32 data, void __iomem *addr)
+{
+ CDBG("%s: %08x %08x\n", __func__, (int) (addr), (data));
+ wmb();
+ writel_relaxed((data), (addr));
+ wmb();
+}
+
+u32 msm_io_r(void __iomem *addr)
+{
+ uint32_t data = readl_relaxed(addr);
+ CDBG("%s: %08x %08x\n", __func__, (int) (addr), (data));
+ return data;
+}
+
+u32 msm_io_r_mb(void __iomem *addr)
+{
+ uint32_t data;
+ rmb();
+ data = readl_relaxed(addr);
+ rmb();
+ CDBG("%s: %08x %08x\n", __func__, (int) (addr), (data));
+ return data;
+}
+
+void msm_io_memcpy_toio(void __iomem *dest_addr,
+ void __iomem *src_addr, u32 len)
+{
+ int i;
+ u32 *d = (u32 *) dest_addr;
+ u32 *s = (u32 *) src_addr;
+ /* memcpy_toio does not work. Use writel for now */
+ for (i = 0; i < len; i++)
+ writel_relaxed(*s++, d++);
+}
+
+void msm_io_dump(void __iomem *addr, int size)
+{
+ char line_str[BUFF_SIZE_128], *p_str;
+ int i;
+ u32 *p = (u32 *) addr;
+ u32 data;
+ CDBG("%s: %p %d\n", __func__, addr, size);
+ line_str[0] = '\0';
+ p_str = line_str;
+ for (i = 0; i < size/4; i++) {
+ if (i % 4 == 0) {
+ snprintf(p_str, 12, "%08x: ", (u32) p);
+ p_str += 10;
+ }
+ data = readl_relaxed(p++);
+ snprintf(p_str, 12, "%08x ", data);
+ p_str += 9;
+ if ((i + 1) % 4 == 0) {
+ CDBG("%s\n", line_str);
+ line_str[0] = '\0';
+ p_str = line_str;
+ }
+ }
+ if (line_str[0] != '\0')
+ CDBG("%s\n", line_str);
+}
+
+void msm_io_memcpy(void __iomem *dest_addr, void __iomem *src_addr, u32 len)
+{
+ CDBG("%s: %p %p %d\n", __func__, dest_addr, src_addr, len);
+ msm_io_memcpy_toio(dest_addr, src_addr, len / 4);
+ msm_io_dump(dest_addr, len);
+}
+
+int msm_camio_clk_enable(enum msm_camio_clk_type clktype)
+{
+ int rc = 0;
+ struct clk *clk = NULL;
+
+ switch (clktype) {
+ case CAMIO_JPEG_CLK:
+ camio_jpeg_clk =
+ clk = clk_get(NULL, "ijpeg_clk");
+ rc = clk_set_rate(clk, 228571000);
+ if (rc < 0)
+ rc = clk_set_rate(clk, 153600000);
+ break;
+
+ case CAMIO_JPEG_PCLK:
+ camio_jpeg_pclk =
+ clk = clk_get(NULL, "ijpeg_pclk");
+ break;
+
+ case CAMIO_VPE_CLK:
+ camio_vpe_clk =
+ clk = clk_get(NULL, "vpe_clk");
+ vpe_clk_rate = clk_round_rate(camio_vpe_clk, vpe_clk_rate);
+ clk_set_rate(camio_vpe_clk, vpe_clk_rate);
+ break;
+
+ case CAMIO_VPE_PCLK:
+ camio_vpe_pclk =
+ clk = clk_get(NULL, "vpe_pclk");
+ break;
+
+ default:
+ break;
+ }
+
+ if (!IS_ERR(clk)) {
+ clk_prepare(clk);
+ clk_enable(clk);
+ } else {
+ rc = -1;
+ }
+ return rc;
+}
+
+int msm_camio_clk_disable(enum msm_camio_clk_type clktype)
+{
+ int rc = 0;
+ struct clk *clk = NULL;
+
+ switch (clktype) {
+ case CAMIO_JPEG_CLK:
+ clk = camio_jpeg_clk;
+ break;
+
+ case CAMIO_JPEG_PCLK:
+ clk = camio_jpeg_pclk;
+ break;
+
+ case CAMIO_VPE_CLK:
+ clk = camio_vpe_clk;
+ break;
+
+ case CAMIO_VPE_PCLK:
+ clk = camio_vpe_pclk;
+ break;
+
+ default:
+ break;
+ }
+
+ if (!IS_ERR(clk)) {
+ clk_disable(clk);
+ clk_unprepare(clk);
+ clk_put(clk);
+ } else {
+ rc = -1;
+ }
+
+ return rc;
+}
+
+int msm_camio_vfe_clk_rate_set(int rate)
+{
+ int rc = 0;
+ struct clk *clk = camio_vfe_clk;
+ if (rate > clk_get_rate(clk))
+ rc = clk_set_rate(clk, rate);
+ return rc;
+}
+
+void msm_camio_clk_rate_set_2(struct clk *clk, int rate)
+{
+ clk_set_rate(clk, rate);
+}
+
+int msm_camio_jpeg_clk_disable(void)
+{
+ int rc = 0;
+ if (fs_ijpeg) {
+ rc = regulator_disable(fs_ijpeg);
+ if (rc < 0) {
+ CDBG("%s: Regulator disable failed %d\n", __func__, rc);
+ return rc;
+ }
+ regulator_put(fs_ijpeg);
+ }
+ rc = msm_camio_clk_disable(CAMIO_JPEG_PCLK);
+ if (rc < 0)
+ return rc;
+ rc = msm_camio_clk_disable(CAMIO_JPEG_CLK);
+ CDBG("%s: exit %d\n", __func__, rc);
+ return rc;
+}
+
+int msm_camio_jpeg_clk_enable(void)
+{
+ int rc = 0;
+ rc = msm_camio_clk_enable(CAMIO_JPEG_CLK);
+ if (rc < 0)
+ return rc;
+ rc = msm_camio_clk_enable(CAMIO_JPEG_PCLK);
+ if (rc < 0)
+ return rc;
+ fs_ijpeg = regulator_get(NULL, "fs_ijpeg");
+ if (IS_ERR(fs_ijpeg)) {
+ CDBG("%s: Regulator FS_IJPEG get failed %ld\n", __func__,
+ PTR_ERR(fs_ijpeg));
+ fs_ijpeg = NULL;
+ } else if (regulator_enable(fs_ijpeg)) {
+ CDBG("%s: Regulator FS_IJPEG enable failed\n", __func__);
+ regulator_put(fs_ijpeg);
+ }
+ CDBG("%s: exit %d\n", __func__, rc);
+ return rc;
+}
+
+int msm_camio_vpe_clk_disable(void)
+{
+ int rc = 0;
+ if (fs_vpe) {
+ regulator_disable(fs_vpe);
+ regulator_put(fs_vpe);
+ }
+
+ rc = msm_camio_clk_disable(CAMIO_VPE_CLK);
+ if (rc < 0)
+ return rc;
+ rc = msm_camio_clk_disable(CAMIO_VPE_PCLK);
+ return rc;
+}
+
+int msm_camio_vpe_clk_enable(uint32_t clk_rate)
+{
+ int rc = 0;
+ fs_vpe = regulator_get(NULL, "fs_vpe");
+ if (IS_ERR(fs_vpe)) {
+ CDBG("%s: Regulator FS_VPE get failed %ld\n", __func__,
+ PTR_ERR(fs_vpe));
+ fs_vpe = NULL;
+ } else if (regulator_enable(fs_vpe)) {
+ CDBG("%s: Regulator FS_VPE enable failed\n", __func__);
+ regulator_put(fs_vpe);
+ }
+
+ vpe_clk_rate = clk_rate;
+ rc = msm_camio_clk_enable(CAMIO_VPE_CLK);
+ if (rc < 0)
+ return rc;
+
+ rc = msm_camio_clk_enable(CAMIO_VPE_PCLK);
+ return rc;
+}
+
+void msm_camio_vfe_blk_reset(void)
+{
+ return;
+}
+
+static void msm_camio_axi_cfg(enum msm_bus_perf_setting perf_setting)
+{
+ switch (perf_setting) {
+ case S_INIT:
+ add_axi_qos();
+ break;
+ case S_PREVIEW:
+ update_axi_qos(MSM_AXI_QOS_PREVIEW);
+ break;
+ case S_VIDEO:
+ update_axi_qos(MSM_AXI_QOS_RECORDING);
+ break;
+ case S_CAPTURE:
+ update_axi_qos(MSM_AXI_QOS_SNAPSHOT);
+ break;
+ case S_DEFAULT:
+ update_axi_qos(PM_QOS_DEFAULT_VALUE);
+ break;
+ case S_EXIT:
+ release_axi_qos();
+ break;
+ default:
+ CDBG("%s: INVALID CASE\n", __func__);
+ }
+}
+
+void msm_camio_bus_scale_cfg(struct msm_bus_scale_pdata *cam_bus_scale_table,
+ enum msm_bus_perf_setting perf_setting)
+{
+ static uint32_t bus_perf_client;
+ int rc = 0;
+ if (cam_bus_scale_table == NULL) {
+ msm_camio_axi_cfg(perf_setting);
+ return;
+ }
+
+ switch (perf_setting) {
+ case S_INIT:
+ bus_perf_client =
+ msm_bus_scale_register_client(cam_bus_scale_table);
+ if (!bus_perf_client) {
+ pr_err("%s: Registration Failed!!!\n", __func__);
+ bus_perf_client = 0;
+ return;
+ }
+ CDBG("%s: S_INIT rc = %u\n", __func__, bus_perf_client);
+ break;
+ case S_EXIT:
+ if (bus_perf_client) {
+ CDBG("%s: S_EXIT\n", __func__);
+ msm_bus_scale_unregister_client(bus_perf_client);
+ } else
+ pr_err("%s: Bus Client NOT Registered!!!\n", __func__);
+ break;
+ case S_PREVIEW:
+ if (bus_perf_client) {
+ rc = msm_bus_scale_client_update_request(
+ bus_perf_client, 1);
+ CDBG("%s: S_PREVIEW rc = %d\n", __func__, rc);
+ } else
+ pr_err("%s: Bus Client NOT Registered!!!\n", __func__);
+ break;
+ case S_VIDEO:
+ if (bus_perf_client) {
+ rc = msm_bus_scale_client_update_request(
+ bus_perf_client, 2);
+ CDBG("%s: S_VIDEO rc = %d\n", __func__, rc);
+ } else
+ pr_err("%s: Bus Client NOT Registered!!!\n", __func__);
+ break;
+ case S_CAPTURE:
+ if (bus_perf_client) {
+ rc = msm_bus_scale_client_update_request(
+ bus_perf_client, 3);
+ CDBG("%s: S_CAPTURE rc = %d\n", __func__, rc);
+ } else
+ pr_err("%s: Bus Client NOT Registered!!!\n", __func__);
+ break;
+
+ case S_ZSL:
+ if (bus_perf_client) {
+ rc = msm_bus_scale_client_update_request(
+ bus_perf_client, 4);
+ CDBG("%s: S_ZSL rc = %d\n", __func__, rc);
+ } else
+ pr_err("%s: Bus Client NOT Registered!!!\n", __func__);
+ break;
+ case S_STEREO_VIDEO:
+ if (bus_perf_client) {
+ rc = msm_bus_scale_client_update_request(
+ bus_perf_client, 5);
+ CDBG("%s: S_STEREO_VIDEO rc = %d\n", __func__, rc);
+ } else
+ pr_err("%s: Bus Client NOT Registered!!!\n", __func__);
+ break;
+ case S_STEREO_CAPTURE:
+ if (bus_perf_client) {
+ rc = msm_bus_scale_client_update_request(
+ bus_perf_client, 6);
+ CDBG("%s: S_STEREO_VIDEO rc = %d\n", __func__, rc);
+ } else
+ pr_err("%s: Bus Client NOT Registered!!!\n", __func__);
+ break;
+ case S_DEFAULT:
+ break;
+ default:
+ pr_warning("%s: INVALID CASE\n", __func__);
+ }
+}
+
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 001e02a..43c25b5 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -197,6 +197,8 @@
/* sensor_type needed to add YUV/SOC in probing */
info.sensor_type = sdata->sensor_type;
info.mount_angle = sdata->sensor_platform_info->mount_angle;
+ info.actuator_enabled = sdata->actuator_info ? 1 : 0;
+ info.strobe_flash_enabled = sdata->strobe_flash_data ? 1 : 0;
/* copy back to user space */
if (copy_to_user((void *)arg,
&info,
@@ -230,16 +232,18 @@
rc = v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
VIDIOC_MSM_ISPIF_CFG, &ispif_params);
- if (rc < 0)
- return rc;
+ } else {
+ pr_err("%s: invalid ispif_sdev\n", __func__);
}
break;
case NOTIFY_ISPIF_STREAM:
/* call ISPIF stream on/off */
- rc = v4l2_subdev_call(p_mctl->ispif_sdev, video,
- s_stream, (int)arg);
- if (rc < 0)
- return rc;
+ if (p_mctl->ispif_sdev) {
+ rc = v4l2_subdev_call(p_mctl->ispif_sdev, video,
+ s_stream, (int)arg);
+ } else {
+ pr_err("%s: invalid ispif_sdev\n", __func__);
+ }
break;
case NOTIFY_ISP_MSG_EVT:
@@ -251,29 +255,56 @@
if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_notify) {
rc = p_mctl->isp_sdev->isp_notify(
p_mctl->isp_sdev->sd, notification, arg);
+ } else {
+ pr_err("%s: invalid isp_sdev\n", __func__);
}
+
break;
case NOTIFY_VPE_MSG_EVT:
if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_notify) {
rc = p_mctl->isp_sdev->isp_notify(
p_mctl->isp_sdev->sd_vpe, notification, arg);
+ } else {
+ pr_err("%s: invalid isp_sdev\n", __func__);
}
+
break;
case NOTIFY_PCLK_CHANGE:
- rc = v4l2_subdev_call(p_mctl->isp_sdev->sd, video,
- s_crystal_freq, *(uint32_t *)arg, 0);
+ if (p_mctl->isp_sdev && p_mctl->isp_sdev->sd) {
+ rc = v4l2_subdev_call(p_mctl->isp_sdev->sd, video,
+ s_crystal_freq, *(uint32_t *)arg, 0);
+ } else {
+ pr_err("%s: invalid ispif_sdev\n", __func__);
+ }
+
break;
case NOTIFY_CSIPHY_CFG:
- rc = v4l2_subdev_call(p_mctl->csiphy_sdev,
- core, ioctl, VIDIOC_MSM_CSIPHY_CFG, arg);
+ if (p_mctl->csiphy_sdev) {
+ rc = v4l2_subdev_call(p_mctl->csiphy_sdev,
+ core, ioctl, VIDIOC_MSM_CSIPHY_CFG,
+ arg);
+ } else {
+ pr_err("%s: invalid csiphy_sdev\n", __func__);
+ }
+
break;
case NOTIFY_CSID_CFG:
- rc = v4l2_subdev_call(p_mctl->csid_sdev,
- core, ioctl, VIDIOC_MSM_CSID_CFG, arg);
+ if (p_mctl->csid_sdev) {
+ rc = v4l2_subdev_call(p_mctl->csid_sdev,
+ core, ioctl, VIDIOC_MSM_CSID_CFG, arg);
+ } else {
+ pr_err("%s: invalid csid_sdev\n", __func__);
+ }
+
break;
case NOTIFY_CSIC_CFG:
- rc = v4l2_subdev_call(p_mctl->csic_sdev,
- core, ioctl, VIDIOC_MSM_CSIC_CFG, arg);
+ if (p_mctl->csic_sdev) {
+ rc = v4l2_subdev_call(p_mctl->csic_sdev,
+ core, ioctl, VIDIOC_MSM_CSIC_CFG, arg);
+ } else {
+ pr_err("%s: invalid csic_sdev\n", __func__);
+ }
+
break;
default:
break;
@@ -630,6 +661,22 @@
goto msm_open_done;
}
+ /* then sensor - move sub dev later*/
+ rc = v4l2_subdev_call(p_mctl->sensor_sdev, core, s_power, 1);
+
+ if (rc < 0) {
+ pr_err("%s: isp init failed: %d\n", __func__, rc);
+ goto msm_open_done;
+ }
+ if (sync->actctrl.a_power_up)
+ rc = sync->actctrl.a_power_up(
+ sync->sdata->actuator_info);
+
+ if (rc < 0) {
+ pr_err("%s: act power failed:%d\n", __func__, rc);
+ goto msm_open_done;
+ }
+
if (camdev->is_csiphy) {
rc = v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
VIDIOC_MSM_CSIPHY_INIT, NULL);
@@ -681,22 +728,6 @@
}
}
- /* then sensor - move sub dev later*/
- rc = v4l2_subdev_call(p_mctl->sensor_sdev, core, s_power, 1);
-
- if (rc < 0) {
- pr_err("%s: isp init failed: %d\n", __func__, rc);
- goto msm_open_done;
- }
- if (sync->actctrl.a_power_up)
- rc = sync->actctrl.a_power_up(
- sync->sdata->actuator_info);
-
- if (rc < 0) {
- pr_err("%s: act power failed:%d\n", __func__, rc);
- goto msm_open_done;
- }
-
if (camdev->is_ispif) {
pm_qos_add_request(&p_mctl->pm_qos_req_list,
PM_QOS_CPU_DMA_LATENCY,
@@ -726,6 +757,11 @@
VIDIOC_MSM_ISPIF_RELEASE, NULL);
}
+ if (camdev->is_csic) {
+ v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
+ VIDIOC_MSM_CSIC_RELEASE, NULL);
+ }
+
if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_release)
p_mctl->isp_sdev->isp_release(&p_mctl->sync,
p_mctl->gemini_sdev);
@@ -735,26 +771,22 @@
VIDIOC_MSM_CSID_RELEASE, NULL);
}
- if (camdev->is_csic) {
- v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
- VIDIOC_MSM_CSIC_RELEASE, NULL);
- }
-
if (camdev->is_csiphy) {
v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
VIDIOC_MSM_CSIPHY_RELEASE, NULL);
}
- if (p_mctl->sync.actctrl.a_power_down)
- p_mctl->sync.actctrl.a_power_down(
- p_mctl->sync.sdata->actuator_info);
-
- v4l2_subdev_call(p_mctl->sensor_sdev, core, s_power, 0);
if (camdev->is_ispif) {
pm_qos_update_request(&p_mctl->pm_qos_req_list,
PM_QOS_DEFAULT_VALUE);
pm_qos_remove_request(&p_mctl->pm_qos_req_list);
}
+ if (p_mctl->sync.actctrl.a_power_down)
+ p_mctl->sync.actctrl.a_power_down(
+ p_mctl->sync.sdata->actuator_info);
+
+ v4l2_subdev_call(p_mctl->sensor_sdev, core, s_power, 0);
+
wake_unlock(&p_mctl->sync.wake_lock);
return rc;
}
@@ -854,10 +886,16 @@
{
int rc = -EINVAL, i;
/* get the video device */
- struct msm_cam_v4l2_device *pcam = video_drvdata(f);
+ struct msm_cam_v4l2_device *pcam = NULL;
struct msm_cam_v4l2_dev_inst *pcam_inst;
D("%s : E ", __func__);
+ if (f == NULL) {
+ pr_err("%s :: cannot open video driver data", __func__);
+ return rc;
+ }
+ pcam = video_drvdata(f);
+
if (!pcam) {
pr_err("%s NULL pointer passed in!\n", __func__);
return rc;
@@ -886,7 +924,7 @@
D("%s pcam_inst %p my_index = %d\n", __func__,
pcam_inst, pcam_inst->my_index);
- D("%s for %s\n", __func__, pcam->pdev->name);
+ D("%s for %s\n", __func__, pcam->mctl.sensor_sdev->name);
rc = msm_setup_v4l2_event_queue(&pcam_inst->eventHandle,
pcam->mctl_node.pvdev);
if (rc < 0) {
@@ -988,12 +1026,25 @@
static int msm_mctl_v4l2_querycap(struct file *f, void *pctx,
struct v4l2_capability *pcaps)
{
- struct msm_cam_v4l2_device *pcam = video_drvdata(f);
+ struct msm_cam_v4l2_device *pcam;
+
+ if (f == NULL) {
+ pr_err("%s :: NULL file pointer", __func__);
+ return -EINVAL;
+ }
+
+ pcam = video_drvdata(f);
D("%s\n", __func__);
WARN_ON(pctx != f->private_data);
- strlcpy(pcaps->driver, pcam->pdev->name, sizeof(pcaps->driver));
+ if (!pcam) {
+ pr_err("%s NULL pointer passed in!\n", __func__);
+ return -EINVAL;
+ }
+
+ strlcpy(pcaps->driver, pcam->mctl.sensor_sdev->name,
+ sizeof(pcaps->driver));
pcaps->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
return 0;
}
diff --git a/drivers/media/video/msm/msm_vfe31_v4l2.c b/drivers/media/video/msm/msm_vfe31_v4l2.c
new file mode 100644
index 0000000..ea181df
--- /dev/null
+++ b/drivers/media/video/msm/msm_vfe31_v4l2.c
@@ -0,0 +1,3850 @@
+/* Copyright (c) 2012 Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/uaccess.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/atomic.h>
+#include <linux/regulator/consumer.h>
+#include <linux/clk.h>
+#include <mach/clk.h>
+#include <mach/irqs.h>
+#include <mach/camera.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/msm_isp.h>
+
+#include "msm.h"
+#include "msm_vfe31_v4l2.h"
+
+atomic_t irq_cnt;
+
+#define BUFF_SIZE_128 128
+
+#define VFE31_AXI_OFFSET 0x0050
+#define vfe31_get_ch_ping_addr(chn) \
+ (msm_io_r(vfe31_ctrl->vfebase + 0x0050 + 0x18 * (chn)))
+#define vfe31_get_ch_pong_addr(chn) \
+ (msm_io_r(vfe31_ctrl->vfebase + 0x0050 + 0x18 * (chn) + 4))
+#define vfe31_get_ch_addr(ping_pong, chn) \
+ (((ping_pong) & (1 << (chn))) == 0 ? \
+ vfe31_get_ch_pong_addr(chn) : vfe31_get_ch_ping_addr(chn))
+
+#define vfe31_put_ch_ping_addr(chn, addr) \
+ (msm_io_w((addr), vfe31_ctrl->vfebase + 0x0050 + 0x18 * (chn)))
+#define vfe31_put_ch_pong_addr(chn, addr) \
+ (msm_io_w((addr), vfe31_ctrl->vfebase + 0x0050 + 0x18 * (chn) + 4))
+#define vfe31_put_ch_addr(ping_pong, chn, addr) \
+ (((ping_pong) & (1 << (chn))) == 0 ? \
+ vfe31_put_ch_pong_addr((chn), (addr)) : \
+ vfe31_put_ch_ping_addr((chn), (addr)))
+
+#define VFE_CLK_RATE 153600000
+#define CAMIF_CFG_RMSK 0x1fffff
+
+static struct vfe31_ctrl_type *vfe31_ctrl;
+static void *vfe_syncdata;
+static uint32_t vfe_clk_rate;
+
+struct vfe31_isr_queue_cmd {
+ struct list_head list;
+ uint32_t vfeInterruptStatus0;
+ uint32_t vfeInterruptStatus1;
+};
+
+/*TODO: Why is V32 reference in arch/arm/mach-msm/include/mach/camera.h?*/
+#define VFE_MSG_V31_START VFE_MSG_V32_START
+#define VFE_MSG_V31_CAPTURE VFE_MSG_V32_CAPTURE
+#define VFE_MSG_V31_JPEG_CAPTURE VFE_MSG_V32_JPEG_CAPTURE
+#define VFE_MSG_V31_START_RECORDING VFE_MSG_V32_START_RECORDING
+
+static struct vfe31_cmd_type vfe31_cmd[] = {
+/* 0*/ {VFE_CMD_DUMMY_0},
+ {VFE_CMD_SET_CLK},
+ {VFE_CMD_RESET},
+ {VFE_CMD_START},
+ {VFE_CMD_TEST_GEN_START},
+/* 5*/ {VFE_CMD_OPERATION_CFG, V31_OPERATION_CFG_LEN},
+ {VFE_CMD_AXI_OUT_CFG, V31_AXI_OUT_LEN, V31_AXI_OUT_OFF, 0xFF},
+ {VFE_CMD_CAMIF_CFG, V31_CAMIF_LEN, V31_CAMIF_OFF, 0xFF},
+ {VFE_CMD_AXI_INPUT_CFG},
+ {VFE_CMD_BLACK_LEVEL_CFG, V31_BLACK_LEVEL_LEN,
+ V31_BLACK_LEVEL_OFF,
+ 0xFF},
+/*10*/ {VFE_CMD_MESH_ROLL_OFF_CFG, V31_MESH_ROLL_OFF_CFG_LEN,
+ V31_MESH_ROLL_OFF_CFG_OFF, 0xFF},
+ {VFE_CMD_DEMUX_CFG, V31_DEMUX_LEN, V31_DEMUX_OFF, 0xFF},
+ {VFE_CMD_FOV_CFG, V31_FOV_LEN, V31_FOV_OFF, 0xFF},
+ {VFE_CMD_MAIN_SCALER_CFG, V31_MAIN_SCALER_LEN,
+ V31_MAIN_SCALER_OFF, 0xFF},
+ {VFE_CMD_WB_CFG, V31_WB_LEN, V31_WB_OFF, 0xFF},
+/*15*/ {VFE_CMD_COLOR_COR_CFG, V31_COLOR_COR_LEN, V31_COLOR_COR_OFF, 0xFF},
+ {VFE_CMD_RGB_G_CFG, V31_RGB_G_LEN, V31_RGB_G_OFF, 0xFF},
+ {VFE_CMD_LA_CFG, V31_LA_LEN, V31_LA_OFF, 0xFF },
+ {VFE_CMD_CHROMA_EN_CFG, V31_CHROMA_EN_LEN, V31_CHROMA_EN_OFF,
+ 0xFF},
+ {VFE_CMD_CHROMA_SUP_CFG, V31_CHROMA_SUP_LEN, V31_CHROMA_SUP_OFF,
+ 0xFF},
+/*20*/ {VFE_CMD_MCE_CFG, V31_MCE_LEN, V31_MCE_OFF, 0xFF},
+ {VFE_CMD_SK_ENHAN_CFG, V31_SCE_LEN, V31_SCE_OFF, 0xFF},
+ {VFE_CMD_ASF_CFG, V31_ASF_LEN, V31_ASF_OFF, 0xFF},
+ {VFE_CMD_S2Y_CFG, V31_S2Y_LEN, V31_S2Y_OFF, 0xFF},
+ {VFE_CMD_S2CbCr_CFG, V31_S2CbCr_LEN, V31_S2CbCr_OFF, 0xFF},
+/*25*/ {VFE_CMD_CHROMA_SUBS_CFG, V31_CHROMA_SUBS_LEN, V31_CHROMA_SUBS_OFF,
+ 0xFF},
+ {VFE_CMD_OUT_CLAMP_CFG, V31_OUT_CLAMP_LEN, V31_OUT_CLAMP_OFF,
+ 0xFF},
+ {VFE_CMD_FRAME_SKIP_CFG, V31_FRAME_SKIP_LEN, V31_FRAME_SKIP_OFF,
+ 0xFF},
+ {VFE_CMD_DUMMY_1},
+ {VFE_CMD_DUMMY_2},
+/*30*/ {VFE_CMD_DUMMY_3},
+ {VFE_CMD_UPDATE},
+ {VFE_CMD_BL_LVL_UPDATE, V31_BLACK_LEVEL_LEN,
+ V31_BLACK_LEVEL_OFF, 0xFF},
+ {VFE_CMD_DEMUX_UPDATE, V31_DEMUX_LEN, V31_DEMUX_OFF, 0xFF},
+ {VFE_CMD_FOV_UPDATE, V31_FOV_LEN, V31_FOV_OFF, 0xFF},
+/*35*/ {VFE_CMD_MAIN_SCALER_UPDATE, V31_MAIN_SCALER_LEN, V31_MAIN_SCALER_OFF,
+ 0xFF},
+ {VFE_CMD_WB_UPDATE, V31_WB_LEN, V31_WB_OFF, 0xFF},
+ {VFE_CMD_COLOR_COR_UPDATE, V31_COLOR_COR_LEN, V31_COLOR_COR_OFF,
+ 0xFF},
+ {VFE_CMD_RGB_G_UPDATE, V31_RGB_G_LEN, V31_CHROMA_EN_OFF, 0xFF},
+ {VFE_CMD_LA_UPDATE, V31_LA_LEN, V31_LA_OFF, 0xFF },
+/*40*/ {VFE_CMD_CHROMA_EN_UPDATE, V31_CHROMA_EN_LEN, V31_CHROMA_EN_OFF,
+ 0xFF},
+ {VFE_CMD_CHROMA_SUP_UPDATE, V31_CHROMA_SUP_LEN,
+ V31_CHROMA_SUP_OFF, 0xFF},
+ {VFE_CMD_MCE_UPDATE, V31_MCE_LEN, V31_MCE_OFF, 0xFF},
+ {VFE_CMD_SK_ENHAN_UPDATE, V31_SCE_LEN, V31_SCE_OFF, 0xFF},
+ {VFE_CMD_S2CbCr_UPDATE, V31_S2CbCr_LEN, V31_S2CbCr_OFF, 0xFF},
+/*45*/ {VFE_CMD_S2Y_UPDATE, V31_S2Y_LEN, V31_S2Y_OFF, 0xFF},
+ {VFE_CMD_ASF_UPDATE, V31_ASF_UPDATE_LEN, V31_ASF_OFF, 0xFF},
+ {VFE_CMD_FRAME_SKIP_UPDATE},
+ {VFE_CMD_CAMIF_FRAME_UPDATE},
+ {VFE_CMD_STATS_AF_UPDATE, V31_STATS_AF_LEN, V31_STATS_AF_OFF},
+/*50*/ {VFE_CMD_STATS_AE_UPDATE, V31_STATS_AE_LEN, V31_STATS_AE_OFF},
+ {VFE_CMD_STATS_AWB_UPDATE, V31_STATS_AWB_LEN,
+ V31_STATS_AWB_OFF},
+ {VFE_CMD_STATS_RS_UPDATE, V31_STATS_RS_LEN, V31_STATS_RS_OFF},
+ {VFE_CMD_STATS_CS_UPDATE, V31_STATS_CS_LEN, V31_STATS_CS_OFF},
+ {VFE_CMD_STATS_SKIN_UPDATE},
+/*55*/ {VFE_CMD_STATS_IHIST_UPDATE, V31_STATS_IHIST_LEN, V31_STATS_IHIST_OFF},
+ {VFE_CMD_DUMMY_4},
+ {VFE_CMD_EPOCH1_ACK},
+ {VFE_CMD_EPOCH2_ACK},
+ {VFE_CMD_START_RECORDING},
+/*60*/ {VFE_CMD_STOP_RECORDING},
+ {VFE_CMD_DUMMY_5},
+ {VFE_CMD_DUMMY_6},
+ {VFE_CMD_CAPTURE, V31_CAPTURE_LEN, 0xFF},
+ {VFE_CMD_DUMMY_7},
+/*65*/ {VFE_CMD_STOP},
+ {VFE_CMD_GET_HW_VERSION, V31_GET_HW_VERSION_LEN,
+ V31_GET_HW_VERSION_OFF},
+ {VFE_CMD_GET_FRAME_SKIP_COUNTS},
+ {VFE_CMD_OUTPUT1_BUFFER_ENQ},
+ {VFE_CMD_OUTPUT2_BUFFER_ENQ},
+/*70*/ {VFE_CMD_OUTPUT3_BUFFER_ENQ},
+ {VFE_CMD_JPEG_OUT_BUF_ENQ},
+ {VFE_CMD_RAW_OUT_BUF_ENQ},
+ {VFE_CMD_RAW_IN_BUF_ENQ},
+ {VFE_CMD_STATS_AF_ENQ},
+/*75*/ {VFE_CMD_STATS_AE_ENQ},
+ {VFE_CMD_STATS_AWB_ENQ},
+ {VFE_CMD_STATS_RS_ENQ},
+ {VFE_CMD_STATS_CS_ENQ},
+ {VFE_CMD_STATS_SKIN_ENQ},
+/*80*/ {VFE_CMD_STATS_IHIST_ENQ},
+ {VFE_CMD_DUMMY_8},
+ {VFE_CMD_JPEG_ENC_CFG},
+ {VFE_CMD_DUMMY_9},
+ {VFE_CMD_STATS_AF_START, V31_STATS_AF_LEN, V31_STATS_AF_OFF},
+/*85*/ {VFE_CMD_STATS_AF_STOP},
+ {VFE_CMD_STATS_AE_START, V31_STATS_AE_LEN, V31_STATS_AE_OFF},
+ {VFE_CMD_STATS_AE_STOP},
+ {VFE_CMD_STATS_AWB_START, V31_STATS_AWB_LEN, V31_STATS_AWB_OFF},
+ {VFE_CMD_STATS_AWB_STOP},
+/*90*/ {VFE_CMD_STATS_RS_START, V31_STATS_RS_LEN, V31_STATS_RS_OFF},
+ {VFE_CMD_STATS_RS_STOP},
+ {VFE_CMD_STATS_CS_START, V31_STATS_CS_LEN, V31_STATS_CS_OFF},
+ {VFE_CMD_STATS_CS_STOP},
+ {VFE_CMD_STATS_SKIN_START},
+/*95*/ {VFE_CMD_STATS_SKIN_STOP},
+ {VFE_CMD_STATS_IHIST_START,
+ V31_STATS_IHIST_LEN, V31_STATS_IHIST_OFF},
+ {VFE_CMD_STATS_IHIST_STOP},
+ {VFE_CMD_DUMMY_10},
+ {VFE_CMD_SYNC_TIMER_SETTING, V31_SYNC_TIMER_LEN,
+ V31_SYNC_TIMER_OFF},
+/*100*/ {VFE_CMD_ASYNC_TIMER_SETTING, V31_ASYNC_TIMER_LEN, V31_ASYNC_TIMER_OFF},
+ {VFE_CMD_LIVESHOT},
+ {VFE_CMD_LA_SETUP},
+ {VFE_CMD_LINEARIZATION_CFG},
+ {VFE_CMD_DEMOSAICV3},
+/*105*/ {VFE_CMD_DEMOSAICV3_ABCC_CFG},
+ {VFE_CMD_DEMOSAICV3_DBCC_CFG},
+ {VFE_CMD_DEMOSAICV3_DBPC_CFG, V31_DEMOSAICV3_DBPC_LEN,
+ V31_DEMOSAICV3_DBPC_CFG_OFF},
+ {VFE_CMD_DEMOSAICV3_ABF_CFG, V31_DEMOSAICV3_ABF_LEN,
+ V31_DEMOSAICV3_ABF_OFF},
+ {VFE_CMD_DEMOSAICV3_ABCC_UPDATE},
+/*110*/ {VFE_CMD_DEMOSAICV3_DBCC_UPDATE},
+ {VFE_CMD_DEMOSAICV3_DBPC_UPDATE, V31_DEMOSAICV3_DBPC_LEN,
+ V31_DEMOSAICV3_DBPC_CFG_OFF},
+ {VFE_CMD_XBAR_CFG},
+ {VFE_CMD_MODULE_CFG, V31_MODULE_CFG_LEN, V31_MODULE_CFG_OFF},
+ {VFE_CMD_ZSL},
+/*115*/ {VFE_CMD_LINEARIZATION_UPDATE},
+ {VFE_CMD_DEMOSAICV3_ABF_UPDATE, V31_DEMOSAICV3_ABF_LEN,
+ V31_DEMOSAICV3_ABF_OFF},
+ {VFE_CMD_CLF_CFG},
+ {VFE_CMD_CLF_LUMA_UPDATE},
+ {VFE_CMD_CLF_CHROMA_UPDATE},
+/*120*/ {VFE_CMD_PCA_ROLL_OFF_CFG},
+ {VFE_CMD_PCA_ROLL_OFF_UPDATE},
+ {VFE_CMD_GET_REG_DUMP},
+ {VFE_CMD_GET_LINEARIZATON_TABLE},
+ {VFE_CMD_GET_MESH_ROLLOFF_TABLE},
+/*125*/ {VFE_CMD_GET_PCA_ROLLOFF_TABLE},
+ {VFE_CMD_GET_RGB_G_TABLE},
+ {VFE_CMD_GET_LA_TABLE},
+ {VFE_CMD_DEMOSAICV3_UPDATE},
+};
+
+uint32_t vfe31_AXI_WM_CFG[] = {
+ 0x0000004C,
+ 0x00000064,
+ 0x0000007C,
+ 0x00000094,
+ 0x000000AC,
+ 0x000000C4,
+ 0x000000DC,
+};
+
+static const char * const vfe31_general_cmd[] = {
+ "DUMMY_0", /* 0 */
+ "SET_CLK",
+ "RESET",
+ "START",
+ "TEST_GEN_START",
+ "OPERATION_CFG", /* 5 */
+ "AXI_OUT_CFG",
+ "CAMIF_CFG",
+ "AXI_INPUT_CFG",
+ "BLACK_LEVEL_CFG",
+ "ROLL_OFF_CFG", /* 10 */
+ "DEMUX_CFG",
+ "FOV_CFG",
+ "MAIN_SCALER_CFG",
+ "WB_CFG",
+ "COLOR_COR_CFG", /* 15 */
+ "RGB_G_CFG",
+ "LA_CFG",
+ "CHROMA_EN_CFG",
+ "CHROMA_SUP_CFG",
+ "MCE_CFG", /* 20 */
+ "SK_ENHAN_CFG",
+ "ASF_CFG",
+ "S2Y_CFG",
+ "S2CbCr_CFG",
+ "CHROMA_SUBS_CFG", /* 25 */
+ "OUT_CLAMP_CFG",
+ "FRAME_SKIP_CFG",
+ "DUMMY_1",
+ "DUMMY_2",
+ "DUMMY_3", /* 30 */
+ "UPDATE",
+ "BL_LVL_UPDATE",
+ "DEMUX_UPDATE",
+ "FOV_UPDATE",
+ "MAIN_SCALER_UPDATE", /* 35 */
+ "WB_UPDATE",
+ "COLOR_COR_UPDATE",
+ "RGB_G_UPDATE",
+ "LA_UPDATE",
+ "CHROMA_EN_UPDATE", /* 40 */
+ "CHROMA_SUP_UPDATE",
+ "MCE_UPDATE",
+ "SK_ENHAN_UPDATE",
+ "S2CbCr_UPDATE",
+ "S2Y_UPDATE", /* 45 */
+ "ASF_UPDATE",
+ "FRAME_SKIP_UPDATE",
+ "CAMIF_FRAME_UPDATE",
+ "STATS_AF_UPDATE",
+ "STATS_AE_UPDATE", /* 50 */
+ "STATS_AWB_UPDATE",
+ "STATS_RS_UPDATE",
+ "STATS_CS_UPDATE",
+ "STATS_SKIN_UPDATE",
+ "STATS_IHIST_UPDATE", /* 55 */
+ "DUMMY_4",
+ "EPOCH1_ACK",
+ "EPOCH2_ACK",
+ "START_RECORDING",
+ "STOP_RECORDING", /* 60 */
+ "DUMMY_5",
+ "DUMMY_6",
+ "CAPTURE",
+ "DUMMY_7",
+ "STOP", /* 65 */
+ "GET_HW_VERSION",
+ "GET_FRAME_SKIP_COUNTS",
+ "OUTPUT1_BUFFER_ENQ",
+ "OUTPUT2_BUFFER_ENQ",
+ "OUTPUT3_BUFFER_ENQ", /* 70 */
+ "JPEG_OUT_BUF_ENQ",
+ "RAW_OUT_BUF_ENQ",
+ "RAW_IN_BUF_ENQ",
+ "STATS_AF_ENQ",
+ "STATS_AE_ENQ", /* 75 */
+ "STATS_AWB_ENQ",
+ "STATS_RS_ENQ",
+ "STATS_CS_ENQ",
+ "STATS_SKIN_ENQ",
+ "STATS_IHIST_ENQ", /* 80 */
+ "DUMMY_8",
+ "JPEG_ENC_CFG",
+ "DUMMY_9",
+ "STATS_AF_START",
+ "STATS_AF_STOP", /* 85 */
+ "STATS_AE_START",
+ "STATS_AE_STOP",
+ "STATS_AWB_START",
+ "STATS_AWB_STOP",
+ "STATS_RS_START", /* 90 */
+ "STATS_RS_STOP",
+ "STATS_CS_START",
+ "STATS_CS_STOP",
+ "STATS_SKIN_START",
+ "STATS_SKIN_STOP", /* 95 */
+ "STATS_IHIST_START",
+ "STATS_IHIST_STOP",
+ "DUMMY_10",
+ "SYNC_TIMER_SETTING",
+ "ASYNC_TIMER_SETTING", /* 100 */
+ "LIVESHOT",
+ "LA_SETUP",
+ "LINEARIZATION_CFG",
+ "DEMOSAICV3",
+ "DEMOSAICV3_ABCC_CFG", /* 105 */
+ "DEMOSAICV3_DBCC_CFG",
+ "DEMOSAICV3_DBPC_CFG",
+ "DEMOSAICV3_ABF_CFG",
+ "DEMOSAICV3_ABCC_UPDATE",
+ "DEMOSAICV3_DBCC_UPDATE", /* 110 */
+ "DEMOSAICV3_DBPC_UPDATE",
+ "XBAR_CFG",
+ "EZTUNE_CFG",
+ "V31_ZSL",
+ "LINEARIZATION_UPDATE", /*115*/
+ "DEMOSAICV3_ABF_UPDATE",
+ "CLF_CFG",
+ "CLF_LUMA_UPDATE",
+ "CLF_CHROMA_UPDATE",
+ "PCA_ROLL_OFF_CFG", /*120*/
+ "PCA_ROLL_OFF_UPDATE",
+ "GET_REG_DUMP",
+ "GET_LINEARIZATON_TABLE",
+ "GET_MESH_ROLLOFF_TABLE",
+ "GET_PCA_ROLLOFF_TABLE", /*125*/
+ "GET_RGB_G_TABLE",
+ "GET_LA_TABLE",
+ "DEMOSAICV3_UPDATE",
+};
+
+static void vfe31_stop(void)
+{
+ unsigned long flags;
+
+ atomic_set(&vfe31_ctrl->vstate, 0);
+
+ /* for reset hw modules, and send msg when reset_irq comes.*/
+ spin_lock_irqsave(&vfe31_ctrl->stop_flag_lock, flags);
+ vfe31_ctrl->stop_ack_pending = TRUE;
+ spin_unlock_irqrestore(&vfe31_ctrl->stop_flag_lock, flags);
+
+ /* disable all interrupts. */
+ /* in either continuous or snapshot mode, stop command can be issued
+ * at any time. stop camif immediately. */
+ msm_io_w_mb(CAMIF_COMMAND_STOP_IMMEDIATELY,
+ vfe31_ctrl->vfebase + VFE_CAMIF_COMMAND);
+
+ /* disable all interrupts. */
+ msm_io_w(VFE_DISABLE_ALL_IRQS,
+ vfe31_ctrl->vfebase + VFE_IRQ_MASK_0);
+ msm_io_w(VFE_DISABLE_ALL_IRQS,
+ vfe31_ctrl->vfebase + VFE_IRQ_MASK_1);
+
+ /* clear all pending interrupts*/
+ msm_io_w(VFE_CLEAR_ALL_IRQS,
+ vfe31_ctrl->vfebase + VFE_IRQ_CLEAR_0);
+ msm_io_w(VFE_CLEAR_ALL_IRQS,
+ vfe31_ctrl->vfebase + VFE_IRQ_CLEAR_1);
+ /* Ensure the write order while writing
+ to the command register using the barrier */
+ msm_io_w_mb(1,
+ vfe31_ctrl->vfebase + VFE_IRQ_CMD);
+
+ /* now enable only halt_irq & reset_irq */
+ msm_io_w(0xf0000000, /* this is for async timer. */
+ vfe31_ctrl->vfebase + VFE_IRQ_MASK_0);
+ msm_io_w(VFE_IMASK_WHILE_STOPPING_1,
+ vfe31_ctrl->vfebase + VFE_IRQ_MASK_1);
+
+ /* then apply axi halt command. */
+ msm_io_w_mb(AXI_HALT,
+ vfe31_ctrl->vfebase + VFE_AXI_CMD);
+
+ msm_io_w_mb(VFE_RESET_UPON_STOP_CMD,
+ vfe31_ctrl->vfebase + VFE_GLOBAL_RESET);
+}
+
+static void vfe31_subdev_notify(int id, int path)
+{
+ struct msm_vfe_resp *rp;
+ unsigned long flags;
+ spin_lock_irqsave(&vfe31_ctrl->sd_notify_lock, flags);
+ rp = msm_isp_sync_alloc(sizeof(struct msm_vfe_resp), GFP_ATOMIC);
+ if (!rp) {
+ CDBG("rp: cannot allocate buffer\n");
+ spin_unlock_irqrestore(&vfe31_ctrl->sd_notify_lock, flags);
+ return;
+ }
+ CDBG("vfe31_subdev_notify : msgId = %d\n", id);
+ rp->evt_msg.type = MSM_CAMERA_MSG;
+ rp->evt_msg.msg_id = path;
+ rp->type = id;
+ v4l2_subdev_notify(&vfe31_ctrl->subdev, NOTIFY_VFE_BUF_EVT, rp);
+ spin_unlock_irqrestore(&vfe31_ctrl->sd_notify_lock, flags);
+}
+
+static int vfe31_config_axi(int mode, uint32_t *ao)
+{
+ uint32_t *ch_info;
+ uint32_t *axi_cfg = ao+V31_AXI_RESERVED;
+ /* Update the corresponding write masters for each output*/
+ ch_info = axi_cfg + V31_AXI_CFG_LEN;
+ vfe31_ctrl->outpath.out0.ch0 = 0x0000FFFF & *ch_info;
+ vfe31_ctrl->outpath.out0.ch1 = 0x0000FFFF & (*ch_info++ >> 16);
+ vfe31_ctrl->outpath.out0.ch2 = 0x0000FFFF & *ch_info++;
+ vfe31_ctrl->outpath.out1.ch0 = 0x0000FFFF & *ch_info;
+ vfe31_ctrl->outpath.out1.ch1 = 0x0000FFFF & (*ch_info++ >> 16);
+ vfe31_ctrl->outpath.out1.ch2 = 0x0000FFFF & *ch_info++;
+ vfe31_ctrl->outpath.out2.ch0 = 0x0000FFFF & *ch_info;
+ vfe31_ctrl->outpath.out2.ch1 = 0x0000FFFF & (*ch_info++ >> 16);
+ vfe31_ctrl->outpath.out2.ch2 = 0x0000FFFF & *ch_info++;
+
+ switch (mode) {
+ case OUTPUT_PRIM:
+ vfe31_ctrl->outpath.output_mode =
+ VFE31_OUTPUT_MODE_PRIMARY;
+ break;
+ case OUTPUT_PRIM_ALL_CHNLS:
+ vfe31_ctrl->outpath.output_mode =
+ VFE31_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
+ break;
+ case OUTPUT_PRIM|OUTPUT_SEC:
+ vfe31_ctrl->outpath.output_mode =
+ VFE31_OUTPUT_MODE_PRIMARY;
+ vfe31_ctrl->outpath.output_mode |=
+ VFE31_OUTPUT_MODE_SECONDARY;
+ break;
+ case OUTPUT_PRIM|OUTPUT_SEC_ALL_CHNLS:
+ vfe31_ctrl->outpath.output_mode =
+ VFE31_OUTPUT_MODE_PRIMARY;
+ vfe31_ctrl->outpath.output_mode |=
+ VFE31_OUTPUT_MODE_SECONDARY_ALL_CHNLS;
+ break;
+ case OUTPUT_PRIM_ALL_CHNLS|OUTPUT_SEC:
+ vfe31_ctrl->outpath.output_mode =
+ VFE31_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
+ vfe31_ctrl->outpath.output_mode |=
+ VFE31_OUTPUT_MODE_SECONDARY;
+ break;
+ default:
+ pr_err("%s Invalid AXI mode %d ", __func__, mode);
+ return -EINVAL;
+ }
+
+ msm_io_memcpy(vfe31_ctrl->vfebase +
+ vfe31_cmd[VFE_CMD_AXI_OUT_CFG].offset, axi_cfg,
+ vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length - V31_AXI_CH_INF_LEN -
+ V31_AXI_RESERVED);
+ return 0;
+}
+
+static void vfe31_reset_internal_variables(void)
+{
+ unsigned long flags;
+ vfe31_ctrl->vfeImaskCompositePacked = 0;
+ /* state control variables */
+ vfe31_ctrl->start_ack_pending = FALSE;
+ atomic_set(&irq_cnt, 0);
+
+ spin_lock_irqsave(&vfe31_ctrl->stop_flag_lock, flags);
+ vfe31_ctrl->stop_ack_pending = FALSE;
+ spin_unlock_irqrestore(&vfe31_ctrl->stop_flag_lock, flags);
+
+ vfe31_ctrl->reset_ack_pending = FALSE;
+
+ spin_lock_irqsave(&vfe31_ctrl->update_ack_lock, flags);
+ vfe31_ctrl->update_ack_pending = FALSE;
+ spin_unlock_irqrestore(&vfe31_ctrl->update_ack_lock, flags);
+
+ vfe31_ctrl->recording_state = VFE_STATE_IDLE;
+ vfe31_ctrl->liveshot_state = VFE_STATE_IDLE;
+
+ atomic_set(&vfe31_ctrl->vstate, 0);
+
+ /* 0 for continuous mode, 1 for snapshot mode */
+ vfe31_ctrl->operation_mode = 0;
+ vfe31_ctrl->outpath.output_mode = 0;
+ vfe31_ctrl->vfe_capture_count = 0;
+
+ /* this is unsigned 32 bit integer. */
+ vfe31_ctrl->vfeFrameId = 0;
+ /* Stats control variables. */
+ memset(&(vfe31_ctrl->afStatsControl), 0,
+ sizeof(struct vfe_stats_control));
+
+ memset(&(vfe31_ctrl->awbStatsControl), 0,
+ sizeof(struct vfe_stats_control));
+
+ memset(&(vfe31_ctrl->aecStatsControl), 0,
+ sizeof(struct vfe_stats_control));
+
+ memset(&(vfe31_ctrl->ihistStatsControl), 0,
+ sizeof(struct vfe_stats_control));
+
+ memset(&(vfe31_ctrl->rsStatsControl), 0,
+ sizeof(struct vfe_stats_control));
+
+ memset(&(vfe31_ctrl->csStatsControl), 0,
+ sizeof(struct vfe_stats_control));
+
+ vfe31_ctrl->frame_skip_cnt = 31;
+ vfe31_ctrl->frame_skip_pattern = 0xffffffff;
+ vfe31_ctrl->snapshot_frame_cnt = 0;
+}
+
+static void vfe31_reset(void)
+{
+ vfe31_reset_internal_variables();
+ /* disable all interrupts. vfeImaskLocal is also reset to 0
+ * to begin with. */
+ msm_io_w(VFE_DISABLE_ALL_IRQS,
+ vfe31_ctrl->vfebase + VFE_IRQ_MASK_0);
+
+ msm_io_w(VFE_DISABLE_ALL_IRQS,
+ vfe31_ctrl->vfebase + VFE_IRQ_MASK_1);
+
+ /* clear all pending interrupts*/
+ msm_io_w(VFE_CLEAR_ALL_IRQS, vfe31_ctrl->vfebase + VFE_IRQ_CLEAR_0);
+ msm_io_w(VFE_CLEAR_ALL_IRQS, vfe31_ctrl->vfebase + VFE_IRQ_CLEAR_1);
+
+ /* Ensure the write order while writing
+ to the command register using the barrier */
+ msm_io_w_mb(1, vfe31_ctrl->vfebase + VFE_IRQ_CMD);
+
+ /* enable reset_ack interrupt. */
+ msm_io_w(VFE_IMASK_WHILE_STOPPING_1,
+ vfe31_ctrl->vfebase + VFE_IRQ_MASK_1);
+
+ /* Write to VFE_GLOBAL_RESET_CMD to reset the vfe hardware. Once reset
+ * is done, hardware interrupt will be generated. VFE ist processes
+ * the interrupt to complete the function call. Note that the reset
+ * function is synchronous. */
+
+ /* Ensure the write order while writing
+ to the command register using the barrier */
+ msm_io_w_mb(VFE_RESET_UPON_RESET_CMD,
+ vfe31_ctrl->vfebase + VFE_GLOBAL_RESET);
+}
+
+static int vfe31_operation_config(uint32_t *cmd)
+{
+ uint32_t *p = cmd;
+
+ vfe31_ctrl->operation_mode = *p;
+ vfe31_ctrl->stats_comp = *(++p);
+ vfe31_ctrl->hfr_mode = *(++p);
+
+ msm_io_w(*(++p), vfe31_ctrl->vfebase + VFE_CFG);
+ msm_io_w(*(++p), vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ msm_io_w(*(++p), vfe31_ctrl->vfebase + VFE_REALIGN_BUF);
+ msm_io_w(*(++p), vfe31_ctrl->vfebase + VFE_CHROMA_UP);
+ msm_io_w(*(++p), vfe31_ctrl->vfebase + VFE_STATS_CFG);
+ return 0;
+}
+
+static uint32_t vfe_stats_awb_buf_init(struct vfe_cmd_stats_buf *in)
+{
+ uint32_t *ptr = in->statsBuf;
+ uint32_t addr;
+
+ addr = ptr[0];
+ msm_io_w(addr, vfe31_ctrl->vfebase + VFE_BUS_STATS_AWB_WR_PING_ADDR);
+ addr = ptr[1];
+ msm_io_w(addr, vfe31_ctrl->vfebase + VFE_BUS_STATS_AWB_WR_PONG_ADDR);
+ vfe31_ctrl->awbStatsControl.nextFrameAddrBuf = in->statsBuf[2];
+ return 0;
+}
+
+static uint32_t vfe_stats_aec_buf_init(struct vfe_cmd_stats_buf *in)
+{
+ uint32_t *ptr = in->statsBuf;
+ uint32_t addr;
+
+ addr = ptr[0];
+ msm_io_w(addr, vfe31_ctrl->vfebase + VFE_BUS_STATS_AEC_WR_PING_ADDR);
+ addr = ptr[1];
+ msm_io_w(addr, vfe31_ctrl->vfebase + VFE_BUS_STATS_AEC_WR_PONG_ADDR);
+
+ vfe31_ctrl->aecStatsControl.nextFrameAddrBuf = in->statsBuf[2];
+ return 0;
+}
+
+static uint32_t vfe_stats_af_buf_init(struct vfe_cmd_stats_buf *in)
+{
+ uint32_t *ptr = in->statsBuf;
+ uint32_t addr;
+
+ addr = ptr[0];
+ msm_io_w(addr, vfe31_ctrl->vfebase + VFE_BUS_STATS_AF_WR_PING_ADDR);
+ addr = ptr[1];
+ msm_io_w(addr, vfe31_ctrl->vfebase + VFE_BUS_STATS_AF_WR_PONG_ADDR);
+
+ vfe31_ctrl->afStatsControl.nextFrameAddrBuf = in->statsBuf[2];
+ return 0;
+}
+
+static uint32_t vfe_stats_ihist_buf_init(struct vfe_cmd_stats_buf *in)
+{
+ uint32_t *ptr = in->statsBuf;
+ uint32_t addr;
+
+ addr = ptr[0];
+ msm_io_w(addr, vfe31_ctrl->vfebase + VFE_BUS_STATS_HIST_WR_PING_ADDR);
+ addr = ptr[1];
+ msm_io_w(addr, vfe31_ctrl->vfebase + VFE_BUS_STATS_HIST_WR_PONG_ADDR);
+
+ vfe31_ctrl->ihistStatsControl.nextFrameAddrBuf = in->statsBuf[2];
+ return 0;
+}
+
+static uint32_t vfe_stats_rs_buf_init(struct vfe_cmd_stats_buf *in)
+{
+ uint32_t *ptr = in->statsBuf;
+ uint32_t addr;
+
+ addr = ptr[0];
+ msm_io_w(addr, vfe31_ctrl->vfebase + VFE_BUS_STATS_RS_WR_PING_ADDR);
+ addr = ptr[1];
+ msm_io_w(addr, vfe31_ctrl->vfebase + VFE_BUS_STATS_RS_WR_PONG_ADDR);
+
+ vfe31_ctrl->rsStatsControl.nextFrameAddrBuf = in->statsBuf[2];
+ return 0;
+}
+
+static uint32_t vfe_stats_cs_buf_init(struct vfe_cmd_stats_buf *in)
+{
+ uint32_t *ptr = in->statsBuf;
+ uint32_t addr;
+
+ addr = ptr[0];
+ msm_io_w(addr, vfe31_ctrl->vfebase + VFE_BUS_STATS_CS_WR_PING_ADDR);
+ addr = ptr[1];
+ msm_io_w(addr, vfe31_ctrl->vfebase + VFE_BUS_STATS_CS_WR_PONG_ADDR);
+
+ vfe31_ctrl->csStatsControl.nextFrameAddrBuf = in->statsBuf[2];
+ return 0;
+}
+
+static void msm_io_dump2(void __iomem *addr, int size)
+{
+ char line_str[BUFF_SIZE_128], *p_str;
+ int i;
+ u32 *p = (u32 *) addr;
+ u32 data;
+ CDBG("%s: %p %d\n", __func__, addr, size);
+ line_str[0] = '\0';
+ p_str = line_str;
+ for (i = 0; i < size/4; i++) {
+ if (i % 4 == 0) {
+ snprintf(p_str, 12, "%08x: ", (u32) p);
+ p_str += 10;
+ }
+ data = readl_relaxed(p++);
+ snprintf(p_str, 12, "%08x ", data);
+ p_str += 9;
+ if ((i + 1) % 4 == 0) {
+ CDBG("%s\n", line_str);
+ line_str[0] = '\0';
+ p_str = line_str;
+ }
+ }
+ if (line_str[0] != '\0')
+ CDBG("%s\n", line_str);
+}
+
+static void vfe31_start_common(void)
+{
+ uint32_t irq_mask = 0x00E00021;
+ vfe31_ctrl->start_ack_pending = TRUE;
+ CDBG("VFE opertaion mode = 0x%x, output mode = 0x%x\n",
+ vfe31_ctrl->operation_mode, vfe31_ctrl->outpath.output_mode);
+ if (vfe31_ctrl->stats_comp)
+ irq_mask |= VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK;
+ else
+ irq_mask |= 0x000FE000;
+
+ msm_io_w(irq_mask, vfe31_ctrl->vfebase + VFE_IRQ_MASK_0);
+ msm_io_w(VFE_IMASK_WHILE_STOPPING_1,
+ vfe31_ctrl->vfebase + VFE_IRQ_MASK_1);
+
+ /* Ensure the write order while writing
+ to the command register using the barrier */
+ msm_io_w_mb(1, vfe31_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ msm_io_w_mb(1, vfe31_ctrl->vfebase + VFE_CAMIF_COMMAND);
+
+ msm_io_dump2(vfe31_ctrl->vfebase, vfe31_ctrl->register_total*4);
+ atomic_set(&vfe31_ctrl->vstate, 1);
+}
+
+static int vfe31_start_recording(void)
+{
+ struct msm_sync *sync = vfe_syncdata;
+ msm_camio_bus_scale_cfg(
+ sync->sdata->pdata->cam_bus_scale_table, S_VIDEO);
+ vfe31_ctrl->recording_state = VFE_STATE_START_REQUESTED;
+ msm_io_w_mb(1, vfe31_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ return 0;
+}
+
+static int vfe31_stop_recording(void)
+{
+ struct msm_sync *sync = vfe_syncdata;
+ vfe31_ctrl->recording_state = VFE_STATE_STOP_REQUESTED;
+ msm_io_w_mb(1, vfe31_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ msm_camio_bus_scale_cfg(
+ sync->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+ return 0;
+}
+
+static void vfe31_start_liveshot(void){
+ struct msm_sync* p_sync = (struct msm_sync *)vfe_syncdata;
+ if (p_sync)
+ p_sync->liveshot_enabled = true;
+
+ /* Hardcode 1 live snapshot for now. */
+ vfe31_ctrl->outpath.out0.capture_cnt = 1;
+ vfe31_ctrl->vfe_capture_count = vfe31_ctrl->outpath.out0.capture_cnt;
+
+ vfe31_ctrl->liveshot_state = VFE_STATE_START_REQUESTED;
+ msm_io_w_mb(1, vfe31_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+}
+
+static int vfe31_zsl(void)
+{
+ struct msm_sync *sync = vfe_syncdata;
+ uint32_t irq_comp_mask = 0;
+ /* capture command is valid for both idle and active state. */
+ irq_comp_mask =
+ msm_io_r(vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+
+ CDBG("%s:op mode %d O/P Mode %d\n", __func__,
+ vfe31_ctrl->operation_mode, vfe31_ctrl->outpath.output_mode);
+
+ if (vfe31_ctrl->outpath.output_mode & VFE31_OUTPUT_MODE_PRIMARY) {
+ irq_comp_mask |= ((0x1 << (vfe31_ctrl->outpath.out0.ch0)) |
+ (0x1 << (vfe31_ctrl->outpath.out0.ch1)));
+ } else if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+ irq_comp_mask |= ((0x1 << (vfe31_ctrl->outpath.out0.ch0)) |
+ (0x1 << (vfe31_ctrl->outpath.out0.ch1)) |
+ (0x1 << (vfe31_ctrl->outpath.out0.ch2)));
+ }
+
+ if (vfe31_ctrl->outpath.output_mode & VFE31_OUTPUT_MODE_SECONDARY) {
+ irq_comp_mask |= ((0x1 << (vfe31_ctrl->outpath.out1.ch0 + 8)) |
+ (0x1 << (vfe31_ctrl->outpath.out1.ch1 + 8)));
+ } else if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+ irq_comp_mask |= ((0x1 << (vfe31_ctrl->outpath.out1.ch0 + 8)) |
+ (0x1 << (vfe31_ctrl->outpath.out1.ch1 + 8)) |
+ (0x1 << (vfe31_ctrl->outpath.out1.ch2 + 8)));
+ }
+
+ if (vfe31_ctrl->outpath.output_mode & VFE31_OUTPUT_MODE_PRIMARY) {
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
+ } else if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch2]);
+ }
+
+ if (vfe31_ctrl->outpath.output_mode & VFE31_OUTPUT_MODE_SECONDARY) {
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch0]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch1]);
+ } else if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch0]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch1]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch2]);
+ }
+
+ msm_io_w(irq_comp_mask, vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+ vfe31_start_common();
+ msm_camio_bus_scale_cfg(
+ sync->sdata->pdata->cam_bus_scale_table, S_ZSL);
+
+ msm_io_w(1, vfe31_ctrl->vfebase + 0x18C);
+ msm_io_w(1, vfe31_ctrl->vfebase + 0x188);
+ return 0;
+}
+static int vfe31_capture_raw(uint32_t num_frames_capture)
+{
+ uint32_t irq_comp_mask = 0;
+ struct msm_sync* p_sync = (struct msm_sync *)vfe_syncdata;
+
+ vfe31_ctrl->outpath.out0.capture_cnt = num_frames_capture;
+ vfe31_ctrl->vfe_capture_count = num_frames_capture;
+
+ irq_comp_mask =
+ msm_io_r(vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+
+ if (vfe31_ctrl->outpath.output_mode & VFE31_OUTPUT_MODE_PRIMARY) {
+ irq_comp_mask |= (0x1 << (vfe31_ctrl->outpath.out0.ch0));
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
+ }
+
+ msm_io_w(irq_comp_mask, vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+ msm_camio_bus_scale_cfg(
+ p_sync->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
+ vfe31_start_common();
+ return 0;
+}
+
+static int vfe31_capture(uint32_t num_frames_capture)
+{
+ uint32_t irq_comp_mask = 0;
+ struct msm_sync* p_sync = (struct msm_sync *)vfe_syncdata;
+ if (p_sync) {
+ p_sync->snap_count = num_frames_capture;
+ p_sync->thumb_count = num_frames_capture;
+ }
+ /* capture command is valid for both idle and active state. */
+ vfe31_ctrl->outpath.out1.capture_cnt = num_frames_capture;
+ if (vfe31_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
+ vfe31_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN ||
+ vfe31_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB ||
+ vfe31_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) {
+ vfe31_ctrl->outpath.out0.capture_cnt =
+ num_frames_capture;
+ }
+
+ vfe31_ctrl->vfe_capture_count = num_frames_capture;
+ irq_comp_mask = msm_io_r(vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+
+ if (vfe31_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
+ vfe31_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB ||
+ vfe31_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN) {
+ if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_PRIMARY) {
+ irq_comp_mask |= (0x1 << vfe31_ctrl->outpath.out0.ch0 |
+ 0x1 << vfe31_ctrl->outpath.out0.ch1);
+ }
+ if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_SECONDARY) {
+ irq_comp_mask |=
+ (0x1 << (vfe31_ctrl->outpath.out1.ch0 + 8) |
+ 0x1 << (vfe31_ctrl->outpath.out1.ch1 + 8));
+ }
+ if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_PRIMARY) {
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
+ }
+ if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_SECONDARY) {
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch0]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch1]);
+ }
+ }
+
+ vfe31_ctrl->vfe_capture_count = num_frames_capture;
+
+ msm_io_w(irq_comp_mask, vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+ msm_io_r(vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+ msm_camio_bus_scale_cfg(
+ p_sync->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
+
+ vfe31_start_common();
+ /* for debug */
+ msm_io_w(1, vfe31_ctrl->vfebase + 0x18C);
+ msm_io_w(1, vfe31_ctrl->vfebase + 0x188);
+ return 0;
+}
+
+static int vfe31_start(void)
+{
+ uint32_t irq_comp_mask = 0;
+ struct msm_sync *sync = vfe_syncdata;
+
+ irq_comp_mask =
+ msm_io_r(vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+
+ if (vfe31_ctrl->outpath.output_mode & VFE31_OUTPUT_MODE_PRIMARY) {
+ irq_comp_mask |= (0x1 << vfe31_ctrl->outpath.out0.ch0 |
+ 0x1 << vfe31_ctrl->outpath.out0.ch1);
+ } else if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+ irq_comp_mask |= (0x1 << vfe31_ctrl->outpath.out0.ch0 |
+ 0x1 << vfe31_ctrl->outpath.out0.ch1 |
+ 0x1 << vfe31_ctrl->outpath.out0.ch2);
+ }
+ if (vfe31_ctrl->outpath.output_mode & VFE31_OUTPUT_MODE_SECONDARY) {
+ irq_comp_mask |= (0x1 << (vfe31_ctrl->outpath.out1.ch0 + 8) |
+ 0x1 << (vfe31_ctrl->outpath.out1.ch1 + 8));
+ } else if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+ irq_comp_mask |= (0x1 << (vfe31_ctrl->outpath.out1.ch0 + 8) |
+ 0x1 << (vfe31_ctrl->outpath.out1.ch1 + 8) |
+ 0x1 << (vfe31_ctrl->outpath.out1.ch2 + 8));
+ }
+ msm_io_w(irq_comp_mask, vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+
+ switch (vfe31_ctrl->operation_mode) {
+ case VFE_OUTPUTS_PREVIEW:
+ case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
+ if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_PRIMARY) {
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
+ } else if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch2]);
+ }
+ break;
+ default:
+ if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_SECONDARY) {
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch0]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch1]);
+ } else if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch0]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch1]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch2]);
+ }
+ break;
+ }
+ msm_camio_bus_scale_cfg(
+ sync->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+ vfe31_start_common();
+ return 0;
+}
+
+static void vfe31_update(void)
+{
+ unsigned long flags;
+
+ if (vfe31_ctrl->update_la) {
+ if (!msm_io_r(vfe31_ctrl->vfebase + V31_LA_OFF))
+ msm_io_w(1, vfe31_ctrl->vfebase + V31_LA_OFF);
+ else
+ msm_io_w(0, vfe31_ctrl->vfebase + V31_LA_OFF);
+ vfe31_ctrl->update_la = false;
+ }
+
+ if (vfe31_ctrl->update_gamma) {
+ if (!msm_io_r(vfe31_ctrl->vfebase + V31_RGB_G_OFF))
+ msm_io_w(7, vfe31_ctrl->vfebase+V31_RGB_G_OFF);
+ else
+ msm_io_w(0, vfe31_ctrl->vfebase+V31_RGB_G_OFF);
+ vfe31_ctrl->update_gamma = false;
+ }
+
+ spin_lock_irqsave(&vfe31_ctrl->update_ack_lock, flags);
+ vfe31_ctrl->update_ack_pending = TRUE;
+ spin_unlock_irqrestore(&vfe31_ctrl->update_ack_lock, flags);
+ /* Ensure the write order while writing
+ to the command register using the barrier */
+ msm_io_w_mb(1, vfe31_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ return;
+}
+
+static void vfe31_sync_timer_stop(void)
+{
+ uint32_t value = 0;
+ vfe31_ctrl->sync_timer_state = 0;
+ if (vfe31_ctrl->sync_timer_number == 0)
+ value = 0x10000;
+ else if (vfe31_ctrl->sync_timer_number == 1)
+ value = 0x20000;
+ else if (vfe31_ctrl->sync_timer_number == 2)
+ value = 0x40000;
+
+ /* Timer Stop */
+ msm_io_w(value, vfe31_ctrl->vfebase + V31_SYNC_TIMER_OFF);
+}
+
+static void vfe31_sync_timer_start(const uint32_t *tbl)
+{
+ /* set bit 8 for auto increment. */
+ uint32_t value = 1;
+ uint32_t val;
+
+ vfe31_ctrl->sync_timer_state = *tbl++;
+ vfe31_ctrl->sync_timer_repeat_count = *tbl++;
+ vfe31_ctrl->sync_timer_number = *tbl++;
+ CDBG("%s timer_state %d, repeat_cnt %d timer number %d\n",
+ __func__, vfe31_ctrl->sync_timer_state,
+ vfe31_ctrl->sync_timer_repeat_count,
+ vfe31_ctrl->sync_timer_number);
+
+ if (vfe31_ctrl->sync_timer_state) { /* Start Timer */
+ value = value << vfe31_ctrl->sync_timer_number;
+ } else { /* Stop Timer */
+ CDBG("Failed to Start timer\n");
+ return;
+ }
+
+ /* Timer Start */
+ msm_io_w(value, vfe31_ctrl->vfebase + V31_SYNC_TIMER_OFF);
+ /* Sync Timer Line Start */
+ value = *tbl++;
+ msm_io_w(value, vfe31_ctrl->vfebase + V31_SYNC_TIMER_OFF +
+ 4 + ((vfe31_ctrl->sync_timer_number) * 12));
+ /* Sync Timer Pixel Start */
+ value = *tbl++;
+ msm_io_w(value, vfe31_ctrl->vfebase + V31_SYNC_TIMER_OFF +
+ 8 + ((vfe31_ctrl->sync_timer_number) * 12));
+ /* Sync Timer Pixel Duration */
+ value = *tbl++;
+ val = vfe_clk_rate / 10000;
+ val = 10000000 / val;
+ val = value * 10000 / val;
+ CDBG("%s: Pixel Clk Cycles!!! %d\n", __func__, val);
+ msm_io_w(val, vfe31_ctrl->vfebase + V31_SYNC_TIMER_OFF +
+ 12 + ((vfe31_ctrl->sync_timer_number) * 12));
+ /* Timer0 Active High/LOW */
+ value = *tbl++;
+ msm_io_w(value, vfe31_ctrl->vfebase + V31_SYNC_TIMER_POLARITY_OFF);
+ /* Selects sync timer 0 output to drive onto timer1 port */
+ value = 0;
+ msm_io_w(value, vfe31_ctrl->vfebase + V31_TIMER_SELECT_OFF);
+}
+
+static void vfe31_program_dmi_cfg(enum VFE31_DMI_RAM_SEL bankSel)
+{
+ /* set bit 8 for auto increment. */
+ uint32_t value = VFE_DMI_CFG_DEFAULT;
+ value += (uint32_t)bankSel;
+ CDBG("%s: banksel = %d\n", __func__, bankSel);
+
+ msm_io_w(value, vfe31_ctrl->vfebase + VFE_DMI_CFG);
+ /* by default, always starts with offset 0.*/
+ msm_io_w(0, vfe31_ctrl->vfebase + VFE_DMI_ADDR);
+}
+static void vfe31_write_gamma_cfg(enum VFE31_DMI_RAM_SEL channel_sel,
+ const uint32_t *tbl)
+{
+ int i;
+ uint32_t value, value1, value2;
+ vfe31_program_dmi_cfg(channel_sel);
+ for (i = 0 ; i < (VFE31_GAMMA_NUM_ENTRIES/2) ; i++) {
+ value = *tbl++;
+ value1 = value & 0x0000FFFF;
+ value2 = (value & 0xFFFF0000)>>16;
+ msm_io_w((value1), vfe31_ctrl->vfebase + VFE_DMI_DATA_LO);
+ msm_io_w((value2), vfe31_ctrl->vfebase + VFE_DMI_DATA_LO);
+ }
+ vfe31_program_dmi_cfg(NO_MEM_SELECTED);
+}
+
+static void vfe31_read_gamma_cfg(enum VFE31_DMI_RAM_SEL channel_sel,
+ uint32_t *tbl)
+{
+ int i;
+ vfe31_program_dmi_cfg(channel_sel);
+ CDBG("%s: Gamma table channel: %d\n", __func__, channel_sel);
+ for (i = 0 ; i < VFE31_GAMMA_NUM_ENTRIES ; i++) {
+ *tbl = msm_io_r(vfe31_ctrl->vfebase + VFE_DMI_DATA_LO);
+ CDBG("%s: %08x\n", __func__, *tbl);
+ tbl++;
+ }
+ vfe31_program_dmi_cfg(NO_MEM_SELECTED);
+}
+
+static void vfe31_write_la_cfg(enum VFE31_DMI_RAM_SEL channel_sel,
+ const uint32_t *tbl)
+{
+ uint32_t i;
+ uint32_t value, value1, value2;
+
+ vfe31_program_dmi_cfg(channel_sel);
+ for (i = 0 ; i < (VFE31_LA_TABLE_LENGTH/2) ; i++) {
+ value = *tbl++;
+ value1 = value & 0x0000FFFF;
+ value2 = (value & 0xFFFF0000)>>16;
+ msm_io_w((value1), vfe31_ctrl->vfebase + VFE_DMI_DATA_LO);
+ msm_io_w((value2), vfe31_ctrl->vfebase + VFE_DMI_DATA_LO);
+ }
+ vfe31_program_dmi_cfg(NO_MEM_SELECTED);
+}
+
+static struct vfe31_output_ch *vfe31_get_ch(int path)
+{
+ struct vfe31_output_ch *ch = NULL;
+
+ if (path == VFE_MSG_OUTPUT_PRIMARY)
+ ch = &vfe31_ctrl->outpath.out0;
+ else if (path == VFE_MSG_OUTPUT_SECONDARY)
+ ch = &vfe31_ctrl->outpath.out1;
+ else
+ pr_err("%s: Invalid path %d\n", __func__, path);
+
+ BUG_ON(ch == NULL);
+ return ch;
+}
+static struct msm_free_buf *vfe31_check_free_buffer(int id, int path)
+{
+ struct vfe31_output_ch *outch = NULL;
+ struct msm_free_buf *b = NULL;
+ vfe31_subdev_notify(id, path);
+ outch = vfe31_get_ch(path);
+ if (outch->free_buf.ch_paddr[0])
+ b = &outch->free_buf;
+ return b;
+}
+static int vfe31_configure_pingpong_buffers(int id, int path)
+{
+ struct vfe31_output_ch *outch = NULL;
+ int rc = 0;
+ vfe31_subdev_notify(id, path);
+ outch = vfe31_get_ch(path);
+ if (outch->ping.ch_paddr[0] && outch->pong.ch_paddr[0]) {
+ /* Configure Preview Ping Pong */
+ CDBG("%s Configure ping/pong address for %d",
+ __func__, path);
+ vfe31_put_ch_ping_addr(outch->ch0,
+ outch->ping.ch_paddr[0]);
+ vfe31_put_ch_pong_addr(outch->ch0,
+ outch->pong.ch_paddr[0]);
+
+ if (vfe31_ctrl->operation_mode !=
+ VFE_OUTPUTS_RAW) {
+ vfe31_put_ch_ping_addr(outch->ch1,
+ outch->ping.ch_paddr[1]);
+ vfe31_put_ch_pong_addr(outch->ch1,
+ outch->pong.ch_paddr[1]);
+ }
+
+ if (outch->ping.num_planes > 2)
+ vfe31_put_ch_ping_addr(outch->ch2,
+ outch->ping.ch_paddr[2]);
+ if (outch->pong.num_planes > 2)
+ vfe31_put_ch_pong_addr(outch->ch2,
+ outch->pong.ch_paddr[2]);
+
+ /* avoid stale info */
+ memset(&outch->ping, 0, sizeof(struct msm_free_buf));
+ memset(&outch->pong, 0, sizeof(struct msm_free_buf));
+ } else {
+ pr_err("%s ping/pong addr is null!!", __func__);
+ rc = -EINVAL;
+ }
+ return rc;
+}
+
+static void vfe31_send_isp_msg(struct vfe31_ctrl_type *vctrl,
+ uint32_t isp_msg_id)
+{
+ struct isp_msg_event isp_msg_evt;
+
+ isp_msg_evt.msg_id = isp_msg_id;
+ isp_msg_evt.sof_count = vfe31_ctrl->vfeFrameId;
+ v4l2_subdev_notify(&vctrl->subdev,
+ NOTIFY_ISP_MSG_EVT, (void *)&isp_msg_evt);
+}
+
+static int vfe31_proc_general(struct msm_isp_cmd *cmd)
+{
+ int i , rc = 0;
+ uint32_t old_val = 0 , new_val = 0;
+ uint32_t *cmdp = NULL;
+ uint32_t *cmdp_local = NULL;
+ uint32_t snapshot_cnt = 0;
+ uint32_t temp1 = 0, temp2 = 0;
+
+ CDBG("vfe31_proc_general: cmdID = %s, length = %d\n",
+ vfe31_general_cmd[cmd->id], cmd->length);
+ switch (cmd->id) {
+ case VFE_CMD_RESET:
+ pr_info("vfe31_proc_general: cmdID = %s\n",
+ vfe31_general_cmd[cmd->id]);
+ vfe31_reset();
+ break;
+ case VFE_CMD_START:
+ pr_info("vfe31_proc_general: cmdID = %s\n",
+ vfe31_general_cmd[cmd->id]);
+ if ((vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_PREVIEW_AND_VIDEO) ||
+ (vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_PREVIEW))
+ /* Configure primary channel */
+ rc = vfe31_configure_pingpong_buffers(
+ VFE_MSG_V31_START, VFE_MSG_OUTPUT_PRIMARY);
+ else
+ /* Configure secondary channel */
+ rc = vfe31_configure_pingpong_buffers(
+ VFE_MSG_V31_START, VFE_MSG_OUTPUT_SECONDARY);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers"
+ " for preview", __func__);
+ rc = -EINVAL;
+ goto proc_general_done;
+ }
+ rc = vfe31_start();
+ break;
+ case VFE_CMD_UPDATE:
+ vfe31_update();
+ break;
+ case VFE_CMD_CAPTURE_RAW:
+ pr_info("%s: cmdID = VFE_CMD_CAPTURE_RAW\n", __func__);
+ if (copy_from_user(&snapshot_cnt, (void __user *)(cmd->value),
+ sizeof(uint32_t))) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ rc = vfe31_configure_pingpong_buffers(VFE_MSG_V31_CAPTURE,
+ VFE_MSG_OUTPUT_PRIMARY);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers"
+ " for snapshot", __func__);
+ rc = -EINVAL;
+ goto proc_general_done;
+ }
+ rc = vfe31_capture_raw(snapshot_cnt);
+ break;
+ case VFE_CMD_CAPTURE:
+ if (copy_from_user(&snapshot_cnt, (void __user *)(cmd->value),
+ sizeof(uint32_t))) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+
+ if (vfe31_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB ||
+ vfe31_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) {
+ if (snapshot_cnt != 1) {
+ pr_err("only support 1 inline snapshot\n");
+ rc = -EINVAL;
+ goto proc_general_done;
+ }
+ /* Configure primary channel for JPEG */
+ rc = vfe31_configure_pingpong_buffers(
+ VFE_MSG_V31_JPEG_CAPTURE,
+ VFE_MSG_OUTPUT_PRIMARY);
+ } else {
+ /* Configure primary channel */
+ rc = vfe31_configure_pingpong_buffers(
+ VFE_MSG_V31_CAPTURE,
+ VFE_MSG_OUTPUT_PRIMARY);
+ }
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers"
+ " for primary output", __func__);
+ rc = -EINVAL;
+ goto proc_general_done;
+ }
+ /* Configure secondary channel */
+ rc = vfe31_configure_pingpong_buffers(VFE_MSG_V31_CAPTURE,
+ VFE_MSG_OUTPUT_SECONDARY);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers"
+ " for secondary output", __func__);
+ rc = -EINVAL;
+ goto proc_general_done;
+ }
+ rc = vfe31_capture(snapshot_cnt);
+ break;
+ case VFE_CMD_START_RECORDING:
+ pr_info("vfe31_proc_general: cmdID = %s\n",
+ vfe31_general_cmd[cmd->id]);
+ if (vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_PREVIEW_AND_VIDEO)
+ rc = vfe31_configure_pingpong_buffers(
+ VFE_MSG_V31_START_RECORDING,
+ VFE_MSG_OUTPUT_SECONDARY);
+ else if (vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_VIDEO_AND_PREVIEW)
+ rc = vfe31_configure_pingpong_buffers(
+ VFE_MSG_V31_START_RECORDING,
+ VFE_MSG_OUTPUT_PRIMARY);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers"
+ " for video", __func__);
+ rc = -EINVAL;
+ goto proc_general_done;
+ }
+ rc = vfe31_start_recording();
+ break;
+ case VFE_CMD_STOP_RECORDING:
+ pr_info("vfe31_proc_general: cmdID = %s\n",
+ vfe31_general_cmd[cmd->id]);
+ rc = vfe31_stop_recording();
+ break;
+ case VFE_CMD_OPERATION_CFG:
+ if (cmd->length != V31_OPERATION_CFG_LEN) {
+ rc = -EINVAL;
+ goto proc_general_done;
+ }
+ cmdp = kmalloc(V31_OPERATION_CFG_LEN, GFP_ATOMIC);
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value),
+ V31_OPERATION_CFG_LEN)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ rc = vfe31_operation_config(cmdp);
+ break;
+
+ case VFE_CMD_STATS_AE_START:
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ old_val = msm_io_r(vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val |= AE_BG_ENABLE_MASK;
+ msm_io_w(old_val,
+ vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ msm_io_memcpy(vfe31_ctrl->vfebase + vfe31_cmd[cmd->id].offset,
+ cmdp, (vfe31_cmd[cmd->id].length));
+ break;
+ case VFE_CMD_STATS_AF_START:
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ old_val = msm_io_r(vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val |= AF_BF_ENABLE_MASK;
+ msm_io_w(old_val,
+ vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ msm_io_memcpy(vfe31_ctrl->vfebase + vfe31_cmd[cmd->id].offset,
+ cmdp, (vfe31_cmd[cmd->id].length));
+ break;
+ case VFE_CMD_STATS_AWB_START:
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ old_val = msm_io_r(vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val |= AWB_ENABLE_MASK;
+ msm_io_w(old_val,
+ vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ msm_io_memcpy(vfe31_ctrl->vfebase + vfe31_cmd[cmd->id].offset,
+ cmdp, (vfe31_cmd[cmd->id].length));
+ break;
+
+ case VFE_CMD_STATS_IHIST_START:
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ old_val = msm_io_r(vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val |= IHIST_ENABLE_MASK;
+ msm_io_w(old_val,
+ vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ msm_io_memcpy(vfe31_ctrl->vfebase + vfe31_cmd[cmd->id].offset,
+ cmdp, (vfe31_cmd[cmd->id].length));
+ break;
+
+ case VFE_CMD_STATS_RS_START:
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ msm_io_memcpy(vfe31_ctrl->vfebase + vfe31_cmd[cmd->id].offset,
+ cmdp, (vfe31_cmd[cmd->id].length));
+ break;
+
+ case VFE_CMD_STATS_CS_START:
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ msm_io_memcpy(vfe31_ctrl->vfebase + vfe31_cmd[cmd->id].offset,
+ cmdp, (vfe31_cmd[cmd->id].length));
+ break;
+
+ case VFE_CMD_MCE_UPDATE:
+ case VFE_CMD_MCE_CFG:
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ /* Incrementing with 4 so as to point to the 2nd Register as
+ the 2nd register has the mce_enable bit */
+ old_val = msm_io_r(vfe31_ctrl->vfebase +
+ V31_CHROMA_SUP_OFF + 4);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ cmdp_local = cmdp;
+ new_val = *cmdp_local;
+ old_val &= MCE_EN_MASK;
+ new_val = new_val | old_val;
+ msm_io_memcpy(vfe31_ctrl->vfebase + V31_CHROMA_SUP_OFF + 4,
+ &new_val, 4);
+ cmdp_local += 1;
+
+ old_val = msm_io_r(vfe31_ctrl->vfebase +
+ V31_CHROMA_SUP_OFF + 8);
+ new_val = *cmdp_local;
+ old_val &= MCE_Q_K_MASK;
+ new_val = new_val | old_val;
+ msm_io_memcpy(vfe31_ctrl->vfebase + V31_CHROMA_SUP_OFF + 8,
+ &new_val, 4);
+ cmdp_local += 1;
+ msm_io_memcpy(vfe31_ctrl->vfebase + vfe31_cmd[cmd->id].offset,
+ cmdp_local, (vfe31_cmd[cmd->id].length));
+ break;
+ case VFE_CMD_CHROMA_SUP_UPDATE:
+ case VFE_CMD_CHROMA_SUP_CFG:
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ cmdp_local = cmdp;
+ msm_io_memcpy(vfe31_ctrl->vfebase + V31_CHROMA_SUP_OFF,
+ cmdp_local, 4);
+
+ cmdp_local += 1;
+ new_val = *cmdp_local;
+ /* Incrementing with 4 so as to point to the 2nd Register as
+ * the 2nd register has the mce_enable bit
+ */
+ old_val = msm_io_r(vfe31_ctrl->vfebase +
+ V31_CHROMA_SUP_OFF + 4);
+ old_val &= ~MCE_EN_MASK;
+ new_val = new_val | old_val;
+ msm_io_memcpy(vfe31_ctrl->vfebase + V31_CHROMA_SUP_OFF + 4,
+ &new_val, 4);
+ cmdp_local += 1;
+
+ old_val = msm_io_r(vfe31_ctrl->vfebase +
+ V31_CHROMA_SUP_OFF + 8);
+ new_val = *cmdp_local;
+ old_val &= ~MCE_Q_K_MASK;
+ new_val = new_val | old_val;
+ msm_io_memcpy(vfe31_ctrl->vfebase + V31_CHROMA_SUP_OFF + 8,
+ &new_val, 4);
+ break;
+
+ case VFE_CMD_MESH_ROLL_OFF_CFG:
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value) , cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ cmdp_local = cmdp;
+ msm_io_memcpy(vfe31_ctrl->vfebase + vfe31_cmd[cmd->id].offset,
+ cmdp_local, 16);
+ cmdp_local += 4;
+ vfe31_program_dmi_cfg(ROLLOFF_RAM);
+ /* for loop for extrcting init table. */
+ for (i = 0; i < (V31_MESH_ROLL_OFF_INIT_TABLE_SIZE * 2); i++) {
+ msm_io_w(*cmdp_local ,
+ vfe31_ctrl->vfebase + VFE_DMI_DATA_LO);
+ cmdp_local++;
+ }
+ CDBG("done writing init table\n");
+ /* by default, always starts with offset 0. */
+ msm_io_w(V31_MESH_ROLL_OFF_DELTA_TABLE_OFFSET,
+ vfe31_ctrl->vfebase + VFE_DMI_ADDR);
+ /* for loop for extracting delta table. */
+ for (i = 0; i < (V31_MESH_ROLL_OFF_DELTA_TABLE_SIZE * 2); i++) {
+ msm_io_w(*cmdp_local,
+ vfe31_ctrl->vfebase + VFE_DMI_DATA_LO);
+ cmdp_local++;
+ }
+ vfe31_program_dmi_cfg(NO_MEM_SELECTED);
+ break;
+
+ case VFE_CMD_GET_MESH_ROLLOFF_TABLE:
+ temp1 = sizeof(uint32_t) * ((V31_MESH_ROLL_OFF_INIT_TABLE_SIZE *
+ 2) + (V31_MESH_ROLL_OFF_DELTA_TABLE_SIZE * 2));
+ if (cmd->length != temp1) {
+ rc = -EINVAL;
+ goto proc_general_done;
+ }
+ cmdp = kzalloc(temp1, GFP_KERNEL);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ cmdp_local = cmdp;
+ vfe31_program_dmi_cfg(ROLLOFF_RAM);
+ CDBG("%s: Mesh Rolloff init Table\n", __func__);
+ for (i = 0; i < (V31_MESH_ROLL_OFF_INIT_TABLE_SIZE * 2); i++) {
+ *cmdp_local =
+ msm_io_r(vfe31_ctrl->vfebase + VFE_DMI_DATA_LO);
+ CDBG("%s: %08x\n", __func__, *cmdp_local);
+ cmdp_local++;
+ }
+ msm_io_w(V31_MESH_ROLL_OFF_DELTA_TABLE_OFFSET,
+ vfe31_ctrl->vfebase + VFE_DMI_ADDR);
+ CDBG("%s: Mesh Rolloff Delta Table\n", __func__);
+ for (i = 0; i < (V31_MESH_ROLL_OFF_DELTA_TABLE_SIZE * 2); i++) {
+ *cmdp_local =
+ msm_io_r(vfe31_ctrl->vfebase + VFE_DMI_DATA_LO);
+ CDBG("%s: %08x\n", __func__, *cmdp_local);
+ cmdp_local++;
+ }
+ CDBG("done reading delta table\n");
+ vfe31_program_dmi_cfg(NO_MEM_SELECTED);
+ if (copy_to_user((void __user *)(cmd->value), cmdp,
+ temp1)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ break;
+ case VFE_CMD_LA_CFG:
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value),
+ cmd->length)) {
+
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ cmdp_local = cmdp;
+ msm_io_memcpy(vfe31_ctrl->vfebase + vfe31_cmd[cmd->id].offset,
+ cmdp_local, (vfe31_cmd[cmd->id].length));
+
+ cmdp_local += 1;
+ vfe31_write_la_cfg(LUMA_ADAPT_LUT_RAM_BANK0, cmdp_local);
+ break;
+
+ case VFE_CMD_LA_UPDATE:
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value),
+ cmd->length)) {
+
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+
+ cmdp_local = cmdp + 1;
+ old_val = msm_io_r(vfe31_ctrl->vfebase + V31_LA_OFF);
+ if (old_val != 0x0)
+ vfe31_write_la_cfg(LUMA_ADAPT_LUT_RAM_BANK0,
+ cmdp_local);
+ else
+ vfe31_write_la_cfg(LUMA_ADAPT_LUT_RAM_BANK1,
+ cmdp_local);
+ vfe31_ctrl->update_la = true;
+ break;
+
+ case VFE_CMD_GET_LA_TABLE:
+ temp1 = sizeof(uint32_t) * VFE31_LA_TABLE_LENGTH / 2;
+ if (cmd->length != temp1) {
+ rc = -EINVAL;
+ goto proc_general_done;
+ }
+ cmdp = kzalloc(temp1, GFP_KERNEL);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ cmdp_local = cmdp;
+ if (msm_io_r(vfe31_ctrl->vfebase + V31_LA_OFF))
+ vfe31_program_dmi_cfg(LUMA_ADAPT_LUT_RAM_BANK1);
+ else
+ vfe31_program_dmi_cfg(LUMA_ADAPT_LUT_RAM_BANK0);
+ for (i = 0 ; i < (VFE31_LA_TABLE_LENGTH / 2) ; i++) {
+ *cmdp_local =
+ msm_io_r(vfe31_ctrl->vfebase + VFE_DMI_DATA_LO);
+ *cmdp_local |= (msm_io_r(vfe31_ctrl->vfebase +
+ VFE_DMI_DATA_LO)) << 16;
+ cmdp_local++;
+ }
+ vfe31_program_dmi_cfg(NO_MEM_SELECTED);
+ if (copy_to_user((void __user *)(cmd->value), cmdp,
+ temp1)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ break;
+ case VFE_CMD_SK_ENHAN_CFG:
+ case VFE_CMD_SK_ENHAN_UPDATE:
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ msm_io_memcpy(vfe31_ctrl->vfebase + V31_SCE_OFF,
+ cmdp, V31_SCE_LEN);
+ break;
+
+ case VFE_CMD_LIVESHOT:
+ /* Configure primary channel */
+ rc = vfe31_configure_pingpong_buffers(VFE_MSG_V31_CAPTURE,
+ VFE_MSG_OUTPUT_PRIMARY);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers"
+ " for primary output", __func__);
+ rc = -EINVAL;
+ goto proc_general_done;
+ }
+ vfe31_start_liveshot();
+ break;
+
+ case VFE_CMD_DEMOSAICV3:
+ if (cmd->length != V31_DEMOSAICV3_LEN) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ cmdp_local = cmdp;
+ new_val = *cmdp_local;
+
+ old_val = msm_io_r(vfe31_ctrl->vfebase + V31_DEMOSAICV3_OFF);
+ old_val &= DEMOSAIC_MASK;
+ new_val = new_val | old_val;
+ *cmdp_local = new_val;
+
+ msm_io_memcpy(vfe31_ctrl->vfebase + V31_DEMOSAICV3_OFF,
+ cmdp_local, V31_DEMOSAICV3_LEN);
+ break;
+
+ case VFE_CMD_DEMOSAICV3_UPDATE:
+ if (cmd->length !=
+ V31_DEMOSAICV3_LEN * V31_DEMOSAICV3_UP_REG_CNT) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ cmdp_local = cmdp;
+ new_val = *cmdp_local;
+
+ old_val = msm_io_r(vfe31_ctrl->vfebase + V31_DEMOSAICV3_OFF);
+ old_val &= DEMOSAIC_MASK;
+ new_val = new_val | old_val;
+ *cmdp_local = new_val;
+
+ msm_io_memcpy(vfe31_ctrl->vfebase + V31_DEMOSAICV3_OFF,
+ cmdp_local, V31_DEMOSAICV3_LEN);
+
+ break;
+
+ case VFE_CMD_DEMOSAICV3_ABCC_CFG:
+ rc = -EFAULT;
+ break;
+
+ case VFE_CMD_DEMOSAICV3_ABF_UPDATE:/* 116 ABF update */
+ case VFE_CMD_DEMOSAICV3_ABF_CFG: /* 108 ABF config */
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ cmdp_local = cmdp;
+ new_val = *cmdp_local;
+
+ old_val = msm_io_r(vfe31_ctrl->vfebase + V31_DEMOSAICV3_OFF);
+ old_val &= ABF_MASK;
+ new_val = new_val | old_val;
+ *cmdp_local = new_val;
+
+ msm_io_memcpy(vfe31_ctrl->vfebase + V31_DEMOSAICV3_OFF,
+ cmdp_local, 4);
+
+ cmdp_local += 1;
+ msm_io_memcpy(vfe31_ctrl->vfebase + vfe31_cmd[cmd->id].offset,
+ cmdp_local, (vfe31_cmd[cmd->id].length));
+ break;
+
+ case VFE_CMD_DEMOSAICV3_DBCC_CFG:
+ case VFE_CMD_DEMOSAICV3_DBCC_UPDATE:
+ return -EINVAL;
+
+ case VFE_CMD_DEMOSAICV3_DBPC_CFG:
+ case VFE_CMD_DEMOSAICV3_DBPC_UPDATE:
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ cmdp_local = cmdp;
+ new_val = *cmdp_local;
+
+ old_val = msm_io_r(vfe31_ctrl->vfebase + V31_DEMOSAICV3_OFF);
+ old_val &= BPC_MASK;
+
+ new_val = new_val | old_val;
+ *cmdp_local = new_val;
+ msm_io_memcpy(vfe31_ctrl->vfebase + V31_DEMOSAICV3_OFF,
+ cmdp_local, V31_DEMOSAICV3_LEN);
+ cmdp_local += 1;
+ msm_io_memcpy(vfe31_ctrl->vfebase + V31_DEMOSAICV3_DBPC_CFG_OFF,
+ cmdp_local, V31_DEMOSAICV3_DBPC_LEN);
+ break;
+
+ case VFE_CMD_RGB_G_CFG:
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ msm_io_memcpy(vfe31_ctrl->vfebase + V31_RGB_G_OFF,
+ cmdp, 4);
+ cmdp += 1;
+
+ vfe31_write_gamma_cfg(RGBLUT_RAM_CH0_BANK0, cmdp);
+ vfe31_write_gamma_cfg(RGBLUT_RAM_CH1_BANK0, cmdp);
+ vfe31_write_gamma_cfg(RGBLUT_RAM_CH2_BANK0, cmdp);
+ cmdp -= 1;
+ break;
+
+ case VFE_CMD_RGB_G_UPDATE:
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp, (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+
+ old_val = msm_io_r(vfe31_ctrl->vfebase + V31_RGB_G_OFF);
+ cmdp += 1;
+ if (old_val != 0x0) {
+ vfe31_write_gamma_cfg(RGBLUT_RAM_CH0_BANK0, cmdp);
+ vfe31_write_gamma_cfg(RGBLUT_RAM_CH1_BANK0, cmdp);
+ vfe31_write_gamma_cfg(RGBLUT_RAM_CH2_BANK0, cmdp);
+ } else {
+ vfe31_write_gamma_cfg(RGBLUT_RAM_CH0_BANK1, cmdp);
+ vfe31_write_gamma_cfg(RGBLUT_RAM_CH1_BANK1, cmdp);
+ vfe31_write_gamma_cfg(RGBLUT_RAM_CH2_BANK1, cmdp);
+ }
+ vfe31_ctrl->update_gamma = TRUE;
+ cmdp -= 1;
+ break;
+
+ case VFE_CMD_GET_RGB_G_TABLE:
+ temp1 = sizeof(uint32_t) * VFE31_GAMMA_NUM_ENTRIES * 3;
+ if (cmd->length != temp1) {
+ rc = -EINVAL;
+ goto proc_general_done;
+ }
+ cmdp = kzalloc(temp1, GFP_KERNEL);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ cmdp_local = cmdp;
+
+ old_val = msm_io_r(vfe31_ctrl->vfebase + V31_RGB_G_OFF);
+ temp2 = old_val ? RGBLUT_RAM_CH0_BANK1 :
+ RGBLUT_RAM_CH0_BANK0;
+ for (i = 0; i < 3; i++) {
+ vfe31_read_gamma_cfg(temp2,
+ cmdp_local + (VFE31_GAMMA_NUM_ENTRIES * i));
+ temp2 += 2;
+ }
+ if (copy_to_user((void __user *)(cmd->value), cmdp,
+ temp1)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ break;
+
+ case VFE_CMD_STATS_AWB_STOP:
+ old_val = msm_io_r(vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val &= ~AWB_ENABLE_MASK;
+ msm_io_w(old_val,
+ vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ break;
+ case VFE_CMD_STATS_AE_STOP:
+ old_val = msm_io_r(vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val &= ~AE_BG_ENABLE_MASK;
+ msm_io_w(old_val,
+ vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ break;
+ case VFE_CMD_STATS_AF_STOP:
+ old_val = msm_io_r(vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val &= ~AF_BF_ENABLE_MASK;
+ msm_io_w(old_val,
+ vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ break;
+
+ case VFE_CMD_STATS_IHIST_STOP:
+ old_val = msm_io_r(vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val &= ~IHIST_ENABLE_MASK;
+ msm_io_w(old_val,
+ vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ break;
+
+ case VFE_CMD_STATS_RS_STOP:
+ old_val = msm_io_r(vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val &= ~RS_ENABLE_MASK;
+ msm_io_w(old_val,
+ vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ break;
+
+ case VFE_CMD_STATS_CS_STOP:
+ old_val = msm_io_r(vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val &= ~CS_ENABLE_MASK;
+ msm_io_w(old_val,
+ vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ break;
+
+ case VFE_CMD_STOP:
+ pr_info("vfe31_proc_general: cmdID = %s\n",
+ vfe31_general_cmd[cmd->id]);
+ vfe31_stop();
+ break;
+
+ case VFE_CMD_SYNC_TIMER_SETTING:
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp, (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ vfe31_sync_timer_start(cmdp);
+ break;
+
+ case VFE_CMD_MODULE_CFG:
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ *cmdp &= ~STATS_ENABLE_MASK;
+ old_val = msm_io_r(vfe31_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val &= STATS_ENABLE_MASK;
+ *cmdp |= old_val;
+
+ msm_io_memcpy(vfe31_ctrl->vfebase + vfe31_cmd[cmd->id].offset,
+ cmdp, (vfe31_cmd[cmd->id].length));
+ break;
+
+ case VFE_CMD_ZSL:
+ rc = vfe31_configure_pingpong_buffers(VFE_MSG_V31_START,
+ VFE_MSG_OUTPUT_PRIMARY);
+ if (rc < 0)
+ goto proc_general_done;
+ rc = vfe31_configure_pingpong_buffers(VFE_MSG_V31_START,
+ VFE_MSG_OUTPUT_SECONDARY);
+ if (rc < 0)
+ goto proc_general_done;
+
+ rc = vfe31_zsl();
+ break;
+
+ case VFE_CMD_ASF_CFG:
+ case VFE_CMD_ASF_UPDATE:
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp, (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ msm_io_memcpy(vfe31_ctrl->vfebase + vfe31_cmd[cmd->id].offset,
+ cmdp, (vfe31_cmd[cmd->id].length));
+ cmdp_local = cmdp + V31_ASF_LEN/4;
+ break;
+
+ case VFE_CMD_GET_HW_VERSION:
+ if (cmd->length != V31_GET_HW_VERSION_LEN) {
+ rc = -EINVAL;
+ goto proc_general_done;
+ }
+ cmdp = kmalloc(V31_GET_HW_VERSION_LEN, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ *cmdp = msm_io_r(vfe31_ctrl->vfebase+V31_GET_HW_VERSION_OFF);
+ if (copy_to_user((void __user *)(cmd->value), cmdp,
+ V31_GET_HW_VERSION_LEN)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ break;
+ case VFE_CMD_GET_REG_DUMP:
+ temp1 = sizeof(uint32_t) * vfe31_ctrl->register_total;
+ if (cmd->length != temp1) {
+ rc = -EINVAL;
+ goto proc_general_done;
+ }
+ cmdp = kmalloc(temp1, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ msm_io_dump(vfe31_ctrl->vfebase, vfe31_ctrl->register_total*4);
+ CDBG("%s: %p %p %d\n", __func__, (void *)cmdp,
+ vfe31_ctrl->vfebase, temp1);
+ memcpy_fromio((void *)cmdp, vfe31_ctrl->vfebase, temp1);
+ if (copy_to_user((void __user *)(cmd->value), cmdp, temp1)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ break;
+ case VFE_CMD_FRAME_SKIP_CFG:
+ if (cmd->length != vfe31_cmd[cmd->id].length)
+ return -EINVAL;
+
+ cmdp = kmalloc(vfe31_cmd[cmd->id].length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+
+ if (copy_from_user(cmdp, (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ msm_io_memcpy(vfe31_ctrl->vfebase + vfe31_cmd[cmd->id].offset,
+ cmdp, (vfe31_cmd[cmd->id].length));
+ vfe31_ctrl->frame_skip_cnt = ((uint32_t)
+ *cmdp & VFE_FRAME_SKIP_PERIOD_MASK) + 1;
+ vfe31_ctrl->frame_skip_pattern = (uint32_t)(*(cmdp + 2));
+ break;
+ default:
+ if (cmd->length != vfe31_cmd[cmd->id].length)
+ return -EINVAL;
+
+ cmdp = kmalloc(vfe31_cmd[cmd->id].length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+
+ if (copy_from_user(cmdp, (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ msm_io_memcpy(vfe31_ctrl->vfebase + vfe31_cmd[cmd->id].offset,
+ cmdp, (vfe31_cmd[cmd->id].length));
+ break;
+
+ }
+
+proc_general_done:
+ kfree(cmdp);
+
+ return rc;
+}
+
+static void vfe31_stats_af_ack(struct vfe_cmd_stats_ack *pAck)
+{
+ unsigned long flags;
+ spinlock_t *lock = (vfe31_ctrl->stats_comp ?
+ &vfe31_ctrl->comp_stats_ack_lock :
+ &vfe31_ctrl->af_ack_lock);
+ spin_lock_irqsave(lock, flags);
+ vfe31_ctrl->afStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
+ vfe31_ctrl->afStatsControl.ackPending = FALSE;
+ spin_unlock_irqrestore(lock, flags);
+}
+
+static void vfe31_stats_awb_ack(struct vfe_cmd_stats_ack *pAck)
+{
+ unsigned long flags;
+ spinlock_t *lock = (vfe31_ctrl->stats_comp ?
+ &vfe31_ctrl->comp_stats_ack_lock :
+ &vfe31_ctrl->awb_ack_lock);
+ spin_lock_irqsave(lock, flags);
+ vfe31_ctrl->awbStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
+ vfe31_ctrl->awbStatsControl.ackPending = FALSE;
+ spin_unlock_irqrestore(lock, flags);
+}
+
+static void vfe31_stats_aec_ack(struct vfe_cmd_stats_ack *pAck)
+{
+ unsigned long flags;
+ spinlock_t *lock = (vfe31_ctrl->stats_comp ?
+ &vfe31_ctrl->comp_stats_ack_lock :
+ &vfe31_ctrl->aec_ack_lock);
+ spin_lock_irqsave(lock, flags);
+ vfe31_ctrl->aecStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
+ vfe31_ctrl->aecStatsControl.ackPending = FALSE;
+ spin_unlock_irqrestore(lock, flags);
+}
+
+static void vfe31_stats_ihist_ack(struct vfe_cmd_stats_ack *pAck)
+{
+ unsigned long flags;
+ spinlock_t *lock = (vfe31_ctrl->stats_comp ?
+ &vfe31_ctrl->comp_stats_ack_lock :
+ &vfe31_ctrl->ihist_ack_lock);
+ spin_lock_irqsave(lock, flags);
+ vfe31_ctrl->ihistStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
+ vfe31_ctrl->ihistStatsControl.ackPending = FALSE;
+ spin_unlock_irqrestore(lock, flags);
+}
+static void vfe31_stats_rs_ack(struct vfe_cmd_stats_ack *pAck)
+{
+ unsigned long flags;
+ spinlock_t *lock = (vfe31_ctrl->stats_comp ?
+ &vfe31_ctrl->comp_stats_ack_lock :
+ &vfe31_ctrl->rs_ack_lock);
+ spin_lock_irqsave(lock, flags);
+ vfe31_ctrl->rsStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
+ vfe31_ctrl->rsStatsControl.ackPending = FALSE;
+ spin_unlock_irqrestore(lock, flags);
+}
+static void vfe31_stats_cs_ack(struct vfe_cmd_stats_ack *pAck)
+{
+ unsigned long flags;
+ spinlock_t *lock = (vfe31_ctrl->stats_comp ?
+ &vfe31_ctrl->comp_stats_ack_lock :
+ &vfe31_ctrl->cs_ack_lock);
+ spin_lock_irqsave(lock, flags);
+ vfe31_ctrl->csStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
+ vfe31_ctrl->csStatsControl.ackPending = FALSE;
+ spin_unlock_irqrestore(lock, flags);
+}
+
+static inline void vfe31_read_irq_status(struct vfe31_irq_status *out)
+{
+ uint32_t *temp;
+ memset(out, 0, sizeof(struct vfe31_irq_status));
+ temp = (uint32_t *)(vfe31_ctrl->vfebase + VFE_IRQ_STATUS_0);
+ out->vfeIrqStatus0 = msm_io_r(temp);
+
+ temp = (uint32_t *)(vfe31_ctrl->vfebase + VFE_IRQ_STATUS_1);
+ out->vfeIrqStatus1 = msm_io_r(temp);
+
+ temp = (uint32_t *)(vfe31_ctrl->vfebase + VFE_CAMIF_STATUS);
+ out->camifStatus = msm_io_r(temp);
+ CDBG("camifStatus = 0x%x\n", out->camifStatus);
+
+ /* clear the pending interrupt of the same kind.*/
+ msm_io_w(out->vfeIrqStatus0, vfe31_ctrl->vfebase + VFE_IRQ_CLEAR_0);
+ msm_io_w(out->vfeIrqStatus1, vfe31_ctrl->vfebase + VFE_IRQ_CLEAR_1);
+
+ /* Ensure the write order while writing
+ to the command register using the barrier */
+ msm_io_w_mb(1, vfe31_ctrl->vfebase + VFE_IRQ_CMD);
+
+}
+
+static void vfe31_process_reg_update_irq(void)
+{
+ unsigned long flags;
+
+ if (vfe31_ctrl->recording_state == VFE_STATE_START_REQUESTED) {
+ if (vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
+ } else if (vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch0]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch1]);
+ }
+ vfe31_ctrl->recording_state = VFE_STATE_STARTED;
+ msm_io_w_mb(1, vfe31_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ CDBG("start video triggered .\n");
+ } else if (vfe31_ctrl->recording_state ==
+ VFE_STATE_STOP_REQUESTED) {
+ if (vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
+ msm_io_w(0, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
+ msm_io_w(0, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
+ } else if (vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
+ msm_io_w(0, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch0]);
+ msm_io_w(0, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch1]);
+ }
+ CDBG("stop video triggered .\n");
+ }
+
+ if (vfe31_ctrl->start_ack_pending == TRUE) {
+ vfe31_send_isp_msg(vfe31_ctrl, MSG_ID_START_ACK);
+ vfe31_ctrl->start_ack_pending = FALSE;
+ } else {
+ if (vfe31_ctrl->recording_state ==
+ VFE_STATE_STOP_REQUESTED) {
+ vfe31_ctrl->recording_state = VFE_STATE_STOPPED;
+ /* request a reg update and send STOP_REC_ACK
+ * when we process the next reg update irq.
+ */
+ msm_io_w_mb(1,
+ vfe31_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ } else if (vfe31_ctrl->recording_state ==
+ VFE_STATE_STOPPED) {
+ vfe31_send_isp_msg(vfe31_ctrl, MSG_ID_STOP_REC_ACK);
+ vfe31_ctrl->recording_state = VFE_STATE_IDLE;
+ }
+ spin_lock_irqsave(&vfe31_ctrl->update_ack_lock, flags);
+ if (vfe31_ctrl->update_ack_pending == TRUE) {
+ vfe31_ctrl->update_ack_pending = FALSE;
+ spin_unlock_irqrestore(
+ &vfe31_ctrl->update_ack_lock, flags);
+ vfe31_send_isp_msg(vfe31_ctrl, MSG_ID_UPDATE_ACK);
+ } else {
+ spin_unlock_irqrestore(
+ &vfe31_ctrl->update_ack_lock, flags);
+ }
+ }
+
+ if (vfe31_ctrl->liveshot_state == VFE_STATE_START_REQUESTED) {
+ pr_info("%s enabling liveshot output\n", __func__);
+ if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_PRIMARY) {
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
+ vfe31_ctrl->liveshot_state = VFE_STATE_STARTED;
+ }
+ }
+
+ if (vfe31_ctrl->liveshot_state == VFE_STATE_STARTED) {
+ vfe31_ctrl->vfe_capture_count--;
+ if (!vfe31_ctrl->vfe_capture_count)
+ vfe31_ctrl->liveshot_state = VFE_STATE_STOP_REQUESTED;
+ msm_io_w_mb(1, vfe31_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ } else if (vfe31_ctrl->liveshot_state == VFE_STATE_STOP_REQUESTED) {
+ CDBG("%s: disabling liveshot output\n", __func__);
+ if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_PRIMARY) {
+ msm_io_w(0, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
+ msm_io_w(0, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
+ vfe31_ctrl->liveshot_state = VFE_STATE_STOPPED;
+ msm_io_w_mb(1, vfe31_ctrl->vfebase +
+ VFE_REG_UPDATE_CMD);
+ }
+ } else if (vfe31_ctrl->liveshot_state == VFE_STATE_STOPPED) {
+ vfe31_ctrl->liveshot_state = VFE_STATE_IDLE;
+ }
+
+ if ((vfe31_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN) ||
+ (vfe31_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB) ||
+ (vfe31_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) ||
+ (vfe31_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB)) {
+ /* in snapshot mode */
+ /* later we need to add check for live snapshot mode. */
+ if (vfe31_ctrl->frame_skip_pattern & (0x1 <<
+ (vfe31_ctrl->snapshot_frame_cnt %
+ vfe31_ctrl->frame_skip_cnt))) {
+ vfe31_ctrl->vfe_capture_count--;
+ /* if last frame to be captured: */
+ if (vfe31_ctrl->vfe_capture_count == 0) {
+ /* stop the bus output:write master enable = 0*/
+ if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_PRIMARY) {
+ msm_io_w(0, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->
+ outpath.out0.ch0]);
+ msm_io_w(0, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->
+ outpath.out0.ch1]);
+ }
+ if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_SECONDARY) {
+ msm_io_w(0, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->
+ outpath.out1.ch0]);
+ msm_io_w(0, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->
+ outpath.out1.ch1]);
+ }
+ msm_io_w_mb
+ (CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
+ vfe31_ctrl->vfebase + VFE_CAMIF_COMMAND);
+ vfe31_ctrl->snapshot_frame_cnt = -1;
+ vfe31_ctrl->frame_skip_cnt = 31;
+ vfe31_ctrl->frame_skip_pattern = 0xffffffff;
+ } /*if snapshot count is 0*/
+ } /*if frame is not being dropped*/
+ vfe31_ctrl->snapshot_frame_cnt++;
+ /* then do reg_update. */
+ msm_io_w(1, vfe31_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ } /* if snapshot mode. */
+}
+
+static void vfe31_set_default_reg_values(void)
+{
+ msm_io_w(0x800080, vfe31_ctrl->vfebase + VFE_DEMUX_GAIN_0);
+ msm_io_w(0x800080, vfe31_ctrl->vfebase + VFE_DEMUX_GAIN_1);
+ /* What value should we program CGC_OVERRIDE to? */
+ msm_io_w(0xFFFFF, vfe31_ctrl->vfebase + VFE_CGC_OVERRIDE);
+
+ /* default frame drop period and pattern */
+ msm_io_w(0x1f, vfe31_ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_CFG);
+ msm_io_w(0x1f, vfe31_ctrl->vfebase + VFE_FRAMEDROP_ENC_CBCR_CFG);
+ msm_io_w(0xFFFFFFFF, vfe31_ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_PATTERN);
+ msm_io_w(0xFFFFFFFF,
+ vfe31_ctrl->vfebase + VFE_FRAMEDROP_ENC_CBCR_PATTERN);
+ msm_io_w(0x1f, vfe31_ctrl->vfebase + VFE_FRAMEDROP_VIEW_Y);
+ msm_io_w(0x1f, vfe31_ctrl->vfebase + VFE_FRAMEDROP_VIEW_CBCR);
+ msm_io_w(0xFFFFFFFF,
+ vfe31_ctrl->vfebase + VFE_FRAMEDROP_VIEW_Y_PATTERN);
+ msm_io_w(0xFFFFFFFF,
+ vfe31_ctrl->vfebase + VFE_FRAMEDROP_VIEW_CBCR_PATTERN);
+ msm_io_w(0, vfe31_ctrl->vfebase + VFE_CLAMP_MIN);
+ msm_io_w(0xFFFFFF, vfe31_ctrl->vfebase + VFE_CLAMP_MAX);
+
+ /* stats UB config */
+ msm_io_w(0x3980007, vfe31_ctrl->vfebase + VFE_BUS_STATS_AEC_UB_CFG);
+ msm_io_w(0x3A00007, vfe31_ctrl->vfebase + VFE_BUS_STATS_AF_UB_CFG);
+ msm_io_w(0x3A8000F, vfe31_ctrl->vfebase + VFE_BUS_STATS_AWB_UB_CFG);
+ msm_io_w(0x3B80007, vfe31_ctrl->vfebase + VFE_BUS_STATS_RS_UB_CFG);
+ msm_io_w(0x3C0001F, vfe31_ctrl->vfebase + VFE_BUS_STATS_CS_UB_CFG);
+ msm_io_w(0x3E0001F, vfe31_ctrl->vfebase + VFE_BUS_STATS_HIST_UB_CFG);
+}
+
+static void vfe31_process_reset_irq(void)
+{
+ unsigned long flags;
+
+ atomic_set(&vfe31_ctrl->vstate, 0);
+
+ spin_lock_irqsave(&vfe31_ctrl->stop_flag_lock, flags);
+ if (vfe31_ctrl->stop_ack_pending) {
+ vfe31_ctrl->stop_ack_pending = FALSE;
+ spin_unlock_irqrestore(&vfe31_ctrl->stop_flag_lock, flags);
+ vfe31_send_isp_msg(vfe31_ctrl, MSG_ID_STOP_ACK);
+ } else {
+ spin_unlock_irqrestore(&vfe31_ctrl->stop_flag_lock, flags);
+ /* this is from reset command. */
+ vfe31_set_default_reg_values();
+
+ /* reload all write masters. (frame & line)*/
+ msm_io_w(0x7FFF, vfe31_ctrl->vfebase + VFE_BUS_CMD);
+ vfe31_send_isp_msg(vfe31_ctrl, MSG_ID_RESET_ACK);
+ }
+}
+
+static void vfe31_process_camif_sof_irq(void)
+{
+ if (vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_RAW) {
+ if (vfe31_ctrl->start_ack_pending) {
+ vfe31_send_isp_msg(vfe31_ctrl, MSG_ID_START_ACK);
+ vfe31_ctrl->start_ack_pending = FALSE;
+ }
+ vfe31_ctrl->vfe_capture_count--;
+ /* if last frame to be captured: */
+ if (vfe31_ctrl->vfe_capture_count == 0) {
+ /* Ensure the write order while writing
+ to the command register using the barrier */
+ msm_io_w_mb(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
+ vfe31_ctrl->vfebase + VFE_CAMIF_COMMAND);
+ }
+ } /* if raw snapshot mode. */
+ if ((vfe31_ctrl->hfr_mode != HFR_MODE_OFF) &&
+ (vfe31_ctrl->operation_mode == VFE_MODE_OF_OPERATION_VIDEO) &&
+ (vfe31_ctrl->vfeFrameId % vfe31_ctrl->hfr_mode != 0)) {
+ vfe31_ctrl->vfeFrameId++;
+ CDBG("Skip the SOF notification when HFR enabled\n");
+ return;
+ }
+ vfe31_ctrl->vfeFrameId++;
+ vfe31_send_isp_msg(vfe31_ctrl, MSG_ID_SOF_ACK);
+ CDBG("camif_sof_irq, frameId = %d\n", vfe31_ctrl->vfeFrameId);
+
+ if (vfe31_ctrl->sync_timer_state) {
+ if (vfe31_ctrl->sync_timer_repeat_count == 0)
+ vfe31_sync_timer_stop();
+ else
+ vfe31_ctrl->sync_timer_repeat_count--;
+ }
+}
+
+static void vfe31_process_error_irq(uint32_t errStatus)
+{
+ uint32_t reg_value, read_val;
+
+ if (errStatus & VFE31_IMASK_CAMIF_ERROR) {
+ pr_err("vfe31_irq: camif errors\n");
+ reg_value = msm_io_r(vfe31_ctrl->vfebase + VFE_CAMIF_STATUS);
+ pr_err("camifStatus = 0x%x\n", reg_value);
+ vfe31_send_isp_msg(vfe31_ctrl, MSG_ID_CAMIF_ERROR);
+ }
+
+ if (errStatus & VFE31_IMASK_STATS_CS_OVWR)
+ pr_err("vfe31_irq: stats cs overwrite\n");
+
+ if (errStatus & VFE31_IMASK_STATS_IHIST_OVWR)
+ pr_err("vfe31_irq: stats ihist overwrite\n");
+
+ if (errStatus & VFE31_IMASK_REALIGN_BUF_Y_OVFL)
+ pr_err("vfe31_irq: realign bug Y overflow\n");
+
+ if (errStatus & VFE31_IMASK_REALIGN_BUF_CB_OVFL)
+ pr_err("vfe31_irq: realign bug CB overflow\n");
+
+ if (errStatus & VFE31_IMASK_REALIGN_BUF_CR_OVFL)
+ pr_err("vfe31_irq: realign bug CR overflow\n");
+
+ if (errStatus & VFE31_IMASK_VIOLATION)
+ pr_err("vfe31_irq: violation interrupt\n");
+
+ if (errStatus & VFE31_IMASK_IMG_MAST_0_BUS_OVFL)
+ pr_err("vfe31_irq: image master 0 bus overflow\n");
+
+ if (errStatus & VFE31_IMASK_IMG_MAST_1_BUS_OVFL)
+ pr_err("vfe31_irq: image master 1 bus overflow\n");
+
+ if (errStatus & VFE31_IMASK_IMG_MAST_2_BUS_OVFL)
+ pr_err("vfe31_irq: image master 2 bus overflow\n");
+
+ if (errStatus & VFE31_IMASK_IMG_MAST_3_BUS_OVFL)
+ pr_err("vfe31_irq: image master 3 bus overflow\n");
+
+ if (errStatus & VFE31_IMASK_IMG_MAST_4_BUS_OVFL)
+ pr_err("vfe31_irq: image master 4 bus overflow\n");
+
+ if (errStatus & VFE31_IMASK_IMG_MAST_5_BUS_OVFL)
+ pr_err("vfe31_irq: image master 5 bus overflow\n");
+
+ if (errStatus & VFE31_IMASK_IMG_MAST_6_BUS_OVFL)
+ pr_err("vfe31_irq: image master 6 bus overflow\n");
+
+ if (errStatus & VFE31_IMASK_STATS_AE_BG_BUS_OVFL)
+ pr_err("vfe31_irq: ae/bg stats bus overflow\n");
+
+ if (errStatus & VFE31_IMASK_STATS_AF_BF_BUS_OVFL)
+ pr_err("vfe31_irq: af/bf stats bus overflow\n");
+
+ if (errStatus & VFE31_IMASK_STATS_AWB_BUS_OVFL)
+ pr_err("vfe31_irq: awb stats bus overflow\n");
+
+ if (errStatus & VFE31_IMASK_STATS_RS_BUS_OVFL)
+ pr_err("vfe31_irq: rs stats bus overflow\n");
+
+ if (errStatus & VFE31_IMASK_STATS_CS_BUS_OVFL)
+ pr_err("vfe31_irq: cs stats bus overflow\n");
+
+ if (errStatus & VFE31_IMASK_STATS_IHIST_BUS_OVFL)
+ pr_err("vfe31_irq: ihist stats bus overflow\n");
+
+ if (errStatus & VFE31_IMASK_STATS_SKIN_BHIST_BUS_OVFL)
+ pr_err("vfe31_irq: skin/bhist stats bus overflow\n");
+
+ if (errStatus & VFE31_IMASK_AXI_ERROR) {
+ pr_err("vfe31_irq: axi error\n");
+ /* read status too when overflow happens.*/
+ read_val = msm_io_r(vfe31_ctrl->vfebase +
+ VFE_BUS_PING_PONG_STATUS);
+ pr_debug("VFE_BUS_PING_PONG_STATUS = 0x%x\n", read_val);
+ read_val = msm_io_r(vfe31_ctrl->vfebase +
+ VFE_BUS_OPERATION_STATUS);
+ pr_debug("VFE_BUS_OPERATION_STATUS = 0x%x\n", read_val);
+ read_val = msm_io_r(vfe31_ctrl->vfebase +
+ VFE_BUS_IMAGE_MASTER_0_WR_PM_STATS_0);
+ pr_debug("VFE_BUS_IMAGE_MASTER_0_WR_PM_STATS_0 = 0x%x\n",
+ read_val);
+ read_val = msm_io_r(vfe31_ctrl->vfebase +
+ VFE_BUS_IMAGE_MASTER_0_WR_PM_STATS_1);
+ pr_debug("VFE_BUS_IMAGE_MASTER_0_WR_PM_STATS_1 = 0x%x\n",
+ read_val);
+ read_val = msm_io_r(vfe31_ctrl->vfebase +
+ VFE_AXI_STATUS);
+ pr_debug("VFE_AXI_STATUS = 0x%x\n", read_val);
+ }
+}
+static void vfe_send_outmsg(struct v4l2_subdev *sd, uint8_t msgid,
+ uint32_t ch0_paddr, uint32_t ch1_paddr, uint32_t ch2_paddr)
+{
+ struct isp_msg_output msg;
+
+ msg.output_id = msgid;
+ msg.buf.ch_paddr[0] = ch0_paddr;
+ msg.buf.ch_paddr[1] = ch1_paddr;
+ msg.buf.ch_paddr[2] = ch2_paddr;
+ msg.frameCounter = vfe31_ctrl->vfeFrameId;
+
+ v4l2_subdev_notify(&vfe31_ctrl->subdev,
+ NOTIFY_VFE_MSG_OUT, &msg);
+ return;
+}
+
+static void vfe31_process_output_path_irq_0(void)
+{
+ uint32_t ping_pong;
+ uint32_t ch0_paddr, ch1_paddr, ch2_paddr;
+ uint8_t out_bool = 0;
+ struct msm_free_buf *free_buf = NULL;
+
+ free_buf = vfe31_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
+ VFE_MSG_OUTPUT_PRIMARY);
+
+ /* we render frames in the following conditions:
+ * 1. Continuous mode and the free buffer is avaialable.
+ * 2. In snapshot shot mode, free buffer is not always available.
+ * when pending snapshot count is <=1, then no need to use
+ * free buffer.
+ */
+ out_bool = ((vfe31_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN ||
+ vfe31_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
+ vfe31_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG ||
+ vfe31_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB ||
+ vfe31_ctrl->operation_mode == VFE_OUTPUTS_RAW ||
+ vfe31_ctrl->liveshot_state == VFE_STATE_STARTED ||
+ vfe31_ctrl->liveshot_state == VFE_STATE_STOP_REQUESTED ||
+ vfe31_ctrl->liveshot_state == VFE_STATE_STOPPED) &&
+ (vfe31_ctrl->vfe_capture_count <= 1)) || free_buf;
+
+ if (out_bool) {
+ ping_pong = msm_io_r(vfe31_ctrl->vfebase +
+ VFE_BUS_PING_PONG_STATUS);
+
+ /* Channel 0*/
+ ch0_paddr = vfe31_get_ch_addr(ping_pong,
+ vfe31_ctrl->outpath.out0.ch0);
+ /* Channel 1*/
+ ch1_paddr = vfe31_get_ch_addr(ping_pong,
+ vfe31_ctrl->outpath.out0.ch1);
+ /* Channel 2*/
+ ch2_paddr = vfe31_get_ch_addr(ping_pong,
+ vfe31_ctrl->outpath.out0.ch2);
+
+ CDBG("output path 0, ch0 = 0x%x, ch1 = 0x%x, ch2 = 0x%x\n",
+ ch0_paddr, ch1_paddr, ch2_paddr);
+ if (free_buf) {
+ /* Y channel */
+ vfe31_put_ch_addr(ping_pong,
+ vfe31_ctrl->outpath.out0.ch0,
+ free_buf->ch_paddr[0]);
+ /* Chroma channel */
+ vfe31_put_ch_addr(ping_pong,
+ vfe31_ctrl->outpath.out0.ch1,
+ free_buf->ch_paddr[1]);
+ if (free_buf->num_planes > 2)
+ vfe31_put_ch_addr(ping_pong,
+ vfe31_ctrl->outpath.out0.ch2,
+ free_buf->ch_paddr[2]);
+ }
+ if (vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_THUMB_AND_MAIN ||
+ vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_MAIN_AND_THUMB ||
+ vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_THUMB_AND_JPEG ||
+ vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_JPEG_AND_THUMB ||
+ vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_RAW ||
+ vfe31_ctrl->liveshot_state == VFE_STATE_STOPPED)
+ vfe31_ctrl->outpath.out0.capture_cnt--;
+
+ vfe_send_outmsg(&vfe31_ctrl->subdev,
+ MSG_ID_OUTPUT_PRIMARY, ch0_paddr,
+ ch1_paddr, ch2_paddr);
+
+ if (vfe31_ctrl->liveshot_state == VFE_STATE_STOPPED)
+ vfe31_ctrl->liveshot_state = VFE_STATE_IDLE;
+
+ } else {
+ vfe31_ctrl->outpath.out0.frame_drop_cnt++;
+ CDBG("path_irq_0 - no free buffer!\n");
+ }
+}
+
+static void vfe31_process_output_path_irq_1(void)
+{
+ uint32_t ping_pong;
+ uint32_t ch0_paddr, ch1_paddr, ch2_paddr;
+ /* this must be snapshot main image output. */
+ uint8_t out_bool = 0;
+ struct msm_free_buf *free_buf = NULL;
+
+ free_buf = vfe31_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
+ VFE_MSG_OUTPUT_SECONDARY);
+ out_bool = ((vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_THUMB_AND_MAIN ||
+ vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_MAIN_AND_THUMB ||
+ vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_RAW ||
+ vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_JPEG_AND_THUMB) &&
+ (vfe31_ctrl->vfe_capture_count <= 1)) || free_buf;
+
+ if (out_bool) {
+ ping_pong = msm_io_r(vfe31_ctrl->vfebase +
+ VFE_BUS_PING_PONG_STATUS);
+
+ /* Y channel */
+ ch0_paddr = vfe31_get_ch_addr(ping_pong,
+ vfe31_ctrl->outpath.out1.ch0);
+ /* Chroma channel */
+ ch1_paddr = vfe31_get_ch_addr(ping_pong,
+ vfe31_ctrl->outpath.out1.ch1);
+ ch2_paddr = vfe31_get_ch_addr(ping_pong,
+ vfe31_ctrl->outpath.out1.ch2);
+
+ pr_debug("%s ch0 = 0x%x, ch1 = 0x%x, ch2 = 0x%x\n",
+ __func__, ch0_paddr, ch1_paddr, ch2_paddr);
+ if (free_buf) {
+ /* Y channel */
+ vfe31_put_ch_addr(ping_pong,
+ vfe31_ctrl->outpath.out1.ch0,
+ free_buf->ch_paddr[0]);
+ /* Chroma channel */
+ vfe31_put_ch_addr(ping_pong,
+ vfe31_ctrl->outpath.out1.ch1,
+ free_buf->ch_paddr[1]);
+ if (free_buf->num_planes > 2)
+ vfe31_put_ch_addr(ping_pong,
+ vfe31_ctrl->outpath.out1.ch2,
+ free_buf->ch_paddr[2]);
+ }
+ if (vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_THUMB_AND_MAIN ||
+ vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_MAIN_AND_THUMB ||
+ vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_RAW ||
+ vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_JPEG_AND_THUMB)
+ vfe31_ctrl->outpath.out1.capture_cnt--;
+
+ vfe_send_outmsg(&vfe31_ctrl->subdev,
+ MSG_ID_OUTPUT_SECONDARY, ch0_paddr,
+ ch1_paddr, ch2_paddr);
+ } else {
+ vfe31_ctrl->outpath.out1.frame_drop_cnt++;
+ CDBG("path_irq_1 - no free buffer!\n");
+ }
+}
+
+static uint32_t vfe31_process_stats_irq_common(uint32_t statsNum,
+ uint32_t newAddr)
+{
+
+ uint32_t pingpongStatus;
+ uint32_t returnAddr;
+ uint32_t pingpongAddr;
+
+ /* must be 0=ping, 1=pong */
+ pingpongStatus =
+ ((msm_io_r(vfe31_ctrl->vfebase +
+ VFE_BUS_PING_PONG_STATUS))
+ & ((uint32_t)(1<<(statsNum + 7)))) >> (statsNum + 7);
+ /* stats bits starts at 7 */
+ CDBG("statsNum %d, pingpongStatus %d\n", statsNum, pingpongStatus);
+ pingpongAddr =
+ ((uint32_t)(vfe31_ctrl->vfebase +
+ VFE_BUS_STATS_PING_PONG_BASE)) +
+ (3*statsNum)*4 + (1-pingpongStatus)*4;
+ returnAddr = msm_io_r((uint32_t *)pingpongAddr);
+ msm_io_w(newAddr, (uint32_t *)pingpongAddr);
+ return returnAddr;
+}
+
+static void
+vfe_send_stats_msg(uint32_t bufAddress, uint32_t statsNum)
+{
+ unsigned long flags;
+ /* fill message with right content. */
+ /* @todo This is causing issues, need further investigate */
+ /* spin_lock_irqsave(&ctrl->state_lock, flags); */
+ struct isp_msg_stats msgStats;
+ msgStats.frameCounter = vfe31_ctrl->vfeFrameId;
+ msgStats.buffer = bufAddress;
+
+ switch (statsNum) {
+ case STATS_AE_NUM:{
+ msgStats.id = MSG_ID_STATS_AEC;
+ spin_lock_irqsave(&vfe31_ctrl->aec_ack_lock, flags);
+ vfe31_ctrl->aecStatsControl.ackPending = TRUE;
+ spin_unlock_irqrestore(&vfe31_ctrl->aec_ack_lock, flags);
+ }
+ break;
+ case STATS_AF_NUM:{
+ msgStats.id = MSG_ID_STATS_AF;
+ spin_lock_irqsave(&vfe31_ctrl->af_ack_lock, flags);
+ vfe31_ctrl->afStatsControl.ackPending = TRUE;
+ spin_unlock_irqrestore(&vfe31_ctrl->af_ack_lock, flags);
+ }
+ break;
+ case STATS_AWB_NUM: {
+ msgStats.id = MSG_ID_STATS_AWB;
+ spin_lock_irqsave(&vfe31_ctrl->awb_ack_lock, flags);
+ vfe31_ctrl->awbStatsControl.ackPending = TRUE;
+ spin_unlock_irqrestore(&vfe31_ctrl->awb_ack_lock, flags);
+ }
+ break;
+
+ case STATS_IHIST_NUM: {
+ msgStats.id = MSG_ID_STATS_IHIST;
+ spin_lock_irqsave(&vfe31_ctrl->ihist_ack_lock, flags);
+ vfe31_ctrl->ihistStatsControl.ackPending = TRUE;
+ spin_unlock_irqrestore(&vfe31_ctrl->ihist_ack_lock, flags);
+ }
+ break;
+ case STATS_RS_NUM: {
+ msgStats.id = MSG_ID_STATS_RS;
+ spin_lock_irqsave(&vfe31_ctrl->rs_ack_lock, flags);
+ vfe31_ctrl->rsStatsControl.ackPending = TRUE;
+ spin_unlock_irqrestore(&vfe31_ctrl->rs_ack_lock, flags);
+ }
+ break;
+ case STATS_CS_NUM: {
+ msgStats.id = MSG_ID_STATS_CS;
+ spin_lock_irqsave(&vfe31_ctrl->cs_ack_lock, flags);
+ vfe31_ctrl->csStatsControl.ackPending = TRUE;
+ spin_unlock_irqrestore(&vfe31_ctrl->cs_ack_lock, flags);
+ }
+ break;
+
+ default:
+ goto stats_done;
+ }
+
+ v4l2_subdev_notify(&vfe31_ctrl->subdev,
+ NOTIFY_VFE_MSG_STATS,
+ &msgStats);
+stats_done:
+ /* spin_unlock_irqrestore(&ctrl->state_lock, flags); */
+ return;
+}
+
+static void vfe_send_comp_stats_msg(uint32_t status_bits)
+{
+ struct msm_stats_buf msgStats;
+ uint32_t temp;
+
+ msgStats.frame_id = vfe31_ctrl->vfeFrameId;
+ msgStats.status_bits = status_bits;
+
+ msgStats.aec.buff = vfe31_ctrl->aecStatsControl.bufToRender;
+ msgStats.awb.buff = vfe31_ctrl->awbStatsControl.bufToRender;
+ msgStats.af.buff = vfe31_ctrl->afStatsControl.bufToRender;
+
+ msgStats.ihist.buff = vfe31_ctrl->ihistStatsControl.bufToRender;
+ msgStats.rs.buff = vfe31_ctrl->rsStatsControl.bufToRender;
+ msgStats.cs.buff = vfe31_ctrl->csStatsControl.bufToRender;
+
+ temp = msm_io_r(vfe31_ctrl->vfebase + VFE_STATS_AWB_SGW_CFG);
+ msgStats.awb_ymin = (0xFF00 & temp) >> 8;
+
+ v4l2_subdev_notify(&vfe31_ctrl->subdev,
+ NOTIFY_VFE_MSG_COMP_STATS, &msgStats);
+}
+
+static void vfe31_process_stats_ae_irq(void)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&vfe31_ctrl->aec_ack_lock, flags);
+ if (!(vfe31_ctrl->aecStatsControl.ackPending)) {
+ spin_unlock_irqrestore(&vfe31_ctrl->aec_ack_lock, flags);
+ vfe31_ctrl->aecStatsControl.bufToRender =
+ vfe31_process_stats_irq_common(STATS_AE_NUM,
+ vfe31_ctrl->aecStatsControl.nextFrameAddrBuf);
+
+ vfe_send_stats_msg(vfe31_ctrl->aecStatsControl.bufToRender,
+ STATS_AE_NUM);
+ } else{
+ spin_unlock_irqrestore(&vfe31_ctrl->aec_ack_lock, flags);
+ vfe31_ctrl->aecStatsControl.droppedStatsFrameCount++;
+ CDBG("%s: droppedStatsFrameCount = %d", __func__,
+ vfe31_ctrl->aecStatsControl.droppedStatsFrameCount);
+ }
+}
+
+static void vfe31_process_stats_awb_irq(void)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&vfe31_ctrl->awb_ack_lock, flags);
+ if (!(vfe31_ctrl->awbStatsControl.ackPending)) {
+ spin_unlock_irqrestore(&vfe31_ctrl->awb_ack_lock, flags);
+ vfe31_ctrl->awbStatsControl.bufToRender =
+ vfe31_process_stats_irq_common(STATS_AWB_NUM,
+ vfe31_ctrl->awbStatsControl.nextFrameAddrBuf);
+
+ vfe_send_stats_msg(vfe31_ctrl->awbStatsControl.bufToRender,
+ STATS_AWB_NUM);
+ } else{
+ spin_unlock_irqrestore(&vfe31_ctrl->awb_ack_lock, flags);
+ vfe31_ctrl->awbStatsControl.droppedStatsFrameCount++;
+ CDBG("%s: droppedStatsFrameCount = %d", __func__,
+ vfe31_ctrl->awbStatsControl.droppedStatsFrameCount);
+ }
+}
+
+static void vfe31_process_stats_af_irq(void)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&vfe31_ctrl->af_ack_lock, flags);
+ if (!(vfe31_ctrl->afStatsControl.ackPending)) {
+ spin_unlock_irqrestore(&vfe31_ctrl->af_ack_lock, flags);
+ vfe31_ctrl->afStatsControl.bufToRender =
+ vfe31_process_stats_irq_common(STATS_AF_NUM,
+ vfe31_ctrl->afStatsControl.nextFrameAddrBuf);
+
+ vfe_send_stats_msg(vfe31_ctrl->afStatsControl.bufToRender,
+ STATS_AF_NUM);
+ } else{
+ spin_unlock_irqrestore(&vfe31_ctrl->af_ack_lock, flags);
+ vfe31_ctrl->afStatsControl.droppedStatsFrameCount++;
+ CDBG("%s: droppedStatsFrameCount = %d", __func__,
+ vfe31_ctrl->afStatsControl.droppedStatsFrameCount);
+ }
+}
+
+static void vfe31_process_stats_ihist_irq(void)
+{
+ if (!(vfe31_ctrl->ihistStatsControl.ackPending)) {
+ vfe31_ctrl->ihistStatsControl.bufToRender =
+ vfe31_process_stats_irq_common(STATS_IHIST_NUM,
+ vfe31_ctrl->ihistStatsControl.nextFrameAddrBuf);
+
+ vfe_send_stats_msg(vfe31_ctrl->ihistStatsControl.bufToRender,
+ STATS_IHIST_NUM);
+ } else {
+ vfe31_ctrl->ihistStatsControl.droppedStatsFrameCount++;
+ CDBG("%s: droppedStatsFrameCount = %d", __func__,
+ vfe31_ctrl->ihistStatsControl.droppedStatsFrameCount);
+ }
+}
+
+static void vfe31_process_stats_rs_irq(void)
+{
+ if (!(vfe31_ctrl->rsStatsControl.ackPending)) {
+ vfe31_ctrl->rsStatsControl.bufToRender =
+ vfe31_process_stats_irq_common(STATS_RS_NUM,
+ vfe31_ctrl->rsStatsControl.nextFrameAddrBuf);
+
+ vfe_send_stats_msg(vfe31_ctrl->rsStatsControl.bufToRender,
+ STATS_RS_NUM);
+ } else {
+ vfe31_ctrl->rsStatsControl.droppedStatsFrameCount++;
+ CDBG("%s: droppedStatsFrameCount = %d", __func__,
+ vfe31_ctrl->rsStatsControl.droppedStatsFrameCount);
+ }
+}
+
+static void vfe31_process_stats_cs_irq(void)
+{
+ if (!(vfe31_ctrl->csStatsControl.ackPending)) {
+ vfe31_ctrl->csStatsControl.bufToRender =
+ vfe31_process_stats_irq_common(STATS_CS_NUM,
+ vfe31_ctrl->csStatsControl.nextFrameAddrBuf);
+
+ vfe_send_stats_msg(vfe31_ctrl->csStatsControl.bufToRender,
+ STATS_CS_NUM);
+ } else {
+ vfe31_ctrl->csStatsControl.droppedStatsFrameCount++;
+ CDBG("%s: droppedStatsFrameCount = %d", __func__,
+ vfe31_ctrl->csStatsControl.droppedStatsFrameCount);
+ }
+}
+
+static void vfe31_process_stats(uint32_t status_bits)
+{
+ unsigned long flags;
+ int32_t process_stats = false;
+ CDBG("%s, stats = 0x%x\n", __func__, status_bits);
+
+ spin_lock_irqsave(&vfe31_ctrl->comp_stats_ack_lock, flags);
+ if (status_bits & VFE_IRQ_STATUS0_STATS_AEC) {
+ if (!vfe31_ctrl->aecStatsControl.ackPending) {
+ vfe31_ctrl->aecStatsControl.ackPending = TRUE;
+ vfe31_ctrl->aecStatsControl.bufToRender =
+ vfe31_process_stats_irq_common(STATS_AE_NUM,
+ vfe31_ctrl->aecStatsControl.nextFrameAddrBuf);
+ process_stats = true;
+ } else{
+ vfe31_ctrl->aecStatsControl.bufToRender = 0;
+ vfe31_ctrl->aecStatsControl.droppedStatsFrameCount++;
+ }
+ } else {
+ vfe31_ctrl->aecStatsControl.bufToRender = 0;
+ }
+
+ if (status_bits & VFE_IRQ_STATUS0_STATS_AWB) {
+ if (!vfe31_ctrl->awbStatsControl.ackPending) {
+ vfe31_ctrl->awbStatsControl.ackPending = TRUE;
+ vfe31_ctrl->awbStatsControl.bufToRender =
+ vfe31_process_stats_irq_common(STATS_AWB_NUM,
+ vfe31_ctrl->awbStatsControl.nextFrameAddrBuf);
+ process_stats = true;
+ } else{
+ vfe31_ctrl->awbStatsControl.droppedStatsFrameCount++;
+ vfe31_ctrl->awbStatsControl.bufToRender = 0;
+ }
+ } else {
+ vfe31_ctrl->awbStatsControl.bufToRender = 0;
+ }
+
+
+ if (status_bits & VFE_IRQ_STATUS0_STATS_AF) {
+ if (!vfe31_ctrl->afStatsControl.ackPending) {
+ vfe31_ctrl->afStatsControl.ackPending = TRUE;
+ vfe31_ctrl->afStatsControl.bufToRender =
+ vfe31_process_stats_irq_common(STATS_AF_NUM,
+ vfe31_ctrl->afStatsControl.nextFrameAddrBuf);
+ process_stats = true;
+ } else {
+ vfe31_ctrl->afStatsControl.bufToRender = 0;
+ vfe31_ctrl->afStatsControl.droppedStatsFrameCount++;
+ }
+ } else {
+ vfe31_ctrl->afStatsControl.bufToRender = 0;
+ }
+
+ if (status_bits & VFE_IRQ_STATUS0_STATS_IHIST) {
+ if (!vfe31_ctrl->ihistStatsControl.ackPending) {
+ vfe31_ctrl->ihistStatsControl.ackPending = TRUE;
+ vfe31_ctrl->ihistStatsControl.bufToRender =
+ vfe31_process_stats_irq_common(STATS_IHIST_NUM,
+ vfe31_ctrl->ihistStatsControl.nextFrameAddrBuf);
+ process_stats = true;
+ } else {
+ vfe31_ctrl->ihistStatsControl.droppedStatsFrameCount++;
+ vfe31_ctrl->ihistStatsControl.bufToRender = 0;
+ }
+ } else {
+ vfe31_ctrl->ihistStatsControl.bufToRender = 0;
+ }
+
+ if (status_bits & VFE_IRQ_STATUS0_STATS_RS) {
+ if (!vfe31_ctrl->rsStatsControl.ackPending) {
+ vfe31_ctrl->rsStatsControl.ackPending = TRUE;
+ vfe31_ctrl->rsStatsControl.bufToRender =
+ vfe31_process_stats_irq_common(STATS_RS_NUM,
+ vfe31_ctrl->rsStatsControl.nextFrameAddrBuf);
+ process_stats = true;
+ } else {
+ vfe31_ctrl->rsStatsControl.droppedStatsFrameCount++;
+ vfe31_ctrl->rsStatsControl.bufToRender = 0;
+ }
+ } else {
+ vfe31_ctrl->rsStatsControl.bufToRender = 0;
+ }
+
+
+ if (status_bits & VFE_IRQ_STATUS0_STATS_CS) {
+ if (!vfe31_ctrl->csStatsControl.ackPending) {
+ vfe31_ctrl->csStatsControl.ackPending = TRUE;
+ vfe31_ctrl->csStatsControl.bufToRender =
+ vfe31_process_stats_irq_common(STATS_CS_NUM,
+ vfe31_ctrl->csStatsControl.nextFrameAddrBuf);
+ process_stats = true;
+ } else {
+ vfe31_ctrl->csStatsControl.droppedStatsFrameCount++;
+ vfe31_ctrl->csStatsControl.bufToRender = 0;
+ }
+ } else {
+ vfe31_ctrl->csStatsControl.bufToRender = 0;
+ }
+
+ spin_unlock_irqrestore(&vfe31_ctrl->comp_stats_ack_lock, flags);
+ if (process_stats)
+ vfe_send_comp_stats_msg(status_bits);
+
+ return;
+}
+
+static void vfe31_process_stats_irq(uint32_t *irqstatus)
+{
+ uint32_t status_bits = VFE_COM_STATUS & *irqstatus;
+
+ if ((vfe31_ctrl->hfr_mode != HFR_MODE_OFF) &&
+ (vfe31_ctrl->vfeFrameId % vfe31_ctrl->hfr_mode != 0)) {
+ CDBG("Skip the stats when HFR enabled\n");
+ return;
+ }
+
+ vfe31_process_stats(status_bits);
+ return;
+}
+
+static void vfe31_do_tasklet(unsigned long data)
+{
+ unsigned long flags;
+
+ struct vfe31_isr_queue_cmd *qcmd = NULL;
+
+ CDBG("=== vfe31_do_tasklet start ===\n");
+
+ while (atomic_read(&irq_cnt)) {
+ spin_lock_irqsave(&vfe31_ctrl->tasklet_lock, flags);
+ qcmd = list_first_entry(&vfe31_ctrl->tasklet_q,
+ struct vfe31_isr_queue_cmd, list);
+ atomic_sub(1, &irq_cnt);
+
+ if (!qcmd) {
+ spin_unlock_irqrestore(&vfe31_ctrl->tasklet_lock,
+ flags);
+ return;
+ }
+
+ list_del(&qcmd->list);
+ spin_unlock_irqrestore(&vfe31_ctrl->tasklet_lock,
+ flags);
+
+ if (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_CAMIF_SOF_MASK) {
+ CDBG("irq camifSofIrq\n");
+ vfe31_process_camif_sof_irq();
+ }
+ /* interrupt to be processed, *qcmd has the payload. */
+ if (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_REG_UPDATE_MASK) {
+ CDBG("irq regUpdateIrq\n");
+ vfe31_process_reg_update_irq();
+ }
+
+ if (qcmd->vfeInterruptStatus1 &
+ VFE_IMASK_WHILE_STOPPING_1) {
+ CDBG("irq resetAckIrq\n");
+ vfe31_process_reset_irq();
+ }
+
+ if (atomic_read(&vfe31_ctrl->vstate)) {
+ if (qcmd->vfeInterruptStatus1 &
+ VFE31_IMASK_ERROR_ONLY_1) {
+ pr_err("irq errorIrq\n");
+ vfe31_process_error_irq(
+ qcmd->vfeInterruptStatus1 &
+ VFE31_IMASK_ERROR_ONLY_1);
+ }
+ /* next, check output path related interrupts. */
+ if (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK) {
+ CDBG("Image composite done 0 irq occured.\n");
+ vfe31_process_output_path_irq_0();
+ }
+ if (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK) {
+ CDBG("Image composite done 1 irq occured.\n");
+ vfe31_process_output_path_irq_1();
+ }
+ /* in snapshot mode if done then send
+ snapshot done message */
+ if (vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_THUMB_AND_MAIN ||
+ vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_MAIN_AND_THUMB ||
+ vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_THUMB_AND_JPEG ||
+ vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_JPEG_AND_THUMB ||
+ vfe31_ctrl->operation_mode ==
+ VFE_OUTPUTS_RAW) {
+ if ((vfe31_ctrl->outpath.out0.capture_cnt == 0)
+ && (vfe31_ctrl->outpath.out1.
+ capture_cnt == 0)) {
+ msm_io_w_mb(
+ CAMIF_COMMAND_STOP_IMMEDIATELY,
+ vfe31_ctrl->vfebase +
+ VFE_CAMIF_COMMAND);
+ vfe31_send_isp_msg(vfe31_ctrl,
+ MSG_ID_SNAPSHOT_DONE);
+ }
+ }
+ /* then process stats irq. */
+ if (vfe31_ctrl->stats_comp) {
+ /* process stats comb interrupt. */
+ if (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK) {
+ CDBG("Stats composite irq occured.\n");
+ vfe31_process_stats_irq(
+ &qcmd->vfeInterruptStatus0);
+ }
+ } else {
+ /* process individual stats interrupt. */
+ if (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_STATS_AEC) {
+ CDBG("Stats AEC irq occured.\n");
+ vfe31_process_stats_ae_irq();
+ }
+ if (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_STATS_AWB) {
+ CDBG("Stats AWB irq occured.\n");
+ vfe31_process_stats_awb_irq();
+ }
+ if (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_STATS_AF) {
+ CDBG("Stats AF irq occured.\n");
+ vfe31_process_stats_af_irq();
+ }
+ if (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_STATS_IHIST) {
+ CDBG("Stats IHIST irq occured.\n");
+ vfe31_process_stats_ihist_irq();
+ }
+ if (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_STATS_RS) {
+ CDBG("Stats RS irq occured.\n");
+ vfe31_process_stats_rs_irq();
+ }
+ if (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_STATS_CS) {
+ CDBG("Stats CS irq occured.\n");
+ vfe31_process_stats_cs_irq();
+ }
+ if (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_SYNC_TIMER0) {
+ CDBG("SYNC_TIMER 0 irq occured.\n");
+ vfe31_send_isp_msg(vfe31_ctrl,
+ MSG_ID_SYNC_TIMER0_DONE);
+ }
+ if (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_SYNC_TIMER1) {
+ CDBG("SYNC_TIMER 1 irq occured.\n");
+ vfe31_send_isp_msg(vfe31_ctrl,
+ MSG_ID_SYNC_TIMER1_DONE);
+ }
+ if (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_SYNC_TIMER2) {
+ CDBG("SYNC_TIMER 2 irq occured.\n");
+ vfe31_send_isp_msg(vfe31_ctrl,
+ MSG_ID_SYNC_TIMER2_DONE);
+ }
+ }
+ }
+ kfree(qcmd);
+ }
+ CDBG("=== vfe31_do_tasklet end ===\n");
+}
+
+DECLARE_TASKLET(vfe31_tasklet, vfe31_do_tasklet, 0);
+
+static irqreturn_t vfe31_parse_irq(int irq_num, void *data)
+{
+ unsigned long flags;
+ struct vfe31_irq_status irq;
+ struct vfe31_isr_queue_cmd *qcmd;
+
+ CDBG("vfe_parse_irq\n");
+
+ vfe31_read_irq_status(&irq);
+
+ if ((irq.vfeIrqStatus0 == 0) && (irq.vfeIrqStatus1 == 0)) {
+ CDBG("vfe_parse_irq: vfeIrqStatus0 & 1 are both 0!\n");
+ return IRQ_HANDLED;
+ }
+
+ qcmd = kzalloc(sizeof(struct vfe31_isr_queue_cmd),
+ GFP_ATOMIC);
+ if (!qcmd) {
+ pr_err("vfe_parse_irq: qcmd malloc failed!\n");
+ return IRQ_HANDLED;
+ }
+
+ spin_lock_irqsave(&vfe31_ctrl->stop_flag_lock, flags);
+ if (vfe31_ctrl->stop_ack_pending) {
+ irq.vfeIrqStatus0 &= VFE_IMASK_WHILE_STOPPING_0;
+ irq.vfeIrqStatus1 &= VFE_IMASK_WHILE_STOPPING_1;
+ }
+ spin_unlock_irqrestore(&vfe31_ctrl->stop_flag_lock, flags);
+
+ CDBG("vfe_parse_irq: Irq_status0 = 0x%x, Irq_status1 = 0x%x.\n",
+ irq.vfeIrqStatus0, irq.vfeIrqStatus1);
+
+ qcmd->vfeInterruptStatus0 = irq.vfeIrqStatus0;
+ qcmd->vfeInterruptStatus1 = irq.vfeIrqStatus1;
+
+ spin_lock_irqsave(&vfe31_ctrl->tasklet_lock, flags);
+ list_add_tail(&qcmd->list, &vfe31_ctrl->tasklet_q);
+
+ atomic_add(1, &irq_cnt);
+ spin_unlock_irqrestore(&vfe31_ctrl->tasklet_lock, flags);
+ tasklet_schedule(&vfe31_tasklet);
+ return IRQ_HANDLED;
+}
+
+static long msm_vfe_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int subdev_cmd, void *arg)
+{
+ struct msm_isp_cmd vfecmd;
+ struct msm_camvfe_params *vfe_params =
+ (struct msm_camvfe_params *)arg;
+ struct msm_vfe_cfg_cmd *cmd = vfe_params->vfe_cfg;
+ void *data = vfe_params->data;
+
+ long rc = 0;
+ uint32_t i = 0;
+ struct vfe_cmd_stats_buf *scfg = NULL;
+ struct msm_pmem_region *regptr = NULL;
+ struct vfe_cmd_stats_ack *sack = NULL;
+ if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
+ cmd->cmd_type != CMD_CONFIG_PONG_ADDR &&
+ cmd->cmd_type != CMD_CONFIG_FREE_BUF_ADDR &&
+ cmd->cmd_type != CMD_STATS_AEC_BUF_RELEASE &&
+ cmd->cmd_type != CMD_STATS_AWB_BUF_RELEASE &&
+ cmd->cmd_type != CMD_STATS_IHIST_BUF_RELEASE &&
+ cmd->cmd_type != CMD_STATS_RS_BUF_RELEASE &&
+ cmd->cmd_type != CMD_STATS_CS_BUF_RELEASE &&
+ cmd->cmd_type != CMD_STATS_AF_BUF_RELEASE) {
+ if (copy_from_user(&vfecmd,
+ (void __user *)(cmd->value),
+ sizeof(vfecmd))) {
+ pr_err("%s %d: copy_from_user failed\n", __func__,
+ __LINE__);
+ return -EFAULT;
+ }
+ } else {
+ /* here eith stats release or frame release. */
+ if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
+ cmd->cmd_type != CMD_CONFIG_PONG_ADDR &&
+ cmd->cmd_type != CMD_CONFIG_FREE_BUF_ADDR) {
+ /* then must be stats release. */
+ if (!data)
+ return -EFAULT;
+ sack = kmalloc(sizeof(struct vfe_cmd_stats_ack),
+ GFP_ATOMIC);
+ if (!sack)
+ return -ENOMEM;
+
+ sack->nextStatsBuf = *(uint32_t *)data;
+ }
+ }
+
+ CDBG("%s: cmdType = %d\n", __func__, cmd->cmd_type);
+
+ if ((cmd->cmd_type == CMD_STATS_AF_ENABLE) ||
+ (cmd->cmd_type == CMD_STATS_AWB_ENABLE) ||
+ (cmd->cmd_type == CMD_STATS_IHIST_ENABLE) ||
+ (cmd->cmd_type == CMD_STATS_RS_ENABLE) ||
+ (cmd->cmd_type == CMD_STATS_CS_ENABLE) ||
+ (cmd->cmd_type == CMD_STATS_AEC_ENABLE)) {
+ struct axidata *axid;
+ axid = data;
+ if (!axid) {
+ rc = -EFAULT;
+ goto vfe31_config_done;
+ }
+
+ scfg =
+ kmalloc(sizeof(struct vfe_cmd_stats_buf),
+ GFP_ATOMIC);
+ if (!scfg) {
+ rc = -ENOMEM;
+ goto vfe31_config_done;
+ }
+ regptr = axid->region;
+ if (axid->bufnum1 > 0) {
+ for (i = 0; i < axid->bufnum1; i++) {
+ scfg->statsBuf[i] =
+ (uint32_t)(regptr->paddr);
+ regptr++;
+ }
+ }
+ /* individual */
+ switch (cmd->cmd_type) {
+ case CMD_STATS_AEC_ENABLE:
+ rc = vfe_stats_aec_buf_init(scfg);
+ break;
+ case CMD_STATS_AF_ENABLE:
+ rc = vfe_stats_af_buf_init(scfg);
+ break;
+ case CMD_STATS_AWB_ENABLE:
+ rc = vfe_stats_awb_buf_init(scfg);
+ break;
+ case CMD_STATS_IHIST_ENABLE:
+ rc = vfe_stats_ihist_buf_init(scfg);
+ break;
+ case CMD_STATS_RS_ENABLE:
+ rc = vfe_stats_rs_buf_init(scfg);
+ break;
+ case CMD_STATS_CS_ENABLE:
+ rc = vfe_stats_cs_buf_init(scfg);
+ break;
+ default:
+ pr_err("%s Unsupported cmd type %d",
+ __func__, cmd->cmd_type);
+ break;
+ }
+ goto vfe31_config_done;
+ }
+ switch (cmd->cmd_type) {
+ case CMD_GENERAL: {
+ rc = vfe31_proc_general(&vfecmd);
+ }
+ break;
+ case CMD_CONFIG_PING_ADDR: {
+ int path = *((int *)cmd->value);
+ struct vfe31_output_ch *outch = vfe31_get_ch(path);
+ outch->ping = *((struct msm_free_buf *)data);
+ }
+ break;
+
+ case CMD_CONFIG_PONG_ADDR: {
+ int path = *((int *)cmd->value);
+ struct vfe31_output_ch *outch = vfe31_get_ch(path);
+ outch->pong = *((struct msm_free_buf *)data);
+ }
+ break;
+
+ case CMD_CONFIG_FREE_BUF_ADDR: {
+ int path = *((int *)cmd->value);
+ struct vfe31_output_ch *outch = vfe31_get_ch(path);
+ outch->free_buf = *((struct msm_free_buf *)data);
+ }
+ break;
+
+ case CMD_SNAP_BUF_RELEASE:
+ break;
+
+ case CMD_STATS_AEC_BUF_RELEASE: {
+ vfe31_stats_aec_ack(sack);
+ }
+ break;
+
+ case CMD_STATS_AF_BUF_RELEASE: {
+ vfe31_stats_af_ack(sack);
+ }
+ break;
+
+ case CMD_STATS_AWB_BUF_RELEASE: {
+ vfe31_stats_awb_ack(sack);
+ }
+ break;
+
+ case CMD_STATS_IHIST_BUF_RELEASE: {
+ vfe31_stats_ihist_ack(sack);
+ }
+ break;
+
+ case CMD_STATS_RS_BUF_RELEASE: {
+ vfe31_stats_rs_ack(sack);
+ }
+ break;
+
+ case CMD_STATS_CS_BUF_RELEASE: {
+ vfe31_stats_cs_ack(sack);
+ }
+ break;
+
+ case CMD_AXI_CFG_PRIM: {
+ uint32_t *axio = NULL;
+ axio = kmalloc(vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length,
+ GFP_ATOMIC);
+ if (!axio) {
+ rc = -ENOMEM;
+ break;
+ }
+
+ if (copy_from_user(axio, (void __user *)(vfecmd.value),
+ vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+ kfree(axio);
+ rc = -EFAULT;
+ break;
+ }
+ vfe31_config_axi(OUTPUT_PRIM, axio);
+ kfree(axio);
+ }
+ break;
+
+ case CMD_AXI_CFG_PRIM_ALL_CHNLS: {
+ uint32_t *axio = NULL;
+ axio = kmalloc(vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length,
+ GFP_ATOMIC);
+ if (!axio) {
+ rc = -ENOMEM;
+ break;
+ }
+
+ if (copy_from_user(axio, (void __user *)(vfecmd.value),
+ vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+ kfree(axio);
+ rc = -EFAULT;
+ break;
+ }
+ vfe31_config_axi(OUTPUT_PRIM_ALL_CHNLS, axio);
+ kfree(axio);
+ }
+ break;
+
+ case CMD_AXI_CFG_PRIM|CMD_AXI_CFG_SEC: {
+ uint32_t *axio = NULL;
+ axio = kmalloc(vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length,
+ GFP_ATOMIC);
+ if (!axio) {
+ rc = -ENOMEM;
+ break;
+ }
+
+ if (copy_from_user(axio, (void __user *)(vfecmd.value),
+ vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+ kfree(axio);
+ rc = -EFAULT;
+ break;
+ }
+ vfe31_config_axi(OUTPUT_PRIM|OUTPUT_SEC, axio);
+ kfree(axio);
+ }
+ break;
+
+ case CMD_AXI_CFG_PRIM|CMD_AXI_CFG_SEC_ALL_CHNLS: {
+ uint32_t *axio = NULL;
+ axio = kmalloc(vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length,
+ GFP_ATOMIC);
+ if (!axio) {
+ rc = -ENOMEM;
+ break;
+ }
+
+ if (copy_from_user(axio, (void __user *)(vfecmd.value),
+ vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+ kfree(axio);
+ rc = -EFAULT;
+ break;
+ }
+ vfe31_config_axi(OUTPUT_PRIM|OUTPUT_SEC_ALL_CHNLS, axio);
+ kfree(axio);
+ }
+ break;
+
+ case CMD_AXI_CFG_PRIM_ALL_CHNLS|CMD_AXI_CFG_SEC: {
+ uint32_t *axio = NULL;
+ axio = kmalloc(vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length,
+ GFP_ATOMIC);
+ if (!axio) {
+ rc = -ENOMEM;
+ break;
+ }
+
+ if (copy_from_user(axio, (void __user *)(vfecmd.value),
+ vfe31_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+ kfree(axio);
+ rc = -EFAULT;
+ break;
+ }
+ vfe31_config_axi(OUTPUT_PRIM_ALL_CHNLS|OUTPUT_SEC, axio);
+ kfree(axio);
+ }
+ break;
+
+ case CMD_AXI_CFG_PRIM_ALL_CHNLS|CMD_AXI_CFG_SEC_ALL_CHNLS: {
+ pr_err("%s Invalid/Unsupported AXI configuration %x",
+ __func__, cmd->cmd_type);
+ }
+ break;
+
+ default:
+ pr_err("%s Unsupported AXI configuration %x ", __func__,
+ cmd->cmd_type);
+ break;
+ }
+vfe31_config_done:
+ kfree(scfg);
+ kfree(sack);
+ CDBG("%s done: rc = %d\n", __func__, (int) rc);
+ return rc;
+}
+
+static int msm_vfe_subdev_s_crystal_freq(struct v4l2_subdev *sd,
+ u32 freq, u32 flags)
+{
+ int rc = 0;
+ int round_rate;
+
+ round_rate = clk_round_rate(vfe31_ctrl->vfe_clk[0], freq);
+ if (rc < 0) {
+ pr_err("%s: clk_round_rate failed %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ vfe_clk_rate = round_rate;
+ rc = clk_set_rate(vfe31_ctrl->vfe_clk[0], round_rate);
+ if (rc < 0)
+ pr_err("%s: clk_set_rate failed %d\n",
+ __func__, rc);
+
+ return rc;
+}
+
+static const struct v4l2_subdev_video_ops msm_vfe_subdev_video_ops = {
+ .s_crystal_freq = msm_vfe_subdev_s_crystal_freq,
+};
+
+static const struct v4l2_subdev_core_ops msm_vfe_subdev_core_ops = {
+ .ioctl = msm_vfe_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_vfe_subdev_ops = {
+ .core = &msm_vfe_subdev_core_ops,
+ .video = &msm_vfe_subdev_video_ops,
+};
+
+static struct msm_cam_clk_info vfe_clk_info[] = {
+ {"vfe_clk", VFE_CLK_RATE},
+ {"vfe_pclk", -1},
+};
+
+static struct msm_cam_clk_info vfe_camif_clk_info[] = {
+ {"camif_pad_pclk", -1},
+ {"vfe_camif_clk", -1},
+};
+
+static void msm_vfe_camio_clk_sel(enum msm_camio_clk_src_type srctype)
+{
+ struct clk *clk = NULL;
+
+ clk = vfe31_ctrl->vfe_clk[0];
+
+ if (clk != NULL) {
+ switch (srctype) {
+ case MSM_CAMIO_CLK_SRC_INTERNAL:
+ clk_set_flags(clk, 0x00000100 << 1);
+ break;
+
+ case MSM_CAMIO_CLK_SRC_EXTERNAL:
+ clk_set_flags(clk, 0x00000100);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+static void msm_vfe_camif_pad_reg_reset(void)
+{
+ uint32_t reg;
+
+ msm_vfe_camio_clk_sel(MSM_CAMIO_CLK_SRC_INTERNAL);
+ usleep_range(10000, 15000);
+
+ reg = (msm_io_r(vfe31_ctrl->camifbase)) & CAMIF_CFG_RMSK;
+ reg |= 0x3;
+ msm_io_w(reg, vfe31_ctrl->camifbase);
+ usleep_range(10000, 15000);
+
+ reg = (msm_io_r(vfe31_ctrl->camifbase)) & CAMIF_CFG_RMSK;
+ reg |= 0x10;
+ msm_io_w(reg, vfe31_ctrl->camifbase);
+ usleep_range(10000, 15000);
+
+ reg = (msm_io_r(vfe31_ctrl->camifbase)) & CAMIF_CFG_RMSK;
+ /* Need to be uninverted*/
+ reg &= 0x03;
+ msm_io_w(reg, vfe31_ctrl->camifbase);
+ usleep_range(10000, 15000);
+}
+
+int msm_vfe_subdev_init(struct v4l2_subdev *sd, void *data,
+ struct platform_device *pdev)
+{
+ int rc = 0;
+ struct msm_sync *sync = data;
+ v4l2_set_subdev_hostdata(sd, data);
+ vfe_syncdata = data;
+
+ spin_lock_init(&vfe31_ctrl->stop_flag_lock);
+ spin_lock_init(&vfe31_ctrl->state_lock);
+ spin_lock_init(&vfe31_ctrl->io_lock);
+ spin_lock_init(&vfe31_ctrl->update_ack_lock);
+ spin_lock_init(&vfe31_ctrl->tasklet_lock);
+
+ spin_lock_init(&vfe31_ctrl->aec_ack_lock);
+ spin_lock_init(&vfe31_ctrl->awb_ack_lock);
+ spin_lock_init(&vfe31_ctrl->af_ack_lock);
+ spin_lock_init(&vfe31_ctrl->ihist_ack_lock);
+ spin_lock_init(&vfe31_ctrl->rs_ack_lock);
+ spin_lock_init(&vfe31_ctrl->cs_ack_lock);
+ spin_lock_init(&vfe31_ctrl->comp_stats_ack_lock);
+ spin_lock_init(&vfe31_ctrl->sd_notify_lock);
+ INIT_LIST_HEAD(&vfe31_ctrl->tasklet_q);
+
+ vfe31_ctrl->update_linear = false;
+ vfe31_ctrl->update_rolloff = false;
+ vfe31_ctrl->update_la = false;
+ vfe31_ctrl->update_gamma = false;
+ vfe31_ctrl->hfr_mode = HFR_MODE_OFF;
+
+ vfe31_ctrl->vfebase = ioremap(vfe31_ctrl->vfemem->start,
+ resource_size(vfe31_ctrl->vfemem));
+ if (!vfe31_ctrl->vfebase) {
+ rc = -ENOMEM;
+ pr_err("%s: vfe ioremap failed\n", __func__);
+ goto vfe_remap_failed;
+ }
+ if (!sync->sdata->csi_if) {
+ vfe31_ctrl->camifbase = ioremap(vfe31_ctrl->camifmem->start,
+ resource_size(vfe31_ctrl->camifmem));
+ if (!vfe31_ctrl->camifbase) {
+ rc = -ENOMEM;
+ pr_err("%s: camif ioremap failed\n", __func__);
+ goto camif_remap_failed;
+ }
+ }
+
+ if (vfe31_ctrl->fs_vfe == NULL) {
+ vfe31_ctrl->fs_vfe =
+ regulator_get(&vfe31_ctrl->pdev->dev, "fs_vfe");
+ if (IS_ERR(vfe31_ctrl->fs_vfe)) {
+ pr_err("%s: Regulator FS_VFE get failed %ld\n",
+ __func__, PTR_ERR(vfe31_ctrl->fs_vfe));
+ vfe31_ctrl->fs_vfe = NULL;
+ goto vfe_fs_failed;
+ } else if (regulator_enable(vfe31_ctrl->fs_vfe)) {
+ pr_err("%s: Regulator FS_VFE enable failed\n",
+ __func__);
+ regulator_put(vfe31_ctrl->fs_vfe);
+ vfe31_ctrl->fs_vfe = NULL;
+ goto vfe_fs_failed;
+ }
+ }
+
+ rc = msm_cam_clk_enable(&vfe31_ctrl->pdev->dev, vfe_clk_info,
+ vfe31_ctrl->vfe_clk, ARRAY_SIZE(vfe_clk_info), 1);
+ if (rc < 0)
+ goto vfe_clk_enable_failed;
+
+ if (!sync->sdata->csi_if) {
+ rc = msm_cam_clk_enable(&vfe31_ctrl->pdev->dev,
+ vfe_camif_clk_info,
+ vfe31_ctrl->vfe_camif_clk,
+ ARRAY_SIZE(vfe_camif_clk_info), 1);
+ if (rc < 0)
+ goto vfe_clk_enable_failed;
+ msm_vfe_camif_pad_reg_reset();
+ }
+
+ msm_camio_bus_scale_cfg(
+ sync->sdata->pdata->cam_bus_scale_table, S_INIT);
+ msm_camio_bus_scale_cfg(
+ sync->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+ vfe31_ctrl->register_total = VFE31_REGISTER_TOTAL;
+
+ enable_irq(vfe31_ctrl->vfeirq->start);
+
+ return rc;
+
+vfe_clk_enable_failed:
+ regulator_disable(vfe31_ctrl->fs_vfe);
+ regulator_put(vfe31_ctrl->fs_vfe);
+ vfe31_ctrl->fs_vfe = NULL;
+vfe_fs_failed:
+ if (!sync->sdata->csi_if)
+ iounmap(vfe31_ctrl->camifbase);
+camif_remap_failed:
+ iounmap(vfe31_ctrl->vfebase);
+vfe_remap_failed:
+ disable_irq(vfe31_ctrl->vfeirq->start);
+ return rc;
+}
+
+void msm_vfe_subdev_release(struct platform_device *pdev)
+{
+ struct msm_sync *sync = vfe_syncdata;
+ disable_irq(vfe31_ctrl->vfeirq->start);
+ tasklet_kill(&vfe31_tasklet);
+
+ if (!sync->sdata->csi_if)
+ msm_cam_clk_enable(&vfe31_ctrl->pdev->dev,
+ vfe_camif_clk_info,
+ vfe31_ctrl->vfe_camif_clk,
+ ARRAY_SIZE(vfe_camif_clk_info), 0);
+
+ msm_cam_clk_enable(&vfe31_ctrl->pdev->dev, vfe_clk_info,
+ vfe31_ctrl->vfe_clk, ARRAY_SIZE(vfe_clk_info), 0);
+ if (vfe31_ctrl->fs_vfe) {
+ regulator_disable(vfe31_ctrl->fs_vfe);
+ regulator_put(vfe31_ctrl->fs_vfe);
+ vfe31_ctrl->fs_vfe = NULL;
+ }
+ CDBG("%s, 31ee_irq\n", __func__);
+ if (!sync->sdata->csi_if)
+ iounmap(vfe31_ctrl->camifbase);
+ iounmap(vfe31_ctrl->vfebase);
+
+ if (atomic_read(&irq_cnt))
+ pr_warning("%s, Warning IRQ Count not ZERO\n", __func__);
+
+ msm_camio_bus_scale_cfg(
+ sync->sdata->pdata->cam_bus_scale_table, S_EXIT);
+ vfe_syncdata = NULL;
+}
+
+
+static int __devinit vfe31_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+ CDBG("%s: device id = %d\n", __func__, pdev->id);
+ vfe31_ctrl = kzalloc(sizeof(struct vfe31_ctrl_type), GFP_KERNEL);
+ if (!vfe31_ctrl) {
+ pr_err("%s: no enough memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ v4l2_subdev_init(&vfe31_ctrl->subdev, &msm_vfe_subdev_ops);
+ snprintf(vfe31_ctrl->subdev.name,
+ sizeof(vfe31_ctrl->subdev.name), "vfe3.1");
+ v4l2_set_subdevdata(&vfe31_ctrl->subdev, vfe31_ctrl);
+ platform_set_drvdata(pdev, &vfe31_ctrl->subdev);
+
+ vfe31_ctrl->vfemem = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "msm_vfe");
+ if (!vfe31_ctrl->vfemem) {
+ pr_err("%s: no mem resource?\n", __func__);
+ rc = -ENODEV;
+ goto vfe31_no_resource;
+ }
+ vfe31_ctrl->vfeirq = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ, "msm_vfe");
+ if (!vfe31_ctrl->vfeirq) {
+ pr_err("%s: no irq resource?\n", __func__);
+ rc = -ENODEV;
+ goto vfe31_no_resource;
+ }
+ vfe31_ctrl->camifmem = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "msm_camif");
+ if (!vfe31_ctrl->camifmem)
+ pr_err("%s: camif not supported\n", __func__);
+
+ vfe31_ctrl->vfeio = request_mem_region(vfe31_ctrl->vfemem->start,
+ resource_size(vfe31_ctrl->vfemem), pdev->name);
+ if (!vfe31_ctrl->vfeio) {
+ pr_err("%s: no valid mem region\n", __func__);
+ rc = -EBUSY;
+ goto vfe31_no_resource;
+ }
+
+ if (vfe31_ctrl->camifmem) {
+ vfe31_ctrl->camifio = request_mem_region(
+ vfe31_ctrl->camifmem->start,
+ resource_size(vfe31_ctrl->camifmem), pdev->name);
+ if (!vfe31_ctrl->camifio) {
+ release_mem_region(vfe31_ctrl->vfemem->start,
+ resource_size(vfe31_ctrl->vfemem));
+ pr_err("%s: no valid mem region\n", __func__);
+ rc = -EBUSY;
+ goto vfe31_no_resource;
+ }
+ }
+
+ rc = request_irq(vfe31_ctrl->vfeirq->start, vfe31_parse_irq,
+ IRQF_TRIGGER_RISING, "vfe", 0);
+ if (rc < 0) {
+ if (vfe31_ctrl->camifmem) {
+ release_mem_region(vfe31_ctrl->camifmem->start,
+ resource_size(vfe31_ctrl->camifmem));
+ }
+ release_mem_region(vfe31_ctrl->vfemem->start,
+ resource_size(vfe31_ctrl->vfemem));
+ pr_err("%s: irq request fail\n", __func__);
+ rc = -EBUSY;
+ goto vfe31_no_resource;
+ }
+
+ disable_irq(vfe31_ctrl->vfeirq->start);
+
+ vfe31_ctrl->pdev = pdev;
+ return 0;
+
+vfe31_no_resource:
+ kfree(vfe31_ctrl);
+ return 0;
+}
+
+static struct platform_driver vfe31_driver = {
+ .probe = vfe31_probe,
+ .driver = {
+ .name = MSM_VFE_DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_vfe31_init_module(void)
+{
+ return platform_driver_register(&vfe31_driver);
+}
+
+static void __exit msm_vfe31_exit_module(void)
+{
+ platform_driver_unregister(&vfe31_driver);
+}
+
+module_init(msm_vfe31_init_module);
+module_exit(msm_vfe31_exit_module);
+MODULE_DESCRIPTION("VFE 3.1 driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm_vfe31_v4l2.h b/drivers/media/video/msm/msm_vfe31_v4l2.h
new file mode 100644
index 0000000..e94f286
--- /dev/null
+++ b/drivers/media/video/msm/msm_vfe31_v4l2.h
@@ -0,0 +1,955 @@
+/* Copyright (c) 2012 Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MSM_VFE31_V4L2_H__
+#define __MSM_VFE31_V4L2_H__
+
+#include <linux/bitops.h>
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/* This defines total number registers in VFE.
+ * Each register is 4 bytes so to get the range,
+ * multiply this number with 4. */
+#define VFE31_REGISTER_TOTAL 0x0000017F
+
+/* at start of camif, bit 1:0 = 0x01:enable
+ * image data capture at frame boundary. */
+#define CAMIF_COMMAND_START 0x00000005
+
+/* bit 2= 0x1:clear the CAMIF_STATUS register
+ * value. */
+#define CAMIF_COMMAND_CLEAR 0x00000004
+
+/* at stop of vfe pipeline, for now it is assumed
+ * that camif will stop at any time. Bit 1:0 = 0x10:
+ * disable image data capture immediately. */
+#define CAMIF_COMMAND_STOP_IMMEDIATELY 0x00000002
+
+/* at stop of vfe pipeline, for now it is assumed
+ * that camif will stop at any time. Bit 1:0 = 0x00:
+ * disable image data capture at frame boundary */
+#define CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY 0x00000000
+
+/* to halt axi bridge */
+#define AXI_HALT 0x00000001
+
+/* clear the halt bit. */
+#define AXI_HALT_CLEAR 0x00000000
+
+/* clear axi_halt_irq */
+#define MASK_AXI_HALT_IRQ 0xFF7FFFFF
+
+/* reset the pipeline when stop command is issued.
+ * (without reset the register.) bit 26-31 = 0,
+ * domain reset, bit 0-9 = 1 for module reset, except
+ * register module. */
+#define VFE_RESET_UPON_STOP_CMD 0x000003ef
+
+/* reset the pipeline when reset command.
+ * bit 26-31 = 0, domain reset, bit 0-9 = 1 for module reset. */
+#define VFE_RESET_UPON_RESET_CMD 0x000003ff
+
+/* bit 5 is for axi status idle or busy.
+ * 1 = halted, 0 = busy */
+#define AXI_STATUS_BUSY_MASK 0x00000020
+
+/* bit 0 & bit 1 = 1, both y and cbcr irqs need to be present
+ * for frame done interrupt */
+#define VFE_COMP_IRQ_BOTH_Y_CBCR 3
+
+/* bit 1 = 1, only cbcr irq triggers frame done interrupt */
+#define VFE_COMP_IRQ_CBCR_ONLY 2
+
+/* bit 0 = 1, only y irq triggers frame done interrupt */
+#define VFE_COMP_IRQ_Y_ONLY 1
+
+/* bit 0 = 1, PM go; bit1 = 1, PM stop */
+#define VFE_PERFORMANCE_MONITOR_GO 0x00000001
+#define VFE_PERFORMANCE_MONITOR_STOP 0x00000002
+
+/* bit 0 = 1, test gen go; bit1 = 1, test gen stop */
+#define VFE_TEST_GEN_GO 0x00000001
+#define VFE_TEST_GEN_STOP 0x00000002
+
+/* the chroma is assumed to be interpolated between
+ * the luma samples. JPEG 4:2:2 */
+#define VFE_CHROMA_UPSAMPLE_INTERPOLATED 0
+
+/* constants for irq registers */
+#define VFE_DISABLE_ALL_IRQS 0
+/* bit =1 is to clear the corresponding bit in VFE_IRQ_STATUS. */
+#define VFE_CLEAR_ALL_IRQS 0xffffffff
+
+#define VFE_IRQ_STATUS0_CAMIF_SOF_MASK 0x00000001
+#define VFE_IRQ_STATUS0_CAMIF_EOF_MASK 0x00000004
+#define VFE_IRQ_STATUS0_REG_UPDATE_MASK 0x00000020
+#define VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK 0x00200000
+#define VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK 0x00400000
+#define VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE2_MASK 0x00800000
+#define VFE_IRQ_STATUS1_RESET_AXI_HALT_ACK_MASK 0x00800000
+#define VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK 0x01000000
+
+#define VFE_IRQ_STATUS0_STATS_AEC 0x2000 /* bit 13 */
+#define VFE_IRQ_STATUS0_STATS_AF 0x4000 /* bit 14 */
+#define VFE_IRQ_STATUS0_STATS_AWB 0x8000 /* bit 15 */
+#define VFE_IRQ_STATUS0_STATS_RS 0x10000 /* bit 16 */
+#define VFE_IRQ_STATUS0_STATS_CS 0x20000 /* bit 17 */
+#define VFE_IRQ_STATUS0_STATS_IHIST 0x40000 /* bit 18 */
+
+#define VFE_IRQ_STATUS0_SYNC_TIMER0 0x2000000 /* bit 25 */
+#define VFE_IRQ_STATUS0_SYNC_TIMER1 0x4000000 /* bit 26 */
+#define VFE_IRQ_STATUS0_SYNC_TIMER2 0x8000000 /* bit 27 */
+#define VFE_IRQ_STATUS0_ASYNC_TIMER0 0x10000000 /* bit 28 */
+#define VFE_IRQ_STATUS0_ASYNC_TIMER1 0x20000000 /* bit 29 */
+#define VFE_IRQ_STATUS0_ASYNC_TIMER2 0x40000000 /* bit 30 */
+#define VFE_IRQ_STATUS0_ASYNC_TIMER3 0x80000000 /* bit 31 */
+
+/* imask for while waiting for stop ack, driver has already
+ * requested stop, waiting for reset irq, and async timer irq.
+ * For irq_status_0, bit 28-31 are for async timer. For
+ * irq_status_1, bit 22 for reset irq, bit 23 for axi_halt_ack
+ irq */
+#define VFE_IMASK_WHILE_STOPPING_0 0xF0000000
+#define VFE_IMASK_WHILE_STOPPING_1 0x00C00000
+#define VFE_IMASK_RESET 0x00400000
+#define VFE_IMASK_AXI_HALT 0x00800000
+
+
+/* no error irq in mask 0 */
+#define VFE_IMASK_ERROR_ONLY_0 0x0
+/* when normal case, don't want to block error status. */
+/* bit 0-21 are error irq bits */
+#define VFE_IMASK_ERROR_ONLY_1 0x003fffff
+
+/* For BPC bit 0,bit 12-17 and bit 26 -20 are set to zero and other's 1 */
+#define BPC_MASK 0xF80C0FFE
+
+/* For BPC bit 1 and 2 are set to zero and other's 1 */
+#define ABF_MASK 0xFFFFFFF9
+
+/* For DBPC bit 0 is set to zero and other's 1 */
+#define DBPC_MASK 0xFFFFFFFE
+
+/* For DBCC bit 1 is set to zero and other's 1 */
+#define DBCC_MASK 0xFFFFFFFD
+
+/* For DBPC/ABF/DBCC/ABCC bits are set to 1 all others 0 */
+#define DEMOSAIC_MASK 0x8FFFFFFF
+/* For MCE enable bit 28 set to zero and other's 1 */
+#define MCE_EN_MASK 0xEFFFFFFF
+
+/* For MCE Q_K bit 28 to 31 set to zero and other's 1 */
+#define MCE_Q_K_MASK 0x0FFFFFFF
+
+#define AE_BG_ENABLE_MASK 0x00000020 /* bit 5 */
+#define AF_BF_ENABLE_MASK 0x00000040 /* bit 6 */
+#define AWB_ENABLE_MASK 0x00000080 /* bit 7 */
+
+#define RS_ENABLE_MASK 0x00000100 /* bit 8 */
+#define CS_ENABLE_MASK 0x00000200 /* bit 9 */
+#define RS_CS_ENABLE_MASK 0x00000300 /* bit 8,9 */
+#define IHIST_ENABLE_MASK 0x00008000 /* bit 15 */
+#define STATS_ENABLE_MASK 0x000483E0 /* bit 18,15,9,8,7,6,5*/
+
+#define VFE_REG_UPDATE_TRIGGER 1
+#define VFE_PM_BUF_MAX_CNT_MASK 0xFF
+#define VFE_DMI_CFG_DEFAULT 0x00000100
+#define VFE_AE_PINGPONG_STATUS_BIT 0x80
+#define VFE_AF_PINGPONG_STATUS_BIT 0x100
+#define VFE_AWB_PINGPONG_STATUS_BIT 0x200
+
+#define HFR_MODE_OFF 1
+#define VFE_FRAME_SKIP_PERIOD_MASK 0x0000001F /*bits 0 -4*/
+
+enum VFE31_DMI_RAM_SEL {
+ NO_MEM_SELECTED = 0,
+ ROLLOFF_RAM = 0x1,
+ RGBLUT_RAM_CH0_BANK0 = 0x2,
+ RGBLUT_RAM_CH0_BANK1 = 0x3,
+ RGBLUT_RAM_CH1_BANK0 = 0x4,
+ RGBLUT_RAM_CH1_BANK1 = 0x5,
+ RGBLUT_RAM_CH2_BANK0 = 0x6,
+ RGBLUT_RAM_CH2_BANK1 = 0x7,
+ STATS_HIST_RAM = 0x8,
+ RGBLUT_CHX_BANK0 = 0x9,
+ RGBLUT_CHX_BANK1 = 0xa,
+ LUMA_ADAPT_LUT_RAM_BANK0 = 0xb,
+ LUMA_ADAPT_LUT_RAM_BANK1 = 0xc
+};
+
+enum vfe_output_state {
+ VFE_STATE_IDLE,
+ VFE_STATE_START_REQUESTED,
+ VFE_STATE_STARTED,
+ VFE_STATE_STOP_REQUESTED,
+ VFE_STATE_STOPPED,
+};
+
+#define V31_CAMIF_OFF 0x000001E4
+#define V31_CAMIF_LEN 32
+
+#define V31_DEMUX_OFF 0x00000284
+#define V31_DEMUX_LEN 20
+
+#define V31_DEMOSAICV3_UP_REG_CNT 5
+
+#define V31_OUT_CLAMP_OFF 0x00000524
+#define V31_OUT_CLAMP_LEN 8
+
+#define V31_OPERATION_CFG_LEN 32
+
+#define V31_AXI_OUT_OFF 0x00000038
+#define V31_AXI_OUT_LEN 212
+#define V31_AXI_CH_INF_LEN 24
+#define V31_AXI_CFG_LEN 47
+#define V31_AXI_RESERVED 1
+
+#define V31_FRAME_SKIP_OFF 0x00000504
+#define V31_FRAME_SKIP_LEN 32
+
+#define V31_CHROMA_SUBS_OFF 0x000004F8
+#define V31_CHROMA_SUBS_LEN 12
+
+#define V31_FOV_OFF 0x00000360
+#define V31_FOV_LEN 8
+
+#define V31_MAIN_SCALER_OFF 0x00000368
+#define V31_MAIN_SCALER_LEN 28
+
+#define V31_S2Y_OFF 0x000004D0
+#define V31_S2Y_LEN 20
+
+#define V31_S2CbCr_OFF 0x000004E4
+#define V31_S2CbCr_LEN 20
+
+#define V31_CHROMA_EN_OFF 0x000003C4
+#define V31_CHROMA_EN_LEN 36
+
+#define V31_SYNC_TIMER_OFF 0x0000020C
+#define V31_SYNC_TIMER_POLARITY_OFF 0x00000234
+#define V31_TIMER_SELECT_OFF 0x0000025C
+#define V31_SYNC_TIMER_LEN 28
+
+#define V31_ASYNC_TIMER_OFF 0x00000238
+#define V31_ASYNC_TIMER_LEN 28
+
+#define V31_BLACK_LEVEL_OFF 0x00000264
+#define V31_BLACK_LEVEL_LEN 16
+
+#define V31_MESH_ROLL_OFF_CFG_OFF 0x00000274
+#define V31_MESH_ROLL_OFF_CFG_LEN 16
+#define V31_MESH_ROLL_OFF_INIT_TABLE_SIZE 13
+#define V31_MESH_ROLL_OFF_DELTA_TABLE_SIZE 208
+#define V31_MESH_ROLL_OFF_DELTA_TABLE_OFFSET 32
+
+#define V31_COLOR_COR_OFF 0x00000388
+#define V31_COLOR_COR_LEN 52
+
+#define V31_WB_OFF 0x00000384
+#define V31_WB_LEN 4
+
+#define V31_RGB_G_OFF 0x000003BC
+#define V31_RGB_G_LEN 4
+
+#define V31_LA_OFF 0x000003C0
+#define V31_LA_LEN 4
+
+#define V31_SCE_OFF 0x00000418
+#define V31_SCE_LEN 136
+
+#define V31_CHROMA_SUP_OFF 0x000003E8
+#define V31_CHROMA_SUP_LEN 12
+
+#define V31_MCE_OFF 0x000003F4
+#define V31_MCE_LEN 36
+#define V31_STATS_AF_OFF 0x0000053c
+#define V31_STATS_AF_LEN 16
+
+#define V31_STATS_AE_OFF 0x00000534
+#define V31_STATS_AE_LEN 8
+
+#define V31_STATS_AWB_OFF 0x0000054c
+#define V31_STATS_AWB_LEN 32
+
+#define V31_STATS_IHIST_OFF 0x0000057c
+#define V31_STATS_IHIST_LEN 8
+
+#define V31_STATS_RS_OFF 0x0000056c
+#define V31_STATS_RS_LEN 8
+
+#define V31_STATS_CS_OFF 0x00000574
+#define V31_STATS_CS_LEN 8
+
+#define V31_ASF_OFF 0x000004A0
+#define V31_ASF_LEN 48
+#define V31_ASF_UPDATE_LEN 36
+#define V31_CAPTURE_LEN 4
+#define V31_GET_HW_VERSION_OFF 0
+#define V31_GET_HW_VERSION_LEN 4
+#define V31_DEMOSAICV3_OFF 0x00000298
+#define V31_DEMOSAICV3_LEN 4
+/* BPC */
+#define V31_DEMOSAICV3_DBPC_CFG_OFF 0x0000029C
+#define V31_DEMOSAICV3_DBPC_LEN 8
+#define V31_XBAR_CFG_OFF 0x00000040
+/* ABF */
+#define V31_DEMOSAICV3_ABF_OFF 0x000002A4
+#define V31_DEMOSAICV3_ABF_LEN 180
+#define V31_XBAR_CFG_LEN 8
+
+#define V31_MODULE_CFG_OFF 0x00000010
+#define V31_MODULE_CFG_LEN 4
+#define V31_EZTUNE_CFG_OFF 0x00000010
+#define V31_EZTUNE_CFG_LEN 4
+
+struct vfe_cmd_hw_version {
+ uint32_t minorVersion;
+ uint32_t majorVersion;
+ uint32_t coreVersion;
+};
+
+enum VFE_AXI_OUTPUT_MODE {
+ VFE_AXI_OUTPUT_MODE_Output1,
+ VFE_AXI_OUTPUT_MODE_Output2,
+ VFE_AXI_OUTPUT_MODE_Output1AndOutput2,
+ VFE_AXI_OUTPUT_MODE_CAMIFToAXIViaOutput2,
+ VFE_AXI_OUTPUT_MODE_Output2AndCAMIFToAXIViaOutput1,
+ VFE_AXI_OUTPUT_MODE_Output1AndCAMIFToAXIViaOutput2,
+ VFE_AXI_LAST_OUTPUT_MODE_ENUM
+};
+
+enum VFE_RAW_WR_PATH_SEL {
+ VFE_RAW_OUTPUT_DISABLED,
+ VFE_RAW_OUTPUT_ENC_CBCR_PATH,
+ VFE_RAW_OUTPUT_VIEW_CBCR_PATH,
+ VFE_RAW_OUTPUT_PATH_INVALID
+};
+
+#define VFE_AXI_OUTPUT_BURST_LENGTH 4
+#define VFE_MAX_NUM_FRAGMENTS_PER_FRAME 4
+#define VFE_AXI_OUTPUT_CFG_FRAME_COUNT 3
+
+struct vfe_cmds_per_write_master {
+ uint16_t imageWidth;
+ uint16_t imageHeight;
+ uint16_t outRowCount;
+ uint16_t outRowIncrement;
+ uint32_t outFragments[VFE_AXI_OUTPUT_CFG_FRAME_COUNT]
+ [VFE_MAX_NUM_FRAGMENTS_PER_FRAME];
+};
+
+struct vfe_cmds_axi_per_output_path {
+ uint8_t fragmentCount;
+ struct vfe_cmds_per_write_master firstWM;
+ struct vfe_cmds_per_write_master secondWM;
+};
+
+enum VFE_AXI_BURST_LENGTH {
+ VFE_AXI_BURST_LENGTH_IS_2 = 2,
+ VFE_AXI_BURST_LENGTH_IS_4 = 4,
+ VFE_AXI_BURST_LENGTH_IS_8 = 8,
+ VFE_AXI_BURST_LENGTH_IS_16 = 16
+};
+
+struct vfe_cmd_fov_crop_config {
+ uint8_t enable;
+ uint16_t firstPixel;
+ uint16_t lastPixel;
+ uint16_t firstLine;
+ uint16_t lastLine;
+};
+
+struct vfe_cmds_main_scaler_stripe_init {
+ uint16_t MNCounterInit;
+ uint16_t phaseInit;
+};
+
+struct vfe_cmds_scaler_one_dimension {
+ uint8_t enable;
+ uint16_t inputSize;
+ uint16_t outputSize;
+ uint32_t phaseMultiplicationFactor;
+ uint8_t interpolationResolution;
+};
+
+struct vfe_cmd_main_scaler_config {
+ uint8_t enable;
+ struct vfe_cmds_scaler_one_dimension hconfig;
+ struct vfe_cmds_scaler_one_dimension vconfig;
+ struct vfe_cmds_main_scaler_stripe_init MNInitH;
+ struct vfe_cmds_main_scaler_stripe_init MNInitV;
+};
+
+struct vfe_cmd_scaler2_config {
+ uint8_t enable;
+ struct vfe_cmds_scaler_one_dimension hconfig;
+ struct vfe_cmds_scaler_one_dimension vconfig;
+};
+
+
+struct vfe_cmd_frame_skip_update {
+ uint32_t output1Pattern;
+ uint32_t output2Pattern;
+};
+
+struct vfe_cmd_output_clamp_config {
+ uint8_t minCh0;
+ uint8_t minCh1;
+ uint8_t minCh2;
+ uint8_t maxCh0;
+ uint8_t maxCh1;
+ uint8_t maxCh2;
+};
+
+struct vfe_cmd_chroma_subsample_config {
+ uint8_t enable;
+ uint8_t cropEnable;
+ uint8_t vsubSampleEnable;
+ uint8_t hsubSampleEnable;
+ uint8_t vCosited;
+ uint8_t hCosited;
+ uint8_t vCositedPhase;
+ uint8_t hCositedPhase;
+ uint16_t cropWidthFirstPixel;
+ uint16_t cropWidthLastPixel;
+ uint16_t cropHeightFirstLine;
+ uint16_t cropHeightLastLine;
+};
+
+enum VFE_START_PIXEL_PATTERN {
+ VFE_BAYER_RGRGRG,
+ VFE_BAYER_GRGRGR,
+ VFE_BAYER_BGBGBG,
+ VFE_BAYER_GBGBGB,
+ VFE_YUV_YCbYCr,
+ VFE_YUV_YCrYCb,
+ VFE_YUV_CbYCrY,
+ VFE_YUV_CrYCbY
+};
+
+enum VFE_BUS_RD_INPUT_PIXEL_PATTERN {
+ VFE_BAYER_RAW,
+ VFE_YUV_INTERLEAVED,
+ VFE_YUV_PSEUDO_PLANAR_Y,
+ VFE_YUV_PSEUDO_PLANAR_CBCR
+};
+
+enum VFE_YUV_INPUT_COSITING_MODE {
+ VFE_YUV_COSITED,
+ VFE_YUV_INTERPOLATED
+};
+
+#define VFE31_GAMMA_NUM_ENTRIES 64
+
+#define VFE31_LA_TABLE_LENGTH 64
+
+#define VFE31_HIST_TABLE_LENGTH 256
+
+struct vfe_cmds_demosaic_abf {
+ uint8_t enable;
+ uint8_t forceOn;
+ uint8_t shift;
+ uint16_t lpThreshold;
+ uint16_t max;
+ uint16_t min;
+ uint8_t ratio;
+};
+
+struct vfe_cmds_demosaic_bpc {
+ uint8_t enable;
+ uint16_t fmaxThreshold;
+ uint16_t fminThreshold;
+ uint16_t redDiffThreshold;
+ uint16_t blueDiffThreshold;
+ uint16_t greenDiffThreshold;
+};
+
+struct vfe_cmd_demosaic_config {
+ uint8_t enable;
+ uint8_t slopeShift;
+ struct vfe_cmds_demosaic_abf abfConfig;
+ struct vfe_cmds_demosaic_bpc bpcConfig;
+};
+
+struct vfe_cmd_demosaic_bpc_update {
+ struct vfe_cmds_demosaic_bpc bpcUpdate;
+};
+
+struct vfe_cmd_demosaic_abf_update {
+ struct vfe_cmds_demosaic_abf abfUpdate;
+};
+
+struct vfe_cmd_white_balance_config {
+ uint8_t enable;
+ uint16_t ch2Gain;
+ uint16_t ch1Gain;
+ uint16_t ch0Gain;
+};
+
+enum VFE_COLOR_CORRECTION_COEF_QFACTOR {
+ COEF_IS_Q7_SIGNED,
+ COEF_IS_Q8_SIGNED,
+ COEF_IS_Q9_SIGNED,
+ COEF_IS_Q10_SIGNED
+};
+
+struct vfe_cmd_color_correction_config {
+ uint8_t enable;
+ enum VFE_COLOR_CORRECTION_COEF_QFACTOR coefQFactor;
+ int16_t C0;
+ int16_t C1;
+ int16_t C2;
+ int16_t C3;
+ int16_t C4;
+ int16_t C5;
+ int16_t C6;
+ int16_t C7;
+ int16_t C8;
+ int16_t K0;
+ int16_t K1;
+ int16_t K2;
+};
+
+#define VFE_LA_TABLE_LENGTH 64
+
+struct vfe_cmd_la_config {
+ uint8_t enable;
+ int16_t table[VFE_LA_TABLE_LENGTH];
+};
+
+#define VFE_GAMMA_TABLE_LENGTH 256
+enum VFE_RGB_GAMMA_TABLE_SELECT {
+ RGB_GAMMA_CH0_SELECTED,
+ RGB_GAMMA_CH1_SELECTED,
+ RGB_GAMMA_CH2_SELECTED,
+ RGB_GAMMA_CH0_CH1_SELECTED,
+ RGB_GAMMA_CH0_CH2_SELECTED,
+ RGB_GAMMA_CH1_CH2_SELECTED,
+ RGB_GAMMA_CH0_CH1_CH2_SELECTED
+};
+
+struct vfe_cmd_rgb_gamma_config {
+ uint8_t enable;
+ enum VFE_RGB_GAMMA_TABLE_SELECT channelSelect;
+ int16_t table[VFE_GAMMA_TABLE_LENGTH];
+};
+
+struct vfe_cmd_chroma_enhan_config {
+ uint8_t enable;
+ int16_t am;
+ int16_t ap;
+ int16_t bm;
+ int16_t bp;
+ int16_t cm;
+ int16_t cp;
+ int16_t dm;
+ int16_t dp;
+ int16_t kcr;
+ int16_t kcb;
+ int16_t RGBtoYConversionV0;
+ int16_t RGBtoYConversionV1;
+ int16_t RGBtoYConversionV2;
+ uint8_t RGBtoYConversionOffset;
+};
+
+struct vfe_cmd_chroma_suppression_config {
+ uint8_t enable;
+ uint8_t m1;
+ uint8_t m3;
+ uint8_t n1;
+ uint8_t n3;
+ uint8_t nn1;
+ uint8_t mm1;
+};
+
+struct vfe_cmd_asf_config {
+ uint8_t enable;
+ uint8_t smoothFilterEnabled;
+ uint8_t sharpMode;
+ uint8_t smoothCoefCenter;
+ uint8_t smoothCoefSurr;
+ uint8_t normalizeFactor;
+ uint8_t sharpK1;
+ uint8_t sharpK2;
+ uint8_t sharpThreshE1;
+ int8_t sharpThreshE2;
+ int8_t sharpThreshE3;
+ int8_t sharpThreshE4;
+ int8_t sharpThreshE5;
+ int8_t filter1Coefficients[9];
+ int8_t filter2Coefficients[9];
+ uint8_t cropEnable;
+ uint16_t cropFirstPixel;
+ uint16_t cropLastPixel;
+ uint16_t cropFirstLine;
+ uint16_t cropLastLine;
+};
+
+struct vfe_cmd_asf_update {
+ uint8_t enable;
+ uint8_t smoothFilterEnabled;
+ uint8_t sharpMode;
+ uint8_t smoothCoefCenter;
+ uint8_t smoothCoefSurr;
+ uint8_t normalizeFactor;
+ uint8_t sharpK1;
+ uint8_t sharpK2;
+ uint8_t sharpThreshE1;
+ int8_t sharpThreshE2;
+ int8_t sharpThreshE3;
+ int8_t sharpThreshE4;
+ int8_t sharpThreshE5;
+ int8_t filter1Coefficients[9];
+ int8_t filter2Coefficients[9];
+ uint8_t cropEnable;
+};
+
+enum VFE_TEST_GEN_SYNC_EDGE {
+ VFE_TEST_GEN_SYNC_EDGE_ActiveHigh,
+ VFE_TEST_GEN_SYNC_EDGE_ActiveLow
+};
+
+
+struct vfe_cmd_bus_pm_start {
+ uint8_t output2YWrPmEnable;
+ uint8_t output2CbcrWrPmEnable;
+ uint8_t output1YWrPmEnable;
+ uint8_t output1CbcrWrPmEnable;
+};
+
+struct vfe_frame_skip_counts {
+ uint32_t totalFrameCount;
+ uint32_t output1Count;
+ uint32_t output2Count;
+};
+
+enum VFE_AXI_RD_UNPACK_HBI_SEL {
+ VFE_AXI_RD_HBI_32_CLOCK_CYCLES,
+ VFE_AXI_RD_HBI_64_CLOCK_CYCLES,
+ VFE_AXI_RD_HBI_128_CLOCK_CYCLES,
+ VFE_AXI_RD_HBI_256_CLOCK_CYCLES,
+ VFE_AXI_RD_HBI_512_CLOCK_CYCLES,
+ VFE_AXI_RD_HBI_1024_CLOCK_CYCLES,
+ VFE_AXI_RD_HBI_2048_CLOCK_CYCLES,
+ VFE_AXI_RD_HBI_4096_CLOCK_CYCLES
+};
+
+struct vfe_frame_bpc_info {
+ uint32_t greenDefectPixelCount;
+ uint32_t redBlueDefectPixelCount;
+};
+
+struct vfe_frame_asf_info {
+ uint32_t asfMaxEdge;
+ uint32_t asfHbiCount;
+};
+
+struct vfe_msg_camif_status {
+ uint8_t camifState;
+ uint32_t pixelCount;
+ uint32_t lineCount;
+};
+
+struct vfe31_irq_status {
+ uint32_t vfeIrqStatus0;
+ uint32_t vfeIrqStatus1;
+ uint32_t camifStatus;
+ uint32_t demosaicStatus;
+ uint32_t asfMaxEdge;
+};
+
+#define V31_PREVIEW_AXI_FLAG 0x00000001
+#define V31_SNAPSHOT_AXI_FLAG (0x00000001<<1)
+
+struct vfe31_cmd_type {
+ uint16_t id;
+ uint32_t length;
+ uint32_t offset;
+ uint32_t flag;
+};
+
+struct vfe31_free_buf {
+ struct list_head node;
+ uint32_t paddr;
+ uint32_t y_off;
+ uint32_t cbcr_off;
+};
+
+struct vfe31_output_ch {
+ struct list_head free_buf_queue;
+ spinlock_t free_buf_lock;
+ uint16_t output_fmt;
+ int8_t ch0;
+ int8_t ch1;
+ int8_t ch2;
+ uint32_t capture_cnt;
+ uint32_t frame_drop_cnt;
+ struct msm_free_buf ping;
+ struct msm_free_buf pong;
+ struct msm_free_buf free_buf;
+};
+
+/* no error irq in mask 0 */
+#define VFE31_IMASK_ERROR_ONLY_0 0x0
+/* when normal case, don't want to block error status. */
+/* bit 0-21 are error irq bits */
+#define VFE31_IMASK_ERROR_ONLY_1 0x003FFFFF
+#define VFE31_IMASK_CAMIF_ERROR (0x00000001<<0)
+#define VFE31_IMASK_STATS_CS_OVWR (0x00000001<<1)
+#define VFE31_IMASK_STATS_IHIST_OVWR (0x00000001<<2)
+#define VFE31_IMASK_REALIGN_BUF_Y_OVFL (0x00000001<<3)
+#define VFE31_IMASK_REALIGN_BUF_CB_OVFL (0x00000001<<4)
+#define VFE31_IMASK_REALIGN_BUF_CR_OVFL (0x00000001<<5)
+#define VFE31_IMASK_VIOLATION (0x00000001<<6)
+#define VFE31_IMASK_IMG_MAST_0_BUS_OVFL (0x00000001<<7)
+#define VFE31_IMASK_IMG_MAST_1_BUS_OVFL (0x00000001<<8)
+#define VFE31_IMASK_IMG_MAST_2_BUS_OVFL (0x00000001<<9)
+#define VFE31_IMASK_IMG_MAST_3_BUS_OVFL (0x00000001<<10)
+#define VFE31_IMASK_IMG_MAST_4_BUS_OVFL (0x00000001<<11)
+#define VFE31_IMASK_IMG_MAST_5_BUS_OVFL (0x00000001<<12)
+#define VFE31_IMASK_IMG_MAST_6_BUS_OVFL (0x00000001<<13)
+#define VFE31_IMASK_STATS_AE_BG_BUS_OVFL (0x00000001<<14)
+#define VFE31_IMASK_STATS_AF_BF_BUS_OVFL (0x00000001<<15)
+#define VFE31_IMASK_STATS_AWB_BUS_OVFL (0x00000001<<16)
+#define VFE31_IMASK_STATS_RS_BUS_OVFL (0x00000001<<17)
+#define VFE31_IMASK_STATS_CS_BUS_OVFL (0x00000001<<18)
+#define VFE31_IMASK_STATS_IHIST_BUS_OVFL (0x00000001<<19)
+#define VFE31_IMASK_STATS_SKIN_BHIST_BUS_OVFL (0x00000001<<20)
+#define VFE31_IMASK_AXI_ERROR (0x00000001<<21)
+
+#define VFE_COM_STATUS 0x000FE000
+
+struct vfe31_output_path {
+ uint16_t output_mode; /* bitmask */
+
+ struct vfe31_output_ch out0; /* preview and thumbnail */
+ struct vfe31_output_ch out1; /* snapshot */
+ struct vfe31_output_ch out2; /* video */
+};
+
+struct vfe31_frame_extra {
+ uint32_t greenDefectPixelCount;
+ uint32_t redBlueDefectPixelCount;
+
+ uint32_t asfMaxEdge;
+ uint32_t asfHbiCount;
+
+ uint32_t yWrPmStats0;
+ uint32_t yWrPmStats1;
+ uint32_t cbcrWrPmStats0;
+ uint32_t cbcrWrPmStats1;
+
+ uint32_t frameCounter;
+};
+
+#define VFE_DISABLE_ALL_IRQS 0
+#define VFE_CLEAR_ALL_IRQS 0xffffffff
+
+#define VFE_HW_VERSION 0x00000000
+#define VFE_GLOBAL_RESET 0x00000004
+#define VFE_MODULE_RESET 0x00000008
+#define VFE_CGC_OVERRIDE 0x0000000C
+#define VFE_MODULE_CFG 0x00000010
+#define VFE_CFG 0x00000014
+#define VFE_IRQ_CMD 0x00000018
+#define VFE_IRQ_MASK_0 0x0000001C
+#define VFE_IRQ_MASK_1 0x00000020
+#define VFE_IRQ_CLEAR_0 0x00000024
+#define VFE_IRQ_CLEAR_1 0x00000028
+#define VFE_IRQ_STATUS_0 0x0000002C
+#define VFE_IRQ_STATUS_1 0x00000030
+#define VFE_IRQ_COMP_MASK 0x00000034
+#define VFE_BUS_CMD 0x00000038
+#define VFE_BUS_PING_PONG_STATUS 0x00000180
+#define VFE_BUS_OPERATION_STATUS 0x00000184
+
+#define VFE_BUS_IMAGE_MASTER_0_WR_PM_STATS_0 0x00000190
+#define VFE_BUS_IMAGE_MASTER_0_WR_PM_STATS_1 0x00000194
+
+#define VFE_AXI_CMD 0x000001D8
+#define VFE_AXI_STATUS 0x000001DC
+#define VFE_BUS_STATS_PING_PONG_BASE 0x000000F4
+
+#define VFE_BUS_STATS_AEC_WR_PING_ADDR 0x000000F4
+#define VFE_BUS_STATS_AEC_WR_PONG_ADDR 0x000000F8
+#define VFE_BUS_STATS_AEC_UB_CFG 0x000000FC
+#define VFE_BUS_STATS_AF_WR_PING_ADDR 0x00000100
+#define VFE_BUS_STATS_AF_WR_PONG_ADDR 0x00000104
+#define VFE_BUS_STATS_AF_UB_CFG 0x00000108
+#define VFE_BUS_STATS_AWB_WR_PING_ADDR 0x0000010C
+#define VFE_BUS_STATS_AWB_WR_PONG_ADDR 0x00000110
+#define VFE_BUS_STATS_AWB_UB_CFG 0x00000114
+#define VFE_BUS_STATS_RS_WR_PING_ADDR 0x00000118
+#define VFE_BUS_STATS_RS_WR_PONG_ADDR 0x0000011C
+#define VFE_BUS_STATS_RS_UB_CFG 0x00000120
+
+#define VFE_BUS_STATS_CS_WR_PING_ADDR 0x00000124
+#define VFE_BUS_STATS_CS_WR_PONG_ADDR 0x00000128
+#define VFE_BUS_STATS_CS_UB_CFG 0x0000012C
+#define VFE_BUS_STATS_HIST_WR_PING_ADDR 0x00000130
+#define VFE_BUS_STATS_HIST_WR_PONG_ADDR 0x00000134
+#define VFE_BUS_STATS_HIST_UB_CFG 0x00000138
+#define VFE_BUS_STATS_SKIN_WR_PING_ADDR 0x0000013C
+#define VFE_BUS_STATS_SKIN_WR_PONG_ADDR 0x00000140
+#define VFE_BUS_STATS_SKIN_UB_CFG 0x00000144
+#define VFE_BUS_PM_CMD 0x00000188
+#define VFE_BUS_PM_CFG 0x0000018C
+#define VFE_CAMIF_COMMAND 0x000001E0
+#define VFE_CAMIF_STATUS 0x00000204
+#define VFE_REG_UPDATE_CMD 0x00000260
+#define VFE_DEMUX_GAIN_0 0x00000288
+#define VFE_DEMUX_GAIN_1 0x0000028C
+#define VFE_CHROMA_UP 0x0000035C
+#define VFE_FRAMEDROP_ENC_Y_CFG 0x00000504
+#define VFE_FRAMEDROP_ENC_CBCR_CFG 0x00000508
+#define VFE_FRAMEDROP_ENC_Y_PATTERN 0x0000050C
+#define VFE_FRAMEDROP_ENC_CBCR_PATTERN 0x00000510
+#define VFE_FRAMEDROP_VIEW_Y 0x00000514
+#define VFE_FRAMEDROP_VIEW_CBCR 0x00000518
+#define VFE_FRAMEDROP_VIEW_Y_PATTERN 0x0000051C
+#define VFE_FRAMEDROP_VIEW_CBCR_PATTERN 0x00000520
+#define VFE_CLAMP_MAX 0x00000524
+#define VFE_CLAMP_MIN 0x00000528
+#define VFE_REALIGN_BUF 0x0000052C
+#define VFE_STATS_CFG 0x00000530
+#define VFE_STATS_AWB_SGW_CFG 0x00000554
+#define VFE_DMI_CFG 0x00000598
+#define VFE_DMI_ADDR 0x0000059C
+#define VFE_DMI_DATA_LO 0x000005A4
+#define VFE_AXI_CFG 0x00000600
+
+#define VFE31_OUTPUT_MODE_PT BIT(0)
+#define VFE31_OUTPUT_MODE_S BIT(1)
+#define VFE31_OUTPUT_MODE_V BIT(2)
+#define VFE31_OUTPUT_MODE_P BIT(3)
+#define VFE31_OUTPUT_MODE_T BIT(4)
+#define VFE31_OUTPUT_MODE_P_ALL_CHNLS BIT(5)
+#define VFE31_OUTPUT_MODE_PRIMARY BIT(6)
+#define VFE31_OUTPUT_MODE_PRIMARY_ALL_CHNLS BIT(7)
+#define VFE31_OUTPUT_MODE_SECONDARY BIT(8)
+#define VFE31_OUTPUT_MODE_SECONDARY_ALL_CHNLS BIT(9)
+struct vfe_stats_control {
+ uint8_t ackPending;
+ uint32_t nextFrameAddrBuf;
+ uint32_t droppedStatsFrameCount;
+ uint32_t bufToRender;
+};
+
+struct vfe31_ctrl_type {
+ uint16_t operation_mode; /* streaming or snapshot */
+ struct vfe31_output_path outpath;
+
+ uint32_t vfeImaskCompositePacked;
+
+ spinlock_t stop_flag_lock;
+ spinlock_t update_ack_lock;
+ spinlock_t state_lock;
+ spinlock_t io_lock;
+
+ spinlock_t aec_ack_lock;
+ spinlock_t awb_ack_lock;
+ spinlock_t af_ack_lock;
+ spinlock_t ihist_ack_lock;
+ spinlock_t rs_ack_lock;
+ spinlock_t cs_ack_lock;
+ spinlock_t comp_stats_ack_lock;
+
+ uint32_t extlen;
+ void *extdata;
+
+ int8_t start_ack_pending;
+ int8_t stop_ack_pending;
+ int8_t reset_ack_pending;
+ int8_t update_ack_pending;
+ enum vfe_output_state recording_state;
+ int8_t update_linear;
+ int8_t update_rolloff;
+ int8_t update_la;
+ int8_t update_gamma;
+ enum vfe_output_state liveshot_state;
+
+ spinlock_t tasklet_lock;
+ struct list_head tasklet_q;
+ void __iomem *vfebase;
+ void __iomem *camifbase;
+ void *syncdata;
+ uint32_t register_total;
+
+ struct resource *vfemem;
+ struct resource *camifmem;
+ struct resource *vfeio;
+ struct resource *camifio;
+ struct resource *vfeirq;
+ struct regulator *fs_vfe;
+
+ uint32_t stats_comp;
+ atomic_t vstate;
+ uint32_t vfe_capture_count;
+ uint32_t sync_timer_repeat_count;
+ uint32_t sync_timer_state;
+ uint32_t sync_timer_number;
+
+ uint32_t vfeFrameId;
+ uint32_t output1Pattern;
+ uint32_t output1Period;
+ uint32_t output2Pattern;
+ uint32_t output2Period;
+ uint32_t vfeFrameSkipCount;
+ uint32_t vfeFrameSkipPeriod;
+ struct vfe_stats_control afStatsControl;
+ struct vfe_stats_control awbStatsControl;
+ struct vfe_stats_control aecStatsControl;
+ struct vfe_stats_control ihistStatsControl;
+ struct vfe_stats_control rsStatsControl;
+ struct vfe_stats_control csStatsControl;
+
+ /* v4l2 subdev */
+ struct v4l2_subdev subdev;
+ struct platform_device *pdev;
+ struct clk *vfe_clk[5];
+ struct clk *vfe_camif_clk[2];
+ spinlock_t sd_notify_lock;
+ uint32_t hfr_mode;
+ uint32_t frame_skip_cnt;
+ uint32_t frame_skip_pattern;
+ uint32_t snapshot_frame_cnt;
+};
+
+enum VFE31_STATS_NUM {
+ STATS_AE_NUM,
+ STATS_AF_NUM,
+ STATS_AWB_NUM,
+ STATS_RS_NUM,
+ STATS_CS_NUM,
+ STATS_IHIST_NUM,
+ STATS_SKIN_NUM,
+ STATS_MAX_NUM,
+};
+
+struct vfe_cmd_stats_ack {
+ uint32_t nextStatsBuf;
+};
+
+#define VFE_STATS_BUFFER_COUNT 3
+
+struct vfe_cmd_stats_buf {
+ uint32_t statsBuf[VFE_STATS_BUFFER_COUNT];
+};
+#endif /* __MSM_VFE31_H__ */
diff --git a/drivers/media/video/msm/sensors/Makefile b/drivers/media/video/msm/sensors/Makefile
index 3052832..07cea70 100644
--- a/drivers/media/video/msm/sensors/Makefile
+++ b/drivers/media/video/msm/sensors/Makefile
@@ -13,3 +13,4 @@
obj-$(CONFIG_MT9E013) += mt9e013_v4l2.o
obj-$(CONFIG_WEBCAM_OV9726) += ov9726_v4l2.o
obj-$(CONFIG_WEBCAM_OV7692_QRD) += ov7692_qrd_v4l2.o
+obj-$(CONFIG_VX6953) += vx6953.o
diff --git a/drivers/media/video/msm/sensors/imx074_v4l2.c b/drivers/media/video/msm/sensors/imx074_v4l2.c
index af9d1f4..5330d7b 100644
--- a/drivers/media/video/msm/sensors/imx074_v4l2.c
+++ b/drivers/media/video/msm/sensors/imx074_v4l2.c
@@ -168,6 +168,19 @@
},
};
+static struct msm_camera_csi_params imx074_csic_params = {
+ .data_format = CSI_10BIT,
+ .lane_cnt = 4,
+ .lane_assign = 0xe4,
+ .dpcm_scheme = 0,
+ .settle_cnt = 0x14,
+};
+
+static struct msm_camera_csi_params *imx074_csic_params_array[] = {
+ &imx074_csic_params,
+ &imx074_csic_params,
+};
+
static struct msm_camera_csid_vc_cfg imx074_cid_cfg[] = {
{0, CSI_RAW10, CSI_DECODE_10BIT},
{1, CSI_EMBED_DATA, CSI_DECODE_8BIT},
@@ -288,6 +301,7 @@
.sensor_write_exp_gain = msm_sensor_write_exp_gain1,
.sensor_write_snapshot_exp_gain = msm_sensor_write_exp_gain1,
.sensor_setting = msm_sensor_setting,
+ .sensor_csi_setting = msm_sensor_setting1,
.sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
.sensor_mode_init = msm_sensor_mode_init,
.sensor_get_output_info = msm_sensor_get_output_info,
@@ -323,6 +337,7 @@
.sensor_id_info = &imx074_id_info,
.sensor_exp_gain_info = &imx074_exp_gain_info,
.cam_mode = MSM_SENSOR_MODE_INVALID,
+ .csic_params = &imx074_csic_params_array[0],
.csi_params = &imx074_csi_params_array[0],
.msm_sensor_mutex = &imx074_mut,
.sensor_i2c_driver = &imx074_i2c_driver,
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index d882e52..3e8d599 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -245,6 +245,10 @@
msleep(30);
csi_config = 1;
}
+ v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
+ NOTIFY_PCLK_CHANGE,
+ &s_ctrl->sensordata->pdata->ioclk.vfe_clk_rate);
+
s_ctrl->func_tbl->sensor_start_stream(s_ctrl);
msleep(50);
}
@@ -312,8 +316,14 @@
s_ctrl->msm_sensor_reg->
output_settings[res].line_length_pclk;
- if (s_ctrl->func_tbl->sensor_setting
- (s_ctrl, MSM_SENSOR_UPDATE_PERIODIC, res) < 0)
+ if (s_ctrl->sensordata->pdata->is_csic ||
+ !s_ctrl->sensordata->csi_if)
+ rc = s_ctrl->func_tbl->sensor_csi_setting(s_ctrl,
+ MSM_SENSOR_UPDATE_PERIODIC, res);
+ else
+ rc = s_ctrl->func_tbl->sensor_setting(s_ctrl,
+ MSM_SENSOR_UPDATE_PERIODIC, res);
+ if (rc < 0)
return rc;
s_ctrl->curr_res = res;
}
@@ -333,8 +343,13 @@
s_ctrl->curr_res = MSM_SENSOR_INVALID_RES;
s_ctrl->cam_mode = mode;
- rc = s_ctrl->func_tbl->sensor_setting(s_ctrl,
- MSM_SENSOR_REG_INIT, 0);
+ if (s_ctrl->sensordata->pdata->is_csic ||
+ !s_ctrl->sensordata->csi_if)
+ rc = s_ctrl->func_tbl->sensor_csi_setting(s_ctrl,
+ MSM_SENSOR_REG_INIT, 0);
+ else
+ rc = s_ctrl->func_tbl->sensor_setting(s_ctrl,
+ MSM_SENSOR_REG_INIT, 0);
}
return rc;
}
@@ -608,6 +623,8 @@
msm_sensor_disable_i2c_mux(
data->sensor_platform_info->i2c_conf);
+ s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
+ msleep(20);
if (data->sensor_platform_info->ext_power_ctrl != NULL)
data->sensor_platform_info->ext_power_ctrl(0);
msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->dev,
@@ -626,7 +643,6 @@
return 0;
}
-
int32_t msm_sensor_match_id(struct msm_sensor_ctrl_t *s_ctrl)
{
int32_t rc = 0;
@@ -658,9 +674,10 @@
{
int rc = 0;
struct msm_sensor_ctrl_t *s_ctrl;
- CDBG("%s_i2c_probe called\n", client->name);
+ CDBG("%s %s_i2c_probe called\n", __func__, client->name);
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- CDBG("i2c_check_functionality failed\n");
+ pr_err("%s %s i2c_check_functionality failed\n",
+ __func__, client->name);
rc = -EFAULT;
return rc;
}
@@ -672,21 +689,28 @@
s_ctrl->sensor_i2c_client->client->addr =
s_ctrl->sensor_i2c_addr;
} else {
+ pr_err("%s %s sensor_i2c_client NULL\n",
+ __func__, client->name);
rc = -EFAULT;
return rc;
}
s_ctrl->sensordata = client->dev.platform_data;
if (s_ctrl->sensordata == NULL) {
- pr_err("%s: NULL sensor data\n", __func__);
+ pr_err("%s %s NULL sensor data\n", __func__, client->name);
return -EFAULT;
}
rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
- if (rc < 0)
- goto probe_fail;
+ if (rc < 0) {
+ pr_err("%s %s power up failed\n", __func__, client->name);
+ return rc;
+ }
- rc = msm_sensor_match_id(s_ctrl);
+ if (s_ctrl->func_tbl->sensor_match_id)
+ rc = s_ctrl->func_tbl->sensor_match_id(s_ctrl);
+ else
+ rc = msm_sensor_match_id(s_ctrl);
if (rc < 0)
goto probe_fail;
@@ -717,7 +741,7 @@
msm_sensor_register(&s_ctrl->sensor_v4l2_subdev);
goto power_down;
probe_fail:
- CDBG("%s_i2c_probe failed\n", client->name);
+ pr_err("%s %s_i2c_probe failed\n", __func__, client->name);
power_down:
if (rc > 0)
rc = 0;
diff --git a/drivers/media/video/msm/sensors/msm_sensor.h b/drivers/media/video/msm/sensors/msm_sensor.h
index d1a6cee..421e1d1 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.h
+++ b/drivers/media/video/msm/sensors/msm_sensor.h
@@ -120,6 +120,8 @@
uint16_t, uint32_t);
int32_t (*sensor_setting) (struct msm_sensor_ctrl_t *,
int update_type, int rt);
+ int32_t (*sensor_csi_setting) (struct msm_sensor_ctrl_t *,
+ int update_type, int rt);
int32_t (*sensor_set_sensor_mode)
(struct msm_sensor_ctrl_t *, int, int);
int32_t (*sensor_mode_init) (struct msm_sensor_ctrl_t *,
@@ -130,6 +132,7 @@
int (*sensor_power_down)
(struct msm_sensor_ctrl_t *);
int (*sensor_power_up) (struct msm_sensor_ctrl_t *);
+ int32_t (*sensor_match_id)(struct msm_sensor_ctrl_t *s_ctrl);
};
struct msm_sensor_ctrl_t {
diff --git a/drivers/media/video/msm/sensors/mt9e013_v4l2.c b/drivers/media/video/msm/sensors/mt9e013_v4l2.c
index a6bc653..e6e2d52 100644
--- a/drivers/media/video/msm/sensors/mt9e013_v4l2.c
+++ b/drivers/media/video/msm/sensors/mt9e013_v4l2.c
@@ -465,7 +465,7 @@
.sensor_set_fps = msm_sensor_set_fps,
.sensor_write_exp_gain = mt9e013_write_exp_gain,
.sensor_write_snapshot_exp_gain = mt9e013_write_exp_snapshot_gain,
- .sensor_setting = msm_sensor_setting1,
+ .sensor_csi_setting = msm_sensor_setting1,
.sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
.sensor_mode_init = msm_sensor_mode_init,
.sensor_get_output_info = msm_sensor_get_output_info,
diff --git a/drivers/media/video/msm/sensors/ov5647_v4l2.c b/drivers/media/video/msm/sensors/ov5647_v4l2.c
index ba0592e..7c23fe6 100644
--- a/drivers/media/video/msm/sensors/ov5647_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov5647_v4l2.c
@@ -693,7 +693,7 @@
.sensor_set_fps = msm_sensor_set_fps,
.sensor_write_exp_gain = ov5647_write_prev_exp_gain,
.sensor_write_snapshot_exp_gain = ov5647_write_pict_exp_gain,
- .sensor_setting = ov5647_sensor_setting,
+ .sensor_csi_setting = ov5647_sensor_setting,
.sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
.sensor_mode_init = msm_sensor_mode_init,
.sensor_get_output_info = msm_sensor_get_output_info,
diff --git a/drivers/media/video/msm/sensors/ov7692_qrd_v4l2.c b/drivers/media/video/msm/sensors/ov7692_qrd_v4l2.c
index 99e96f0..9fe2e8a 100644
--- a/drivers/media/video/msm/sensors/ov7692_qrd_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov7692_qrd_v4l2.c
@@ -688,7 +688,7 @@
.sensor_group_hold_on = msm_sensor_group_hold_on,
.sensor_group_hold_off = msm_sensor_group_hold_off,
.sensor_set_fps = ov7692_sensor_set_fps,
- .sensor_setting = msm_sensor_setting3,
+ .sensor_csi_setting = msm_sensor_setting3,
.sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
.sensor_mode_init = msm_sensor_mode_init,
.sensor_get_output_info = msm_sensor_get_output_info,
diff --git a/drivers/media/video/msm/sensors/ov9726_v4l2.c b/drivers/media/video/msm/sensors/ov9726_v4l2.c
index 17291ff..61c693e 100644
--- a/drivers/media/video/msm/sensors/ov9726_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov9726_v4l2.c
@@ -229,7 +229,7 @@
.sensor_set_fps = msm_sensor_set_fps,
.sensor_write_exp_gain = msm_sensor_write_exp_gain1,
.sensor_write_snapshot_exp_gain = msm_sensor_write_exp_gain1,
- .sensor_setting = msm_sensor_setting1,
+ .sensor_csi_setting = msm_sensor_setting1,
.sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
.sensor_mode_init = msm_sensor_mode_init,
.sensor_get_output_info = msm_sensor_get_output_info,
diff --git a/drivers/media/video/msm/sensors/s5k4e1_v4l2.c b/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
index 699f0dd..6671073 100644
--- a/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
+++ b/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
@@ -450,7 +450,7 @@
.sensor_set_fps = msm_sensor_set_fps,
.sensor_write_exp_gain = s5k4e1_write_prev_exp_gain,
.sensor_write_snapshot_exp_gain = s5k4e1_write_pict_exp_gain,
- .sensor_setting = msm_sensor_setting1,
+ .sensor_csi_setting = msm_sensor_setting1,
.sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
.sensor_mode_init = msm_sensor_mode_init,
.sensor_get_output_info = msm_sensor_get_output_info,
diff --git a/drivers/media/video/msm/sensors/vx6953.c b/drivers/media/video/msm/sensors/vx6953.c
new file mode 100644
index 0000000..b43782c
--- /dev/null
+++ b/drivers/media/video/msm/sensors/vx6953.c
@@ -0,0 +1,2058 @@
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_sensor.h"
+#include "msm.h"
+#include "vx6953.h"
+#include "vx6953_reg.h"
+#define SENSOR_NAME "vx6953"
+#define PLATFORM_DRIVER_NAME "msm_camera_vx6953"
+#define vx6953_obj vx6953_##obj
+
+DEFINE_MUTEX(vx6953_mut);
+
+#undef CDBG
+#define CDBG printk
+#define REG_GROUPED_PARAMETER_HOLD 0x0104
+#define GROUPED_PARAMETER_HOLD_OFF 0x00
+#define GROUPED_PARAMETER_HOLD 0x01
+#define REG_MODE_SELECT 0x0100
+#define MODE_SELECT_STANDBY_MODE 0x00
+#define MODE_SELECT_STREAM 0x01
+/* Integration Time */
+#define REG_COARSE_INTEGRATION_TIME_HI 0x0202
+#define REG_COARSE_INTEGRATION_TIME_LO 0x0203
+/* Gain */
+#define REG_ANALOGUE_GAIN_CODE_GLOBAL_HI 0x0204
+#define REG_ANALOGUE_GAIN_CODE_GLOBAL_LO 0x0205
+/* Digital Gain */
+#define REG_DIGITAL_GAIN_GREEN_R_HI 0x020E
+#define REG_DIGITAL_GAIN_GREEN_R_LO 0x020F
+#define REG_DIGITAL_GAIN_RED_HI 0x0210
+#define REG_DIGITAL_GAIN_RED_LO 0x0211
+#define REG_DIGITAL_GAIN_BLUE_HI 0x0212
+#define REG_DIGITAL_GAIN_BLUE_LO 0x0213
+#define REG_DIGITAL_GAIN_GREEN_B_HI 0x0214
+#define REG_DIGITAL_GAIN_GREEN_B_LO 0x0215
+/* output bits setting */
+#define REG_0x0112 0x0112
+#define REG_0x0113 0x0113
+/* PLL registers */
+#define REG_VT_PIX_CLK_DIV 0x0301
+#define REG_PRE_PLL_CLK_DIV 0x0305
+#define REG_PLL_MULTIPLIER 0x0307
+#define REG_OP_PIX_CLK_DIV 0x0309
+#define REG_0x034c 0x034c
+#define REG_0x034d 0x034d
+#define REG_0x034e 0x034e
+#define REG_0x034f 0x034f
+#define REG_0x0387 0x0387
+#define REG_0x0383 0x0383
+#define REG_FRAME_LENGTH_LINES_HI 0x0340
+#define REG_FRAME_LENGTH_LINES_LO 0x0341
+#define REG_LINE_LENGTH_PCK_HI 0x0342
+#define REG_LINE_LENGTH_PCK_LO 0x0343
+#define REG_0x3030 0x3030
+#define REG_0x0111 0x0111
+#define REG_0x0136 0x0136
+#define REG_0x0137 0x0137
+#define REG_0x0b00 0x0b00
+#define REG_0x3001 0x3001
+#define REG_0x3004 0x3004
+#define REG_0x3007 0x3007
+#define REG_0x301a 0x301a
+#define REG_0x3101 0x3101
+#define REG_0x3364 0x3364
+#define REG_0x3365 0x3365
+#define REG_0x0b83 0x0b83
+#define REG_0x0b84 0x0b84
+#define REG_0x0b85 0x0b85
+#define REG_0x0b88 0x0b88
+#define REG_0x0b89 0x0b89
+#define REG_0x0b8a 0x0b8a
+#define REG_0x3005 0x3005
+#define REG_0x3010 0x3010
+#define REG_0x3036 0x3036
+#define REG_0x3041 0x3041
+#define REG_0x0b80 0x0b80
+#define REG_0x0900 0x0900
+#define REG_0x0901 0x0901
+#define REG_0x0902 0x0902
+#define REG_0x3016 0x3016
+#define REG_0x301d 0x301d
+#define REG_0x317e 0x317e
+#define REG_0x317f 0x317f
+#define REG_0x3400 0x3400
+#define REG_0x303a 0x303a
+#define REG_0x1716 0x1716
+#define REG_0x1717 0x1717
+#define REG_0x1718 0x1718
+#define REG_0x1719 0x1719
+#define REG_0x3006 0x3006
+#define REG_0x301b 0x301b
+#define REG_0x3098 0x3098
+#define REG_0x309d 0x309d
+#define REG_0x3011 0x3011
+#define REG_0x3035 0x3035
+#define REG_0x3045 0x3045
+#define REG_0x3210 0x3210
+#define REG_0x0111 0x0111
+#define REG_0x3410 0x3410
+#define REG_0x0b06 0x0b06
+#define REG_0x0b07 0x0b07
+#define REG_0x0b08 0x0b08
+#define REG_0x0b09 0x0b09
+#define REG_0x3640 0x3640
+/* Test Pattern */
+#define REG_TEST_PATTERN_MODE 0x0601
+/* 16bit address - 8 bit context register structure */
+#define VX6953_STM5M0EDOF_OFFSET 9
+#define Q8 0x00000100
+#define Q10 0x00000400
+#define VX6953_STM5M0EDOF_MAX_SNAPSHOT_EXPOSURE_LINE_COUNT 2922
+#define VX6953_STM5M0EDOF_DEFAULT_MASTER_CLK_RATE 24000000
+#define VX6953_STM5M0EDOF_OP_PIXEL_CLOCK_RATE 79800000
+#define VX6953_STM5M0EDOF_VT_PIXEL_CLOCK_RATE 88670000
+/* Full Size */
+#define VX6953_FULL_SIZE_WIDTH 2608
+#define VX6953_FULL_SIZE_HEIGHT 1960
+#define VX6953_FULL_SIZE_DUMMY_PIXELS 1
+#define VX6953_FULL_SIZE_DUMMY_LINES 0
+/* Quarter Size */
+#define VX6953_QTR_SIZE_WIDTH 1304
+#define VX6953_QTR_SIZE_HEIGHT 980
+#define VX6953_QTR_SIZE_DUMMY_PIXELS 1
+#define VX6953_QTR_SIZE_DUMMY_LINES 0
+/* Blanking as measured on the scope */
+/* Full Size */
+#define VX6953_HRZ_FULL_BLK_PIXELS 348
+#define VX6953_VER_FULL_BLK_LINES 40
+/* Quarter Size */
+#define VX6953_HRZ_QTR_BLK_PIXELS 1628
+#define VX6953_VER_QTR_BLK_LINES 28
+#define MAX_LINE_LENGTH_PCK 8190
+#define MAX_FRAME_LENGTH_LINES 16383
+#define VX6953_REVISION_NUMBER_CUT2 0x10/*revision number for Cut2.0*/
+#define VX6953_REVISION_NUMBER_CUT3 0x20/*revision number for Cut3.0*/
+static struct msm_sensor_ctrl_t vx6953_s_ctrl;
+static uint32_t fps_divider;/* init to 1 * 0x00000400 */
+static uint16_t fps;
+static uint8_t vx6953_stm5m0edof_delay_msecs_stdby;
+static struct msm_camera_i2c_reg_conf vx6953_start_settings[] = {
+ {0x0100, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf vx6953_stop_settings[] = {
+ {0x0100, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf vx6953_groupon_settings[] = {
+ {0x0104, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf vx6953_groupoff_settings[] = {
+ {0x0104, 0x00},
+};
+
+static struct msm_camera_i2c_reg_conf vx6953_prev_settings[] = {
+ {0x0202, 0x03},/*REG = 0x0202 coarse integration_time_hi*/
+ {0x0203, 0xD0},/*REG = 0x0203 coarse_integration_time_lo*/
+ {0x0205, 0xC0},/*REG = 0x0205 analogue_gain_code_global*/
+ {0x0340, 0x03},/*REG = 0x0340 frame_length_lines_hi*/
+ {0x0341, 0xf0},/*REG = 0x0341 frame_length_lines_lo*/
+ {0x0342, 0x0b},/*REG = 0x0342 line_length_pck_hi*/
+ {0x0343, 0x74},/*REG = 0x0343 line_length_pck_lo*/
+ {0x3005, 0x03},/*REG = 0x3005*/
+ {0x3010, 0x00},/*REG = 0x3010*/
+ {0x3011, 0x01},/*REG = 0x3011*/
+ {0x301a, 0x6a},/*REG = 0x301a*/
+ {0x3035, 0x03},/*REG = 0x3035*/
+ {0x3036, 0x2c},/*REG = 0x3036*/
+ {0x3041, 0x00},/*REG = 0x3041*/
+ {0x3042, 0x24},/*REG = 0x3042*/
+ {0x3045, 0x81},/*REG = 0x3045*/
+ {0x0b80, 0x02},/*REG = 0x0b80 edof estimate*/
+ {0x0900, 0x01},/*REG = 0x0900*/
+ {0x0901, 0x22},/*REG = 0x0901*/
+ {0x0902, 0x04},/*REG = 0x0902*/
+ {0x0383, 0x03},/*REG = 0x0383*/
+ {0x0387, 0x03},/*REG = 0x0387*/
+ {0x034c, 0x05},/*REG = 0x034c*/
+ {0x034d, 0x18},/*REG = 0x034d*/
+ {0x034e, 0x03},/*REG = 0x034e*/
+ {0x034f, 0xd4},/*REG = 0x034f*/
+ {0x1716, 0x02},/*0x1716*/
+ {0x1717, 0x04},/*0x1717*/
+ {0x1718, 0x08},/*0x1718*/
+ {0x1719, 0x2c},/*0x1719*/
+};
+
+static struct msm_camera_i2c_reg_conf vx6953_snap_settings[] = {
+ {0x0202, 0x07},/*REG = 0x0202 coarse_integration_time_hi*/
+ {0x0203, 0x00},/*REG = 0x0203 coarse_integration_time_lo*/
+ {0x0205, 0xc0},/*REG = 0x0205 analogue_gain_code_global*/
+ {0x0340, 0x07},/*REG = 0x0340 frame_length_lines_hi*/
+ {0x0341, 0xd0},/*REG = 0x0341 frame_length_lines_lo*/
+ {0x0342, 0x0b},/*REG = 0x0342 line_length_pck_hi*/
+ {0x0343, 0x8c},/*REG = 0x0343 line_length_pck_lo*/
+ {0x3005, 0x01},/*REG = 0x3005*/
+ {0x3010, 0x00},/*REG = 0x3010*/
+ {0x3011, 0x00},/*REG = 0x3011*/
+ {0x301a, 0x55},/*REG = 0x301a*/
+ {0x3035, 0x01},/*REG = 0x3035*/
+ {0x3036, 0x23},/*REG = 0x3036*/
+ {0x3041, 0x00},/*REG = 0x3041*/
+ {0x3042, 0x24},/*REG = 0x3042*/
+ {0x3045, 0xb7},/*REG = 0x3045*/
+ {0x0b80, 0x01},/*REG = 0x0b80 edof application*/
+ {0x0900, 0x00},/*REG = 0x0900*/
+ {0x0901, 0x00},/*REG = 0x0901*/
+ {0x0902, 0x00},/*REG = 0x0902*/
+ {0x0383, 0x01},/*REG = 0x0383*/
+ {0x0387, 0x01},/*REG = 0x0387*/
+ {0x034c, 0x0A},/*REG = 0x034c*/
+ {0x034d, 0x30},/*REG = 0x034d*/
+ {0x034e, 0x07},/*REG = 0x034e*/
+ {0x034f, 0xA8},/*REG = 0x034f*/
+ {0x1716, 0x02},/*0x1716*/
+ {0x1717, 0x0d},/*0x1717*/
+ {0x1718, 0x07},/*0x1718*/
+ {0x1719, 0x7d},/*0x1719*/
+};
+
+static struct msm_camera_i2c_reg_conf vx6953_recommend_settings[] = {
+ {0x0103, 0x01}, /* standby */
+ {0x0100, 0x00}, /* stop streaming */
+ /* patch cut 2*/
+ {0xFB94, 0}, /*intialise Data Xfer Status reg*/
+ {0xFB95, 0}, /*gain 1 (0x00)*/
+ {0xFB96, 0}, /*gain 1.07 (0x10)*/
+ {0xFB97, 0}, /*gain 1.14 (0x20)*/
+ {0xFB98, 0}, /*gain 1.23 (0x30)*/
+ {0xFB99, 0}, /*gain 1.33 (0x40)*/
+ {0xFB9A, 0}, /*gain 1.45 (0x50)*/
+ {0xFB9B, 0}, /*gain 1.6 (0x60)*/
+ {0xFB9C, 0}, /*gain 1.78 (0x70)*/
+ {0xFB9D, 2}, /*gain 2 (0x80)*/
+ {0xFB9E, 2}, /*gain 2.29 (0x90)*/
+ {0xFB9F, 3}, /*gain 2.67 (0xA0)*/
+ {0xFBA0, 3}, /*gain 3.2 (0xB0)*/
+ {0xFBA1, 4}, /*gain 4 (0xC0)*/
+ {0xFBA2, 7}, /*gain 5.33 (0xD0)*/
+ {0xFBA3, 10}, /*gain 8 (0xE0)*/
+ {0xFBA4, 11}, /*gain 9.14 (0xE4)*/
+ {0xFBA5, 13}, /*gain 10.67 (0xE8)*/
+ {0xFBA6, 15}, /*gain 12.8 (0xEC)*/
+ {0xFBA7, 19}, /*gain 16 (0xF0)*/
+ {0xF800, 0x12},
+ {0xF801, 0x06},
+ {0xF802, 0xf7},
+ {0xF803, 0x90},
+ {0xF804, 0x02},
+ {0xF805, 0x05},
+ {0xF806, 0xe0},
+ {0xF807, 0xff},
+ {0xF808, 0x65},
+ {0xF809, 0x7d},
+ {0xF80A, 0x70},
+ {0xF80B, 0x03},
+ {0xF80C, 0x02},
+ {0xF80D, 0xf9},
+ {0xF80E, 0x1c},
+ {0xF80F, 0x8f},
+ {0xF810, 0x7d},
+ {0xF811, 0xe4},
+ {0xF812, 0xf5},
+ {0xF813, 0x7a},
+ {0xF814, 0x75},
+ {0xF815, 0x78},
+ {0xF816, 0x30},
+ {0xF817, 0x75},
+ {0xF818, 0x79},
+ {0xF819, 0x53},
+ {0xF81A, 0x85},
+ {0xF81B, 0x79},
+ {0xF81C, 0x82},
+ {0xF81D, 0x85},
+ {0xF81E, 0x78},
+ {0xF81F, 0x83},
+ {0xF820, 0xe0},
+ {0xF821, 0xc3},
+ {0xF822, 0x95},
+ {0xF823, 0x7b},
+ {0xF824, 0xf0},
+ {0xF825, 0x74},
+ {0xF826, 0x02},
+ {0xF827, 0x25},
+ {0xF828, 0x79},
+ {0xF829, 0xf5},
+ {0xF82A, 0x79},
+ {0xF82B, 0xe4},
+ {0xF82C, 0x35},
+ {0xF82D, 0x78},
+ {0xF82E, 0xf5},
+ {0xF82F, 0x78},
+ {0xF830, 0x05},
+ {0xF831, 0x7a},
+ {0xF832, 0xe5},
+ {0xF833, 0x7a},
+ {0xF834, 0xb4},
+ {0xF835, 0x08},
+ {0xF836, 0xe3},
+ {0xF837, 0xe5},
+ {0xF838, 0x7d},
+ {0xF839, 0x70},
+ {0xF83A, 0x04},
+ {0xF83B, 0xff},
+ {0xF83C, 0x02},
+ {0xF83D, 0xf8},
+ {0xF83E, 0xe4},
+ {0xF83F, 0xe5},
+ {0xF840, 0x7d},
+ {0xF841, 0xb4},
+ {0xF842, 0x10},
+ {0xF843, 0x05},
+ {0xF844, 0x7f},
+ {0xF845, 0x01},
+ {0xF846, 0x02},
+ {0xF847, 0xf8},
+ {0xF848, 0xe4},
+ {0xF849, 0xe5},
+ {0xF84A, 0x7d},
+ {0xF84B, 0xb4},
+ {0xF84C, 0x20},
+ {0xF84D, 0x05},
+ {0xF84E, 0x7f},
+ {0xF84F, 0x02},
+ {0xF850, 0x02},
+ {0xF851, 0xf8},
+ {0xF852, 0xe4},
+ {0xF853, 0xe5},
+ {0xF854, 0x7d},
+ {0xF855, 0xb4},
+ {0xF856, 0x30},
+ {0xF857, 0x05},
+ {0xF858, 0x7f},
+ {0xF859, 0x03},
+ {0xF85A, 0x02},
+ {0xF85B, 0xf8},
+ {0xF85C, 0xe4},
+ {0xF85D, 0xe5},
+ {0xF85E, 0x7d},
+ {0xF85F, 0xb4},
+ {0xF860, 0x40},
+ {0xF861, 0x04},
+ {0xF862, 0x7f},
+ {0xF863, 0x04},
+ {0xF864, 0x80},
+ {0xF865, 0x7e},
+ {0xF866, 0xe5},
+ {0xF867, 0x7d},
+ {0xF868, 0xb4},
+ {0xF869, 0x50},
+ {0xF86A, 0x04},
+ {0xF86B, 0x7f},
+ {0xF86C, 0x05},
+ {0xF86D, 0x80},
+ {0xF86E, 0x75},
+ {0xF86F, 0xe5},
+ {0xF870, 0x7d},
+ {0xF871, 0xb4},
+ {0xF872, 0x60},
+ {0xF873, 0x04},
+ {0xF874, 0x7f},
+ {0xF875, 0x06},
+ {0xF876, 0x80},
+ {0xF877, 0x6c},
+ {0xF878, 0xe5},
+ {0xF879, 0x7d},
+ {0xF87A, 0xb4},
+ {0xF87B, 0x70},
+ {0xF87C, 0x04},
+ {0xF87D, 0x7f},
+ {0xF87E, 0x07},
+ {0xF87F, 0x80},
+ {0xF880, 0x63},
+ {0xF881, 0xe5},
+ {0xF882, 0x7d},
+ {0xF883, 0xb4},
+ {0xF884, 0x80},
+ {0xF885, 0x04},
+ {0xF886, 0x7f},
+ {0xF887, 0x08},
+ {0xF888, 0x80},
+ {0xF889, 0x5a},
+ {0xF88A, 0xe5},
+ {0xF88B, 0x7d},
+ {0xF88C, 0xb4},
+ {0xF88D, 0x90},
+ {0xF88E, 0x04},
+ {0xF88F, 0x7f},
+ {0xF890, 0x09},
+ {0xF891, 0x80},
+ {0xF892, 0x51},
+ {0xF893, 0xe5},
+ {0xF894, 0x7d},
+ {0xF895, 0xb4},
+ {0xF896, 0xa0},
+ {0xF897, 0x04},
+ {0xF898, 0x7f},
+ {0xF899, 0x0a},
+ {0xF89A, 0x80},
+ {0xF89B, 0x48},
+ {0xF89C, 0xe5},
+ {0xF89D, 0x7d},
+ {0xF89E, 0xb4},
+ {0xF89F, 0xb0},
+ {0xF8A0, 0x04},
+ {0xF8A1, 0x7f},
+ {0xF8A2, 0x0b},
+ {0xF8A3, 0x80},
+ {0xF8A4, 0x3f},
+ {0xF8A5, 0xe5},
+ {0xF8A6, 0x7d},
+ {0xF8A7, 0xb4},
+ {0xF8A8, 0xc0},
+ {0xF8A9, 0x04},
+ {0xF8AA, 0x7f},
+ {0xF8AB, 0x0c},
+ {0xF8AC, 0x80},
+ {0xF8AD, 0x36},
+ {0xF8AE, 0xe5},
+ {0xF8AF, 0x7d},
+ {0xF8B0, 0xb4},
+ {0xF8B1, 0xd0},
+ {0xF8B2, 0x04},
+ {0xF8B3, 0x7f},
+ {0xF8B4, 0x0d},
+ {0xF8B5, 0x80},
+ {0xF8B6, 0x2d},
+ {0xF8B7, 0xe5},
+ {0xF8B8, 0x7d},
+ {0xF8B9, 0xb4},
+ {0xF8BA, 0xe0},
+ {0xF8BB, 0x04},
+ {0xF8BC, 0x7f},
+ {0xF8BD, 0x0e},
+ {0xF8BE, 0x80},
+ {0xF8BF, 0x24},
+ {0xF8C0, 0xe5},
+ {0xF8C1, 0x7d},
+ {0xF8C2, 0xb4},
+ {0xF8C3, 0xe4},
+ {0xF8C4, 0x04},
+ {0xF8C5, 0x7f},
+ {0xF8C6, 0x0f},
+ {0xF8C7, 0x80},
+ {0xF8C8, 0x1b},
+ {0xF8C9, 0xe5},
+ {0xF8CA, 0x7d},
+ {0xF8CB, 0xb4},
+ {0xF8CC, 0xe8},
+ {0xF8CD, 0x04},
+ {0xF8CE, 0x7f},
+ {0xF8CF, 0x10},
+ {0xF8D0, 0x80},
+ {0xF8D1, 0x12},
+ {0xF8D2, 0xe5},
+ {0xF8D3, 0x7d},
+ {0xF8D4, 0xb4},
+ {0xF8D5, 0xec},
+ {0xF8D6, 0x04},
+ {0xF8D7, 0x7f},
+ {0xF8D8, 0x11},
+ {0xF8D9, 0x80},
+ {0xF8DA, 0x09},
+ {0xF8DB, 0xe5},
+ {0xF8DC, 0x7d},
+ {0xF8DD, 0x7f},
+ {0xF8DE, 0x00},
+ {0xF8DF, 0xb4},
+ {0xF8E0, 0xf0},
+ {0xF8E1, 0x02},
+ {0xF8E2, 0x7f},
+ {0xF8E3, 0x12},
+ {0xF8E4, 0x8f},
+ {0xF8E5, 0x7c},
+ {0xF8E6, 0xef},
+ {0xF8E7, 0x24},
+ {0xF8E8, 0x95},
+ {0xF8E9, 0xff},
+ {0xF8EA, 0xe4},
+ {0xF8EB, 0x34},
+ {0xF8EC, 0xfb},
+ {0xF8ED, 0x8f},
+ {0xF8EE, 0x82},
+ {0xF8EF, 0xf5},
+ {0xF8F0, 0x83},
+ {0xF8F1, 0xe4},
+ {0xF8F2, 0x93},
+ {0xF8F3, 0xf5},
+ {0xF8F4, 0x7c},
+ {0xF8F5, 0xf5},
+ {0xF8F6, 0x7b},
+ {0xF8F7, 0xe4},
+ {0xF8F8, 0xf5},
+ {0xF8F9, 0x7a},
+ {0xF8FA, 0x75},
+ {0xF8FB, 0x78},
+ {0xF8FC, 0x30},
+ {0xF8FD, 0x75},
+ {0xF8FE, 0x79},
+ {0xF8FF, 0x53},
+ {0xF900, 0x85},
+ {0xF901, 0x79},
+ {0xF902, 0x82},
+ {0xF903, 0x85},
+ {0xF904, 0x78},
+ {0xF905, 0x83},
+ {0xF906, 0xe0},
+ {0xF907, 0x25},
+ {0xF908, 0x7c},
+ {0xF909, 0xf0},
+ {0xF90A, 0x74},
+ {0xF90B, 0x02},
+ {0xF90C, 0x25},
+ {0xF90D, 0x79},
+ {0xF90E, 0xf5},
+ {0xF90F, 0x79},
+ {0xF910, 0xe4},
+ {0xF911, 0x35},
+ {0xF912, 0x78},
+ {0xF913, 0xf5},
+ {0xF914, 0x78},
+ {0xF915, 0x05},
+ {0xF916, 0x7a},
+ {0xF917, 0xe5},
+ {0xF918, 0x7a},
+ {0xF919, 0xb4},
+ {0xF91A, 0x08},
+ {0xF91B, 0xe4},
+ {0xF91C, 0x02},
+ {0xF91D, 0x18},
+ {0xF91E, 0x32},
+ {0xF91F, 0x22},
+ {0xF920, 0xf0},
+ {0xF921, 0x90},
+ {0xF922, 0xa0},
+ {0xF923, 0xf8},
+ {0xF924, 0xe0},
+ {0xF925, 0x70},
+ {0xF926, 0x02},
+ {0xF927, 0xa3},
+ {0xF928, 0xe0},
+ {0xF929, 0x70},
+ {0xF92A, 0x0a},
+ {0xF92B, 0x90},
+ {0xF92C, 0xa1},
+ {0xF92D, 0x10},
+ {0xF92E, 0xe0},
+ {0xF92F, 0xfe},
+ {0xF930, 0xa3},
+ {0xF931, 0xe0},
+ {0xF932, 0xff},
+ {0xF933, 0x80},
+ {0xF934, 0x04},
+ {0xF935, 0x7e},
+ {0xF936, 0x00},
+ {0xF937, 0x7f},
+ {0xF938, 0x00},
+ {0xF939, 0x8e},
+ {0xF93A, 0x7e},
+ {0xF93B, 0x8f},
+ {0xF93C, 0x7f},
+ {0xF93D, 0x90},
+ {0xF93E, 0x36},
+ {0xF93F, 0x0d},
+ {0xF940, 0xe0},
+ {0xF941, 0x44},
+ {0xF942, 0x02},
+ {0xF943, 0xf0},
+ {0xF944, 0x90},
+ {0xF945, 0x36},
+ {0xF946, 0x0e},
+ {0xF947, 0xe5},
+ {0xF948, 0x7e},
+ {0xF949, 0xf0},
+ {0xF94A, 0xa3},
+ {0xF94B, 0xe5},
+ {0xF94C, 0x7f},
+ {0xF94D, 0xf0},
+ {0xF94E, 0xe5},
+ {0xF94F, 0x3a},
+ {0xF950, 0x60},
+ {0xF951, 0x0c},
+ {0xF952, 0x90},
+ {0xF953, 0x36},
+ {0xF954, 0x09},
+ {0xF955, 0xe0},
+ {0xF956, 0x70},
+ {0xF957, 0x06},
+ {0xF958, 0x90},
+ {0xF959, 0x36},
+ {0xF95A, 0x08},
+ {0xF95B, 0xf0},
+ {0xF95C, 0xf5},
+ {0xF95D, 0x3a},
+ {0xF95E, 0x02},
+ {0xF95F, 0x03},
+ {0xF960, 0x94},
+ {0xF961, 0x22},
+ {0xF962, 0x78},
+ {0xF963, 0x07},
+ {0xF964, 0xe6},
+ {0xF965, 0xd3},
+ {0xF966, 0x94},
+ {0xF967, 0x00},
+ {0xF968, 0x40},
+ {0xF969, 0x16},
+ {0xF96A, 0x16},
+ {0xF96B, 0xe6},
+ {0xF96C, 0x90},
+ {0xF96D, 0x30},
+ {0xF96E, 0xa1},
+ {0xF96F, 0xf0},
+ {0xF970, 0x90},
+ {0xF971, 0x43},
+ {0xF972, 0x83},
+ {0xF973, 0xe0},
+ {0xF974, 0xb4},
+ {0xF975, 0x01},
+ {0xF976, 0x0f},
+ {0xF977, 0x90},
+ {0xF978, 0x43},
+ {0xF979, 0x87},
+ {0xF97A, 0xe0},
+ {0xF97B, 0xb4},
+ {0xF97C, 0x01},
+ {0xF97D, 0x08},
+ {0xF97E, 0x80},
+ {0xF97F, 0x00},
+ {0xF980, 0x90},
+ {0xF981, 0x30},
+ {0xF982, 0xa0},
+ {0xF983, 0x74},
+ {0xF984, 0x01},
+ {0xF985, 0xf0},
+ {0xF986, 0x22},
+ {0xF987, 0xf0},
+ {0xF988, 0x90},
+ {0xF989, 0x35},
+ {0xF98A, 0xba},
+ {0xF98B, 0xe0},
+ {0xF98C, 0xb4},
+ {0xF98D, 0x0a},
+ {0xF98E, 0x0d},
+ {0xF98F, 0xa3},
+ {0xF990, 0xe0},
+ {0xF991, 0xb4},
+ {0xF992, 0x01},
+ {0xF993, 0x08},
+ {0xF994, 0x90},
+ {0xF995, 0xfb},
+ {0xF996, 0x94},
+ {0xF997, 0xe0},
+ {0xF998, 0x90},
+ {0xF999, 0x35},
+ {0xF99A, 0xb8},
+ {0xF99B, 0xf0},
+ {0xF99C, 0xd0},
+ {0xF99D, 0xd0},
+ {0xF99E, 0xd0},
+ {0xF99F, 0x82},
+ {0xF9A0, 0xd0},
+ {0xF9A1, 0x83},
+ {0xF9A2, 0xd0},
+ {0xF9A3, 0xe0},
+ {0xF9A4, 0x32},
+ {0xF9A5, 0x22},
+ {0xF9A6, 0xe5},
+ {0xF9A7, 0x7f},
+ {0xF9A8, 0x45},
+ {0xF9A9, 0x7e},
+ {0xF9AA, 0x60},
+ {0xF9AB, 0x15},
+ {0xF9AC, 0x90},
+ {0xF9AD, 0x01},
+ {0xF9AE, 0x00},
+ {0xF9AF, 0xe0},
+ {0xF9B0, 0x70},
+ {0xF9B1, 0x0f},
+ {0xF9B2, 0x90},
+ {0xF9B3, 0xa0},
+ {0xF9B4, 0xf8},
+ {0xF9B5, 0xe5},
+ {0xF9B6, 0x7e},
+ {0xF9B7, 0xf0},
+ {0xF9B8, 0xa3},
+ {0xF9B9, 0xe5},
+ {0xF9BA, 0x7f},
+ {0xF9BB, 0xf0},
+ {0xF9BC, 0xe4},
+ {0xF9BD, 0xf5},
+ {0xF9BE, 0x7e},
+ {0xF9BF, 0xf5},
+ {0xF9C0, 0x7f},
+ {0xF9C1, 0x22},
+ {0xF9C2, 0x02},
+ {0xF9C3, 0x0e},
+ {0xF9C4, 0x79},
+ {0xF9C5, 0x22},
+ /* Offsets:*/
+ {0x35C6, 0x00},/* FIDDLEDARKCAL*/
+ {0x35C7, 0x00},
+ {0x35C8, 0x01},/*STOREDISTANCEATSTOPSTREAMING*/
+ {0x35C9, 0x20},
+ {0x35CA, 0x01},/*BRUCEFIX*/
+ {0x35CB, 0x62},
+ {0x35CC, 0x01},/*FIXDATAXFERSTATUSREG*/
+ {0x35CD, 0x87},
+ {0x35CE, 0x01},/*FOCUSDISTANCEUPDATE*/
+ {0x35CF, 0xA6},
+ {0x35D0, 0x01},/*SKIPEDOFRESET*/
+ {0x35D1, 0xC2},
+ {0x35D2, 0x00},
+ {0x35D3, 0xFB},
+ {0x35D4, 0x00},
+ {0x35D5, 0x94},
+ {0x35D6, 0x00},
+ {0x35D7, 0xFB},
+ {0x35D8, 0x00},
+ {0x35D9, 0x94},
+ {0x35DA, 0x00},
+ {0x35DB, 0xFB},
+ {0x35DC, 0x00},
+ {0x35DD, 0x94},
+ {0x35DE, 0x00},
+ {0x35DF, 0xFB},
+ {0x35E0, 0x00},
+ {0x35E1, 0x94},
+ {0x35E6, 0x18},/* FIDDLEDARKCAL*/
+ {0x35E7, 0x2F},
+ {0x35E8, 0x03},/* STOREDISTANCEATSTOPSTREAMING*/
+ {0x35E9, 0x93},
+ {0x35EA, 0x18},/* BRUCEFIX*/
+ {0x35EB, 0x99},
+ {0x35EC, 0x00},/* FIXDATAXFERSTATUSREG*/
+ {0x35ED, 0xA3},
+ {0x35EE, 0x21},/* FOCUSDISTANCEUPDATE*/
+ {0x35EF, 0x5B},
+ {0x35F0, 0x0E},/* SKIPEDOFRESET*/
+ {0x35F1, 0x74},
+ {0x35F2, 0x04},
+ {0x35F3, 0x64},
+ {0x35F4, 0x04},
+ {0x35F5, 0x65},
+ {0x35F6, 0x04},
+ {0x35F7, 0x7B},
+ {0x35F8, 0x04},
+ {0x35F9, 0x7C},
+ {0x35FA, 0x04},
+ {0x35FB, 0xDD},
+ {0x35FC, 0x04},
+ {0x35FD, 0xDE},
+ {0x35FE, 0x04},
+ {0x35FF, 0xEF},
+ {0x3600, 0x04},
+ {0x3601, 0xF0},
+ /*Jump/Data:*/
+ {0x35C2, 0x3F},/* Jump Reg*/
+ {0x35C3, 0xFF},/* Jump Reg*/
+ {0x35C4, 0x3F},/* Data Reg*/
+ {0x35C5, 0xC0},/* Data Reg*/
+ {0x35C0, 0x01},/* Enable*/
+ /* end of patch cut 2 */
+ /* common settings */
+ {0x0112, 10},/*REG = 0x0112 , 10 bit */
+ {0x0113, 10},/*REG = 0x0113*/
+ {0x0301, 9},/*REG = 0x0301 vt_pix_clk_div*/
+ {0x0305, 4},/*REG = 0x0305 pre_pll_clk_div*/
+ {0x0307, 133},/*REG = 0x0307 pll_multiplier*/
+ {0x0309, 10},/*REG = 0x0309 op_pix_clk_div*/
+ {0x3030, 0x08},/*REG = 0x3030*/
+ {0x0111, 0x02},/*REG = 0x0111*/
+ {0x0b00, 0x01},/*REG = 0x0b00 ,lens shading off */
+ {0x3001, 0x30},/*REG = 0x3001*/
+ {0x3004, 0x33},/*REG = 0x3004*/
+ {0x3007, 0x09},/*REG = 0x3007*/
+ {0x3016, 0x1F},/*REG = 0x3016*/
+ {0x301d, 0x03},/*REG = 0x301d*/
+ {0x317E, 0x11},/*REG = 0x317E*/
+ {0x317F, 0x09},/*REG = 0x317F*/
+ {0x3400, 0x38},/*REG = 0x3400*/
+ {0x0b06, 0x00},/*REG_0x0b06*/
+ {0x0b07, 0x80},/*REG_0x0b07*/
+ {0x0b08, 0x01},/*REG_0x0b08*/
+ {0x0b09, 0x4F},/*REG_0x0b09*/
+ {0x0136, 0x18},/*REG_0x0136*/
+ {0x0137, 0x00},/*/REG_0x0137*/
+ {0x0b83, 0x20},/*REG = 0x0b83*/
+ {0x0b84, 0x90},/*REG = 0x0b84*/
+ {0x0b85, 0x20},/*REG = 0x0b85*/
+ {0x0b88, 0x80},/*REG = 0x0b88*/
+ {0x0b89, 0x00},/*REG = 0x0b89*/
+ {0x0b8a, 0x00},/*REG = 0x0b8a*/
+ /* end of common settings */
+};
+
+static struct v4l2_subdev_info vx6953_subdev_info[] = {
+ {
+ .code = V4L2_MBUS_FMT_SGRBG10_1X10,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .fmt = 1,
+ .order = 0,
+ },
+ /* more can be supported, to be added later */
+};
+
+static struct msm_camera_i2c_conf_array vx6953_init_conf[] = {
+ {&vx6953_recommend_settings[0],
+ ARRAY_SIZE(vx6953_recommend_settings), 0, MSM_CAMERA_I2C_BYTE_DATA}
+};
+
+static struct msm_camera_i2c_conf_array vx6953_confs[] = {
+ {&vx6953_snap_settings[0],
+ ARRAY_SIZE(vx6953_snap_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+ {&vx6953_prev_settings[0],
+ ARRAY_SIZE(vx6953_prev_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+};
+
+static struct msm_sensor_output_info_t vx6953_dimensions[] = {
+ {
+ .x_output = 0xA30,
+ .y_output = 0x7A8,
+ .line_length_pclk = 0xB8C,
+ .frame_length_lines = 0x7D0,
+ .vt_pixel_clk = 88666666,
+ .op_pixel_clk = 192000000,
+ .binning_factor = 1,
+ },
+ {
+ .x_output = 0x518,
+ .y_output = 0x3D4,
+ .line_length_pclk = 0xB74,
+ .frame_length_lines = 0x3F0,
+ .vt_pixel_clk = 88666666,
+ .op_pixel_clk = 192000000,
+ .binning_factor = 1,
+ },
+};
+
+static struct msm_camera_csi_params vx6953_csi_params = {
+ .data_format = CSI_8BIT,
+ .lane_cnt = 1,
+ .lane_assign = 0xe4,
+ .dpcm_scheme = 0,
+ .settle_cnt = 7,
+};
+
+static struct msm_camera_csi_params *vx6953_csi_params_array[] = {
+ &vx6953_csi_params,
+ &vx6953_csi_params,
+};
+
+static struct msm_sensor_output_reg_addr_t vx6953_reg_addr = {
+ .x_output = 0x034C,
+ .y_output = 0x034E,
+ .line_length_pclk = 0x0342,
+ .frame_length_lines = 0x0340,
+};
+
+static struct msm_sensor_id_info_t vx6953_id_info = {
+ .sensor_id_reg_addr = 0x0000,
+ .sensor_id = 0x03B9,
+};
+
+static struct msm_sensor_exp_gain_info_t vx6953_exp_gain_info = {
+ .coarse_int_time_addr = 0x0202,
+ .global_gain_addr = 0x0204,
+ .vert_offset = 9,
+};
+
+static const struct i2c_device_id vx6953_i2c_id[] = {
+ {SENSOR_NAME, (kernel_ulong_t)&vx6953_s_ctrl},
+ { }
+};
+
+static struct i2c_driver vx6953_i2c_driver = {
+ .id_table = vx6953_i2c_id,
+ .probe = msm_sensor_i2c_probe,
+ .driver = {
+ .name = SENSOR_NAME,
+ },
+};
+
+static struct msm_camera_i2c_client vx6953_sensor_i2c_client = {
+ .addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static int __init msm_sensor_init_module(void)
+{
+ return i2c_add_driver(&vx6953_i2c_driver);
+}
+
+static int32_t vx6953_set_fps(struct msm_sensor_ctrl_t *s_ctrl,
+ struct fps_cfg *fps) {
+ return 0;
+}
+
+int32_t vx6953_write_exp_gain(struct msm_sensor_ctrl_t *s_ctrl,
+ uint16_t gain, uint32_t line) {
+ return 0;
+}
+
+static struct v4l2_subdev_core_ops vx6953_subdev_core_ops = {
+ .ioctl = msm_sensor_subdev_ioctl,
+ .s_power = msm_sensor_power,
+};
+
+static struct v4l2_subdev_video_ops vx6953_subdev_video_ops = {
+ .enum_mbus_fmt = msm_sensor_v4l2_enum_fmt,
+};
+
+static struct v4l2_subdev_ops vx6953_subdev_ops = {
+ .core = &vx6953_subdev_core_ops,
+ .video = &vx6953_subdev_video_ops,
+};
+
+static struct msm_camera_i2c_reg_conf vx6953_edof_estimation[] = {
+ {REG_0x0b80, 0x02},
+};
+
+static struct msm_camera_i2c_reg_conf vx6953_edof_application[] = {
+ {REG_0x0b80, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf vx6953_edof_default[] = {
+ {REG_0x0b80, 0x00},
+};
+
+static int vx6953_enable_edof(enum edof_mode_t edof_mode)
+{
+ int rc = 0;
+ if (edof_mode == VX6953_EDOF_ESTIMATION) {
+ /* EDof Estimation mode for preview */
+ msm_camera_i2c_write_tbl(
+ vx6953_s_ctrl.sensor_i2c_client,
+ vx6953_edof_estimation,
+ ARRAY_SIZE(vx6953_edof_estimation),
+ vx6953_s_ctrl.msm_sensor_reg->default_data_type);
+ CDBG("VX6953_EDOF_ESTIMATION");
+ } else if (edof_mode == VX6953_EDOF_APPLICATION) {
+ /* EDof Application mode for Capture */
+ msm_camera_i2c_write_tbl(
+ vx6953_s_ctrl.sensor_i2c_client,
+ vx6953_edof_application,
+ ARRAY_SIZE(vx6953_edof_application),
+ vx6953_s_ctrl.msm_sensor_reg->default_data_type);
+ CDBG("VX6953_EDOF_APPLICATION");
+ } else {
+ /* EDOF disabled */
+ msm_camera_i2c_write_tbl(
+ vx6953_s_ctrl.sensor_i2c_client,
+ vx6953_edof_default,
+ ARRAY_SIZE(vx6953_edof_default),
+ vx6953_s_ctrl.msm_sensor_reg->default_data_type);
+ CDBG("VX6953_EDOF_DISABLE");
+ }
+ return rc;
+}
+
+static struct msm_camera_i2c_reg_conf vx6953_standby[] = {
+ {0x103, 0x01},
+};
+
+static struct msm_camera_i2c_reg_conf patch_tbl_cut2[] = {
+ {0xFB94, 0}, /*intialise Data Xfer Status reg*/
+ {0xFB95, 0}, /*gain 1 (0x00)*/
+ {0xFB96, 0}, /*gain 1.07 (0x10)*/
+ {0xFB97, 0}, /*gain 1.14 (0x20)*/
+ {0xFB98, 0}, /*gain 1.23 (0x30)*/
+ {0xFB99, 0}, /*gain 1.33 (0x40)*/
+ {0xFB9A, 0}, /*gain 1.45 (0x50)*/
+ {0xFB9B, 0}, /*gain 1.6 (0x60)*/
+ {0xFB9C, 0}, /*gain 1.78 (0x70)*/
+ {0xFB9D, 2}, /*gain 2 (0x80)*/
+ {0xFB9E, 2}, /*gain 2.29 (0x90)*/
+ {0xFB9F, 3}, /*gain 2.67 (0xA0)*/
+ {0xFBA0, 3}, /*gain 3.2 (0xB0)*/
+ {0xFBA1, 4}, /*gain 4 (0xC0)*/
+ {0xFBA2, 7}, /*gain 5.33 (0xD0)*/
+ {0xFBA3, 10}, /*gain 8 (0xE0)*/
+ {0xFBA4, 11}, /*gain 9.14 (0xE4)*/
+ {0xFBA5, 13}, /*gain 10.67 (0xE8)*/
+ {0xFBA6, 15}, /*gain 12.8 (0xEC)*/
+ {0xFBA7, 19}, /*gain 16 (0xF0)*/
+ {0xF800, 0x12},
+ {0xF801, 0x06},
+ {0xF802, 0xf7},
+ {0xF803, 0x90},
+ {0xF804, 0x02},
+ {0xF805, 0x05},
+ {0xF806, 0xe0},
+ {0xF807, 0xff},
+ {0xF808, 0x65},
+ {0xF809, 0x7d},
+ {0xF80A, 0x70},
+ {0xF80B, 0x03},
+ {0xF80C, 0x02},
+ {0xF80D, 0xf9},
+ {0xF80E, 0x1c},
+ {0xF80F, 0x8f},
+ {0xF810, 0x7d},
+ {0xF811, 0xe4},
+ {0xF812, 0xf5},
+ {0xF813, 0x7a},
+ {0xF814, 0x75},
+ {0xF815, 0x78},
+ {0xF816, 0x30},
+ {0xF817, 0x75},
+ {0xF818, 0x79},
+ {0xF819, 0x53},
+ {0xF81A, 0x85},
+ {0xF81B, 0x79},
+ {0xF81C, 0x82},
+ {0xF81D, 0x85},
+ {0xF81E, 0x78},
+ {0xF81F, 0x83},
+ {0xF820, 0xe0},
+ {0xF821, 0xc3},
+ {0xF822, 0x95},
+ {0xF823, 0x7b},
+ {0xF824, 0xf0},
+ {0xF825, 0x74},
+ {0xF826, 0x02},
+ {0xF827, 0x25},
+ {0xF828, 0x79},
+ {0xF829, 0xf5},
+ {0xF82A, 0x79},
+ {0xF82B, 0xe4},
+ {0xF82C, 0x35},
+ {0xF82D, 0x78},
+ {0xF82E, 0xf5},
+ {0xF82F, 0x78},
+ {0xF830, 0x05},
+ {0xF831, 0x7a},
+ {0xF832, 0xe5},
+ {0xF833, 0x7a},
+ {0xF834, 0xb4},
+ {0xF835, 0x08},
+ {0xF836, 0xe3},
+ {0xF837, 0xe5},
+ {0xF838, 0x7d},
+ {0xF839, 0x70},
+ {0xF83A, 0x04},
+ {0xF83B, 0xff},
+ {0xF83C, 0x02},
+ {0xF83D, 0xf8},
+ {0xF83E, 0xe4},
+ {0xF83F, 0xe5},
+ {0xF840, 0x7d},
+ {0xF841, 0xb4},
+ {0xF842, 0x10},
+ {0xF843, 0x05},
+ {0xF844, 0x7f},
+ {0xF845, 0x01},
+ {0xF846, 0x02},
+ {0xF847, 0xf8},
+ {0xF848, 0xe4},
+ {0xF849, 0xe5},
+ {0xF84A, 0x7d},
+ {0xF84B, 0xb4},
+ {0xF84C, 0x20},
+ {0xF84D, 0x05},
+ {0xF84E, 0x7f},
+ {0xF84F, 0x02},
+ {0xF850, 0x02},
+ {0xF851, 0xf8},
+ {0xF852, 0xe4},
+ {0xF853, 0xe5},
+ {0xF854, 0x7d},
+ {0xF855, 0xb4},
+ {0xF856, 0x30},
+ {0xF857, 0x05},
+ {0xF858, 0x7f},
+ {0xF859, 0x03},
+ {0xF85A, 0x02},
+ {0xF85B, 0xf8},
+ {0xF85C, 0xe4},
+ {0xF85D, 0xe5},
+ {0xF85E, 0x7d},
+ {0xF85F, 0xb4},
+ {0xF860, 0x40},
+ {0xF861, 0x04},
+ {0xF862, 0x7f},
+ {0xF863, 0x04},
+ {0xF864, 0x80},
+ {0xF865, 0x7e},
+ {0xF866, 0xe5},
+ {0xF867, 0x7d},
+ {0xF868, 0xb4},
+ {0xF869, 0x50},
+ {0xF86A, 0x04},
+ {0xF86B, 0x7f},
+ {0xF86C, 0x05},
+ {0xF86D, 0x80},
+ {0xF86E, 0x75},
+ {0xF86F, 0xe5},
+ {0xF870, 0x7d},
+ {0xF871, 0xb4},
+ {0xF872, 0x60},
+ {0xF873, 0x04},
+ {0xF874, 0x7f},
+ {0xF875, 0x06},
+ {0xF876, 0x80},
+ {0xF877, 0x6c},
+ {0xF878, 0xe5},
+ {0xF879, 0x7d},
+ {0xF87A, 0xb4},
+ {0xF87B, 0x70},
+ {0xF87C, 0x04},
+ {0xF87D, 0x7f},
+ {0xF87E, 0x07},
+ {0xF87F, 0x80},
+ {0xF880, 0x63},
+ {0xF881, 0xe5},
+ {0xF882, 0x7d},
+ {0xF883, 0xb4},
+ {0xF884, 0x80},
+ {0xF885, 0x04},
+ {0xF886, 0x7f},
+ {0xF887, 0x08},
+ {0xF888, 0x80},
+ {0xF889, 0x5a},
+ {0xF88A, 0xe5},
+ {0xF88B, 0x7d},
+ {0xF88C, 0xb4},
+ {0xF88D, 0x90},
+ {0xF88E, 0x04},
+ {0xF88F, 0x7f},
+ {0xF890, 0x09},
+ {0xF891, 0x80},
+ {0xF892, 0x51},
+ {0xF893, 0xe5},
+ {0xF894, 0x7d},
+ {0xF895, 0xb4},
+ {0xF896, 0xa0},
+ {0xF897, 0x04},
+ {0xF898, 0x7f},
+ {0xF899, 0x0a},
+ {0xF89A, 0x80},
+ {0xF89B, 0x48},
+ {0xF89C, 0xe5},
+ {0xF89D, 0x7d},
+ {0xF89E, 0xb4},
+ {0xF89F, 0xb0},
+ {0xF8A0, 0x04},
+ {0xF8A1, 0x7f},
+ {0xF8A2, 0x0b},
+ {0xF8A3, 0x80},
+ {0xF8A4, 0x3f},
+ {0xF8A5, 0xe5},
+ {0xF8A6, 0x7d},
+ {0xF8A7, 0xb4},
+ {0xF8A8, 0xc0},
+ {0xF8A9, 0x04},
+ {0xF8AA, 0x7f},
+ {0xF8AB, 0x0c},
+ {0xF8AC, 0x80},
+ {0xF8AD, 0x36},
+ {0xF8AE, 0xe5},
+ {0xF8AF, 0x7d},
+ {0xF8B0, 0xb4},
+ {0xF8B1, 0xd0},
+ {0xF8B2, 0x04},
+ {0xF8B3, 0x7f},
+ {0xF8B4, 0x0d},
+ {0xF8B5, 0x80},
+ {0xF8B6, 0x2d},
+ {0xF8B7, 0xe5},
+ {0xF8B8, 0x7d},
+ {0xF8B9, 0xb4},
+ {0xF8BA, 0xe0},
+ {0xF8BB, 0x04},
+ {0xF8BC, 0x7f},
+ {0xF8BD, 0x0e},
+ {0xF8BE, 0x80},
+ {0xF8BF, 0x24},
+ {0xF8C0, 0xe5},
+ {0xF8C1, 0x7d},
+ {0xF8C2, 0xb4},
+ {0xF8C3, 0xe4},
+ {0xF8C4, 0x04},
+ {0xF8C5, 0x7f},
+ {0xF8C6, 0x0f},
+ {0xF8C7, 0x80},
+ {0xF8C8, 0x1b},
+ {0xF8C9, 0xe5},
+ {0xF8CA, 0x7d},
+ {0xF8CB, 0xb4},
+ {0xF8CC, 0xe8},
+ {0xF8CD, 0x04},
+ {0xF8CE, 0x7f},
+ {0xF8CF, 0x10},
+ {0xF8D0, 0x80},
+ {0xF8D1, 0x12},
+ {0xF8D2, 0xe5},
+ {0xF8D3, 0x7d},
+ {0xF8D4, 0xb4},
+ {0xF8D5, 0xec},
+ {0xF8D6, 0x04},
+ {0xF8D7, 0x7f},
+ {0xF8D8, 0x11},
+ {0xF8D9, 0x80},
+ {0xF8DA, 0x09},
+ {0xF8DB, 0xe5},
+ {0xF8DC, 0x7d},
+ {0xF8DD, 0x7f},
+ {0xF8DE, 0x00},
+ {0xF8DF, 0xb4},
+ {0xF8E0, 0xf0},
+ {0xF8E1, 0x02},
+ {0xF8E2, 0x7f},
+ {0xF8E3, 0x12},
+ {0xF8E4, 0x8f},
+ {0xF8E5, 0x7c},
+ {0xF8E6, 0xef},
+ {0xF8E7, 0x24},
+ {0xF8E8, 0x95},
+ {0xF8E9, 0xff},
+ {0xF8EA, 0xe4},
+ {0xF8EB, 0x34},
+ {0xF8EC, 0xfb},
+ {0xF8ED, 0x8f},
+ {0xF8EE, 0x82},
+ {0xF8EF, 0xf5},
+ {0xF8F0, 0x83},
+ {0xF8F1, 0xe4},
+ {0xF8F2, 0x93},
+ {0xF8F3, 0xf5},
+ {0xF8F4, 0x7c},
+ {0xF8F5, 0xf5},
+ {0xF8F6, 0x7b},
+ {0xF8F7, 0xe4},
+ {0xF8F8, 0xf5},
+ {0xF8F9, 0x7a},
+ {0xF8FA, 0x75},
+ {0xF8FB, 0x78},
+ {0xF8FC, 0x30},
+ {0xF8FD, 0x75},
+ {0xF8FE, 0x79},
+ {0xF8FF, 0x53},
+ {0xF900, 0x85},
+ {0xF901, 0x79},
+ {0xF902, 0x82},
+ {0xF903, 0x85},
+ {0xF904, 0x78},
+ {0xF905, 0x83},
+ {0xF906, 0xe0},
+ {0xF907, 0x25},
+ {0xF908, 0x7c},
+ {0xF909, 0xf0},
+ {0xF90A, 0x74},
+ {0xF90B, 0x02},
+ {0xF90C, 0x25},
+ {0xF90D, 0x79},
+ {0xF90E, 0xf5},
+ {0xF90F, 0x79},
+ {0xF910, 0xe4},
+ {0xF911, 0x35},
+ {0xF912, 0x78},
+ {0xF913, 0xf5},
+ {0xF914, 0x78},
+ {0xF915, 0x05},
+ {0xF916, 0x7a},
+ {0xF917, 0xe5},
+ {0xF918, 0x7a},
+ {0xF919, 0xb4},
+ {0xF91A, 0x08},
+ {0xF91B, 0xe4},
+ {0xF91C, 0x02},
+ {0xF91D, 0x18},
+ {0xF91E, 0x32},
+ {0xF91F, 0x22},
+ {0xF920, 0xf0},
+ {0xF921, 0x90},
+ {0xF922, 0xa0},
+ {0xF923, 0xf8},
+ {0xF924, 0xe0},
+ {0xF925, 0x70},
+ {0xF926, 0x02},
+ {0xF927, 0xa3},
+ {0xF928, 0xe0},
+ {0xF929, 0x70},
+ {0xF92A, 0x0a},
+ {0xF92B, 0x90},
+ {0xF92C, 0xa1},
+ {0xF92D, 0x10},
+ {0xF92E, 0xe0},
+ {0xF92F, 0xfe},
+ {0xF930, 0xa3},
+ {0xF931, 0xe0},
+ {0xF932, 0xff},
+ {0xF933, 0x80},
+ {0xF934, 0x04},
+ {0xF935, 0x7e},
+ {0xF936, 0x00},
+ {0xF937, 0x7f},
+ {0xF938, 0x00},
+ {0xF939, 0x8e},
+ {0xF93A, 0x7e},
+ {0xF93B, 0x8f},
+ {0xF93C, 0x7f},
+ {0xF93D, 0x90},
+ {0xF93E, 0x36},
+ {0xF93F, 0x0d},
+ {0xF940, 0xe0},
+ {0xF941, 0x44},
+ {0xF942, 0x02},
+ {0xF943, 0xf0},
+ {0xF944, 0x90},
+ {0xF945, 0x36},
+ {0xF946, 0x0e},
+ {0xF947, 0xe5},
+ {0xF948, 0x7e},
+ {0xF949, 0xf0},
+ {0xF94A, 0xa3},
+ {0xF94B, 0xe5},
+ {0xF94C, 0x7f},
+ {0xF94D, 0xf0},
+ {0xF94E, 0xe5},
+ {0xF94F, 0x3a},
+ {0xF950, 0x60},
+ {0xF951, 0x0c},
+ {0xF952, 0x90},
+ {0xF953, 0x36},
+ {0xF954, 0x09},
+ {0xF955, 0xe0},
+ {0xF956, 0x70},
+ {0xF957, 0x06},
+ {0xF958, 0x90},
+ {0xF959, 0x36},
+ {0xF95A, 0x08},
+ {0xF95B, 0xf0},
+ {0xF95C, 0xf5},
+ {0xF95D, 0x3a},
+ {0xF95E, 0x02},
+ {0xF95F, 0x03},
+ {0xF960, 0x94},
+ {0xF961, 0x22},
+ {0xF962, 0x78},
+ {0xF963, 0x07},
+ {0xF964, 0xe6},
+ {0xF965, 0xd3},
+ {0xF966, 0x94},
+ {0xF967, 0x00},
+ {0xF968, 0x40},
+ {0xF969, 0x16},
+ {0xF96A, 0x16},
+ {0xF96B, 0xe6},
+ {0xF96C, 0x90},
+ {0xF96D, 0x30},
+ {0xF96E, 0xa1},
+ {0xF96F, 0xf0},
+ {0xF970, 0x90},
+ {0xF971, 0x43},
+ {0xF972, 0x83},
+ {0xF973, 0xe0},
+ {0xF974, 0xb4},
+ {0xF975, 0x01},
+ {0xF976, 0x0f},
+ {0xF977, 0x90},
+ {0xF978, 0x43},
+ {0xF979, 0x87},
+ {0xF97A, 0xe0},
+ {0xF97B, 0xb4},
+ {0xF97C, 0x01},
+ {0xF97D, 0x08},
+ {0xF97E, 0x80},
+ {0xF97F, 0x00},
+ {0xF980, 0x90},
+ {0xF981, 0x30},
+ {0xF982, 0xa0},
+ {0xF983, 0x74},
+ {0xF984, 0x01},
+ {0xF985, 0xf0},
+ {0xF986, 0x22},
+ {0xF987, 0xf0},
+ {0xF988, 0x90},
+ {0xF989, 0x35},
+ {0xF98A, 0xba},
+ {0xF98B, 0xe0},
+ {0xF98C, 0xb4},
+ {0xF98D, 0x0a},
+ {0xF98E, 0x0d},
+ {0xF98F, 0xa3},
+ {0xF990, 0xe0},
+ {0xF991, 0xb4},
+ {0xF992, 0x01},
+ {0xF993, 0x08},
+ {0xF994, 0x90},
+ {0xF995, 0xfb},
+ {0xF996, 0x94},
+ {0xF997, 0xe0},
+ {0xF998, 0x90},
+ {0xF999, 0x35},
+ {0xF99A, 0xb8},
+ {0xF99B, 0xf0},
+ {0xF99C, 0xd0},
+ {0xF99D, 0xd0},
+ {0xF99E, 0xd0},
+ {0xF99F, 0x82},
+ {0xF9A0, 0xd0},
+ {0xF9A1, 0x83},
+ {0xF9A2, 0xd0},
+ {0xF9A3, 0xe0},
+ {0xF9A4, 0x32},
+ {0xF9A5, 0x22},
+ {0xF9A6, 0xe5},
+ {0xF9A7, 0x7f},
+ {0xF9A8, 0x45},
+ {0xF9A9, 0x7e},
+ {0xF9AA, 0x60},
+ {0xF9AB, 0x15},
+ {0xF9AC, 0x90},
+ {0xF9AD, 0x01},
+ {0xF9AE, 0x00},
+ {0xF9AF, 0xe0},
+ {0xF9B0, 0x70},
+ {0xF9B1, 0x0f},
+ {0xF9B2, 0x90},
+ {0xF9B3, 0xa0},
+ {0xF9B4, 0xf8},
+ {0xF9B5, 0xe5},
+ {0xF9B6, 0x7e},
+ {0xF9B7, 0xf0},
+ {0xF9B8, 0xa3},
+ {0xF9B9, 0xe5},
+ {0xF9BA, 0x7f},
+ {0xF9BB, 0xf0},
+ {0xF9BC, 0xe4},
+ {0xF9BD, 0xf5},
+ {0xF9BE, 0x7e},
+ {0xF9BF, 0xf5},
+ {0xF9C0, 0x7f},
+ {0xF9C1, 0x22},
+ {0xF9C2, 0x02},
+ {0xF9C3, 0x0e},
+ {0xF9C4, 0x79},
+ {0xF9C5, 0x22},
+ /* Offsets:*/
+ {0x35C6, 0x00},/* FIDDLEDARKCAL*/
+ {0x35C7, 0x00},
+ {0x35C8, 0x01},/*STOREDISTANCEATSTOPSTREAMING*/
+ {0x35C9, 0x20},
+ {0x35CA, 0x01},/*BRUCEFIX*/
+ {0x35CB, 0x62},
+ {0x35CC, 0x01},/*FIXDATAXFERSTATUSREG*/
+ {0x35CD, 0x87},
+ {0x35CE, 0x01},/*FOCUSDISTANCEUPDATE*/
+ {0x35CF, 0xA6},
+ {0x35D0, 0x01},/*SKIPEDOFRESET*/
+ {0x35D1, 0xC2},
+ {0x35D2, 0x00},
+ {0x35D3, 0xFB},
+ {0x35D4, 0x00},
+ {0x35D5, 0x94},
+ {0x35D6, 0x00},
+ {0x35D7, 0xFB},
+ {0x35D8, 0x00},
+ {0x35D9, 0x94},
+ {0x35DA, 0x00},
+ {0x35DB, 0xFB},
+ {0x35DC, 0x00},
+ {0x35DD, 0x94},
+ {0x35DE, 0x00},
+ {0x35DF, 0xFB},
+ {0x35E0, 0x00},
+ {0x35E1, 0x94},
+ {0x35E6, 0x18},/* FIDDLEDARKCAL*/
+ {0x35E7, 0x2F},
+ {0x35E8, 0x03},/* STOREDISTANCEATSTOPSTREAMING*/
+ {0x35E9, 0x93},
+ {0x35EA, 0x18},/* BRUCEFIX*/
+ {0x35EB, 0x99},
+ {0x35EC, 0x00},/* FIXDATAXFERSTATUSREG*/
+ {0x35ED, 0xA3},
+ {0x35EE, 0x21},/* FOCUSDISTANCEUPDATE*/
+ {0x35EF, 0x5B},
+ {0x35F0, 0x0E},/* SKIPEDOFRESET*/
+ {0x35F1, 0x74},
+ {0x35F2, 0x04},
+ {0x35F3, 0x64},
+ {0x35F4, 0x04},
+ {0x35F5, 0x65},
+ {0x35F6, 0x04},
+ {0x35F7, 0x7B},
+ {0x35F8, 0x04},
+ {0x35F9, 0x7C},
+ {0x35FA, 0x04},
+ {0x35FB, 0xDD},
+ {0x35FC, 0x04},
+ {0x35FD, 0xDE},
+ {0x35FE, 0x04},
+ {0x35FF, 0xEF},
+ {0x3600, 0x04},
+ {0x3601, 0xF0},
+ /*Jump/Data:*/
+ {0x35C2, 0x3F},/* Jump Reg*/
+ {0x35C3, 0xFF},/* Jump Reg*/
+ {0x35C4, 0x3F},/* Data Reg*/
+ {0x35C5, 0xC0},/* Data Reg*/
+ {0x35C0, 0x01},/* Enable*/
+};
+struct msm_camera_i2c_reg_conf init_tbl[] = {
+ {0x0112, 10},
+ {0x0113, 10},
+ {0x0301, 9},
+ {0x0305, 4},
+ {0x0307, 133},
+ {0x0309, 10},
+ {0x0202, 0x03},
+ {0x0203, 0xd0},
+ {0x0205, 0xc0},
+ {0x3030, 0x08},
+ {0x0111, 0x02},
+ {0x0b00, 0x01},
+ {0x3001, 0x30},
+ {0x3004, 0x33},
+ {0x3007, 0x09},
+ {0x3016, 0x1F},
+ {0x301d, 0x03},
+ {0x317e, 0x11},
+ {0x317f, 0x09},
+ {0x3400, 0x38},
+ {0x0b06, 0x00},
+ {0x0b07, 0x80},
+ {0x0b08, 0x01},
+ {0x0b09, 0x4F},
+ {0x0136, 0x18},
+ {0x0137, 0x00},
+ {0x0b83, 0x20},
+ {0x0b84, 0x90},
+ {0x0b85, 0x20},
+ {0x0b88, 0x80},
+ {0x0b89, 0x00},
+ {0x0b8a, 0x00},
+ {0x0340, 0x03}, /*REG = 0x0340 frame_length_lines_hi*/
+ {0x0341, 0xf0}, /*REG = 0x0341 frame_length_lines_lo*/
+ {0x0342, 0x0b}, /*REG = 0x0342 line_length_pck_hi*/
+ {0x0343, 0x74}, /*REG = 0x0343 line_length_pck_lo*/
+ {0x3005, 0x03}, /*REG = 0x3005*/
+ {0x3010, 0x00}, /*REG = 0x3010*/
+ {0x3011, 0x01}, /*REG = 0x3011*/
+ {0x301a, 0x6a}, /*REG = 0x301a*/
+ {0x3035, 0x03}, /*REG = 0x3035*/
+ {0x3036, 0x2c}, /*REG = 0x3036*/
+ {0x3041, 0x00}, /*REG = 0x3041*/
+ {0x3042, 0x24}, /*REG = 0x3042*/
+ {0x3045, 0x81}, /*REG = 0x3045*/
+ {0x0b80, 0x02}, /*REG = 0x0b80 edof estimate*/
+ {0x0900, 0x01}, /*REG = 0x0900*/
+ {0x0901, 0x22}, /*REG = 0x0901*/
+ {0x0902, 0x04}, /*REG = 0x0902*/
+ {0x0383, 0x03}, /*REG = 0x0383*/
+ {0x0387, 0x03}, /*REG = 0x0387*/
+ {0x034c, 0x05}, /*REG = 0x034c*/
+ {0x034d, 0x18}, /*REG = 0x034d*/
+ {0x034e, 0x03}, /*REG = 0x034e*/
+ {0x034f, 0xd4}, /*REG = 0x034f*/
+ {0x1716, 0x02}, /*0x1716*/
+ {0x1717, 0x04}, /*0x1717*/
+ {0x1718, 0x08}, /*0x1718*/
+ {0x1719, 0x2c}, /*0x1719*/
+};
+
+struct msm_camera_i2c_reg_conf mode_tbl1[] = {
+ {REG_0x0112, 10},/*REG = 0x0112 , 10 bit */
+ {REG_0x0113, 10},/*REG = 0x0113*/
+ {REG_VT_PIX_CLK_DIV, 9},/*REG = 0x0301 vt_pix_clk_div*/
+ {REG_PRE_PLL_CLK_DIV, 4},/*REG = 0x0305 pre_pll_clk_div*/
+ {REG_PLL_MULTIPLIER, 133},/*REG = 0x0307 pll_multiplier*/
+ {REG_OP_PIX_CLK_DIV, 10},/*REG = 0x0309 op_pix_clk_div*/
+ {REG_FRAME_LENGTH_LINES_HI, 0x03},/*REG = 0x0340 frame_length_lines_hi*/
+ {REG_FRAME_LENGTH_LINES_LO, 0xf0},/*REG = 0x0341 frame_length_lines_lo*/
+ {REG_LINE_LENGTH_PCK_HI, 0x0b}, /*REG = 0x0342 line_length_pck_hi*/
+ {REG_LINE_LENGTH_PCK_LO, 0x74}, /*REG = 0x0343 line_length_pck_lo*/
+ {REG_0x3005, 0x03}, /*REG = 0x3005*/
+ {0x3010, 0x00}, /*REG = 0x3010*/
+ {REG_0x3011, 0x01}, /*REG = 0x3011*/
+ {REG_0x301a, 0x6a}, /*REG = 0x301a*/
+ {REG_0x3035, 0x03}, /*REG = 0x3035*/
+ {REG_0x3036, 0x2c}, /*REG = 0x3036*/
+ {REG_0x3041, 0x00}, /*REG = 0x3041*/
+ {0x3042, 0x24}, /*REG = 0x3042*/
+ {REG_0x3045, 0x81}, /*REG = 0x3045*/
+ {REG_0x0b80, 0x02}, /*REG = 0x0b80 edof estimate*/
+ {REG_0x0900, 0x01}, /*REG = 0x0900*/
+ {REG_0x0901, 0x22}, /*REG = 0x0901*/
+ {REG_0x0902, 0x04}, /*REG = 0x0902*/
+ {REG_0x0383, 0x03}, /*REG = 0x0383*/
+ {REG_0x0387, 0x03}, /*REG = 0x0387*/
+ {REG_0x034c, 0x05}, /*REG = 0x034c*/
+ {REG_0x034d, 0x18}, /*REG = 0x034d*/
+ {REG_0x034e, 0x03}, /*REG = 0x034e*/
+ {REG_0x034f, 0xd4}, /*REG = 0x034f*/
+ {REG_0x1716, 0x02}, /*0x1716*/
+ {REG_0x1717, 0x04}, /*0x1717*/
+ {REG_0x1718, 0x08}, /*0x1718*/
+ {REG_0x1719, 0x2c}, /*0x1719*/
+};
+
+struct msm_camera_i2c_reg_conf mode_tbl2[] = {
+ {REG_0x0112, 10},/*REG = 0x0112 , 10 bit */
+ {REG_0x0113, 10},/*REG = 0x0113*/
+ {REG_VT_PIX_CLK_DIV, 9},/*REG = 0x0301 vt_pix_clk_div*/
+ {REG_PRE_PLL_CLK_DIV, 4},/*REG = 0x0305 pre_pll_clk_div*/
+ {REG_PLL_MULTIPLIER, 133},/*REG = 0x0307 pll_multiplier*/
+ {REG_OP_PIX_CLK_DIV, 10},/*REG = 0x0309 op_pix_clk_div*/
+ {REG_FRAME_LENGTH_LINES_HI, 0x07},/*REG = 0x0340 frame_length_lines_hi*/
+ {REG_FRAME_LENGTH_LINES_LO, 0xd0},/*REG = 0x0341 frame_length_lines_lo*/
+ {REG_LINE_LENGTH_PCK_HI, 0x0b},/*REG = 0x0342 line_length_pck_hi*/
+ {REG_LINE_LENGTH_PCK_LO, 0x8c},/*REG = 0x0343 line_length_pck_lo*/
+ {REG_0x3005, 0x01},/*REG = 0x3005*/
+ {0x3010, 0x00},/*REG = 0x3010*/
+ {REG_0x3011, 0x00},/*REG = 0x3011*/
+ {REG_0x301a, 0x55},/*REG = 0x301a*/
+ {REG_0x3035, 0x01},/*REG = 0x3035*/
+ {REG_0x3036, 0x23},/*REG = 0x3036*/
+ {REG_0x3041, 0x00},/*REG = 0x3041*/
+ {0x3042, 0x24},/*REG = 0x3042*/
+ {REG_0x3045, 0xb7},/*REG = 0x3045*/
+ {REG_0x0b80, 0x01},/*REG = 0x0b80 edof application*/
+ {REG_0x0900, 0x00},/*REG = 0x0900*/
+ {REG_0x0901, 0x00},/*REG = 0x0901*/
+ {REG_0x0902, 0x00},/*REG = 0x0902*/
+ {REG_0x0383, 0x01},/*REG = 0x0383*/
+ {REG_0x0387, 0x01},/*REG = 0x0387*/
+ {REG_0x034c, 0x0A},/*REG = 0x034c*/
+ {REG_0x034d, 0x30},/*REG = 0x034d*/
+ {REG_0x034e, 0x07},/*REG = 0x034e*/
+ {REG_0x034f, 0xA8},/*REG = 0x034f*/
+ {REG_0x1716, 0x02},/*0x1716*/
+ {REG_0x1717, 0x0d},/*0x1717*/
+ {REG_0x1718, 0x07},/*0x1718*/
+ {REG_0x1719, 0x7d},/*0x1719*/
+};
+
+static int32_t vx6953_sensor_setting(int update_type, int rt)
+{
+
+ int32_t rc = 0;
+ uint16_t frame_cnt = 0;
+ CDBG("%s update type = %d, rt = %d\n",
+ __func__, update_type, rt);
+
+ switch (update_type) {
+ case REG_INIT:
+ if (rt == RES_PREVIEW || rt == RES_CAPTURE) {
+ /* reset fps_divider */
+ fps = 30 * Q8;
+ /* stop streaming */
+
+ /* Reset everything first */
+ msm_camera_i2c_write_tbl(
+ vx6953_s_ctrl.sensor_i2c_client,
+ vx6953_standby,
+ ARRAY_SIZE(vx6953_standby),
+ vx6953_s_ctrl.msm_sensor_reg->
+ default_data_type);
+
+ msleep(20);
+
+ CDBG("Init vx6953_sensor_setting standby\n");
+ msm_camera_i2c_write_tbl(
+ vx6953_s_ctrl.sensor_i2c_client,
+ vx6953_stop_settings,
+ ARRAY_SIZE(vx6953_stop_settings),
+ vx6953_s_ctrl.msm_sensor_reg->
+ default_data_type);
+ /*vx6953_stm5m0edof_delay_msecs_stdby*/
+ msleep(vx6953_stm5m0edof_delay_msecs_stdby);
+ msm_camera_i2c_write_tbl(
+ vx6953_s_ctrl.sensor_i2c_client,
+ patch_tbl_cut2,
+ ARRAY_SIZE(patch_tbl_cut2),
+ vx6953_s_ctrl.msm_sensor_reg->
+ default_data_type);
+ msm_camera_i2c_write_tbl(
+ vx6953_s_ctrl.sensor_i2c_client,
+ init_tbl,
+ ARRAY_SIZE(init_tbl),
+ vx6953_s_ctrl.msm_sensor_reg->
+ default_data_type);
+ msleep(vx6953_stm5m0edof_delay_msecs_stdby);
+ }
+ return rc;
+ case UPDATE_PERIODIC:
+ if (rt == RES_PREVIEW || rt == RES_CAPTURE) {
+ struct msm_camera_i2c_reg_conf init_mode_tbl[] = {
+ {REG_0x0112,
+ vx6953_regs.reg_pat_init[0].reg_0x0112},
+ {REG_0x0113,
+ vx6953_regs.reg_pat_init[0].reg_0x0113},
+ {REG_VT_PIX_CLK_DIV,
+ vx6953_regs.reg_pat_init[0].
+ vt_pix_clk_div},
+ {REG_PRE_PLL_CLK_DIV,
+ vx6953_regs.reg_pat_init[0].
+ pre_pll_clk_div},
+ {REG_PLL_MULTIPLIER,
+ vx6953_regs.reg_pat_init[0].
+ pll_multiplier},
+ {REG_OP_PIX_CLK_DIV,
+ vx6953_regs.reg_pat_init[0].
+ op_pix_clk_div},
+ {REG_COARSE_INTEGRATION_TIME_HI,
+ vx6953_regs.reg_pat[rt].
+ coarse_integration_time_hi},
+ {REG_COARSE_INTEGRATION_TIME_LO,
+ vx6953_regs.reg_pat[rt].
+ coarse_integration_time_lo},
+ {REG_ANALOGUE_GAIN_CODE_GLOBAL_LO,
+ vx6953_regs.reg_pat[rt].
+ analogue_gain_code_global},
+ {REG_0x3030,
+ vx6953_regs.reg_pat_init[0].reg_0x3030},
+ /* 953 specific registers */
+ {REG_0x0111,
+ vx6953_regs.reg_pat_init[0].reg_0x0111},
+ {REG_0x0b00,
+ vx6953_regs.reg_pat_init[0].reg_0x0b00},
+ {REG_0x3001,
+ vx6953_regs.reg_pat_init[0].reg_0x3001},
+ {REG_0x3004,
+ vx6953_regs.reg_pat_init[0].reg_0x3004},
+ {REG_0x3007,
+ vx6953_regs.reg_pat_init[0].reg_0x3007},
+ {REG_0x3016,
+ vx6953_regs.reg_pat_init[0].reg_0x3016},
+ {REG_0x301d,
+ vx6953_regs.reg_pat_init[0].reg_0x301d},
+ {REG_0x317e,
+ vx6953_regs.reg_pat_init[0].reg_0x317e},
+ {REG_0x317f,
+ vx6953_regs.reg_pat_init[0].reg_0x317f},
+ {REG_0x3400,
+ vx6953_regs.reg_pat_init[0].reg_0x3400},
+ {0x0b06,
+ vx6953_regs.reg_pat_init[0].reg_0x0b06},
+ /*Single_defect_correct_weight = auto*/
+ {0x0b07,
+ vx6953_regs.reg_pat_init[0].reg_0x0b07},
+ /*Dynamic couplet correction ENABLED*/
+ {0x0b08,
+ vx6953_regs.reg_pat_init[0].reg_0x0b08},
+ /*Dynamic couplet correction weight*/
+ {0x0b09,
+ vx6953_regs.reg_pat_init[0].reg_0x0b09},
+ /* Clock Setup */
+ /* Tell sensor ext clk is 24MHz*/
+ {0x0136,
+ vx6953_regs.reg_pat_init[0].reg_0x0136},
+ {0x0137,
+ vx6953_regs.reg_pat_init[0].reg_0x0137},
+ /* The white balance gains must be written
+ to the sensor every frame. */
+ /* Edof */
+ {REG_0x0b83,
+ vx6953_regs.reg_pat_init[0].reg_0x0b83},
+ {REG_0x0b84,
+ vx6953_regs.reg_pat_init[0].reg_0x0b84},
+ {0x0b85,
+ vx6953_regs.reg_pat_init[0].reg_0x0b85},
+ {0x0b88,
+ vx6953_regs.reg_pat_init[0].reg_0x0b88},
+ {0x0b89,
+ vx6953_regs.reg_pat_init[0].reg_0x0b89},
+ {REG_0x0b8a,
+ vx6953_regs.reg_pat_init[0].reg_0x0b8a},
+ /* Mode specific regieters */
+ {REG_FRAME_LENGTH_LINES_HI,
+ vx6953_regs.reg_pat[rt].
+ frame_length_lines_hi},
+ {REG_FRAME_LENGTH_LINES_LO,
+ vx6953_regs.reg_pat[rt].
+ frame_length_lines_lo},
+ {REG_LINE_LENGTH_PCK_HI,
+ vx6953_regs.reg_pat[rt].
+ line_length_pck_hi},
+ {REG_LINE_LENGTH_PCK_LO,
+ vx6953_regs.reg_pat[rt].
+ line_length_pck_lo},
+ {REG_0x3005,
+ vx6953_regs.reg_pat[rt].reg_0x3005},
+ {0x3010,
+ vx6953_regs.reg_pat[rt].reg_0x3010},
+ {REG_0x3011,
+ vx6953_regs.reg_pat[rt].reg_0x3011},
+ {REG_0x301a,
+ vx6953_regs.reg_pat[rt].reg_0x301a},
+ {REG_0x3035,
+ vx6953_regs.reg_pat[rt].reg_0x3035},
+ {REG_0x3036,
+ vx6953_regs.reg_pat[rt].reg_0x3036},
+ {REG_0x3041,
+ vx6953_regs.reg_pat[rt].reg_0x3041},
+ {0x3042,
+ vx6953_regs.reg_pat[rt].reg_0x3042},
+ {REG_0x3045,
+ vx6953_regs.reg_pat[rt].reg_0x3045},
+ /*EDOF: Estimation settings for Preview mode
+ Application settings for capture mode
+ (standard settings - Not tuned) */
+ {REG_0x0b80,
+ vx6953_regs.reg_pat[rt].reg_0x0b80},
+ {REG_0x0900,
+ vx6953_regs.reg_pat[rt].reg_0x0900},
+ {REG_0x0901,
+ vx6953_regs.reg_pat[rt].reg_0x0901},
+ {REG_0x0902,
+ vx6953_regs.reg_pat[rt].reg_0x0902},
+ {REG_0x0383,
+ vx6953_regs.reg_pat[rt].reg_0x0383},
+ {REG_0x0387,
+ vx6953_regs.reg_pat[rt].reg_0x0387},
+ /* Change output size / frame rate */
+ {REG_0x034c,
+ vx6953_regs.reg_pat[rt].reg_0x034c},
+ {REG_0x034d,
+ vx6953_regs.reg_pat[rt].reg_0x034d},
+ {REG_0x034e,
+ vx6953_regs.reg_pat[rt].reg_0x034e},
+ {REG_0x034f,
+ vx6953_regs.reg_pat[rt].reg_0x034f},
+ {REG_0x1716,
+ vx6953_regs.reg_pat[rt].reg_0x1716},
+ {REG_0x1717,
+ vx6953_regs.reg_pat[rt].reg_0x1717},
+ {REG_0x1718,
+ vx6953_regs.reg_pat[rt].reg_0x1718},
+ {REG_0x1719,
+ vx6953_regs.reg_pat[rt].reg_0x1719},
+ };
+ /* stop streaming */
+ msleep(20);
+
+ /* Reset everything first */
+ msm_camera_i2c_write_tbl(
+ vx6953_s_ctrl.sensor_i2c_client,
+ vx6953_standby,
+ ARRAY_SIZE(vx6953_standby),
+ vx6953_s_ctrl.msm_sensor_reg->
+ default_data_type);
+
+
+ msleep(20);
+
+ msm_camera_i2c_write_tbl(
+ vx6953_s_ctrl.sensor_i2c_client,
+ vx6953_stop_settings,
+ ARRAY_SIZE(vx6953_stop_settings),
+ vx6953_s_ctrl.msm_sensor_reg->
+ default_data_type);
+ /*vx6953_stm5m0edof_delay_msecs_stdby*/
+ msleep(vx6953_stm5m0edof_delay_msecs_stdby);
+
+ msleep(vx6953_stm5m0edof_delay_msecs_stdby);
+
+ msm_camera_i2c_write_tbl(
+ vx6953_s_ctrl.sensor_i2c_client,
+ patch_tbl_cut2,
+ ARRAY_SIZE(patch_tbl_cut2),
+ vx6953_s_ctrl.msm_sensor_reg->
+ default_data_type);
+
+ msm_camera_i2c_write_tbl(
+ vx6953_s_ctrl.sensor_i2c_client,
+ init_mode_tbl,
+ ARRAY_SIZE(init_mode_tbl),
+ vx6953_s_ctrl.msm_sensor_reg->
+ default_data_type);
+
+
+ vx6953_s_ctrl.curr_csic_params =
+ vx6953_s_ctrl.csic_params[0];
+ v4l2_subdev_notify(&vx6953_s_ctrl.sensor_v4l2_subdev,
+ NOTIFY_CSIC_CFG,
+ vx6953_s_ctrl.curr_csic_params);
+
+ msleep(vx6953_stm5m0edof_delay_msecs_stdby);
+ if (rt == RES_PREVIEW) {
+ CDBG("%s write mode_tbl for preview\n",
+ __func__);
+ msm_camera_i2c_write_tbl(
+ vx6953_s_ctrl.sensor_i2c_client,
+ mode_tbl1,
+ ARRAY_SIZE(mode_tbl1),
+ vx6953_s_ctrl.msm_sensor_reg->
+ default_data_type);
+ } else if (rt == RES_CAPTURE) {
+ CDBG("%s write mode_tbl for capture\n",
+ __func__);
+ msm_camera_i2c_write_tbl(
+ vx6953_s_ctrl.sensor_i2c_client,
+ mode_tbl2,
+ ARRAY_SIZE(mode_tbl2),
+ vx6953_s_ctrl.msm_sensor_reg->
+ default_data_type);
+ }
+ msleep(vx6953_stm5m0edof_delay_msecs_stdby);
+
+ /* Start sensor streaming */
+ msm_camera_i2c_write_tbl(
+ vx6953_s_ctrl.sensor_i2c_client,
+ vx6953_start_settings,
+ ARRAY_SIZE(vx6953_start_settings),
+ vx6953_s_ctrl.msm_sensor_reg->
+ default_data_type);
+ msleep(20);
+
+ msm_camera_i2c_read(
+ vx6953_s_ctrl.sensor_i2c_client,
+ 0x0005,
+ &frame_cnt,
+ MSM_CAMERA_I2C_BYTE_ADDR);
+ while (frame_cnt == 0xFF) {
+ msm_camera_i2c_read(
+ vx6953_s_ctrl.sensor_i2c_client,
+ 0x0005,
+ &frame_cnt,
+ MSM_CAMERA_I2C_BYTE_ADDR);
+ CDBG("%s frame_cnt = %d\n",
+ __func__, frame_cnt);
+ usleep_range(5000, 10000);
+ }
+ }
+ return rc;
+ default:
+ return rc;
+ }
+ return rc;
+}
+
+static int32_t vx6953_init_config(void)
+{
+ int32_t rc = 0;
+ int rt;
+ /* change sensor resolution if needed */
+ CDBG("%s called\n", __func__);
+ rt = RES_PREVIEW;
+ vx6953_stm5m0edof_delay_msecs_stdby =
+ ((((2 * 1000 * fps_divider) /
+ fps) * Q8) / Q10) + 1;
+
+ vx6953_sensor_setting(REG_INIT, rt);
+
+ vx6953_enable_edof(VX6953_EDOF_ESTIMATION);
+ return rc;
+}
+
+static int32_t vx6953_update_config(int rt)
+{
+ int32_t rc = 0;
+ CDBG("%s rt = %d\n", __func__, rt);
+ if (rt == MSM_SENSOR_RES_FULL)
+ rt = RES_CAPTURE;
+ else if (rt == MSM_SENSOR_RES_QTR)
+ rt = RES_PREVIEW;
+
+ vx6953_stm5m0edof_delay_msecs_stdby = 67;
+ vx6953_sensor_setting(UPDATE_PERIODIC, rt);
+
+ if (rt == RES_PREVIEW)
+ vx6953_enable_edof(VX6953_EDOF_ESTIMATION);
+ else if (rt == RES_CAPTURE)
+ vx6953_enable_edof(VX6953_EDOF_APPLICATION);
+
+ return rc;
+} /*end of vx6953_snapshot_config*/
+
+static int32_t vx6953_set_sensor_mode(struct msm_sensor_ctrl_t *s_ctrl,
+ int update_type, int rt)
+{
+ int32_t rc = 0;
+
+ fps_divider = 1 * 0x00000400;
+ fps = 30*Q8;
+
+ switch (update_type) {
+ case MSM_SENSOR_REG_INIT:
+ rc = vx6953_init_config();
+ break;
+ case MSM_SENSOR_UPDATE_PERIODIC:
+ rc = vx6953_update_config(rt);
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+ return rc;
+}
+static struct msm_sensor_fn_t vx6953_func_tbl = {
+ .sensor_start_stream = msm_sensor_start_stream,
+ .sensor_stop_stream = msm_sensor_stop_stream,
+ .sensor_group_hold_on = msm_sensor_group_hold_on,
+ .sensor_group_hold_off = msm_sensor_group_hold_off,
+ .sensor_set_fps = vx6953_set_fps,
+ .sensor_write_exp_gain = vx6953_write_exp_gain,
+ .sensor_write_snapshot_exp_gain = vx6953_write_exp_gain,
+ .sensor_csi_setting = vx6953_set_sensor_mode,
+ .sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
+ .sensor_mode_init = msm_sensor_mode_init,
+ .sensor_get_output_info = msm_sensor_get_output_info,
+ .sensor_config = msm_sensor_config,
+ .sensor_power_up = msm_sensor_power_up,
+ .sensor_power_down = msm_sensor_power_down,
+};
+
+static struct msm_sensor_reg_t vx6953_data_regs = {
+ .default_data_type = MSM_CAMERA_I2C_BYTE_DATA,
+ .start_stream_conf = vx6953_start_settings,
+ .start_stream_conf_size = ARRAY_SIZE(vx6953_start_settings),
+ .stop_stream_conf = vx6953_stop_settings,
+ .stop_stream_conf_size = ARRAY_SIZE(vx6953_stop_settings),
+ .group_hold_on_conf = vx6953_groupon_settings,
+ .group_hold_on_conf_size = ARRAY_SIZE(vx6953_groupon_settings),
+ .group_hold_off_conf = vx6953_groupoff_settings,
+ .group_hold_off_conf_size =
+ ARRAY_SIZE(vx6953_groupoff_settings),
+ .init_settings = &vx6953_init_conf[0],
+ .init_size = ARRAY_SIZE(vx6953_init_conf),
+ .mode_settings = &vx6953_confs[0],
+ .output_settings = &vx6953_dimensions[0],
+ .num_conf = ARRAY_SIZE(vx6953_confs),
+};
+
+static struct msm_sensor_ctrl_t vx6953_s_ctrl = {
+ .msm_sensor_reg = &vx6953_data_regs,
+ .sensor_i2c_client = &vx6953_sensor_i2c_client,
+ .sensor_i2c_addr = 0x20,
+ .sensor_output_reg_addr = &vx6953_reg_addr,
+ .sensor_id_info = &vx6953_id_info,
+ .sensor_exp_gain_info = &vx6953_exp_gain_info,
+ .cam_mode = MSM_SENSOR_MODE_INVALID,
+ .csic_params = &vx6953_csi_params_array[0],
+ .msm_sensor_mutex = &vx6953_mut,
+ .sensor_i2c_driver = &vx6953_i2c_driver,
+ .sensor_v4l2_subdev_info = vx6953_subdev_info,
+ .sensor_v4l2_subdev_info_size = ARRAY_SIZE(vx6953_subdev_info),
+ .sensor_v4l2_subdev_ops = &vx6953_subdev_ops,
+ .func_tbl = &vx6953_func_tbl,
+ .clk_rate = MSM_SENSOR_MCLK_24HZ,
+};
+
+module_init(msm_sensor_init_module);
+MODULE_DESCRIPTION("Sensor VX6953 (BAYER 5M)");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/media/video/msm/sensors/vx6953.h b/drivers/media/video/msm/sensors/vx6953.h
new file mode 100644
index 0000000..0fcdb53
--- /dev/null
+++ b/drivers/media/video/msm/sensors/vx6953.h
@@ -0,0 +1,135 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef VX6953_H
+#define VX6953_H
+#include <linux/types.h>
+#include <mach/board.h>
+struct reg_struct_init {
+ uint8_t reg_0x0112; /* 0x0112*/
+ uint8_t reg_0x0113; /* 0x0113*/
+ uint8_t vt_pix_clk_div; /* 0x0301*/
+ uint8_t pre_pll_clk_div; /* 0x0305*/
+ uint8_t pll_multiplier; /* 0x0307*/
+ uint8_t op_pix_clk_div; /* 0x0309*/
+ uint8_t reg_0x3030; /*0x3030*/
+ uint8_t reg_0x0111; /*0x0111*/
+ uint8_t reg_0x0b00; /*0x0b00*/
+ uint8_t reg_0x3001; /*0x3001*/
+ uint8_t reg_0x3004; /*0x3004*/
+ uint8_t reg_0x3007; /*0x3007*/
+ uint8_t reg_0x3016; /*0x3016*/
+ uint8_t reg_0x301d; /*0x301d*/
+ uint8_t reg_0x317e; /*0x317E*/
+ uint8_t reg_0x317f; /*0x317F*/
+ uint8_t reg_0x3400; /*0x3400*/
+ uint8_t reg_0x0b06; /*0x0b06*/
+ uint8_t reg_0x0b07; /*0x0b07*/
+ uint8_t reg_0x0b08; /*0x0b08*/
+ uint8_t reg_0x0b09; /*0x0b09*/
+ uint8_t reg_0x0136;
+ uint8_t reg_0x0137;
+ /* Edof */
+ uint8_t reg_0x0b83; /*0x0b83*/
+ uint8_t reg_0x0b84; /*0x0b84*/
+ uint8_t reg_0x0b85; /*0x0b85*/
+ uint8_t reg_0x0b88; /*0x0b88*/
+ uint8_t reg_0x0b89; /*0x0b89*/
+ uint8_t reg_0x0b8a; /*0x0b8a*/
+ };
+struct reg_struct {
+ uint8_t coarse_integration_time_hi; /*REG_COARSE_INTEGRATION_TIME_HI*/
+ uint8_t coarse_integration_time_lo; /*REG_COARSE_INTEGRATION_TIME_LO*/
+ uint8_t analogue_gain_code_global;
+ uint8_t frame_length_lines_hi; /* 0x0340*/
+ uint8_t frame_length_lines_lo; /* 0x0341*/
+ uint8_t line_length_pck_hi; /* 0x0342*/
+ uint8_t line_length_pck_lo; /* 0x0343*/
+ uint8_t reg_0x3005; /* 0x3005*/
+ uint8_t reg_0x3010; /* 0x3010*/
+ uint8_t reg_0x3011; /* 0x3011*/
+ uint8_t reg_0x301a; /* 0x301a*/
+ uint8_t reg_0x3035; /* 0x3035*/
+ uint8_t reg_0x3036; /* 0x3036*/
+ uint8_t reg_0x3041; /*0x3041*/
+ uint8_t reg_0x3042; /*0x3042*/
+ uint8_t reg_0x3045; /*0x3045*/
+ uint8_t reg_0x0b80; /* 0x0b80*/
+ uint8_t reg_0x0900; /*0x0900*/
+ uint8_t reg_0x0901; /* 0x0901*/
+ uint8_t reg_0x0902; /*0x0902*/
+ uint8_t reg_0x0383; /*0x0383*/
+ uint8_t reg_0x0387; /* 0x0387*/
+ uint8_t reg_0x034c; /* 0x034c*/
+ uint8_t reg_0x034d; /*0x034d*/
+ uint8_t reg_0x034e; /* 0x034e*/
+ uint8_t reg_0x034f; /* 0x034f*/
+ uint8_t reg_0x1716; /*0x1716*/
+ uint8_t reg_0x1717; /*0x1717*/
+ uint8_t reg_0x1718; /*0x1718*/
+ uint8_t reg_0x1719; /*0x1719*/
+ uint8_t reg_0x3210;/*0x3210*/
+ uint8_t reg_0x111; /*0x111*/
+ uint8_t reg_0x3410; /*0x3410*/
+ uint8_t reg_0x3098;
+ uint8_t reg_0x309D;
+ uint8_t reg_0x0200;
+ uint8_t reg_0x0201;
+ };
+struct vx6953_i2c_reg_conf {
+ unsigned short waddr;
+ unsigned short wdata;
+};
+
+enum vx6953_test_mode_t {
+ TEST_OFF,
+ TEST_1,
+ TEST_2,
+ TEST_3
+};
+
+enum vx6953_resolution_t {
+ QTR_SIZE,
+ FULL_SIZE,
+ INVALID_SIZE
+};
+enum vx6953_setting {
+ RES_PREVIEW,
+ RES_CAPTURE
+};
+enum mt9p012_reg_update {
+ /* Sensor egisters that need to be updated during initialization */
+ REG_INIT,
+ /* Sensor egisters that needs periodic I2C writes */
+ UPDATE_PERIODIC,
+ /* All the sensor Registers will be updated */
+ UPDATE_ALL,
+ /* Not valid update */
+ UPDATE_INVALID
+};
+
+enum sensor_revision_t {
+ VX6953_STM5M0EDOF_CUT_1,
+ VX6953_STM5M0EDOF_CUT_2,
+ VX6953_STM5M0EDOF_CUT_3
+};
+enum edof_mode_t {
+ VX6953_EDOF_DISABLE, /* 0x00 */
+ VX6953_EDOF_APPLICATION, /* 0x01 */
+ VX6953_EDOF_ESTIMATION /* 0x02 */
+};
+struct vx6953_reg {
+ const struct reg_struct_init *reg_pat_init;
+ const struct reg_struct *reg_pat;
+};
+#endif /* VX6953_H */
diff --git a/drivers/media/video/msm/sensors/vx6953_reg.h b/drivers/media/video/msm/sensors/vx6953_reg.h
new file mode 100644
index 0000000..b76aa93
--- /dev/null
+++ b/drivers/media/video/msm/sensors/vx6953_reg.h
@@ -0,0 +1,134 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+
+struct reg_struct_init vx6953_reg_init[1] = {
+ {
+ 10, /*REG = 0x0112 , 10 bit */
+ 10, /*REG = 0x0113*/
+ 9, /*REG = 0x0301 vt_pix_clk_div*/
+ 4, /*REG = 0x0305 pre_pll_clk_div*/
+ 133, /*REG = 0x0307 pll_multiplier*/
+ 10, /*REG = 0x0309 op_pix_clk_div*/
+ 0x08, /*REG = 0x3030*/
+ 0x02, /*REG = 0x0111*/
+ 0x01, /*REG = 0x0b00 ,lens shading off */
+ 0x30, /*REG = 0x3001*/
+ 0x33, /*REG = 0x3004*/
+ 0x09, /*REG = 0x3007*/
+ 0x1F, /*REG = 0x3016*/
+ 0x03, /*REG = 0x301d*/
+ 0x11, /*REG = 0x317E*/
+ 0x09, /*REG = 0x317F*/
+ 0x38, /*REG = 0x3400*/
+ 0x00, /*REG_0x0b06*/
+ 0x80, /*REG_0x0b07*/
+ 0x01, /*REG_0x0b08*/
+ 0x4F, /*REG_0x0b09*/
+ 0x18, /*REG_0x0136*/
+ 0x00, /*/REG_0x0137*/
+ 0x20, /*REG = 0x0b83*/
+ 0x90, /*REG = 0x0b84*/
+ 0x20, /*REG = 0x0b85*/
+ 0x80, /*REG = 0x0b88*/
+ 0x00, /*REG = 0x0b89*/
+ 0x00, /*REG = 0x0b8a*/
+ }
+};
+struct reg_struct vx6953_reg_pat[2] = {
+ {/* Preview */
+ 0x03, /*REG = 0x0202 coarse integration_time_hi*/
+ 0xd0, /*REG = 0x0203 coarse_integration_time_lo*/
+ 0xc0, /*REG = 0x0205 analogue_gain_code_global*/
+ 0x03, /*REG = 0x0340 frame_length_lines_hi*/
+ 0xf0, /*REG = 0x0341 frame_length_lines_lo*/
+ 0x0b, /*REG = 0x0342 line_length_pck_hi*/
+ 0x74, /*REG = 0x0343 line_length_pck_lo*/
+ 0x03, /*REG = 0x3005*/
+ 0x00, /*REG = 0x3010*/
+ 0x01, /*REG = 0x3011*/
+ 0x6a, /*REG = 0x301a*/
+ 0x03, /*REG = 0x3035*/
+ 0x2c, /*REG = 0x3036*/
+ 0x00, /*REG = 0x3041*/
+ 0x24, /*REG = 0x3042*/
+ 0x81, /*REG = 0x3045*/
+ 0x02, /*REG = 0x0b80 edof estimate*/
+ 0x01, /*REG = 0x0900*/
+ 0x22, /*REG = 0x0901*/
+ 0x04, /*REG = 0x0902*/
+ 0x03, /*REG = 0x0383*/
+ 0x03, /*REG = 0x0387*/
+ 0x05, /*REG = 0x034c*/
+ 0x18, /*REG = 0x034d*/
+ 0x03, /*REG = 0x034e*/
+ 0xd4, /*REG = 0x034f*/
+ 0x02, /*0x1716*/
+ 0x04, /*0x1717*/
+ 0x08, /*0x1718*/
+ 0x2c, /*0x1719*/
+ 0x01, /*0x3210*/
+ 0x02, /*0x111*/
+ 0x01, /*0x3410*/
+ 0x01, /*0x3098*/
+ 0x05, /*0x309D*/
+ 0x02,
+ 0x04,
+ },
+ { /* Snapshot */
+ 0x07,/*REG = 0x0202 coarse_integration_time_hi*/
+ 0x00,/*REG = 0x0203 coarse_integration_time_lo*/
+ 0xc0,/*REG = 0x0205 analogue_gain_code_global*/
+ 0x07,/*REG = 0x0340 frame_length_lines_hi*/
+ 0xd0,/*REG = 0x0341 frame_length_lines_lo*/
+ 0x0b,/*REG = 0x0342 line_length_pck_hi*/
+ 0x8c,/*REG = 0x0343 line_length_pck_lo*/
+ 0x01,/*REG = 0x3005*/
+ 0x00,/*REG = 0x3010*/
+ 0x00,/*REG = 0x3011*/
+ 0x55,/*REG = 0x301a*/
+ 0x01,/*REG = 0x3035*/
+ 0x23,/*REG = 0x3036*/
+ 0x00,/*REG = 0x3041*/
+ 0x24,/*REG = 0x3042*/
+ 0xb7,/*REG = 0x3045*/
+ 0x01,/*REG = 0x0b80 edof application*/
+ 0x00,/*REG = 0x0900*/
+ 0x00,/*REG = 0x0901*/
+ 0x00,/*REG = 0x0902*/
+ 0x01,/*REG = 0x0383*/
+ 0x01,/*REG = 0x0387*/
+ 0x0A,/*REG = 0x034c*/
+ 0x30,/*REG = 0x034d*/
+ 0x07,/*REG = 0x034e*/
+ 0xA8,/*REG = 0x034f*/
+ 0x02,/*0x1716*/
+ 0x0d,/*0x1717*/
+ 0x07,/*0x1718*/
+ 0x7d,/*0x1719*/
+ 0x01,/*0x3210*/
+ 0x02,/*0x111*/
+ 0x01,/*0x3410*/
+ 0x01,/*0x3098*/
+ 0x05, /*0x309D*/
+ 0x02,
+ 0x00,
+ }
+};
+
+
+
+struct vx6953_reg vx6953_regs = {
+ .reg_pat_init = &vx6953_reg_init[0],
+ .reg_pat = &vx6953_reg_pat[0],
+};
diff --git a/drivers/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index 57dff2e..483eab0 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.c
+++ b/drivers/media/video/msm/wfd/enc-subdev.c
@@ -1241,7 +1241,20 @@
err:
return rc;
}
-
+static long venc_set_max_perf_level(struct video_client_ctx *client_ctx,
+ int val)
+{
+ int rc = 0;
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_perf_level perf;
+ vcd_property_hdr.prop_id = VCD_REQ_PERF_LEVEL;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_perf_level);
+ perf.level = VCD_PERF_LEVEL2;
+ rc = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &perf);
+ return rc;
+}
static long venc_set_header_mode(struct video_client_ctx *client_ctx,
__s32 mode)
{
@@ -1879,6 +1892,9 @@
rc = venc_set_multislicing_mode(client_ctx, ctrl->id,
ctrl->value);
break;
+ case V4L2_CID_MPEG_QCOM_SET_PERF_LEVEL:
+ rc = venc_set_max_perf_level(client_ctx, ctrl->value);
+ break;
default:
WFD_MSG_ERR("Set property not suported: %d\n", ctrl->id);
rc = -ENOTSUPP;
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 60e1e55..937490d 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1,4 +1,5 @@
+
/* Qualcomm Secure Execution Environment Communicator (QSEECOM) driver
*
* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
@@ -31,6 +32,7 @@
#include <linux/types.h>
#include <linux/clk.h>
#include <linux/qseecom.h>
+#include <linux/freezer.h>
#include <mach/msm_bus.h>
#include <mach/msm_bus_board.h>
#include <mach/scm.h>
@@ -438,7 +440,7 @@
spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
while (atomic_read(&data->ioctl_count) > 1) {
- if (wait_event_interruptible(data->abort_wq,
+ if (wait_event_freezable(data->abort_wq,
atomic_read(&data->ioctl_count) <= 1)) {
pr_err("Interrupted from abort\n");
ret = -ERESTARTSYS;
@@ -546,7 +548,7 @@
}
pr_debug("waking up rcv_req_wq and "
"waiting for send_resp_wq\n");
- if (wait_event_interruptible(qseecom.send_resp_wq,
+ if (wait_event_freezable(qseecom.send_resp_wq,
__qseecom_listener_has_sent_rsp(data))) {
pr_warning("Interrupted: exiting send_cmd loop\n");
return -ERESTARTSYS;
@@ -707,7 +709,7 @@
{
wake_up_all(&qseecom.send_resp_wq);
while (atomic_read(&data->ioctl_count) > 1) {
- if (wait_event_interruptible(data->abort_wq,
+ if (wait_event_freezable(data->abort_wq,
atomic_read(&data->ioctl_count) <= 1)) {
pr_err("Interrupted from abort\n");
return -ERESTARTSYS;
@@ -784,7 +786,7 @@
data->abort = 1;
wake_up_all(&qseecom.send_resp_wq);
while (atomic_read(&data->ioctl_count) > 0) {
- if (wait_event_interruptible(data->abort_wq,
+ if (wait_event_freezable(data->abort_wq,
atomic_read(&data->ioctl_count) <= 0)) {
pr_err("Interrupted from abort\n");
ret = -ERESTARTSYS;
@@ -872,7 +874,7 @@
pr_debug("waking up rcv_req_wq and "
"waiting for send_resp_wq\n");
- if (wait_event_interruptible(qseecom.send_resp_wq,
+ if (wait_event_freezable(qseecom.send_resp_wq,
__qseecom_listener_has_sent_rsp(data))) {
pr_warning("qseecom Interrupted: exiting send_cmd loop\n");
return -ERESTARTSYS;
@@ -1080,7 +1082,7 @@
this_lstnr = __qseecom_find_svc(data->listener.id);
while (1) {
- if (wait_event_interruptible(this_lstnr->rcv_req_wq,
+ if (wait_event_freezable(this_lstnr->rcv_req_wq,
__qseecom_listener_has_rcvd_req(data,
this_lstnr))) {
pr_warning("Interrupted: exiting wait_rcv_req loop\n");
diff --git a/drivers/net/msm_rmnet_bam.c b/drivers/net/msm_rmnet_bam.c
index 401b63c..bbcf3c4 100644
--- a/drivers/net/msm_rmnet_bam.c
+++ b/drivers/net/msm_rmnet_bam.c
@@ -79,6 +79,7 @@
#endif
struct sk_buff *waiting_for_ul_skb;
spinlock_t lock;
+ spinlock_t tx_queue_lock;
struct tasklet_struct tsklt;
u32 operation_mode; /* IOCTL specified mode (protocol, QoS header) */
uint8_t device_up;
@@ -321,6 +322,7 @@
{
struct rmnet_private *p = netdev_priv(dev);
u32 opmode = p->operation_mode;
+ unsigned long flags;
DBG1("%s: write complete\n", __func__);
if (RMNET_IS_MODE_IP(opmode) ||
@@ -335,12 +337,15 @@
((struct net_device *)(dev))->name, p->stats.tx_packets,
skb->len, skb->mark);
dev_kfree_skb_any(skb);
+
+ spin_lock_irqsave(&p->tx_queue_lock, flags);
if (netif_queue_stopped(dev) &&
msm_bam_dmux_is_ch_low(p->ch_id)) {
DBG0("%s: Low WM hit, waking queue=%p\n",
__func__, skb);
netif_wake_queue(dev);
}
+ spin_unlock_irqrestore(&p->tx_queue_lock, flags);
}
static void bam_notify(void *dev, int event, unsigned long data)
@@ -509,10 +514,12 @@
goto exit;
}
+ spin_lock_irqsave(&p->tx_queue_lock, flags);
if (msm_bam_dmux_is_ch_full(p->ch_id)) {
netif_stop_queue(dev);
DBG0("%s: High WM hit, stopping queue=%p\n", __func__, skb);
}
+ spin_unlock_irqrestore(&p->tx_queue_lock, flags);
exit:
msm_bam_dmux_ul_power_unvote();
@@ -770,6 +777,7 @@
p->waiting_for_ul_skb = NULL;
p->in_reset = 0;
spin_lock_init(&p->lock);
+ spin_lock_init(&p->tx_queue_lock);
#ifdef CONFIG_MSM_RMNET_DEBUG
p->timeout_us = timeout_us;
p->wakeups_xmit = p->wakeups_rcv = 0;
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index c275a06..e21862a 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -44,6 +44,8 @@
#define ADC_ARB_SECP_DATA0 0x196
#define ADC_ARB_BMS_CNTRL 0x18D
+#define AMUX_TRIM_2 0x322
+#define TEST_PROGRAM_REV 0x339
enum pmic_bms_interrupts {
PM8921_BMS_SBI_WRITE_OK,
@@ -121,6 +123,7 @@
int batt_temp_suspend;
int soc_rbatt_suspend;
int default_rbatt_mohm;
+ int amux_2_trim_delta;
uint16_t prev_last_good_ocv_raw;
};
@@ -520,6 +523,20 @@
return 0;
}
+static int adjust_xo_vbatt_reading_for_mbg(struct pm8921_bms_chip *chip,
+ int result)
+{
+ int64_t numerator;
+ int64_t denominator;
+
+ if (chip->amux_2_trim_delta == 0)
+ return result;
+
+ numerator = (s64)result * 1000000;
+ denominator = (1000000 + (410 * (s64)chip->amux_2_trim_delta));
+ return div_s64(numerator, denominator);
+}
+
static int convert_vbatt_raw_to_uv(struct pm8921_bms_chip *chip,
int usb_chg,
uint16_t reading, int *result)
@@ -528,6 +545,7 @@
pr_debug("raw = %04x vbatt = %u\n", reading, *result);
*result = adjust_xo_vbatt_reading(chip, usb_chg, *result);
pr_debug("after adj vbatt = %u\n", *result);
+ *result = adjust_xo_vbatt_reading_for_mbg(chip, *result);
return 0;
}
@@ -902,6 +920,19 @@
return 0;
}
+#define MBG_TRANSIENT_ERROR_RAW 51
+static void adjust_pon_ocv_raw(struct pm8921_bms_chip *chip,
+ struct pm8921_soc_params *raw)
+{
+ /* in 8921 parts the PON ocv is taken when the MBG is not settled.
+ * decrease the pon ocv by 15mV raw value to account for it
+ * Since a 1/3rd of vbatt is supplied to the adc the raw value
+ * needs to be adjusted by 5mV worth bits
+ */
+ if (raw->last_good_ocv_raw >= MBG_TRANSIENT_ERROR_RAW)
+ raw->last_good_ocv_raw -= MBG_TRANSIENT_ERROR_RAW;
+}
+
static int read_soc_params_raw(struct pm8921_bms_chip *chip,
struct pm8921_soc_params *raw)
{
@@ -919,8 +950,13 @@
usb_chg = usb_chg_plugged_in();
- if (chip->prev_last_good_ocv_raw == 0 ||
- chip->prev_last_good_ocv_raw != raw->last_good_ocv_raw) {
+ if (chip->prev_last_good_ocv_raw == 0) {
+ chip->prev_last_good_ocv_raw = raw->last_good_ocv_raw;
+ adjust_pon_ocv_raw(chip, raw);
+ convert_vbatt_raw_to_uv(chip, usb_chg,
+ raw->last_good_ocv_raw, &raw->last_good_ocv_uv);
+ last_ocv_uv = raw->last_good_ocv_uv;
+ } else if (chip->prev_last_good_ocv_raw != raw->last_good_ocv_raw) {
chip->prev_last_good_ocv_raw = raw->last_good_ocv_raw;
convert_vbatt_raw_to_uv(chip, usb_chg,
raw->last_good_ocv_raw, &raw->last_good_ocv_uv);
@@ -929,9 +965,6 @@
raw->last_good_ocv_uv = last_ocv_uv;
}
- if (raw->last_good_ocv_uv)
- last_ocv_uv = raw->last_good_ocv_uv;
-
pr_debug("0p625 = %duV\n", chip->xoadc_v0625);
pr_debug("1p25 = %duV\n", chip->xoadc_v125);
pr_debug("last_good_ocv_raw= 0x%x, last_good_ocv_uv= %duV\n",
@@ -2190,6 +2223,61 @@
}
}
+#define REG_SBI_CONFIG 0x04F
+#define PAGE3_ENABLE_MASK 0x6
+#define PROGRAM_REV_MASK 0x0F
+#define PROGRAM_REV 0x9
+static int read_ocv_trim(struct pm8921_bms_chip *chip)
+{
+ int rc;
+ u8 reg, sbi_config;
+
+ rc = pm8xxx_readb(chip->dev->parent, REG_SBI_CONFIG, &sbi_config);
+ if (rc) {
+ pr_err("error = %d reading sbi config reg\n", rc);
+ return rc;
+ }
+
+ reg = sbi_config | PAGE3_ENABLE_MASK;
+ rc = pm8xxx_writeb(chip->dev->parent, REG_SBI_CONFIG, reg);
+ if (rc) {
+ pr_err("error = %d writing sbi config reg\n", rc);
+ return rc;
+ }
+
+ rc = pm8xxx_readb(chip->dev->parent, TEST_PROGRAM_REV, ®);
+ if (rc)
+ pr_err("Error %d reading %d addr %d\n",
+ rc, reg, TEST_PROGRAM_REV);
+ pr_err("program rev reg is 0x%x\n", reg);
+ reg &= PROGRAM_REV_MASK;
+
+ /* If the revision is equal or higher do not adjust trim delta */
+ if (reg >= PROGRAM_REV) {
+ chip->amux_2_trim_delta = 0;
+ goto restore_sbi_config;
+ }
+
+ rc = pm8xxx_readb(chip->dev->parent, AMUX_TRIM_2, ®);
+ if (rc) {
+ pr_err("error = %d reading trim reg\n", rc);
+ return rc;
+ }
+
+ pr_err("trim reg is 0x%x\n", reg);
+ chip->amux_2_trim_delta = abs(0x49 - reg);
+ pr_err("trim delta is %d\n", chip->amux_2_trim_delta);
+
+restore_sbi_config:
+ rc = pm8xxx_writeb(chip->dev->parent, REG_SBI_CONFIG, sbi_config);
+ if (rc) {
+ pr_err("error = %d writing sbi config reg\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
static int __devinit pm8921_bms_probe(struct platform_device *pdev)
{
int rc = 0;
@@ -2259,6 +2347,11 @@
the_chip = chip;
create_debugfs_entries(chip);
+ rc = read_ocv_trim(chip);
+ if (rc) {
+ pr_err("couldn't adjust ocv_trim rc= %d\n", rc);
+ goto free_irqs;
+ }
check_initial_ocv(chip);
INIT_DELAYED_WORK(&chip->calib_ccadc_work, calibrate_ccadc_work);
diff --git a/drivers/power/pm8xxx-ccadc.c b/drivers/power/pm8xxx-ccadc.c
index 65bc654..ce72a5b 100644
--- a/drivers/power/pm8xxx-ccadc.c
+++ b/drivers/power/pm8xxx-ccadc.c
@@ -214,8 +214,8 @@
break;
}
if (i == ADC_WAIT_COUNT) {
- pr_err("waited too long for offset eoc\n");
- return rc;
+ pr_err("waited too long for offset eoc returning -EBUSY\n");
+ return -EBUSY;
}
rc = pm8xxx_readb(chip->dev->parent, ADC_ARB_SECP_DATA0, &data_lsb);
diff --git a/drivers/usb/gadget/f_mbim.c b/drivers/usb/gadget/f_mbim.c
index 8288496..21b393e 100644
--- a/drivers/usb/gadget/f_mbim.c
+++ b/drivers/usb/gadget/f_mbim.c
@@ -553,7 +553,7 @@
}
spin_lock_irqsave(&dev->lock, flags);
- list_add(&cpkt->list, &dev->cpkt_resp_q);
+ list_add_tail(&cpkt->list, &dev->cpkt_resp_q);
spin_unlock_irqrestore(&dev->lock, flags);
fmbim_ctrl_response_available(dev);
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 347711b..dbbfad4 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -25,9 +25,12 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/err.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
#include <linux/wakelock.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
+#include <mach/msm_bus.h>
#include <linux/usb/msm_hsusb_hw.h>
#include <linux/usb/msm_hsusb.h>
@@ -55,8 +58,10 @@
int peripheral_status_irq;
int wakeup_irq;
bool wakeup_irq_enabled;
+ uint32_t bus_perf_client;
};
+static bool debug_bus_voting_enabled = true;
static inline struct msm_hsic_hcd *hcd_to_hsic(struct usb_hcd *hcd)
{
return (struct msm_hsic_hcd *) (hcd->hcd_priv);
@@ -464,6 +469,14 @@
if (ret < 0)
dev_err(mehci->dev, "unable to set vddcx voltage: min:0.5v max:1.3v\n");
+ if (mehci->bus_perf_client && debug_bus_voting_enabled) {
+ ret = msm_bus_scale_client_update_request(
+ mehci->bus_perf_client, 0);
+ if (ret)
+ dev_err(mehci->dev, "%s: Failed to dvote for "
+ "bus bandwidth %d\n", __func__, ret);
+ }
+
atomic_set(&mehci->in_lpm, 1);
enable_irq(hcd->irq);
wake_unlock(&mehci->wlock);
@@ -487,6 +500,14 @@
wake_lock(&mehci->wlock);
+ if (mehci->bus_perf_client && debug_bus_voting_enabled) {
+ ret = msm_bus_scale_client_update_request(
+ mehci->bus_perf_client, 1);
+ if (ret)
+ dev_err(mehci->dev, "%s: Failed to vote for "
+ "bus bandwidth %d\n", __func__, ret);
+ }
+
ret = regulator_set_voltage(mehci->hsic_vddcx,
USB_PHY_VDD_DIG_VOL_MIN,
USB_PHY_VDD_DIG_VOL_MAX);
@@ -754,6 +775,88 @@
return IRQ_HANDLED;
}
+static int ehci_hsic_msm_bus_show(struct seq_file *s, void *unused)
+{
+ if (debug_bus_voting_enabled)
+ seq_printf(s, "enabled\n");
+ else
+ seq_printf(s, "disabled\n");
+
+ return 0;
+}
+
+static int ehci_hsic_msm_bus_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ehci_hsic_msm_bus_show, inode->i_private);
+}
+
+static ssize_t ehci_hsic_msm_bus_write(struct file *file,
+ const char __user *ubuf, size_t count, loff_t *ppos)
+{
+ char buf[8];
+ int ret;
+ struct seq_file *s = file->private_data;
+ struct msm_hsic_hcd *mehci = s->private;
+
+ memset(buf, 0x00, sizeof(buf));
+
+ if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
+ return -EFAULT;
+
+ if (!strncmp(buf, "enable", 6)) {
+ /* Do not vote here. Let hsic driver decide when to vote */
+ debug_bus_voting_enabled = true;
+ } else {
+ debug_bus_voting_enabled = false;
+ if (mehci->bus_perf_client) {
+ ret = msm_bus_scale_client_update_request(
+ mehci->bus_perf_client, 0);
+ if (ret)
+ dev_err(mehci->dev, "%s: Failed to devote "
+ "for bus bw %d\n", __func__, ret);
+ }
+ }
+
+ return count;
+}
+
+const struct file_operations ehci_hsic_msm_bus_fops = {
+ .open = ehci_hsic_msm_bus_open,
+ .read = seq_read,
+ .write = ehci_hsic_msm_bus_write,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static struct dentry *ehci_hsic_msm_dbg_root;
+static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
+{
+ struct dentry *ehci_hsic_msm_dentry;
+
+ ehci_hsic_msm_dbg_root = debugfs_create_dir("ehci_hsic_msm_dbg", NULL);
+
+ if (!ehci_hsic_msm_dbg_root || IS_ERR(ehci_hsic_msm_dbg_root))
+ return -ENODEV;
+
+ ehci_hsic_msm_dentry = debugfs_create_file("bus_voting",
+ S_IRUGO | S_IWUSR,
+ ehci_hsic_msm_dbg_root, mehci,
+ &ehci_hsic_msm_bus_fops);
+
+ if (!ehci_hsic_msm_dentry) {
+ debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void ehci_hsic_msm_debugfs_cleanup(void)
+{
+ debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
+}
+
+
static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
{
@@ -886,6 +989,27 @@
}
}
+ ret = ehci_hsic_msm_debugfs_init(mehci);
+ if (ret)
+ dev_dbg(&pdev->dev, "mode debugfs file is"
+ "not available\n");
+
+ if (pdata && pdata->bus_scale_table) {
+ mehci->bus_perf_client =
+ msm_bus_scale_register_client(pdata->bus_scale_table);
+ /* Configure BUS performance parameters for MAX bandwidth */
+ if (mehci->bus_perf_client) {
+ ret = msm_bus_scale_client_update_request(
+ mehci->bus_perf_client, 1);
+ if (ret)
+ dev_err(&pdev->dev, "%s: Failed to vote for "
+ "bus bandwidth %d\n", __func__, ret);
+ } else {
+ dev_err(&pdev->dev, "%s: Failed to register BUS "
+ "scaling client!!\n", __func__);
+ }
+ }
+
/*
* This pdev->dev is assigned parent of root-hub by USB core,
* hence, runtime framework automatically calls this driver's
@@ -930,6 +1054,10 @@
free_irq(mehci->wakeup_irq, mehci);
}
+ if (mehci->bus_perf_client)
+ msm_bus_scale_unregister_client(mehci->bus_perf_client);
+
+ ehci_hsic_msm_debugfs_cleanup();
device_init_wakeup(&pdev->dev, 0);
pm_runtime_set_suspended(&pdev->dev);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index b4a9512..7f155c2 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -2522,9 +2522,13 @@
#endif
}
- if (mfd->mdp_rev >= MDP_REV_41 && !mfd->use_ov0_blt &&
+ if (mfd->mdp_rev >= MDP_REV_42 && !mfd->use_ov0_blt &&
(pipe->mixer_num == MDP4_MIXER0)) {
- ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL;
+ ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL;
+ } else if (mfd->mdp_rev == MDP_REV_41 &&
+ mdp4_overlay_is_rgb_type(pipe->src_format) &&
+ !mfd->use_ov0_blt && (pipe->mixer_num == MDP4_MIXER0)) {
+ ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL;
} else {
mdp4_mixer_stage_down(pipe);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
index d6749e2..7b284e9 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
@@ -430,6 +430,9 @@
}
}
break;
+ case VCD_REQ_PERF_LEVEL:
+ vcd_status = VCD_S_SUCCESS;
+ break;
default:
vcd_status = VCD_ERR_ILLEGAL_OP;
break;
@@ -943,6 +946,9 @@
}
break;
}
+ case VCD_REQ_PERF_LEVEL:
+ vcd_status = VCD_S_SUCCESS;
+ break;
default:
DDL_MSG_ERROR("INVALID ID %d\n", (int)property_hdr->prop_id);
vcd_status = VCD_ERR_ILLEGAL_OP;
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
index 708d34f..90c98d7 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -845,3 +845,23 @@
mutex_unlock(&resource_context.secure_lock);
return rc;
}
+
+u32 get_res_trk_perf_level(enum vcd_perf_level perf_level)
+{
+ u32 res_trk_perf_level;
+ switch (perf_level) {
+ case VCD_PERF_LEVEL0:
+ res_trk_perf_level = RESTRK_1080P_VGA_PERF_LEVEL;
+ break;
+ case VCD_PERF_LEVEL1:
+ res_trk_perf_level = RESTRK_1080P_720P_PERF_LEVEL;
+ break;
+ case VCD_PERF_LEVEL2:
+ res_trk_perf_level = RESTRK_1080P_MAX_PERF_LEVEL;
+ break;
+ default:
+ VCD_MSG_ERROR("Invalid perf level: %d\n", perf_level);
+ res_trk_perf_level = -EINVAL;
+ }
+ return res_trk_perf_level;
+}
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h
index 9975573..7d68412 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h
@@ -42,4 +42,5 @@
int res_trk_close_secure_session(void);
void res_trk_secure_set(void);
void res_trk_secure_unset(void);
+u32 get_res_trk_perf_level(enum vcd_perf_level);
#endif
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
index bd0d94e..f8ec0dc 100644
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
@@ -753,3 +753,7 @@
{
return 0;
}
+u32 get_res_trk_perf_level(enum vcd_perf_level perf_level)
+{
+ return -ENOTSUPP;
+}
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h
index 898195a..cc414e2 100644
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h
@@ -37,4 +37,5 @@
int res_trk_close_secure_session(void);
void res_trk_secure_set(void);
void res_trk_secure_unset(void);
+u32 get_res_trk_perf_level(enum vcd_perf_level perf_level);
#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd.h b/drivers/video/msm/vidc/common/vcd/vcd.h
index 9fc76d8..0d1ff7e 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd.h
@@ -390,4 +390,7 @@
void vcd_handle_ind_info_output_reconfig
(struct vcd_clnt_ctxt *cctxt, u32 status);
+u32 vcd_req_perf_level(struct vcd_clnt_ctxt *cctxt,
+ struct vcd_property_perf_level *);
+
#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
index 9376900..09f79a0 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
@@ -534,6 +534,10 @@
cctxt->bframe = iperiod->b_frames;
break;
}
+ case VCD_REQ_PERF_LEVEL:
+ rc = vcd_req_perf_level(cctxt,
+ (struct vcd_property_perf_level *)prop_val);
+ break;
default:
{
break;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_core.h b/drivers/video/msm/vidc/common/vcd/vcd_core.h
index 1f844e8..b8438e1 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_core.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_core.h
@@ -209,6 +209,7 @@
u32 vcd_enable_ion;
struct vcd_clnt_ctxt *next;
u32 meta_mode;
+ int perf_set_by_client;
};
#define VCD_BUFFERPOOL_INUSE_DECREMENT(val) \
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c b/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c
index dec9b4e..ab21bac 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c
@@ -102,9 +102,10 @@
VCD_FAILED_RETURN(rc,
"Failed: Get VCD_I_FRAME_RATE");
}
- cctxt->reqd_perf_lvl = cctxt->frm_p_units *
- cctxt->frm_rate.fps_numerator /
- cctxt->frm_rate.fps_denominator;
+ if (!cctxt->perf_set_by_client)
+ cctxt->reqd_perf_lvl = cctxt->frm_p_units *
+ cctxt->frm_rate.fps_numerator /
+ cctxt->frm_rate.fps_denominator;
cctxt->sched_clnt_hdl = sched_cctxt;
memset(sched_cctxt, 0,
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index eec83b6b..fd8d02a 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -17,7 +17,6 @@
#include "vcd.h"
#include "vdec_internal.h"
-
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MAP_TABLE_SZ 64
@@ -2923,6 +2922,30 @@
return rc;
}
+u32 vcd_req_perf_level(
+ struct vcd_clnt_ctxt *cctxt,
+ struct vcd_property_perf_level *perf_level)
+{
+ u32 rc;
+ u32 res_trk_perf_level;
+ if (!perf_level) {
+ VCD_MSG_ERROR("Invalid parameters\n");
+ return -EINVAL;
+ }
+ res_trk_perf_level = get_res_trk_perf_level(perf_level->level);
+ if (res_trk_perf_level < 0) {
+ rc = -ENOTSUPP;
+ goto perf_level_not_supp;
+ }
+ rc = vcd_set_perf_level(cctxt->dev_ctxt, res_trk_perf_level);
+ if (!rc) {
+ cctxt->reqd_perf_lvl = res_trk_perf_level;
+ cctxt->perf_set_by_client = 1;
+ }
+perf_level_not_supp:
+ return rc;
+}
+
u32 vcd_set_frame_size(
struct vcd_clnt_ctxt *cctxt,
struct vcd_property_frame_size *frm_size)
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index bb6a01d..1a6df8b 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -331,6 +331,7 @@
unsigned strobe;
unsigned data;
unsigned hub_reset;
+ struct msm_bus_scale_pdata *bus_scale_table;
};
struct msm_usb_host_platform_data {
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 0a0fb1b..147b068 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1521,6 +1521,9 @@
/* MPEG-class control IDs specific to the Samsung MFC 5.1 driver as defined by V4L2 */
#define V4L2_CID_MPEG_MFC51_BASE (V4L2_CTRL_CLASS_MPEG | 0x1100)
+#define V4L2_CID_MPEG_QCOM_BASE (V4L2_CTRL_CLASS_MPEG | 0x2100)
+
+#define V4L2_CID_MPEG_QCOM_SET_PERF_LEVEL (V4L2_CID_MPEG_QCOM_BASE + 0)
#define V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY (V4L2_CID_MPEG_MFC51_BASE+0)
#define V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE (V4L2_CID_MPEG_MFC51_BASE+1)
diff --git a/include/media/msm/vcd_property.h b/include/media/msm/vcd_property.h
index 0b501ea..51cc78f 100644
--- a/include/media/msm/vcd_property.h
+++ b/include/media/msm/vcd_property.h
@@ -51,6 +51,7 @@
#define VCD_I_DISABLE_DMX (VCD_START_BASE + 0x23)
#define VCD_I_DISABLE_DMX_SUPPORT (VCD_START_BASE + 0x24)
#define VCD_I_ENABLE_SPS_PPS_FOR_IDR (VCD_START_BASE + 0x25)
+#define VCD_REQ_PERF_LEVEL (VCD_START_BASE + 0x26)
#define VCD_START_REQ (VCD_START_BASE + 0x1000)
#define VCD_I_REQ_IFRAME (VCD_START_REQ + 0x1)
@@ -92,6 +93,11 @@
u32 scan_lines;
};
+enum vcd_perf_level {
+ VCD_PERF_LEVEL0,
+ VCD_PERF_LEVEL1,
+ VCD_PERF_LEVEL2,
+};
#define VCD_METADATA_DATANONE 0x001
#define VCD_METADATA_QCOMFILLER 0x002
@@ -123,6 +129,10 @@
u32 target_bitrate;
};
+struct vcd_property_perf_level {
+ enum vcd_perf_level level;
+};
+
enum vcd_yuv_buffer_format {
VCD_BUFFER_FORMAT_NV12 = 0x1,
VCD_BUFFER_FORMAT_TILE_4x2 = 0x2,
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index a448df6..92323cb 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -18,16 +18,17 @@
#endif
#include <linux/types.h>
#include <linux/ioctl.h>
+#ifdef __KERNEL__
#include <linux/cdev.h>
+#endif
#ifdef MSM_CAMERA_GCC
#include <time.h>
#else
#include <linux/time.h>
#endif
-#ifdef __KERNEL__
#include <linux/ion.h>
-#endif
+
#define MSM_CAM_IOCTL_MAGIC 'm'
#define MSM_CAM_IOCTL_GET_SENSOR_INFO \
@@ -1224,6 +1225,8 @@
struct msm_camsensor_info {
char name[MAX_SENSOR_NAME];
uint8_t flash_enabled;
+ uint8_t strobe_flash_enabled;
+ uint8_t actuator_enabled;
int8_t total_steps;
uint8_t support_3d;
enum flash_type flashtype;
diff --git a/include/media/rc-map.h b/include/media/rc-map.h
index 226ea68..2114287 100644
--- a/include/media/rc-map.h
+++ b/include/media/rc-map.h
@@ -114,6 +114,7 @@
#define RC_MAP_NORWOOD "rc-norwood"
#define RC_MAP_NPGTECH "rc-npgtech"
#define RC_MAP_PCTV_SEDNA "rc-pctv-sedna"
+#define RC_MAP_RC6_PHILIPS "rc-philips"
#define RC_MAP_PINNACLE_COLOR "rc-pinnacle-color"
#define RC_MAP_PINNACLE_GREY "rc-pinnacle-grey"
#define RC_MAP_PINNACLE_PCTV_HD "rc-pinnacle-pctv-hd"
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 3b46a50..728d856 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -1990,8 +1990,7 @@
if (v->st_enable)
voice_send_set_pp_enable_cmd(v, MODULE_ID_VOICE_MODULE_ST,
v->st_enable);
- if (v->fens_enable)
- voice_send_set_pp_enable_cmd(v, MODULE_ID_VOICE_MODULE_FENS,
+ voice_send_set_pp_enable_cmd(v, MODULE_ID_VOICE_MODULE_FENS,
v->fens_enable);
if (is_voip_session(v->session_id))