Merge "regulator: pm8xxx-regulator: Add slew_rate platform data parameter" into msm-3.0
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 2698ea7..e62dfbd 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -315,9 +315,9 @@
};
};
- regulator@1d00 {
+ regulator@a000 {
regulator-name = "8941_boost";
- reg = <0x1d00 0x100>;
+ reg = <0xa000 0x100>;
compatible = "qcom,qpnp-regulator";
status = "disabled";
};
diff --git a/arch/arm/boot/dts/msmcopper-regulator.dtsi b/arch/arm/boot/dts/msmcopper-regulator.dtsi
index bb26e00..0d0c587 100644
--- a/arch/arm/boot/dts/msmcopper-regulator.dtsi
+++ b/arch/arm/boot/dts/msmcopper-regulator.dtsi
@@ -41,7 +41,7 @@
status = "okay";
};
- pm8941_boost: regulator@1d00 {
+ pm8941_boost: regulator@a000 {
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
qcom,enable-time = <500>;
diff --git a/arch/arm/mach-msm/board-8064-display.c b/arch/arm/mach-msm/board-8064-display.c
index 60bc26c..040e573 100644
--- a/arch/arm/mach-msm/board-8064-display.c
+++ b/arch/arm/mach-msm/board-8064-display.c
@@ -227,7 +227,7 @@
};
static int mdp_core_clk_rate_table[] = {
- 85330000,
+ 59080000,
128000000,
160000000,
200000000,
@@ -235,7 +235,7 @@
static struct msm_panel_common_pdata mdp_pdata = {
.gpio = MDP_VSYNC_GPIO,
- .mdp_core_clk_rate = 85330000,
+ .mdp_core_clk_rate = 59080000,
.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-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index b018a20..6ef1335a 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -1023,6 +1023,151 @@
},
};
+#ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
+static struct gpiomux_setting sdc2_clk_active_cfg = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting sdc2_cmd_data_0_3_active_cfg = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting sdc2_suspended_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting sdc2_data_1_suspended_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct msm_gpiomux_config apq8064_sdc2_configs[] __initdata = {
+ {
+ .gpio = 59,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc2_clk_active_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc2_suspended_cfg,
+ },
+ },
+ {
+ .gpio = 57,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc2_cmd_data_0_3_active_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc2_suspended_cfg,
+ },
+
+ },
+ {
+ .gpio = 62,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc2_cmd_data_0_3_active_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc2_suspended_cfg,
+ },
+ },
+ {
+ .gpio = 61,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc2_cmd_data_0_3_active_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc2_data_1_suspended_cfg,
+ },
+ },
+ {
+ .gpio = 60,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc2_cmd_data_0_3_active_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc2_suspended_cfg,
+ },
+ },
+ {
+ .gpio = 58,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc2_cmd_data_0_3_active_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc2_suspended_cfg,
+ },
+ },
+};
+#endif
+
+
+#ifdef CONFIG_MMC_MSM_SDC4_SUPPORT
+static struct gpiomux_setting sdc4_clk_active_cfg = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting sdc4_cmd_data_0_3_active_cfg = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting sdc4_suspended_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting sdc4_data_1_suspended_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct msm_gpiomux_config apq8064_sdc4_configs[] __initdata = {
+ {
+ .gpio = 68,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc4_clk_active_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc4_suspended_cfg,
+ },
+ },
+ {
+ .gpio = 67,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc4_cmd_data_0_3_active_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc4_suspended_cfg,
+ },
+
+ },
+ {
+ .gpio = 66,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc4_cmd_data_0_3_active_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc4_suspended_cfg,
+ },
+ },
+ {
+ .gpio = 65,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc4_cmd_data_0_3_active_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc4_data_1_suspended_cfg,
+ },
+ },
+ {
+ .gpio = 64,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc4_cmd_data_0_3_active_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc4_suspended_cfg,
+ },
+ },
+ {
+ .gpio = 63,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc4_cmd_data_0_3_active_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc4_suspended_cfg,
+ },
+ },
+};
+#endif
+
void __init apq8064_init_gpiomux(void)
{
int rc;
@@ -1104,4 +1249,14 @@
if (machine_is_mpq8064_cdp())
msm_gpiomux_install(mpq8064_ir_configs,
ARRAY_SIZE(mpq8064_ir_configs));
+
+#ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
+ msm_gpiomux_install(apq8064_sdc2_configs,
+ ARRAY_SIZE(apq8064_sdc2_configs));
+#endif
+
+#ifdef CONFIG_MMC_MSM_SDC4_SUPPORT
+ msm_gpiomux_install(apq8064_sdc4_configs,
+ ARRAY_SIZE(apq8064_sdc4_configs));
+#endif
}
diff --git a/arch/arm/mach-msm/board-8064-storage.c b/arch/arm/mach-msm/board-8064-storage.c
index 72126c8..96e54b6 100644
--- a/arch/arm/mach-msm/board-8064-storage.c
+++ b/arch/arm/mach-msm/board-8064-storage.c
@@ -188,13 +188,50 @@
},
};
+static struct msm_mmc_gpio sdc2_gpio[] = {
+ {59, "sdc2_clk"},
+ {57, "sdc2_cmd"},
+ {62, "sdc2_dat_0"},
+ {61, "sdc2_dat_1"},
+ {60, "sdc2_dat_2"},
+ {58, "sdc2_dat_3"},
+};
+
+static struct msm_mmc_gpio sdc4_gpio[] = {
+ {68, "sdc4_clk"},
+ {67, "sdc4_cmd"},
+ {66, "sdc4_dat_0"},
+ {65, "sdc4_dat_1"},
+ {64, "sdc4_dat_2"},
+ {63, "sdc4_dat_3"},
+};
+
+static struct msm_mmc_gpio_data mmc_gpio_data[MAX_SDCC_CONTROLLER] = {
+ [SDCC2] = {
+ .gpio = sdc2_gpio,
+ .size = ARRAY_SIZE(sdc2_gpio),
+ },
+ [SDCC4] = {
+ .gpio = sdc4_gpio,
+ .size = ARRAY_SIZE(sdc4_gpio),
+ }
+};
+
static struct msm_mmc_pin_data mmc_slot_pin_data[MAX_SDCC_CONTROLLER] = {
[SDCC1] = {
.pad_data = &mmc_pad_data[SDCC1],
},
+ [SDCC2] = {
+ .is_gpio = 1,
+ .gpio_data = &mmc_gpio_data[SDCC2],
+ },
[SDCC3] = {
.pad_data = &mmc_pad_data[SDCC3],
},
+ [SDCC4] = {
+ .is_gpio = 1,
+ .gpio_data = &mmc_gpio_data[SDCC4],
+ },
};
#define MSM_MPM_PIN_SDC1_DAT1 17
@@ -227,6 +264,26 @@
static struct mmc_platform_data *apq8064_sdc1_pdata;
#endif
+#ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
+static unsigned int sdc2_sup_clk_rates[] = {
+ 400000, 24000000, 48000000
+};
+
+static struct mmc_platform_data sdc2_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
+ .mmc_bus_width = MMC_CAP_4_BIT_DATA,
+ .sup_clk_table = sdc2_sup_clk_rates,
+ .sup_clk_cnt = ARRAY_SIZE(sdc2_sup_clk_rates),
+ .pclk_src_dfab = 1,
+ .pin_data = &mmc_slot_pin_data[SDCC2],
+ .sdiowakeup_irq = MSM_GPIO_TO_INT(61),
+ .msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
+};
+static struct mmc_platform_data *apq8064_sdc2_pdata = &sdc2_data;
+#else
+static struct mmc_platform_data *apq8064_sdc2_pdata;
+#endif
+
#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
static unsigned int sdc3_sup_clk_rates[] = {
400000, 24000000, 48000000, 96000000, 192000000
@@ -258,6 +315,27 @@
static struct mmc_platform_data *apq8064_sdc3_pdata;
#endif
+
+#ifdef CONFIG_MMC_MSM_SDC4_SUPPORT
+static unsigned int sdc4_sup_clk_rates[] = {
+ 400000, 24000000, 48000000
+};
+
+static struct mmc_platform_data sdc4_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
+ .mmc_bus_width = MMC_CAP_4_BIT_DATA,
+ .sup_clk_table = sdc4_sup_clk_rates,
+ .sup_clk_cnt = ARRAY_SIZE(sdc4_sup_clk_rates),
+ .pclk_src_dfab = 1,
+ .pin_data = &mmc_slot_pin_data[SDCC4],
+ .sdiowakeup_irq = MSM_GPIO_TO_INT(65),
+ .msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
+};
+static struct mmc_platform_data *apq8064_sdc4_pdata = &sdc4_data;
+#else
+static struct mmc_platform_data *apq8064_sdc4_pdata;
+#endif
+
void __init apq8064_init_mmc(void)
{
if ((machine_is_apq8064_rumi3()) || machine_is_apq8064_sim()) {
@@ -278,6 +356,9 @@
if (apq8064_sdc1_pdata)
apq8064_add_sdcc(1, apq8064_sdc1_pdata);
+ if (apq8064_sdc2_pdata)
+ apq8064_add_sdcc(2, apq8064_sdc2_pdata);
+
if (apq8064_sdc3_pdata) {
if (!machine_is_apq8064_cdp()) {
apq8064_sdc3_pdata->wpswitch_gpio = 0;
@@ -292,4 +373,7 @@
}
apq8064_add_sdcc(3, apq8064_sdc3_pdata);
}
+
+ if (apq8064_sdc4_pdata)
+ apq8064_add_sdcc(4, apq8064_sdc4_pdata);
}
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 0234de6..566befb 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -2191,6 +2191,7 @@
&apq8064_rpm_device,
&apq8064_rpm_log_device,
&apq8064_rpm_stat_device,
+ &apq_device_tz_log,
&msm_bus_8064_apps_fabric,
&msm_bus_8064_sys_fabric,
&msm_bus_8064_mm_fabric,
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index a1b9c1c..7b4ca29 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -6107,6 +6107,9 @@
if (cpu_is_msm8960() || cpu_is_apq8064())
rmwreg(0x2, DSI2_BYTE_NS_REG, 0x7);
+ /* Source the dsi1_esc_clk from the DSI1 PHY PLLs */
+ rmwreg(0x1, DSI1_ESC_NS_REG, 0x7);
+
/*
* Source the sata_phy_ref_clk from PXO and set predivider of
* sata_pmalive_clk to 1.
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index e8e88d7..355a6d3 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -503,7 +503,7 @@
*/
static int local_vote_clk_reset(struct clk *c, enum clk_reset_action action)
{
- struct branch_clk *vclk = to_branch_clk(c);
+ struct local_vote_clk *vclk = to_local_vote_clk(c);
return __branch_clk_reset(BCR_REG(vclk), action);
}
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index ef9b62a..1382632 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -850,6 +850,22 @@
},
};
+#define SHARED_IMEM_TZ_BASE 0x2a03f720
+static struct resource tzlog_resources[] = {
+ {
+ .start = SHARED_IMEM_TZ_BASE,
+ .end = SHARED_IMEM_TZ_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device apq_device_tz_log = {
+ .name = "tz_log",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(tzlog_resources),
+ .resource = tzlog_resources,
+};
+
/* MSM Video core device */
#ifdef CONFIG_MSM_BUS_SCALING
static struct msm_bus_vectors vidc_init_vectors[] = {
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index f8ab18a..f180aa5 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -401,3 +401,5 @@
extern struct platform_device copper_device_tz_log;
extern struct platform_device mdm_sglte_device;
+
+extern struct platform_device apq_device_tz_log;
diff --git a/drivers/bluetooth/hci_smd.c b/drivers/bluetooth/hci_smd.c
index 8f51e2d..18cef72 100644
--- a/drivers/bluetooth/hci_smd.c
+++ b/drivers/bluetooth/hci_smd.c
@@ -22,6 +22,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
+#include <linux/semaphore.h>
#include <linux/string.h>
#include <linux/skbuff.h>
#include <linux/wakelock.h>
@@ -43,7 +44,9 @@
static int hcismd_set;
-static DEFINE_MUTEX(hci_smd_enable);
+static DEFINE_SEMAPHORE(hci_smd_enable);
+
+static int restart_in_progress;
static int hcismd_set_enable(const char *val, struct kernel_param *kp);
module_param_call(hcismd_set, hcismd_set_enable, NULL, &hcismd_set, 0644);
@@ -496,18 +499,24 @@
static void hci_dev_restart(struct work_struct *worker)
{
- mutex_lock(&hci_smd_enable);
+ down(&hci_smd_enable);
+ restart_in_progress = 1;
hci_smd_deregister_dev(&hs);
hci_smd_register_smd(&hs);
- mutex_unlock(&hci_smd_enable);
+ up(&hci_smd_enable);
kfree(worker);
}
static void hci_dev_smd_open(struct work_struct *worker)
{
- mutex_lock(&hci_smd_enable);
+ down(&hci_smd_enable);
+ if (restart_in_progress == 1) {
+ /* Allow wcnss to initialize */
+ restart_in_progress = 0;
+ msleep(10000);
+ }
hci_smd_hci_register_dev(&hs);
- mutex_unlock(&hci_smd_enable);
+ up(&hci_smd_enable);
kfree(worker);
}
@@ -515,7 +524,9 @@
{
int ret = 0;
- mutex_lock(&hci_smd_enable);
+ pr_err("hcismd_set_enable %d", hcismd_set);
+
+ down(&hci_smd_enable);
ret = param_set_int(val, kp);
@@ -525,7 +536,8 @@
switch (hcismd_set) {
case 1:
- hci_smd_register_smd(&hs);
+ if (hs.hdev == NULL)
+ hci_smd_register_smd(&hs);
break;
case 0:
hci_smd_deregister_dev(&hs);
@@ -535,7 +547,7 @@
}
done:
- mutex_unlock(&hci_smd_enable);
+ up(&hci_smd_enable);
return ret;
}
static int __init hci_smd_init(void)
@@ -544,6 +556,8 @@
"msm_smd_Rx");
wake_lock_init(&hs.wake_lock_tx, WAKE_LOCK_SUSPEND,
"msm_smd_Tx");
+ restart_in_progress = 0;
+ hs.hdev = NULL;
return 0;
}
module_init(hci_smd_init);
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index fff494c..2a191d5 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -352,7 +352,7 @@
}
kzfree(handle);
file->private_data = NULL;
- if (podev->platform_support.bus_scale_table != NULL)
+ if (podev != NULL && podev->platform_support.bus_scale_table != NULL)
qcedev_ce_high_bw_req(podev, false);
return 0;
}
diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c
index 21c3aff..63dfc2d 100644
--- a/drivers/crypto/msm/qcrypto.c
+++ b/drivers/crypto/msm/qcrypto.c
@@ -888,7 +888,7 @@
ctx->authsize, 1);
} else {
- unsigned char tmp[SHA256_DIGESTSIZE];
+ unsigned char tmp[SHA256_DIGESTSIZE] = {0};
/* compare icv from src */
scatterwalk_map_and_copy(tmp,
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index b60f99f..e4d4081 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -11,8 +11,9 @@
EXTRA_CFLAGS += -Idrivers/media/video/msm/eeprom
EXTRA_CFLAGS += -Idrivers/media/video/msm/sensors
EXTRA_CFLAGS += -Idrivers/media/video/msm/actuators
+ EXTRA_CFLAGS += -Idrivers/media/video/msm/server
obj-$(CONFIG_MSM_CAMERA) += msm_isp.o msm.o msm_mem.o msm_mctl.o msm_mctl_buf.o msm_mctl_pp.o
- obj-$(CONFIG_MSM_CAMERA) += io/ eeprom/ sensors/ actuators/ csi/
+ obj-$(CONFIG_MSM_CAMERA) += server/ eeprom/ sensors/ actuators/ csi/
obj-$(CONFIG_MSM_CAMERA) += msm_gesture.o
else
obj-$(CONFIG_MSM_CAMERA) += msm_camera.o
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
index c04ece2..111d878 100644
--- a/drivers/media/video/msm/csi/msm_csid.c
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -107,6 +107,8 @@
void __iomem *csidbase;
csid_dev = v4l2_get_subdevdata(cfg_params->subdev);
csidbase = csid_dev->base;
+ if (csidbase == NULL)
+ return -ENOMEM;
csid_params = cfg_params->parms;
val = csid_params->lane_cnt - 1;
diff --git a/drivers/media/video/msm/csi/msm_csiphy.c b/drivers/media/video/msm/csi/msm_csiphy.c
index 7c59ae8..df01c6b 100644
--- a/drivers/media/video/msm/csi/msm_csiphy.c
+++ b/drivers/media/video/msm/csi/msm_csiphy.c
@@ -68,6 +68,9 @@
void __iomem *csiphybase;
csiphy_dev = v4l2_get_subdevdata(cfg_params->subdev);
csiphybase = csiphy_dev->base;
+ if (csiphybase == NULL)
+ return -ENOMEM;
+
csiphy_params = cfg_params->parms;
lane_mask = csiphy_params->lane_mask;
lane_cnt = csiphy_params->lane_cnt;
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 347321c..0696b96 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -19,13 +19,9 @@
#include <linux/spinlock.h>
#include <linux/proc_fs.h>
#include "msm.h"
-#include "msm_csid.h"
-#include "msm_csic.h"
-#include "msm_csiphy.h"
-#include "msm_ispif.h"
+#include "msm_cam_server.h"
#include "msm_sensor.h"
#include "msm_actuator.h"
-#include "msm_vfe32.h"
#include "msm_camera_eeprom.h"
#define MSM_MAX_CAMERA_SENSORS 5
@@ -37,111 +33,11 @@
#endif
static unsigned msm_camera_v4l2_nr = -1;
-static struct msm_cam_server_dev g_server_dev;
-static struct class *msm_class;
-static dev_t msm_devno;
static int vnode_count;
module_param(msm_camera_v4l2_nr, uint, 0644);
MODULE_PARM_DESC(msm_camera_v4l2_nr, "videoX start number, -1 is autodetect");
-static long msm_server_send_v4l2_evt(void *evt);
-static void msm_cam_server_subdev_notify(struct v4l2_subdev *sd,
- unsigned int notification, void *arg);
-
-static void msm_queue_init(struct msm_device_queue *queue, const char *name)
-{
- D("%s\n", __func__);
- spin_lock_init(&queue->lock);
- queue->len = 0;
- queue->max = 0;
- queue->name = name;
- INIT_LIST_HEAD(&queue->list);
- init_waitqueue_head(&queue->wait);
-}
-
-static void msm_enqueue(struct msm_device_queue *queue,
- struct list_head *entry)
-{
- unsigned long flags;
- spin_lock_irqsave(&queue->lock, flags);
- queue->len++;
- if (queue->len > queue->max) {
- queue->max = queue->len;
- pr_info("%s: queue %s new max is %d\n", __func__,
- queue->name, queue->max);
- }
- list_add_tail(entry, &queue->list);
- wake_up(&queue->wait);
- D("%s: woke up %s\n", __func__, queue->name);
- spin_unlock_irqrestore(&queue->lock, flags);
-}
-
-static void msm_drain_eventq(struct msm_device_queue *queue)
-{
- unsigned long flags;
- struct msm_queue_cmd *qcmd;
- spin_lock_irqsave(&queue->lock, flags);
- while (!list_empty(&queue->list)) {
- qcmd = list_first_entry(&queue->list,
- struct msm_queue_cmd, list_eventdata);
- list_del_init(&qcmd->list_eventdata);
- kfree(qcmd->command);
- free_qcmd(qcmd);
- }
- spin_unlock_irqrestore(&queue->lock, flags);
-}
-
-static int32_t msm_find_free_queue(void)
-{
- int i;
- for (i = 0; i < MAX_NUM_ACTIVE_CAMERA; i++) {
- struct msm_cam_server_queue *queue;
- queue = &g_server_dev.server_queue[i];
- if (!queue->queue_active)
- return i;
- }
- return -EINVAL;
-}
-
-uint32_t msm_camera_get_mctl_handle(void)
-{
- uint32_t i;
- if ((g_server_dev.mctl_handle_cnt << 8) == 0)
- g_server_dev.mctl_handle_cnt++;
- for (i = 0; i < MAX_NUM_ACTIVE_CAMERA; i++) {
- if (g_server_dev.mctl[i].handle == 0) {
- g_server_dev.mctl[i].handle =
- (++g_server_dev.mctl_handle_cnt) << 8 | i;
- memset(&g_server_dev.mctl[i].mctl,
- 0, sizeof(g_server_dev.mctl[i].mctl));
- return g_server_dev.mctl[i].handle;
- }
- }
- return 0;
-}
-
-struct msm_cam_media_controller *msm_camera_get_mctl(uint32_t handle)
-{
- uint32_t mctl_index;
- mctl_index = handle & 0xff;
- if ((mctl_index < MAX_NUM_ACTIVE_CAMERA) &&
- (g_server_dev.mctl[mctl_index].handle == handle))
- return &g_server_dev.mctl[mctl_index].mctl;
- return NULL;
-}
-
-void msm_camera_free_mctl(uint32_t handle)
-{
- uint32_t mctl_index;
- mctl_index = handle & 0xff;
- if ((mctl_index < MAX_NUM_ACTIVE_CAMERA) &&
- (g_server_dev.mctl[mctl_index].handle == handle))
- g_server_dev.mctl[mctl_index].handle = 0;
- else
- pr_err("%s: invalid free handle\n", __func__);
-}
-
/* callback function from all subdevices of a msm_cam_v4l2_device */
static void msm_cam_v4l2_subdev_notify(struct v4l2_subdev *sd,
unsigned int notification, void *arg)
@@ -157,663 +53,11 @@
if (pcam == NULL)
return;
- pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
if (pmctl == NULL)
return;
}
-static int msm_ctrl_cmd_done(void *arg)
-{
- void __user *uptr;
- struct msm_queue_cmd *qcmd;
- struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg;
- struct msm_ctrl_cmd *command =
- kzalloc(sizeof(struct msm_ctrl_cmd), GFP_KERNEL);
- if (!command) {
- pr_err("%s Insufficient memory. return", __func__);
- return -ENOMEM;
- }
-
- D("%s\n", __func__);
- if (copy_from_user(command, (void __user *)ioctl_ptr->ioctl_ptr,
- sizeof(struct msm_ctrl_cmd))) {
- pr_err("%s: copy_from_user failed, size=%d\n",
- __func__, sizeof(struct msm_ctrl_cmd));
- return -EINVAL;
- }
-
- D("%s qid %d evtid %d %d\n", __func__, command->queue_idx,
- command->evt_id,
- g_server_dev.server_queue[command->queue_idx].evt_id);
- g_server_dev.server_queue[command->queue_idx].ctrl = command;
- if (command->evt_id !=
- g_server_dev.server_queue[command->queue_idx].evt_id) {
- pr_err("%s Invalid event id from userspace cmd id %d %d qid %d\n",
- __func__, command->evt_id,
- g_server_dev.server_queue[command->queue_idx].evt_id,
- command->queue_idx);
- return -EINVAL;
- }
-
- mutex_lock(&g_server_dev.server_queue_lock);
- qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_KERNEL);
- atomic_set(&qcmd->on_heap, 1);
- uptr = command->value;
- qcmd->command = command;
-
- if (command->length > 0) {
- command->value =
- g_server_dev.server_queue[command->queue_idx].ctrl_data;
- if (command->length > max_control_command_size) {
- pr_err("%s: user data %d is too big (max %d)\n",
- __func__, command->length,
- max_control_command_size);
- free_qcmd(qcmd);
- return -EINVAL;
- }
- if (copy_from_user(command->value, uptr, command->length)) {
- free_qcmd(qcmd);
- return -EINVAL;
- }
- }
- msm_enqueue(&g_server_dev.server_queue
- [command->queue_idx].ctrl_q, &qcmd->list_control);
- mutex_unlock(&g_server_dev.server_queue_lock);
- return 0;
-}
-
-/* send control command to config and wait for results*/
-static int msm_server_control(struct msm_cam_server_dev *server_dev,
- struct msm_ctrl_cmd *out)
-{
- int rc = 0;
- void *value;
- struct msm_queue_cmd *rcmd;
- struct msm_queue_cmd *event_qcmd;
- struct msm_ctrl_cmd *ctrlcmd;
- struct msm_device_queue *queue =
- &server_dev->server_queue[out->queue_idx].ctrl_q;
-
- struct v4l2_event v4l2_evt;
- struct msm_isp_event_ctrl *isp_event;
- isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl), GFP_KERNEL);
- if (!isp_event) {
- pr_err("%s Insufficient memory. return", __func__);
- return -ENOMEM;
- }
- event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_KERNEL);
- if (!event_qcmd) {
- pr_err("%s Insufficient memory. return", __func__);
- return -ENOMEM;
- }
-
- D("%s\n", __func__);
- mutex_lock(&server_dev->server_queue_lock);
- if (++server_dev->server_evt_id == 0)
- server_dev->server_evt_id++;
- D("%s qid %d evtid %d\n", __func__, out->queue_idx,
- server_dev->server_evt_id);
-
- server_dev->server_queue[out->queue_idx].evt_id =
- server_dev->server_evt_id;
- v4l2_evt.type = V4L2_EVENT_PRIVATE_START + MSM_CAM_RESP_V4L2;
- v4l2_evt.u.data[0] = out->queue_idx;
- /* setup event object to transfer the command; */
- isp_event->resptype = MSM_CAM_RESP_V4L2;
- isp_event->isp_data.ctrl = *out;
- isp_event->isp_data.ctrl.evt_id = server_dev->server_evt_id;
-
- atomic_set(&event_qcmd->on_heap, 1);
- event_qcmd->command = isp_event;
-
- msm_enqueue(&server_dev->server_queue[out->queue_idx].eventData_q,
- &event_qcmd->list_eventdata);
-
- /* now send command to config thread in userspace,
- * and wait for results */
- v4l2_event_queue(server_dev->server_command_queue.pvdev,
- &v4l2_evt);
- D("%s v4l2_event_queue: type = 0x%x\n", __func__, v4l2_evt.type);
- mutex_unlock(&server_dev->server_queue_lock);
-
- /* wait for config return status */
- D("Waiting for config status\n");
- rc = wait_event_interruptible_timeout(queue->wait,
- !list_empty_careful(&queue->list),
- msecs_to_jiffies(out->timeout_ms));
- D("Waiting is over for config status\n");
- if (list_empty_careful(&queue->list)) {
- if (!rc)
- rc = -ETIMEDOUT;
- if (rc < 0) {
- kfree(isp_event);
- pr_err("%s: wait_event error %d\n", __func__, rc);
- return rc;
- }
- }
-
- rcmd = msm_dequeue(queue, list_control);
- BUG_ON(!rcmd);
- D("%s Finished servicing ioctl\n", __func__);
-
- ctrlcmd = (struct msm_ctrl_cmd *)(rcmd->command);
- value = out->value;
- if (ctrlcmd->length > 0 && value != NULL &&
- ctrlcmd->length <= out->length)
- memcpy(value, ctrlcmd->value, ctrlcmd->length);
-
- memcpy(out, ctrlcmd, sizeof(struct msm_ctrl_cmd));
- out->value = value;
-
- kfree(ctrlcmd);
- server_dev->server_queue[out->queue_idx].ctrl = NULL;
-
- free_qcmd(rcmd);
- kfree(isp_event);
- D("%s: rc %d\n", __func__, rc);
- /* rc is the time elapsed. */
- if (rc >= 0) {
- /* TODO: Refactor msm_ctrl_cmd::status field */
- if (out->status == 0)
- rc = -1;
- else if (out->status == 1 || out->status == 4)
- rc = 0;
- else
- rc = -EINVAL;
- }
- return rc;
-}
-
-/*send open command to server*/
-static int msm_send_open_server(struct msm_cam_v4l2_device *pcam)
-{
- int rc = 0;
- struct msm_ctrl_cmd ctrlcmd;
- D("%s qid %d\n", __func__, pcam->server_queue_idx);
- ctrlcmd.type = MSM_V4L2_OPEN;
- ctrlcmd.timeout_ms = 10000;
- ctrlcmd.length = strnlen(g_server_dev.config_info.config_dev_name[0],
- MAX_DEV_NAME_LEN)+1;
- ctrlcmd.value = (char *)g_server_dev.config_info.config_dev_name[0];
- ctrlcmd.vnode_id = pcam->vnode_id;
- ctrlcmd.queue_idx = pcam->server_queue_idx;
- ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
-
- /* send command to config thread in usersspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
-
- return rc;
-}
-
-static int msm_send_close_server(struct msm_cam_v4l2_device *pcam)
-{
- int rc = 0;
- struct msm_ctrl_cmd ctrlcmd;
- D("%s qid %d\n", __func__, pcam->server_queue_idx);
- ctrlcmd.type = MSM_V4L2_CLOSE;
- ctrlcmd.timeout_ms = 10000;
- ctrlcmd.length = strnlen(g_server_dev.config_info.config_dev_name[0],
- MAX_DEV_NAME_LEN)+1;
- ctrlcmd.value = (char *)g_server_dev.config_info.config_dev_name[0];
- ctrlcmd.vnode_id = pcam->vnode_id;
- ctrlcmd.queue_idx = pcam->server_queue_idx;
- ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
-
- /* send command to config thread in usersspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
-
- return rc;
-}
-
-static int msm_server_set_fmt(struct msm_cam_v4l2_device *pcam, int idx,
- struct v4l2_format *pfmt)
-{
- int rc = 0;
- int i = 0;
- struct v4l2_pix_format *pix = &pfmt->fmt.pix;
- struct msm_ctrl_cmd ctrlcmd;
- struct img_plane_info plane_info;
-
- plane_info.width = pix->width;
- plane_info.height = pix->height;
- plane_info.pixelformat = pix->pixelformat;
- plane_info.buffer_type = pfmt->type;
- plane_info.ext_mode = pcam->dev_inst[idx]->image_mode;
- plane_info.num_planes = 1;
- D("%s: %d, %d, 0x%x\n", __func__,
- pfmt->fmt.pix.width, pfmt->fmt.pix.height,
- pfmt->fmt.pix.pixelformat);
-
- if (pfmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- D("%s, Attention! Wrong buf-type %d\n", __func__, pfmt->type);
-
- for (i = 0; i < pcam->num_fmts; i++)
- if (pcam->usr_fmts[i].fourcc == pix->pixelformat)
- break;
- if (i == pcam->num_fmts) {
- pr_err("%s: User requested pixelformat %x not supported\n",
- __func__, pix->pixelformat);
- return -EINVAL;
- }
-
- ctrlcmd.type = MSM_V4L2_VID_CAP_TYPE;
- ctrlcmd.length = sizeof(struct img_plane_info);
- ctrlcmd.value = (void *)&plane_info;
- ctrlcmd.timeout_ms = 10000;
- ctrlcmd.vnode_id = pcam->vnode_id;
- ctrlcmd.queue_idx = pcam->server_queue_idx;
- ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
-
- /* send command to config thread in usersspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
-
- if (rc >= 0) {
- pcam->dev_inst[idx]->vid_fmt = *pfmt;
- pcam->dev_inst[idx]->sensor_pxlcode
- = pcam->usr_fmts[i].pxlcode;
- D("%s:inst=0x%x,idx=%d,width=%d,heigth=%d\n",
- __func__, (u32)pcam->dev_inst[idx], idx,
- pcam->dev_inst[idx]->vid_fmt.fmt.pix.width,
- pcam->dev_inst[idx]->vid_fmt.fmt.pix.height);
- pcam->dev_inst[idx]->plane_info = plane_info;
- }
-
- return rc;
-}
-
-static int msm_server_set_fmt_mplane(struct msm_cam_v4l2_device *pcam, int idx,
- struct v4l2_format *pfmt)
-{
- int rc = 0;
- int i = 0;
- struct v4l2_pix_format_mplane *pix_mp = &pfmt->fmt.pix_mp;
- struct msm_ctrl_cmd ctrlcmd;
- struct img_plane_info plane_info;
-
- plane_info.width = pix_mp->width;
- plane_info.height = pix_mp->height;
- plane_info.pixelformat = pix_mp->pixelformat;
- plane_info.buffer_type = pfmt->type;
- plane_info.ext_mode = pcam->dev_inst[idx]->image_mode;
- plane_info.num_planes = pix_mp->num_planes;
- if (plane_info.num_planes <= 0 ||
- plane_info.num_planes > VIDEO_MAX_PLANES) {
- pr_err("%s Invalid number of planes set %d", __func__,
- plane_info.num_planes);
- return -EINVAL;
- }
- D("%s: %d, %d, 0x%x\n", __func__,
- pfmt->fmt.pix_mp.width, pfmt->fmt.pix_mp.height,
- pfmt->fmt.pix_mp.pixelformat);
-
- if (pfmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- pr_err("%s, Attention! Wrong buf-type %d\n",
- __func__, pfmt->type);
- return -EINVAL;
- }
-
- for (i = 0; i < pcam->num_fmts; i++)
- if (pcam->usr_fmts[i].fourcc == pix_mp->pixelformat)
- break;
- if (i == pcam->num_fmts) {
- pr_err("%s: User requested pixelformat %x not supported\n",
- __func__, pix_mp->pixelformat);
- return -EINVAL;
- }
-
- ctrlcmd.type = MSM_V4L2_VID_CAP_TYPE;
- ctrlcmd.length = sizeof(struct img_plane_info);
- ctrlcmd.value = (void *)&plane_info;
- ctrlcmd.timeout_ms = 10000;
- ctrlcmd.vnode_id = pcam->vnode_id;
- ctrlcmd.queue_idx = pcam->server_queue_idx;
-
- /* send command to config thread in usersspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
- if (rc >= 0) {
- pcam->dev_inst[idx]->vid_fmt = *pfmt;
- pcam->dev_inst[idx]->sensor_pxlcode
- = pcam->usr_fmts[i].pxlcode;
- D("%s:inst=0x%x,idx=%d,width=%d,heigth=%d\n",
- __func__, (u32)pcam->dev_inst[idx], idx,
- pcam->dev_inst[idx]->vid_fmt.fmt.pix_mp.width,
- pcam->dev_inst[idx]->vid_fmt.fmt.pix_mp.height);
- pcam->dev_inst[idx]->plane_info = plane_info;
- }
-
- return rc;
-}
-
-static int msm_server_streamon(struct msm_cam_v4l2_device *pcam, int idx)
-{
- int rc = 0;
- struct msm_ctrl_cmd ctrlcmd;
- D("%s\n", __func__);
- ctrlcmd.type = MSM_V4L2_STREAM_ON;
- ctrlcmd.timeout_ms = 10000;
- ctrlcmd.length = 0;
- ctrlcmd.value = NULL;
- ctrlcmd.stream_type = pcam->dev_inst[idx]->image_mode;
- ctrlcmd.vnode_id = pcam->vnode_id;
- ctrlcmd.queue_idx = pcam->server_queue_idx;
- ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
-
-
- /* send command to config thread in usersspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
-
- return rc;
-}
-
-static int msm_server_streamoff(struct msm_cam_v4l2_device *pcam, int idx)
-{
- int rc = 0;
- struct msm_ctrl_cmd ctrlcmd;
-
- D("%s, pcam = 0x%x\n", __func__, (u32)pcam);
- ctrlcmd.type = MSM_V4L2_STREAM_OFF;
- ctrlcmd.timeout_ms = 10000;
- ctrlcmd.length = 0;
- ctrlcmd.value = NULL;
- ctrlcmd.stream_type = pcam->dev_inst[idx]->image_mode;
- ctrlcmd.vnode_id = pcam->vnode_id;
- ctrlcmd.queue_idx = pcam->server_queue_idx;
- ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
-
- /* send command to config thread in usersspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
-
- return rc;
-}
-
-static int msm_server_proc_ctrl_cmd(struct msm_cam_v4l2_device *pcam,
- struct v4l2_control *ctrl, int is_set_cmd)
-{
- int rc = 0;
- struct msm_ctrl_cmd ctrlcmd, *tmp_cmd;
- uint8_t *ctrl_data = NULL;
- void __user *uptr_cmd;
- void __user *uptr_value;
- uint32_t cmd_len = sizeof(struct msm_ctrl_cmd);
- uint32_t value_len;
-
- tmp_cmd = (struct msm_ctrl_cmd *)ctrl->value;
- uptr_cmd = (void __user *)ctrl->value;
- uptr_value = (void __user *)tmp_cmd->value;
- value_len = tmp_cmd->length;
-
- D("%s: cmd type = %d, up1=0x%x, ulen1=%d, up2=0x%x, ulen2=%d\n",
- __func__, tmp_cmd->type, (uint32_t)uptr_cmd, cmd_len,
- (uint32_t)uptr_value, tmp_cmd->length);
-
- ctrl_data = kzalloc(value_len+cmd_len, GFP_KERNEL);
- if (ctrl_data == 0) {
- pr_err("%s could not allocate memory\n", __func__);
- rc = -ENOMEM;
- goto end;
- }
- tmp_cmd = (struct msm_ctrl_cmd *)ctrl_data;
- if (copy_from_user((void *)ctrl_data, uptr_cmd,
- cmd_len)) {
- pr_err("%s: copy_from_user failed.\n", __func__);
- rc = -EINVAL;
- goto end;
- }
- tmp_cmd->value = (void *)(ctrl_data+cmd_len);
- if (uptr_value && tmp_cmd->length > 0) {
- if (copy_from_user((void *)tmp_cmd->value, uptr_value,
- value_len)) {
- pr_err("%s: copy_from_user failed, size=%d\n",
- __func__, value_len);
- rc = -EINVAL;
- goto end;
- }
- } else
- tmp_cmd->value = NULL;
-
- ctrlcmd.type = MSM_V4L2_SET_CTRL_CMD;
- ctrlcmd.length = cmd_len + value_len;
- ctrlcmd.value = (void *)ctrl_data;
- if (tmp_cmd->timeout_ms > 0)
- ctrlcmd.timeout_ms = tmp_cmd->timeout_ms;
- else
- ctrlcmd.timeout_ms = 1000;
- ctrlcmd.vnode_id = pcam->vnode_id;
- ctrlcmd.queue_idx = pcam->server_queue_idx;
- ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
- /* send command to config thread in usersspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
- D("%s: msm_server_control rc=%d\n", __func__, rc);
- if (rc == 0) {
- if (uptr_value && tmp_cmd->length > 0 &&
- copy_to_user((void __user *)uptr_value,
- (void *)(ctrl_data+cmd_len), tmp_cmd->length)) {
- pr_err("%s: copy_to_user failed, size=%d\n",
- __func__, tmp_cmd->length);
- rc = -EINVAL;
- goto end;
- }
- tmp_cmd->value = uptr_value;
- if (copy_to_user((void __user *)uptr_cmd,
- (void *)tmp_cmd, cmd_len)) {
- pr_err("%s: copy_to_user failed in cpy, size=%d\n",
- __func__, cmd_len);
- rc = -EINVAL;
- goto end;
- }
- }
-end:
- D("%s: END, type = %d, vaddr = 0x%x, vlen = %d, status = %d, rc = %d\n",
- __func__, tmp_cmd->type, (uint32_t)tmp_cmd->value,
- tmp_cmd->length, tmp_cmd->status, rc);
- kfree(ctrl_data);
- return rc;
-}
-
-static int msm_server_s_ctrl(struct msm_cam_v4l2_device *pcam,
- struct v4l2_control *ctrl)
-{
- int rc = 0;
- struct msm_ctrl_cmd ctrlcmd;
- uint8_t ctrl_data[max_control_command_size];
-
- WARN_ON(ctrl == NULL);
- if (ctrl == NULL) {
- pr_err("%s Invalid control\n", __func__);
- return -EINVAL;
- }
- if (ctrl->id == MSM_V4L2_PID_CTRL_CMD)
- return msm_server_proc_ctrl_cmd(pcam, ctrl, 1);
-
- memset(ctrl_data, 0, sizeof(ctrl_data));
-
- ctrlcmd.type = MSM_V4L2_SET_CTRL;
- ctrlcmd.length = sizeof(struct v4l2_control);
- ctrlcmd.value = (void *)ctrl_data;
- memcpy(ctrlcmd.value, ctrl, ctrlcmd.length);
- ctrlcmd.timeout_ms = 1000;
- ctrlcmd.vnode_id = pcam->vnode_id;
- ctrlcmd.queue_idx = pcam->server_queue_idx;
- ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
-
- /* send command to config thread in usersspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
-
- return rc;
-}
-
-static int msm_server_g_ctrl(struct msm_cam_v4l2_device *pcam,
- struct v4l2_control *ctrl)
-{
- int rc = 0;
- struct msm_ctrl_cmd ctrlcmd;
- uint8_t ctrl_data[max_control_command_size];
-
- WARN_ON(ctrl == NULL);
- if (ctrl == NULL) {
- pr_err("%s Invalid control\n", __func__);
- return -EINVAL;
- }
- if (ctrl->id == MSM_V4L2_PID_CTRL_CMD)
- return msm_server_proc_ctrl_cmd(pcam, ctrl, 0);
-
- memset(ctrl_data, 0, sizeof(ctrl_data));
-
- ctrlcmd.type = MSM_V4L2_GET_CTRL;
- ctrlcmd.length = sizeof(struct v4l2_control);
- ctrlcmd.value = (void *)ctrl_data;
- memcpy(ctrlcmd.value, ctrl, ctrlcmd.length);
- ctrlcmd.timeout_ms = 1000;
- ctrlcmd.vnode_id = pcam->vnode_id;
- ctrlcmd.queue_idx = pcam->server_queue_idx;
- ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
-
- /* send command to config thread in usersspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
-
- ctrl->value = ((struct v4l2_control *)ctrlcmd.value)->value;
-
- return rc;
-}
-
-static int msm_server_q_ctrl(struct msm_cam_v4l2_device *pcam,
- struct v4l2_queryctrl *queryctrl)
-{
- int rc = 0;
- struct msm_ctrl_cmd ctrlcmd;
- uint8_t ctrl_data[max_control_command_size];
-
- WARN_ON(queryctrl == NULL);
- memset(ctrl_data, 0, sizeof(ctrl_data));
-
- ctrlcmd.type = MSM_V4L2_QUERY_CTRL;
- ctrlcmd.length = sizeof(struct v4l2_queryctrl);
- ctrlcmd.value = (void *)ctrl_data;
- memcpy(ctrlcmd.value, queryctrl, ctrlcmd.length);
- ctrlcmd.timeout_ms = 1000;
- ctrlcmd.vnode_id = pcam->vnode_id;
- ctrlcmd.queue_idx = pcam->server_queue_idx;
- ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
-
- /* send command to config thread in userspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
- D("%s: rc = %d\n", __func__, rc);
-
- if (rc >= 0)
- memcpy(queryctrl, ctrlcmd.value, sizeof(struct v4l2_queryctrl));
-
- return rc;
-}
-
-static int msm_server_get_fmt(struct msm_cam_v4l2_device *pcam,
- int idx, struct v4l2_format *pfmt)
-{
- struct v4l2_pix_format *pix = &pfmt->fmt.pix;
-
- pix->width = pcam->dev_inst[idx]->vid_fmt.fmt.pix.width;
- pix->height = pcam->dev_inst[idx]->vid_fmt.fmt.pix.height;
- pix->field = pcam->dev_inst[idx]->vid_fmt.fmt.pix.field;
- pix->pixelformat = pcam->dev_inst[idx]->vid_fmt.fmt.pix.pixelformat;
- pix->bytesperline = pcam->dev_inst[idx]->vid_fmt.fmt.pix.bytesperline;
- pix->colorspace = pcam->dev_inst[idx]->vid_fmt.fmt.pix.colorspace;
- if (pix->bytesperline < 0)
- return pix->bytesperline;
-
- pix->sizeimage = pix->height * pix->bytesperline;
-
- return 0;
-}
-
-static int msm_server_get_fmt_mplane(struct msm_cam_v4l2_device *pcam,
- int idx, struct v4l2_format *pfmt)
-{
- *pfmt = pcam->dev_inst[idx]->vid_fmt;
- return 0;
-}
-
-static int msm_server_try_fmt(struct msm_cam_v4l2_device *pcam,
- struct v4l2_format *pfmt)
-{
- int rc = 0;
- int i = 0;
- struct v4l2_pix_format *pix = &pfmt->fmt.pix;
-
- D("%s: 0x%x\n", __func__, pix->pixelformat);
- if (pfmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- pr_err("%s: pfmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE!\n",
- __func__);
- return -EINVAL;
- }
-
- /* check if the format is supported by this host-sensor combo */
- for (i = 0; i < pcam->num_fmts; i++) {
- D("%s: usr_fmts.fourcc: 0x%x\n", __func__,
- pcam->usr_fmts[i].fourcc);
- if (pcam->usr_fmts[i].fourcc == pix->pixelformat)
- break;
- }
-
- if (i == pcam->num_fmts) {
- pr_err("%s: Format %x not found\n", __func__, pix->pixelformat);
- return -EINVAL;
- }
- return rc;
-}
-
-static int msm_server_try_fmt_mplane(struct msm_cam_v4l2_device *pcam,
- struct v4l2_format *pfmt)
-{
- int rc = 0;
- int i = 0;
- struct v4l2_pix_format_mplane *pix_mp = &pfmt->fmt.pix_mp;
-
- D("%s: 0x%x\n", __func__, pix_mp->pixelformat);
- if (pfmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- pr_err("%s: Incorrect format type %d ",
- __func__, pfmt->type);
- return -EINVAL;
- }
-
- /* check if the format is supported by this host-sensor combo */
- for (i = 0; i < pcam->num_fmts; i++) {
- D("%s: usr_fmts.fourcc: 0x%x\n", __func__,
- pcam->usr_fmts[i].fourcc);
- if (pcam->usr_fmts[i].fourcc == pix_mp->pixelformat)
- break;
- }
-
- if (i == pcam->num_fmts) {
- pr_err("%s: Format %x not found\n",
- __func__, pix_mp->pixelformat);
- return -EINVAL;
- }
- return rc;
-}
-
-static int msm_camera_get_crop(struct msm_cam_v4l2_device *pcam,
- int idx, struct v4l2_crop *crop)
-{
- int rc = 0;
- struct msm_ctrl_cmd ctrlcmd;
-
- BUG_ON(crop == NULL);
-
- ctrlcmd.type = MSM_V4L2_GET_CROP;
- ctrlcmd.length = sizeof(struct v4l2_crop);
- ctrlcmd.value = (void *)crop;
- ctrlcmd.timeout_ms = 1000;
- ctrlcmd.vnode_id = pcam->vnode_id;
- ctrlcmd.queue_idx = pcam->server_queue_idx;
- ctrlcmd.stream_type = pcam->dev_inst[idx]->image_mode;
- ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
-
- /* send command to config thread in userspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
- D("%s: rc = %d\n", __func__, rc);
-
- return rc;
-}
-
/*
*
* implementation of v4l2_ioctl_ops
@@ -1115,7 +359,7 @@
not in use when we free the buffers */
mutex_lock(&pcam->vid_lock);
pcam_inst->streamon = 0;
- if (g_server_dev.use_count > 0)
+ if (msm_server_get_usecount() > 0)
rc = msm_server_streamoff(pcam, pcam_inst->my_index);
mutex_unlock(&pcam->vid_lock);
if (rc < 0)
@@ -1259,7 +503,7 @@
(void *)pfmt->fmt.pix.priv);
WARN_ON(pctx != f->private_data);
- pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
if (pmctl == NULL)
return -EINVAL;
@@ -1294,7 +538,7 @@
D("%s Inst %p\n", __func__, pcam_inst);
WARN_ON(pctx != f->private_data);
- pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
if (pmctl == NULL)
return -EINVAL;
@@ -1347,7 +591,7 @@
WARN_ON(pctx != f->private_data);
mutex_lock(&pcam->vid_lock);
- rc = msm_camera_get_crop(pcam, pcam_inst->my_index, crop);
+ rc = msm_server_get_crop(pcam, pcam_inst->my_index, crop);
mutex_unlock(&pcam->vid_lock);
return rc;
}
@@ -1440,55 +684,6 @@
return rc;
}
-static int msm_server_v4l2_subscribe_event(struct v4l2_fh *fh,
- struct v4l2_event_subscription *sub)
-{
- int rc = 0;
-
- D("%s: fh = 0x%x, type = 0x%x", __func__, (u32)fh, sub->type);
- if (sub->type == V4L2_EVENT_ALL) {
- /*sub->type = MSM_ISP_EVENT_START;*/
- sub->type = V4L2_EVENT_PRIVATE_START + MSM_CAM_RESP_CTRL;
- D("sub->type start = 0x%x\n", sub->type);
- do {
- rc = v4l2_event_subscribe(fh, sub);
- if (rc < 0) {
- D("%s: failed for evtType = 0x%x, rc = %d\n",
- __func__, sub->type, rc);
- /* unsubscribe all events here and return */
- sub->type = V4L2_EVENT_ALL;
- v4l2_event_unsubscribe(fh, sub);
- return rc;
- } else
- D("%s: subscribed evtType = 0x%x, rc = %d\n",
- __func__, sub->type, rc);
- sub->type++;
- D("sub->type while = 0x%x\n", sub->type);
- } while (sub->type !=
- V4L2_EVENT_PRIVATE_START + MSM_SVR_RESP_MAX);
- } else {
- D("sub->type not V4L2_EVENT_ALL = 0x%x\n", sub->type);
- rc = v4l2_event_subscribe(fh, sub);
- if (rc < 0)
- D("%s: failed for evtType = 0x%x, rc = %d\n",
- __func__, sub->type, rc);
- }
-
- D("%s: rc = %d\n", __func__, rc);
- return rc;
-}
-
-static int msm_server_v4l2_unsubscribe_event(struct v4l2_fh *fh,
- struct v4l2_event_subscription *sub)
-{
- int rc = 0;
-
- D("%s: fh = 0x%x\n", __func__, (u32)fh);
- rc = v4l2_event_unsubscribe(fh, sub);
- D("%s: rc = %d\n", __func__, rc);
- return rc;
-}
-
/* v4l2_ioctl_ops */
static const struct v4l2_ioctl_ops g_msm_ioctl_ops = {
.vidioc_querycap = msm_camera_v4l2_querycap,
@@ -1530,213 +725,10 @@
.vidioc_unsubscribe_event = msm_camera_v4l2_unsubscribe_event,
};
-/* open an active camera session to manage the streaming logic */
-static int msm_cam_server_open_session(struct msm_cam_server_dev *ps,
- struct msm_cam_v4l2_device *pcam)
-{
- int rc = 0;
- struct msm_cam_media_controller *pmctl;
-
- D("%s\n", __func__);
-
- if (!ps || !pcam) {
- pr_err("%s NULL pointer passed in!\n", __func__);
- return rc;
- }
-
- /* The number of camera instance should be controlled by the
- resource manager. Currently supporting one active instance
- until multiple instances are supported */
- if (atomic_read(&ps->number_pcam_active) > 0) {
- pr_err("%s Cannot have more than one active camera %d\n",
- __func__, atomic_read(&ps->number_pcam_active));
- return -EINVAL;
- }
- /* book keeping this camera session*/
- ps->pcam_active = pcam;
- atomic_inc(&ps->number_pcam_active);
-
- D("config pcam = 0x%p\n", ps->pcam_active);
-
- /* initialization the media controller module*/
- msm_mctl_init(pcam);
-
- /*for single VFE msms (8660, 8960v1), just populate the session
- with our VFE devices that registered*/
- pmctl = msm_camera_get_mctl(pcam->mctl_handle);
- pmctl->axi_sdev = ps->axi_device[0];
- pmctl->isp_sdev = ps->isp_subdev[0];
- return rc;
-}
-
-/* close an active camera session to server */
-static int msm_cam_server_close_session(struct msm_cam_server_dev *ps,
- struct msm_cam_v4l2_device *pcam)
-{
- int rc = 0;
- D("%s\n", __func__);
-
- if (!ps || !pcam) {
- D("%s NULL pointer passed in!\n", __func__);
- return rc;
- }
-
-
- atomic_dec(&ps->number_pcam_active);
- ps->pcam_active = NULL;
-
- msm_mctl_free(pcam);
- return rc;
-}
-
-int msm_server_open_client(int *p_qidx)
-{
- int rc = 0;
- int server_q_idx = 0;
- struct msm_cam_server_queue *queue = NULL;
-
- mutex_lock(&g_server_dev.server_lock);
- server_q_idx = msm_find_free_queue();
- if (server_q_idx < 0) {
- mutex_unlock(&g_server_dev.server_lock);
- return server_q_idx;
- }
-
- *p_qidx = server_q_idx;
- queue = &g_server_dev.server_queue[server_q_idx];
- queue->ctrl = NULL;
- queue->ctrl_data = kzalloc(sizeof(uint8_t) *
- max_control_command_size, GFP_KERNEL);
- msm_queue_init(&queue->ctrl_q, "control");
- msm_queue_init(&queue->eventData_q, "eventdata");
- queue->queue_active = 1;
- mutex_unlock(&g_server_dev.server_lock);
- return rc;
-}
-
-int msm_server_send_ctrl(struct msm_ctrl_cmd *out,
- int ctrl_id)
-{
- int rc = 0;
- void *value;
- struct msm_queue_cmd *rcmd;
- struct msm_queue_cmd *event_qcmd;
- struct msm_ctrl_cmd *ctrlcmd;
- struct msm_cam_server_dev *server_dev = &g_server_dev;
- struct msm_device_queue *queue =
- &server_dev->server_queue[out->queue_idx].ctrl_q;
-
- struct v4l2_event v4l2_evt;
- struct msm_isp_event_ctrl *isp_event;
- isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl), GFP_KERNEL);
- if (!isp_event) {
- pr_err("%s Insufficient memory. return", __func__);
- return -ENOMEM;
- }
- event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_KERNEL);
- if (!event_qcmd) {
- pr_err("%s Insufficient memory. return", __func__);
- kfree(isp_event);
- return -ENOMEM;
- }
-
- D("%s\n", __func__);
- mutex_lock(&server_dev->server_queue_lock);
- if (++server_dev->server_evt_id == 0)
- server_dev->server_evt_id++;
-
- D("%s qid %d evtid %d\n", __func__, out->queue_idx,
- server_dev->server_evt_id);
- server_dev->server_queue[out->queue_idx].evt_id =
- server_dev->server_evt_id;
- v4l2_evt.type = V4L2_EVENT_PRIVATE_START + ctrl_id;
- v4l2_evt.u.data[0] = out->queue_idx;
- /* setup event object to transfer the command; */
- isp_event->resptype = MSM_CAM_RESP_V4L2;
- isp_event->isp_data.ctrl = *out;
- isp_event->isp_data.ctrl.evt_id = server_dev->server_evt_id;
-
- atomic_set(&event_qcmd->on_heap, 1);
- event_qcmd->command = isp_event;
-
- msm_enqueue(&server_dev->server_queue[out->queue_idx].eventData_q,
- &event_qcmd->list_eventdata);
-
- /* now send command to config thread in userspace,
- * and wait for results */
- v4l2_event_queue(server_dev->server_command_queue.pvdev,
- &v4l2_evt);
- D("%s v4l2_event_queue: type = 0x%x\n", __func__, v4l2_evt.type);
- mutex_unlock(&server_dev->server_queue_lock);
-
- /* wait for config return status */
- D("Waiting for config status\n");
- rc = wait_event_interruptible_timeout(queue->wait,
- !list_empty_careful(&queue->list),
- msecs_to_jiffies(out->timeout_ms));
- D("Waiting is over for config status\n");
- if (list_empty_careful(&queue->list)) {
- if (!rc)
- rc = -ETIMEDOUT;
- if (rc < 0) {
- kfree(isp_event);
- pr_err("%s: wait_event error %d\n", __func__, rc);
- return rc;
- }
- }
-
- rcmd = msm_dequeue(queue, list_control);
- BUG_ON(!rcmd);
- D("%s Finished servicing ioctl\n", __func__);
-
- ctrlcmd = (struct msm_ctrl_cmd *)(rcmd->command);
- value = out->value;
- if (ctrlcmd->length > 0)
- memcpy(value, ctrlcmd->value, ctrlcmd->length);
-
- memcpy(out, ctrlcmd, sizeof(struct msm_ctrl_cmd));
- out->value = value;
-
- kfree(ctrlcmd);
- server_dev->server_queue[out->queue_idx].ctrl = NULL;
-
- free_qcmd(rcmd);
- kfree(isp_event);
- D("%s: rc %d\n", __func__, rc);
- /* rc is the time elapsed. */
- if (rc >= 0) {
- /* TODO: Refactor msm_ctrl_cmd::status field */
- if (out->status == 0)
- rc = -1;
- else if (out->status == 1 || out->status == 4)
- rc = 0;
- else
- rc = -EINVAL;
- }
- return rc;
-}
-
-int msm_server_close_client(int idx)
-{
- int rc = 0;
- struct msm_cam_server_queue *queue = NULL;
- mutex_lock(&g_server_dev.server_lock);
- queue = &g_server_dev.server_queue[idx];
- queue->queue_active = 0;
- kfree(queue->ctrl);
- queue->ctrl = NULL;
- kfree(queue->ctrl_data);
- queue->ctrl_data = NULL;
- msm_queue_drain(&queue->ctrl_q, list_control);
- msm_drain_eventq(&queue->eventData_q);
- mutex_unlock(&g_server_dev.server_lock);
- return rc;
-}
/* v4l2_file_operations */
static int msm_open(struct file *f)
{
- int i;
- int rc = -EINVAL;
+ int i, rc = -EINVAL;
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
int ion_client_created = 0;
#endif
@@ -1746,7 +738,6 @@
struct msm_cam_v4l2_device *pcam = video_drvdata(f);
struct msm_cam_v4l2_dev_inst *pcam_inst;
struct msm_cam_media_controller *pmctl = NULL;
- struct msm_cam_server_queue *queue = NULL;
D("%s\n", __func__);
@@ -1754,7 +745,7 @@
pr_err("%s NULL pointer passed in!\n", __func__);
return rc;
}
- if (!g_server_dev.use_count) {
+ if (!msm_server_get_usecount()) {
pr_err("%s: error, daemon not yet started.", __func__);
return -EINVAL;
}
@@ -1789,28 +780,12 @@
pcam->use_count++;
D("%s use_count %d\n", __func__, pcam->use_count);
if (pcam->use_count == 1) {
- int ges_evt = MSM_V4L2_GES_CAM_OPEN;
- pcam->server_queue_idx = server_q_idx;
- queue = &g_server_dev.server_queue[server_q_idx];
- queue->ctrl = NULL;
- queue->ctrl_data = kzalloc(sizeof(uint8_t) *
- max_control_command_size, GFP_KERNEL);
- msm_queue_init(&queue->ctrl_q, "control");
- msm_queue_init(&queue->eventData_q, "eventdata");
- queue->queue_active = 1;
-
- pr_err("%s send gesture evt\n", __func__);
- msm_cam_server_subdev_notify(g_server_dev.gesture_device,
- NOTIFY_GESTURE_CAM_EVT, &ges_evt);
-
- rc = msm_cam_server_open_session(&g_server_dev, pcam);
+ rc = msm_server_begin_session(pcam, server_q_idx);
if (rc < 0) {
- pr_err("%s: cam_server_open_session failed %d\n",
- __func__, rc);
- goto msm_cam_server_open_session_failed;
+ pr_err("%s error starting server session ", __func__);
+ goto msm_cam_server_begin_session_failed;
}
-
- pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
pmctl->client = msm_ion_client_create(-1, "camera");
@@ -1852,14 +827,14 @@
if (pcam->use_count == 1) {
rc = msm_send_open_server(pcam);
- if (rc < 0) {
+ if (rc < 0 && rc != -ERESTARTSYS) {
pr_err("%s: msm_send_open_server failed %d\n",
__func__, rc);
goto msm_send_open_server_failed;
}
}
mutex_unlock(&pcam->vid_lock);
- D("%s: end", __func__);
+ D("%s: end\n", __func__);
return rc;
msm_send_open_server_failed:
@@ -1873,25 +848,16 @@
if (pcam->use_count == 1) {
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
if (ion_client_created) {
- pr_err("%s: destroy ion client", __func__);
+ D("%s: destroy ion client", __func__);
kref_put(&pmctl->refcount, msm_release_ion_client);
}
#endif
- if (msm_cam_server_close_session(&g_server_dev, pcam) < 0)
- pr_err("%s: msm_cam_server_close_session failed\n",
+ if (msm_server_end_session(pcam) < 0)
+ pr_err("%s: msm_server_end_session failed\n",
__func__);
}
-msm_cam_server_open_session_failed:
+msm_cam_server_begin_session_failed:
if (pcam->use_count == 1) {
- if (queue != NULL) {
- queue->queue_active = 0;
- msm_drain_eventq(&queue->eventData_q);
- kfree(queue->ctrl_data);
- queue->ctrl_data = NULL;
- msm_queue_drain(&queue->ctrl_q, list_control);
- msm_drain_eventq(&queue->eventData_q);
- queue = NULL;
- }
pcam->dev_inst[i] = NULL;
pcam->use_count = 0;
}
@@ -1901,73 +867,6 @@
return rc;
}
-int msm_cam_server_close_mctl_session(struct msm_cam_v4l2_device *pcam)
-{
- int rc = 0;
- struct msm_cam_media_controller *pmctl = NULL;
-
- pmctl = msm_camera_get_mctl(pcam->mctl_handle);
- if (!pmctl) {
- D("%s: invalid handle\n", __func__);
- return -ENODEV;
- }
-
- if (pmctl->mctl_release) {
- rc = pmctl->mctl_release(pmctl);
- if (rc < 0)
- pr_err("mctl_release fails %d\n", rc);
- }
-
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- kref_put(&pmctl->refcount, msm_release_ion_client);
-#endif
-
- rc = msm_cam_server_close_session(&g_server_dev, pcam);
- if (rc < 0)
- pr_err("msm_cam_server_close_session fails %d\n", rc);
-
- return rc;
-}
-
-int msm_cam_server_open_mctl_session(struct msm_cam_v4l2_device *pcam,
- int *p_active)
-{
- int rc = 0;
- struct msm_cam_media_controller *pmctl = NULL;
- D("%s: %p", __func__, g_server_dev.pcam_active);
- *p_active = 0;
- if (g_server_dev.pcam_active) {
- D("%s: Active camera present return", __func__);
- return 0;
- }
- rc = msm_cam_server_open_session(&g_server_dev, pcam);
- if (rc < 0) {
- pr_err("%s: cam_server_open_session failed %d\n",
- __func__, rc);
- return rc;
- }
-
- pmctl = msm_camera_get_mctl(pcam->mctl_handle);
- /* Should be set to sensor ops if any but right now its OK!! */
- if (!pmctl->mctl_open) {
- D("%s: media contoller is not inited\n",
- __func__);
- rc = -ENODEV;
- return rc;
- }
-
- D("%s: call mctl_open\n", __func__);
- rc = pmctl->mctl_open(pmctl, MSM_APPS_ID_V4L2);
-
- if (rc < 0) {
- pr_err("%s: HW open failed rc = 0x%x\n", __func__, rc);
- return rc;
- }
- pmctl->pcam_ptr = pcam;
- *p_active = 1;
- return rc;
-}
-
static int msm_addr_remap(struct msm_cam_v4l2_dev_inst *pcam_inst,
struct vm_area_struct *vma)
{
@@ -1977,7 +876,7 @@
int rc = 0;
struct msm_cam_media_controller *mctl;
- mctl = msm_camera_get_mctl(pcam_inst->pcam->mctl_handle);
+ mctl = msm_cam_server_get_mctl(pcam_inst->pcam->mctl_handle);
if (!mctl) {
pr_err("%s: invalid mctl pointer", __func__);
return -EFAULT;
@@ -2035,8 +934,8 @@
void msm_release_ion_client(struct kref *ref)
{
struct msm_cam_media_controller *mctl = container_of(ref,
- struct msm_cam_media_controller, refcount);
- pr_err("%s Calling ion_client_destroy ", __func__);
+ struct msm_cam_media_controller, refcount);
+ pr_err("%s Calling ion_client_destroy\n", __func__);
ion_client_destroy(mctl->client);
}
@@ -2045,7 +944,6 @@
int rc = 0;
struct msm_cam_v4l2_device *pcam;
struct msm_cam_v4l2_dev_inst *pcam_inst;
- struct msm_cam_server_queue *queue;
struct msm_cam_media_controller *pmctl;
pcam_inst = container_of(f->private_data,
struct msm_cam_v4l2_dev_inst, eventHandle);
@@ -2055,7 +953,7 @@
return -EINVAL;
}
- pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
if (!pmctl) {
pr_err("%s NULL mctl pointer\n", __func__);
return -EINVAL;
@@ -2091,37 +989,24 @@
f->private_data = NULL;
if (pcam->use_count == 0) {
- int ges_evt = MSM_V4L2_GES_CAM_CLOSE;
- if (g_server_dev.use_count > 0) {
+ if (msm_server_get_usecount() > 0) {
rc = msm_send_close_server(pcam);
if (rc < 0)
pr_err("msm_send_close_server failed %d\n", rc);
}
+
if (pmctl->mctl_release) {
rc = pmctl->mctl_release(pmctl);
if (rc < 0)
pr_err("mctl_release fails %d\n", rc);
}
+
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
kref_put(&pmctl->refcount, msm_release_ion_client);
#endif
- queue = &g_server_dev.server_queue[pcam->server_queue_idx];
- queue->queue_active = 0;
- kfree(queue->ctrl);
- queue->ctrl = NULL;
- kfree(queue->ctrl_data);
- queue->ctrl_data = NULL;
- msm_queue_drain(&queue->ctrl_q, list_control);
- msm_drain_eventq(&queue->eventData_q);
- rc = msm_cam_server_close_session(&g_server_dev, pcam);
+ rc = msm_server_end_session(pcam);
if (rc < 0)
- pr_err("msm_cam_server_close_session fails %d\n", rc);
-
- if (g_server_dev.use_count == 0)
- mutex_unlock(&g_server_dev.server_lock);
-
- msm_cam_server_subdev_notify(g_server_dev.gesture_device,
- NOTIFY_GESTURE_CAM_EVT, &ges_evt);
+ pr_err("msm_server_end_session fails %d\n", rc);
}
mutex_unlock(&pcam->vid_lock);
return rc;
@@ -2156,280 +1041,8 @@
return rc;
}
-static unsigned int msm_poll_server(struct file *fp,
- struct poll_table_struct *wait)
-{
- int rc = 0;
-
- D("%s\n", __func__);
- poll_wait(fp,
- &g_server_dev.server_command_queue.eventHandle.events->wait,
- wait);
- if (v4l2_event_pending(&g_server_dev.server_command_queue.eventHandle))
- rc |= POLLPRI;
-
- return rc;
-}
-static long msm_ioctl_server(struct file *file, void *fh,
- bool valid_prio, int cmd, void *arg)
-{
- int rc = -EINVAL;
- struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg;
- struct msm_camera_info temp_cam_info;
- struct msm_cam_config_dev_info temp_config_info;
- struct msm_mctl_node_info temp_mctl_info;
- int i;
-
- D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
-
- switch (cmd) {
- case MSM_CAM_V4L2_IOCTL_GET_CAMERA_INFO:
- if (copy_from_user(&temp_cam_info,
- (void __user *)ioctl_ptr->ioctl_ptr,
- sizeof(struct msm_camera_info))) {
- rc = -EINVAL;
- return rc;
- }
- for (i = 0; i < g_server_dev.camera_info.num_cameras; i++) {
- if (copy_to_user((void __user *)
- temp_cam_info.video_dev_name[i],
- g_server_dev.camera_info.video_dev_name[i],
- strnlen(
- g_server_dev.camera_info.video_dev_name[i],
- MAX_DEV_NAME_LEN))) {
- rc = -EINVAL;
- return rc;
- }
- temp_cam_info.has_3d_support[i] =
- g_server_dev.camera_info.has_3d_support[i];
- temp_cam_info.is_internal_cam[i] =
- g_server_dev.camera_info.is_internal_cam[i];
- temp_cam_info.s_mount_angle[i] =
- g_server_dev.camera_info.s_mount_angle[i];
- temp_cam_info.sensor_type[i] =
- g_server_dev.camera_info.sensor_type[i];
-
- }
- temp_cam_info.num_cameras =
- g_server_dev.camera_info.num_cameras;
- if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
- &temp_cam_info,
- sizeof(struct msm_camera_info))) {
- rc = -EINVAL;
- return rc;
- }
- rc = 0;
- break;
-
- case MSM_CAM_V4L2_IOCTL_GET_CONFIG_INFO:
- if (copy_from_user(&temp_config_info,
- (void __user *)ioctl_ptr->ioctl_ptr,
- sizeof(struct msm_cam_config_dev_info))) {
-
- rc = -EINVAL;
- return rc;
- }
- for (i = 0;
- i < g_server_dev.config_info.num_config_nodes; i++) {
- if (copy_to_user(
- (void __user *)temp_config_info.config_dev_name[i],
- g_server_dev.config_info.config_dev_name[i],
- strlen(g_server_dev.config_info.config_dev_name[i]))) {
- rc = -EINVAL;
- return rc;
- }
- }
- temp_config_info.num_config_nodes =
- g_server_dev.config_info.num_config_nodes;
- if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
- &temp_config_info,
- sizeof(struct msm_cam_config_dev_info))) {
- rc = -EINVAL;
- return rc;
- }
- rc = 0;
- break;
- case MSM_CAM_V4L2_IOCTL_GET_MCTL_INFO:
- if (copy_from_user(&temp_mctl_info,
- (void __user *)ioctl_ptr->ioctl_ptr,
- sizeof(struct msm_mctl_node_info))) {
- rc = -EINVAL;
- return rc;
- }
- for (i = 0; i < g_server_dev.mctl_node_info.num_mctl_nodes;
- i++) {
- if (copy_to_user((void __user *)
- temp_mctl_info.mctl_node_name[i],
- g_server_dev.mctl_node_info.mctl_node_name[i], strnlen(
- g_server_dev.mctl_node_info.mctl_node_name[i],
- MAX_DEV_NAME_LEN))) {
- rc = -EINVAL;
- return rc;
- }
- }
- temp_mctl_info.num_mctl_nodes =
- g_server_dev.mctl_node_info.num_mctl_nodes;
- if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
- &temp_mctl_info,
- sizeof(struct msm_mctl_node_info))) {
- rc = -EINVAL;
- return rc;
- }
- rc = 0;
- break;
-
- case MSM_CAM_V4L2_IOCTL_CTRL_CMD_DONE:
- D("%s: MSM_CAM_IOCTL_CTRL_CMD_DONE\n", __func__);
- rc = msm_ctrl_cmd_done(arg);
- break;
-
- case MSM_CAM_V4L2_IOCTL_GET_EVENT_PAYLOAD: {
- struct msm_queue_cmd *event_cmd;
- struct msm_isp_event_ctrl u_isp_event;
- struct msm_isp_event_ctrl *k_isp_event;
- struct msm_device_queue *queue;
- void __user *u_ctrl_value = NULL;
- if (copy_from_user(&u_isp_event,
- (void __user *)ioctl_ptr->ioctl_ptr,
- sizeof(struct msm_isp_event_ctrl))) {
- rc = -EINVAL;
- return rc;
- }
- queue = &g_server_dev.server_queue
- [u_isp_event.isp_data.ctrl.queue_idx].eventData_q;
- event_cmd = msm_dequeue(queue, list_eventdata);
- if (!event_cmd) {
- pr_err("%s: No event payload\n", __func__);
- rc = -EINVAL;
- return rc;
- }
- k_isp_event = (struct msm_isp_event_ctrl *)
- event_cmd->command;
- free_qcmd(event_cmd);
-
- /* Save the pointer of the user allocated command buffer*/
- u_ctrl_value = u_isp_event.isp_data.ctrl.value;
-
- /* Copy the event structure into user struct*/
- u_isp_event = *k_isp_event;
-
- /* Restore the saved pointer of the user
- * allocated command buffer. */
- u_isp_event.isp_data.ctrl.value = u_ctrl_value;
-
- /* Copy the ctrl cmd, if present*/
- if (k_isp_event->isp_data.ctrl.length > 0) {
- void *k_ctrl_value =
- k_isp_event->isp_data.ctrl.value;
- if (copy_to_user(u_ctrl_value, k_ctrl_value,
- k_isp_event->isp_data.ctrl.length)) {
- rc = -EINVAL;
- break;
- }
- }
- if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
- &u_isp_event,
- sizeof(struct msm_isp_event_ctrl))) {
- rc = -EINVAL;
- return rc;
- }
- rc = 0;
- break;
- }
-
- case MSM_CAM_IOCTL_SEND_EVENT:
- rc = msm_server_send_v4l2_evt(arg);
- break;
-
- default:
- pr_err("%s: Invalid IOCTL = %d", __func__, cmd);
- break;
- }
- return rc;
-}
-
-static int msm_open_server(struct file *fp)
-{
- int rc = 0;
- D("%s: open %s\n", __func__, fp->f_path.dentry->d_name.name);
- mutex_lock(&g_server_dev.server_lock);
- g_server_dev.use_count++;
- if (g_server_dev.use_count == 1)
- fp->private_data =
- &g_server_dev.server_command_queue.eventHandle;
- mutex_unlock(&g_server_dev.server_lock);
- return rc;
-}
-
-static unsigned int msm_poll_config(struct file *fp,
- struct poll_table_struct *wait)
-{
- int rc = 0;
- struct msm_cam_config_dev *config = fp->private_data;
- if (config == NULL)
- return -EINVAL;
-
- D("%s\n", __func__);
-
- poll_wait(fp,
- &config->config_stat_event_queue.eventHandle.events->wait, wait);
- if (v4l2_event_pending(&config->config_stat_event_queue.eventHandle))
- rc |= POLLPRI;
- return rc;
-}
-
-static int msm_close_server(struct file *fp)
-{
- struct v4l2_event_subscription sub;
- D("%s\n", __func__);
- mutex_lock(&g_server_dev.server_lock);
- if (g_server_dev.use_count > 0)
- g_server_dev.use_count--;
- mutex_unlock(&g_server_dev.server_lock);
- if (g_server_dev.use_count == 0) {
- if (g_server_dev.pcam_active) {
- struct v4l2_event v4l2_ev;
- mutex_lock(&g_server_dev.server_lock);
-
- v4l2_ev.type = V4L2_EVENT_PRIVATE_START
- + MSM_CAM_APP_NOTIFY_ERROR_EVENT;
- ktime_get_ts(&v4l2_ev.timestamp);
- v4l2_event_queue(
- g_server_dev.pcam_active->pvdev, &v4l2_ev);
- }
- sub.type = V4L2_EVENT_ALL;
- msm_server_v4l2_unsubscribe_event(
- &g_server_dev.server_command_queue.eventHandle, &sub);
- }
- return 0;
-}
-
-static long msm_server_send_v4l2_evt(void *evt)
-{
- struct v4l2_event *v4l2_ev = (struct v4l2_event *)evt;
- int rc = 0;
-
- if (NULL == evt) {
- pr_err("%s: evt is NULL\n", __func__);
- return -EINVAL;
- }
-
- D("%s: evt type 0x%x\n", __func__, v4l2_ev->type);
- if ((v4l2_ev->type >= MSM_GES_APP_EVT_MIN) &&
- (v4l2_ev->type < MSM_GES_APP_EVT_MAX)) {
- msm_cam_server_subdev_notify(g_server_dev.gesture_device,
- NOTIFY_GESTURE_EVT, v4l2_ev);
- } else {
- pr_err("%s: Invalid evt %d\n", __func__, v4l2_ev->type);
- rc = -EINVAL;
- }
- D("%s: end\n", __func__);
-
- return rc;
-}
-
-static long msm_v4l2_evt_notify(struct msm_cam_media_controller *mctl,
- unsigned int cmd, unsigned long evt)
+long msm_v4l2_evt_notify(struct msm_cam_media_controller *mctl,
+ unsigned int cmd, unsigned long evt)
{
struct v4l2_event v4l2_ev;
struct msm_cam_v4l2_device *pcam = NULL;
@@ -2451,280 +1064,6 @@
return 0;
}
-static long msm_ioctl_config(struct file *fp, unsigned int cmd,
- unsigned long arg)
-{
-
- int rc = 0;
- struct v4l2_event ev;
- struct msm_cam_config_dev *config_cam = fp->private_data;
- struct v4l2_event_subscription temp_sub;
-
- D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
-
- switch (cmd) {
- /* memory management shall be handeld here*/
- case MSM_CAM_IOCTL_REGISTER_PMEM:
- return msm_register_pmem(
- &config_cam->p_mctl->stats_info.pmem_stats_list,
- (void __user *)arg, config_cam->p_mctl->client);
- break;
-
- case MSM_CAM_IOCTL_UNREGISTER_PMEM:
- return msm_pmem_table_del(
- &config_cam->p_mctl->stats_info.pmem_stats_list,
- (void __user *)arg, config_cam->p_mctl->client);
- break;
-
- case VIDIOC_SUBSCRIBE_EVENT:
- if (copy_from_user(&temp_sub,
- (void __user *)arg,
- sizeof(struct v4l2_event_subscription))) {
- rc = -EINVAL;
- return rc;
- }
- rc = msm_server_v4l2_subscribe_event
- (&config_cam->config_stat_event_queue.eventHandle,
- &temp_sub);
- if (rc < 0) {
- pr_err("%s: cam_v4l2_subscribe_event failed rc=%d\n",
- __func__, rc);
- return rc;
- }
- break;
-
- case VIDIOC_UNSUBSCRIBE_EVENT:
- if (copy_from_user(&temp_sub, (void __user *)arg,
- sizeof(struct v4l2_event_subscription))) {
- rc = -EINVAL;
- return rc;
- }
- rc = msm_server_v4l2_unsubscribe_event
- (&config_cam->config_stat_event_queue.eventHandle,
- &temp_sub);
- if (rc < 0) {
- pr_err("%s: server_unsubscribe_event failed rc=%d\n",
- __func__, rc);
- return rc;
- }
- break;
-
- case VIDIOC_DQEVENT: {
- void __user *u_msg_value = NULL, *user_ptr = NULL;
- struct msm_isp_event_ctrl u_isp_event;
- struct msm_isp_event_ctrl *k_isp_event;
-
- /* First, copy the v4l2 event structure from userspace */
- D("%s: VIDIOC_DQEVENT\n", __func__);
- if (copy_from_user(&ev, (void __user *)arg,
- sizeof(struct v4l2_event)))
- break;
- /* Next, get the pointer to event_ctrl structure
- * embedded inside the v4l2_event.u.data array. */
- user_ptr = (void __user *)(*((uint32_t *)ev.u.data));
-
- /* Next, copy the userspace event ctrl structure */
- if (copy_from_user((void *)&u_isp_event, user_ptr,
- sizeof(struct msm_isp_event_ctrl))) {
- break;
- }
- /* Save the pointer of the user allocated command buffer*/
- u_msg_value = u_isp_event.isp_data.isp_msg.data;
-
- /* Dequeue the event queued into the v4l2 queue*/
- rc = v4l2_event_dequeue(
- &config_cam->config_stat_event_queue.eventHandle,
- &ev, fp->f_flags & O_NONBLOCK);
- if (rc < 0) {
- pr_err("no pending events?");
- break;
- }
- /* Use k_isp_event to point to the event_ctrl structure
- * embedded inside v4l2_event.u.data */
- k_isp_event = (struct msm_isp_event_ctrl *)
- (*((uint32_t *)ev.u.data));
- /* Copy the event structure into user struct. */
- u_isp_event = *k_isp_event;
- if (ev.type != (V4L2_EVENT_PRIVATE_START +
- MSM_CAM_RESP_DIV_FRAME_EVT_MSG) &&
- ev.type != (V4L2_EVENT_PRIVATE_START +
- MSM_CAM_RESP_MCTL_PP_EVENT)) {
-
- /* Restore the saved pointer of the
- * user allocated command buffer. */
- u_isp_event.isp_data.isp_msg.data = u_msg_value;
-
- if (ev.type == (V4L2_EVENT_PRIVATE_START +
- MSM_CAM_RESP_STAT_EVT_MSG)) {
- if (k_isp_event->isp_data.isp_msg.len > 0) {
- void *k_msg_value =
- k_isp_event->isp_data.isp_msg.data;
- if (copy_to_user(u_msg_value,
- k_msg_value,
- k_isp_event->isp_data.isp_msg.len)) {
- rc = -EINVAL;
- break;
- }
- kfree(k_msg_value);
- }
- }
- }
- /* Copy the event ctrl structure back
- * into user's structure. */
- if (copy_to_user(user_ptr,
- (void *)&u_isp_event, sizeof(
- struct msm_isp_event_ctrl))) {
- rc = -EINVAL;
- break;
- }
- kfree(k_isp_event);
-
- /* Copy the v4l2_event structure back to the user*/
- if (copy_to_user((void __user *)arg, &ev,
- sizeof(struct v4l2_event))) {
- rc = -EINVAL;
- break;
- }
- }
-
- break;
-
- case MSM_CAM_IOCTL_V4L2_EVT_NOTIFY:
- rc = msm_v4l2_evt_notify(config_cam->p_mctl, cmd, arg);
- break;
-
- case MSM_CAM_IOCTL_SET_MEM_MAP_INFO:
- if (copy_from_user(&config_cam->mem_map, (void __user *)arg,
- sizeof(struct msm_mem_map_info)))
- rc = -EINVAL;
- break;
-
- default:{
- /* For the rest of config command, forward to media controller*/
- struct msm_cam_media_controller *p_mctl = config_cam->p_mctl;
- if (p_mctl && p_mctl->mctl_cmd) {
- rc = config_cam->p_mctl->mctl_cmd(p_mctl, cmd, arg);
- } else {
- rc = -EINVAL;
- pr_err("%s: media controller is null\n", __func__);
- }
-
- break;
- } /* end of default*/
- } /* end of switch*/
- return rc;
-}
-
-static int msm_mmap_config(struct file *fp, struct vm_area_struct *vma)
-{
- struct msm_cam_config_dev *config_cam = fp->private_data;
- int rc = 0;
- int phyaddr;
- int retval;
- unsigned long size;
-
- D("%s: phy_addr=0x%x", __func__, config_cam->mem_map.cookie);
- phyaddr = (int)config_cam->mem_map.cookie;
- if (!phyaddr) {
- pr_err("%s: no physical memory to map", __func__);
- return -EFAULT;
- }
- memset(&config_cam->mem_map, 0,
- sizeof(struct msm_mem_map_info));
- size = vma->vm_end - vma->vm_start;
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- retval = remap_pfn_range(vma, vma->vm_start,
- phyaddr >> PAGE_SHIFT,
- size, vma->vm_page_prot);
- if (retval) {
- pr_err("%s: remap failed, rc = %d",
- __func__, retval);
- rc = -ENOMEM;
- goto end;
- }
- D("%s: phy_addr=0x%x: %08lx-%08lx, pgoff %08lx\n",
- __func__, (uint32_t)phyaddr,
- vma->vm_start, vma->vm_end, vma->vm_pgoff);
-end:
- return rc;
-}
-
-static int msm_open_config(struct inode *inode, struct file *fp)
-{
- int rc;
- struct msm_cam_config_dev *config_cam = container_of(inode->i_cdev,
- struct msm_cam_config_dev, config_cdev);
-
- D("%s: open %s\n", __func__, fp->f_path.dentry->d_name.name);
-
- rc = nonseekable_open(inode, fp);
- if (rc < 0) {
- pr_err("%s: nonseekable_open error %d\n", __func__, rc);
- return rc;
- }
- config_cam->use_count++;
-
- /*config_cam->isp_subdev = g_server_dev.pcam_active->mctl.isp_sdev;*/
- /* assume there is only one active camera possible*/
- config_cam->p_mctl =
- msm_camera_get_mctl(g_server_dev.pcam_active->mctl_handle);
-
- INIT_HLIST_HEAD(&config_cam->p_mctl->stats_info.pmem_stats_list);
- spin_lock_init(&config_cam->p_mctl->stats_info.pmem_stats_spinlock);
-
- config_cam->p_mctl->config_device = config_cam;
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- kref_get(&config_cam->p_mctl->refcount);
-#endif
- fp->private_data = config_cam;
- return rc;
-}
-
-static int msm_close_config(struct inode *node, struct file *f)
-{
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- struct msm_cam_config_dev *config_cam = f->private_data;
- D("%s Decrementing ref count of config node ", __func__);
- kref_put(&config_cam->p_mctl->refcount, msm_release_ion_client);
-#endif
- return 0;
-}
-
-static struct v4l2_file_operations g_msm_fops = {
- .owner = THIS_MODULE,
- .open = msm_open,
- .poll = msm_poll,
- .mmap = msm_mmap,
- .release = msm_close,
- .ioctl = video_ioctl2,
-};
-
-/* Init a config node for ISP control,
- * which will create a config device (/dev/config0/ and plug in
- * ISP's operation "v4l2_ioctl_ops*"
- */
-static const struct v4l2_file_operations msm_fops_server = {
- .owner = THIS_MODULE,
- .open = msm_open_server,
- .poll = msm_poll_server,
- .unlocked_ioctl = video_ioctl2,
- .release = msm_close_server,
-};
-
-static const struct v4l2_ioctl_ops msm_ioctl_ops_server = {
- .vidioc_subscribe_event = msm_server_v4l2_subscribe_event,
- .vidioc_default = msm_ioctl_server,
-};
-
-static const struct file_operations msm_fops_config = {
- .owner = THIS_MODULE,
- .open = msm_open_config,
- .poll = msm_poll_config,
- .unlocked_ioctl = msm_ioctl_config,
- .mmap = msm_mmap_config,
- .release = msm_close_config,
-};
-
int msm_setup_v4l2_event_queue(struct v4l2_fh *eventHandle,
struct video_device *pvdev)
{
@@ -2752,319 +1091,14 @@
return rc;
}
-static int msm_setup_config_dev(int node, char *device_name)
-{
- int rc = -ENODEV;
- struct device *device_config;
- int dev_num = node;
- dev_t devno;
- struct msm_cam_config_dev *config_cam;
-
- config_cam = kzalloc(sizeof(*config_cam), GFP_KERNEL);
- if (!config_cam) {
- pr_err("%s: could not allocate memory for msm_cam_config_device\n",
- __func__);
- return -ENOMEM;
- }
-
- D("%s\n", __func__);
-
- devno = MKDEV(MAJOR(msm_devno), dev_num+1);
- device_config = device_create(msm_class, NULL, devno, NULL, "%s%d",
- device_name, dev_num);
-
- if (IS_ERR(device_config)) {
- rc = PTR_ERR(device_config);
- pr_err("%s: error creating device: %d\n", __func__, rc);
- goto config_setup_fail;
- }
-
- cdev_init(&config_cam->config_cdev, &msm_fops_config);
- config_cam->config_cdev.owner = THIS_MODULE;
-
- rc = cdev_add(&config_cam->config_cdev, devno, 1);
- if (rc < 0) {
- pr_err("%s: error adding cdev: %d\n", __func__, rc);
- device_destroy(msm_class, devno);
- goto config_setup_fail;
- }
-
- g_server_dev.config_info.config_dev_name[dev_num] =
- dev_name(device_config);
- D("%s Connected config device %s\n", __func__,
- g_server_dev.config_info.config_dev_name[dev_num]);
- g_server_dev.config_info.config_dev_id[dev_num] = dev_num;
-
- config_cam->config_stat_event_queue.pvdev = video_device_alloc();
- if (config_cam->config_stat_event_queue.pvdev == NULL) {
- pr_err("%s: video_device_alloc failed\n", __func__);
- goto config_setup_fail;
- }
-
- rc = msm_setup_v4l2_event_queue(
- &config_cam->config_stat_event_queue.eventHandle,
- config_cam->config_stat_event_queue.pvdev);
- if (rc < 0) {
- pr_err("%s failed to initialize event queue\n", __func__);
- video_device_release(config_cam->config_stat_event_queue.pvdev);
- goto config_setup_fail;
- }
-
- return rc;
-
-config_setup_fail:
- kfree(config_cam);
- return rc;
-}
-
-static void msm_cam_server_subdev_notify(struct v4l2_subdev *sd,
- unsigned int notification, void *arg)
-{
- int rc = -EINVAL;
- struct msm_sensor_ctrl_t *s_ctrl;
- struct msm_camera_sensor_info *sinfo;
- struct msm_camera_device_platform_data *camdev;
- uint8_t csid_core = 0;
-
- if (notification == NOTIFY_CID_CHANGE ||
- notification == NOTIFY_ISPIF_STREAM ||
- notification == NOTIFY_PCLK_CHANGE ||
- notification == NOTIFY_CSIPHY_CFG ||
- notification == NOTIFY_CSID_CFG ||
- notification == NOTIFY_CSIC_CFG) {
- s_ctrl = get_sctrl(sd);
- sinfo = (struct msm_camera_sensor_info *) s_ctrl->sensordata;
- camdev = sinfo->pdata;
- csid_core = camdev->csid_core;
- }
-
- switch (notification) {
- case NOTIFY_CID_CHANGE:
- /* reconfig the ISPIF*/
- if (g_server_dev.ispif_device) {
- struct msm_ispif_params_list ispif_params;
- ispif_params.len = 1;
- ispif_params.params[0].intftype = PIX0;
- ispif_params.params[0].cid_mask = 0x0001;
- ispif_params.params[0].csid = csid_core;
-
- rc = v4l2_subdev_call(
- g_server_dev.ispif_device, core, ioctl,
- VIDIOC_MSM_ISPIF_CFG, &ispif_params);
- if (rc < 0)
- return;
- }
- break;
- case NOTIFY_ISPIF_STREAM:
- /* call ISPIF stream on/off */
- rc = v4l2_subdev_call(g_server_dev.ispif_device, video,
- s_stream, (int)arg);
- if (rc < 0)
- return;
-
- break;
- case NOTIFY_ISP_MSG_EVT:
- case NOTIFY_VFE_MSG_OUT:
- case NOTIFY_VFE_MSG_STATS:
- case NOTIFY_VFE_MSG_COMP_STATS:
- case NOTIFY_VFE_BUF_EVT:
- case NOTIFY_VFE_BUF_FREE_EVT:
- if (g_server_dev.isp_subdev[0] &&
- g_server_dev.isp_subdev[0]->isp_notify) {
- rc = g_server_dev.isp_subdev[0]->isp_notify(
- g_server_dev.vfe_device[0], notification, arg);
- }
- break;
- case NOTIFY_VPE_MSG_EVT: {
- struct msm_cam_media_controller *pmctl =
- (struct msm_cam_media_controller *)
- v4l2_get_subdev_hostdata(sd);
- struct msm_vpe_resp *vdata = (struct msm_vpe_resp *)arg;
- msm_mctl_pp_notify(pmctl,
- (struct msm_mctl_pp_frame_info *)
- vdata->extdata);
- break;
- }
- case NOTIFY_VFE_IRQ:{
- struct msm_vfe_cfg_cmd cfg_cmd;
- struct msm_camvfe_params vfe_params;
- cfg_cmd.cmd_type = CMD_VFE_PROCESS_IRQ;
- vfe_params.vfe_cfg = &cfg_cmd;
- vfe_params.data = arg;
- rc = v4l2_subdev_call(g_server_dev.vfe_device[0],
- core, ioctl, 0, &vfe_params);
- }
- break;
- case NOTIFY_AXI_IRQ:
- rc = v4l2_subdev_call(g_server_dev.axi_device[0],
- core, ioctl, VIDIOC_MSM_AXI_IRQ, arg);
- break;
- case NOTIFY_PCLK_CHANGE:
- if (g_server_dev.axi_device[0])
- rc = v4l2_subdev_call(g_server_dev.axi_device[0], video,
- s_crystal_freq, *(uint32_t *)arg, 0);
- else
- rc = v4l2_subdev_call(g_server_dev.vfe_device[0], video,
- s_crystal_freq, *(uint32_t *)arg, 0);
- break;
- case NOTIFY_CSIPHY_CFG:
- rc = v4l2_subdev_call(g_server_dev.csiphy_device[csid_core],
- core, ioctl, VIDIOC_MSM_CSIPHY_CFG, arg);
- break;
- case NOTIFY_CSID_CFG:
- rc = v4l2_subdev_call(g_server_dev.csid_device[csid_core],
- core, ioctl, VIDIOC_MSM_CSID_CFG, arg);
- break;
- case NOTIFY_CSIC_CFG:
- rc = v4l2_subdev_call(g_server_dev.csic_device[csid_core],
- core, ioctl, VIDIOC_MSM_CSIC_CFG, arg);
- break;
- case NOTIFY_GESTURE_EVT:
- rc = v4l2_subdev_call(g_server_dev.gesture_device,
- core, ioctl, VIDIOC_MSM_GESTURE_EVT, arg);
- break;
- case NOTIFY_GESTURE_CAM_EVT:
- rc = v4l2_subdev_call(g_server_dev.gesture_device,
- core, ioctl, VIDIOC_MSM_GESTURE_CAM_EVT, arg);
- break;
- default:
- break;
- }
-
- return;
-}
-
-int msm_cam_register_subdev_node(struct v4l2_subdev *sd,
- enum msm_cam_subdev_type sdev_type, uint8_t index)
-{
- struct video_device *vdev;
- int err = 0;
-
- if (sdev_type == CSIPHY_DEV) {
- if (index >= MAX_NUM_CSIPHY_DEV)
- return -EINVAL;
- g_server_dev.csiphy_device[index] = sd;
- } else if (sdev_type == CSID_DEV) {
- if (index >= MAX_NUM_CSID_DEV)
- return -EINVAL;
- g_server_dev.csid_device[index] = sd;
- } else if (sdev_type == CSIC_DEV) {
- if (index >= MAX_NUM_CSIC_DEV)
- return -EINVAL;
- g_server_dev.csic_device[index] = sd;
- } else if (sdev_type == ISPIF_DEV) {
- g_server_dev.ispif_device = sd;
- } else if (sdev_type == VFE_DEV) {
- if (index >= MAX_NUM_VFE_DEV)
- return -EINVAL;
- g_server_dev.vfe_device[index] = sd;
- } else if (sdev_type == VPE_DEV) {
- if (index >= MAX_NUM_VPE_DEV)
- return -EINVAL;
- g_server_dev.vpe_device[index] = sd;
- } else if (sdev_type == AXI_DEV) {
- if (index >= MAX_NUM_AXI_DEV)
- return -EINVAL;
- g_server_dev.axi_device[index] = sd;
- } else if (sdev_type == GESTURE_DEV) {
- g_server_dev.gesture_device = sd;
- }
-
- err = v4l2_device_register_subdev(&g_server_dev.v4l2_dev, sd);
- if (err < 0)
- return err;
-
- /* Register a device node for every subdev marked with the
- * V4L2_SUBDEV_FL_HAS_DEVNODE flag.
- */
- if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE))
- return err;
-
- vdev = &sd->devnode;
- strlcpy(vdev->name, sd->name, sizeof(vdev->name));
- vdev->v4l2_dev = &g_server_dev.v4l2_dev;
- vdev->fops = &v4l2_subdev_fops;
- vdev->release = video_device_release_empty;
- err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
- sd->owner);
- if (err < 0)
- return err;
-#if defined(CONFIG_MEDIA_CONTROLLER)
- sd->entity.v4l.major = VIDEO_MAJOR;
- sd->entity.v4l.minor = vdev->minor;
-#endif
- return 0;
-}
-
-static int msm_setup_server_dev(struct platform_device *pdev)
-{
- int rc = -ENODEV, i;
-
- D("%s\n", __func__);
- g_server_dev.server_pdev = pdev;
- g_server_dev.v4l2_dev.dev = &pdev->dev;
- g_server_dev.v4l2_dev.notify = msm_cam_server_subdev_notify;
- rc = v4l2_device_register(g_server_dev.v4l2_dev.dev,
- &g_server_dev.v4l2_dev);
- if (rc < 0)
- return -EINVAL;
-
- g_server_dev.video_dev = video_device_alloc();
- if (g_server_dev.video_dev == NULL) {
- pr_err("%s: video_device_alloc failed\n", __func__);
- return rc;
- }
-
- strlcpy(g_server_dev.video_dev->name, pdev->name,
- sizeof(g_server_dev.video_dev->name));
-
- g_server_dev.video_dev->v4l2_dev = &g_server_dev.v4l2_dev;
- g_server_dev.video_dev->fops = &msm_fops_server;
- g_server_dev.video_dev->ioctl_ops = &msm_ioctl_ops_server;
- g_server_dev.video_dev->release = video_device_release;
- g_server_dev.video_dev->minor = 100;
- g_server_dev.video_dev->vfl_type = 1;
-
- video_set_drvdata(g_server_dev.video_dev, &g_server_dev);
-
- strlcpy(g_server_dev.media_dev.model, "qcamera",
- sizeof(g_server_dev.media_dev.model));
- g_server_dev.media_dev.dev = &pdev->dev;
- rc = media_device_register(&g_server_dev.media_dev);
- g_server_dev.v4l2_dev.mdev = &g_server_dev.media_dev;
-
- rc = video_register_device(g_server_dev.video_dev,
- VFL_TYPE_GRABBER, 100);
-
- mutex_init(&g_server_dev.server_lock);
- mutex_init(&g_server_dev.server_queue_lock);
- g_server_dev.pcam_active = NULL;
- g_server_dev.camera_info.num_cameras = 0;
- atomic_set(&g_server_dev.number_pcam_active, 0);
- g_server_dev.server_evt_id = 0;
-
- /*initialize fake video device and event queue*/
-
- g_server_dev.server_command_queue.pvdev = g_server_dev.video_dev;
- rc = msm_setup_v4l2_event_queue(
- &g_server_dev.server_command_queue.eventHandle,
- g_server_dev.server_command_queue.pvdev);
-
- if (rc < 0) {
- pr_err("%s failed to initialize event queue\n", __func__);
- video_device_release(g_server_dev.server_command_queue.pvdev);
- return rc;
- }
-
- for (i = 0; i < MAX_NUM_ACTIVE_CAMERA; i++) {
- struct msm_cam_server_queue *queue;
- queue = &g_server_dev.server_queue[i];
- queue->queue_active = 0;
- msm_queue_init(&queue->ctrl_q, "control");
- msm_queue_init(&queue->eventData_q, "eventdata");
- }
- return rc;
-}
+static struct v4l2_file_operations g_msm_fops = {
+ .owner = THIS_MODULE,
+ .open = msm_open,
+ .poll = msm_poll,
+ .mmap = msm_mmap,
+ .release = msm_close,
+ .ioctl = video_ioctl2,
+};
static int msm_cam_dev_init(struct msm_cam_v4l2_device *pcam)
{
@@ -3105,7 +1139,7 @@
strlcpy(pvdev->name, pcam->sensor_sdev->name, sizeof(pvdev->name));
pvdev->release = video_device_release;
- pvdev->fops = &g_msm_fops;
+ pvdev->fops = &g_msm_fops;
pvdev->ioctl_ops = &g_msm_ioctl_ops;
pvdev->minor = -1;
pvdev->vfl_type = 1;
@@ -3131,16 +1165,7 @@
pcam->pvdev = pvdev;
video_set_drvdata(pcam->pvdev, pcam);
- /* If isp HW registeration is successful,
- * then create event queue to
- * receievent event froms HW
- */
- /* yyan: no global - each sensor will
- * create a new vidoe node! */
- /* g_pmsm_camera_v4l2_dev = pmsm_camera_v4l2_dev; */
- /* g_pmsm_camera_v4l2_dev->pvdev = pvdev; */
-
- return rc ;
+ return rc;
reg_fail:
video_device_release(pvdev);
@@ -3281,46 +1306,7 @@
__func__, rc);
goto failure;
}
-
- g_server_dev.camera_info.video_dev_name
- [g_server_dev.camera_info.num_cameras]
- = video_device_node_name(pcam->pvdev);
- D("%s Connected video device %s\n", __func__,
- g_server_dev.camera_info.video_dev_name
- [g_server_dev.camera_info.num_cameras]);
-
- g_server_dev.camera_info.s_mount_angle
- [g_server_dev.camera_info.num_cameras]
- = sdata->sensor_platform_info->mount_angle;
-
- g_server_dev.camera_info.is_internal_cam
- [g_server_dev.camera_info.num_cameras]
- = sdata->camera_type;
-
- g_server_dev.mctl_node_info.mctl_node_name
- [g_server_dev.mctl_node_info.num_mctl_nodes]
- = video_device_node_name(pcam->mctl_node.pvdev);
-
- pr_info("%s mctl_node_name[%d] = %s\n", __func__,
- g_server_dev.mctl_node_info.num_mctl_nodes,
- g_server_dev.mctl_node_info.mctl_node_name
- [g_server_dev.mctl_node_info.num_mctl_nodes]);
-
- /*Temporary solution to store info in media device structure
- until we can expand media device structure to support more
- device info*/
- snprintf(pcam->media_dev.serial,
- sizeof(pcam->media_dev.serial),
- "%s-%d-%d", QCAMERA_NAME,
- sdata->sensor_platform_info->mount_angle,
- sdata->camera_type);
-
- g_server_dev.camera_info.num_cameras++;
- g_server_dev.mctl_node_info.num_mctl_nodes++;
-
- D("%s done, rc = %d\n", __func__, rc);
- D("%s number of sensors connected is %d\n", __func__,
- g_server_dev.camera_info.num_cameras);
+ msm_server_update_sensor_info(pcam, sdata);
/* register the subdevice, must be done for callbacks */
rc = msm_cam_register_subdev_node(sensor_sd, SENSOR_DEV, vnode_count);
@@ -3358,83 +1344,3 @@
}
EXPORT_SYMBOL(msm_sensor_register);
-static int __devinit msm_camera_probe(struct platform_device *pdev)
-{
- int rc = 0, i;
- /*for now just create a config 0 node
- put logic here later to know how many configs to create*/
- g_server_dev.config_info.num_config_nodes = 1;
-
- rc = msm_isp_init_module(g_server_dev.config_info.num_config_nodes);
- if (rc < 0) {
- pr_err("Failed to initialize isp\n");
- return rc;
- }
-
- if (!msm_class) {
- rc = alloc_chrdev_region(&msm_devno, 0,
- g_server_dev.config_info.num_config_nodes+1, "msm_camera");
- if (rc < 0) {
- pr_err("%s: failed to allocate chrdev: %d\n", __func__,
- rc);
- return rc;
- }
-
- msm_class = class_create(THIS_MODULE, "msm_camera");
- if (IS_ERR(msm_class)) {
- rc = PTR_ERR(msm_class);
- pr_err("%s: create device class failed: %d\n",
- __func__, rc);
- return rc;
- }
- }
-
- D("creating server and config nodes\n");
- rc = msm_setup_server_dev(pdev);
- if (rc < 0) {
- pr_err("%s: failed to create server dev: %d\n", __func__,
- rc);
- return rc;
- }
-
- for (i = 0; i < g_server_dev.config_info.num_config_nodes; i++) {
- rc = msm_setup_config_dev(i, "config");
- if (rc < 0) {
- pr_err("%s:failed to create config dev: %d\n",
- __func__, rc);
- return rc;
- }
- }
-
- msm_isp_register(&g_server_dev);
- return rc;
-}
-
-static int __exit msm_camera_exit(struct platform_device *pdev)
-{
- msm_isp_unregister(&g_server_dev);
- return 0;
-}
-
-
-static struct platform_driver msm_cam_server_driver = {
- .probe = msm_camera_probe,
- .remove = msm_camera_exit,
- .driver = {
- .name = "msm_cam_server",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init msm_camera_init(void)
-{
- return platform_driver_register(&msm_cam_server_driver);
-}
-
-static void __exit msm_cam_server_exit(void)
-{
- platform_driver_unregister(&msm_cam_server_driver);
-}
-
-module_init(msm_camera_init);
-module_exit(msm_cam_server_exit);
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 6798cbb..dfb7ca2 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -397,7 +397,6 @@
uint32_t queue_active;
struct msm_device_queue ctrl_q;
struct msm_device_queue eventData_q;
- struct msm_ctrl_cmd *ctrl;
uint8_t *ctrl_data;
uint32_t evt_id;
};
@@ -456,7 +455,6 @@
/* camera server related functions */
-
/* ISP related functions */
void msm_isp_vfe_dev_init(struct v4l2_subdev *vd);
/*
@@ -571,15 +569,14 @@
void msm_release_ion_client(struct kref *ref);
int msm_cam_register_subdev_node(struct v4l2_subdev *sd,
enum msm_cam_subdev_type sdev_type, uint8_t index);
-uint32_t msm_camera_get_mctl_handle(void);
-struct msm_cam_media_controller *msm_camera_get_mctl(uint32_t handle);
-void msm_camera_free_mctl(uint32_t handle);
int msm_server_open_client(int *p_qidx);
int msm_server_send_ctrl(struct msm_ctrl_cmd *out, int ctrl_id);
int msm_server_close_client(int idx);
int msm_cam_server_open_mctl_session(struct msm_cam_v4l2_device *pcam,
int *p_active);
int msm_cam_server_close_mctl_session(struct msm_cam_v4l2_device *pcam);
+long msm_v4l2_evt_notify(struct msm_cam_media_controller *mctl,
+ unsigned int cmd, unsigned long evt);
#endif /* __KERNEL__ */
#endif /* _MSM_H */
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index e9eb68f..19f9411 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -28,6 +28,7 @@
#include <linux/android_pmem.h>
#include "msm.h"
+#include "msm_cam_server.h"
#include "msm_csid.h"
#include "msm_csic.h"
#include "msm_csiphy.h"
@@ -858,13 +859,13 @@
pr_err("%s: param is NULL", __func__);
return -EINVAL;
}
- pcam->mctl_handle = msm_camera_get_mctl_handle();
+ pcam->mctl_handle = msm_cam_server_get_mctl_handle();
if (pcam->mctl_handle == 0) {
pr_err("%s: cannot get mctl handle", __func__);
return -EINVAL;
}
- pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
if (!pmctl) {
pr_err("%s: invalid mctl controller", __func__);
return -EINVAL;
@@ -903,7 +904,7 @@
struct msm_cam_media_controller *pmctl = NULL;
D("%s\n", __func__);
- pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
if (!pmctl) {
pr_err("%s: invalid mctl controller", __func__);
return -EINVAL;
@@ -911,7 +912,7 @@
mutex_destroy(&pmctl->lock);
wake_lock_destroy(&pmctl->wake_lock);
- msm_camera_free_mctl(pcam->mctl_handle);
+ msm_cam_server_free_mctl(pcam->mctl_handle);
return rc;
}
@@ -967,7 +968,7 @@
return rc;
}
- pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
if (!pmctl) {
pr_err("%s mctl NULL!\n", __func__);
return rc;
@@ -1043,7 +1044,7 @@
return -EINVAL;
}
- pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
mutex_lock(&pcam->mctl_node.dev_lock);
D("%s : active %d ", __func__, pcam->mctl_node.active);
if (pcam->mctl_node.active == 1) {
@@ -1478,7 +1479,7 @@
(void *)pfmt->fmt.pix.priv);
WARN_ON(pctx != f->private_data);
- pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
if (!pcam_inst->vbqueue_initialized) {
pmctl->mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
V4L2_BUF_TYPE_VIDEO_CAPTURE);
@@ -1502,7 +1503,7 @@
pcam_inst, pcam_inst->vbqueue_initialized);
WARN_ON(pctx != f->private_data);
- pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
if (!pcam_inst->vbqueue_initialized) {
pmctl->mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index 416e542..522ea7d 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -26,6 +26,7 @@
#include <linux/android_pmem.h>
#include "msm.h"
+#include "msm_cam_server.h"
#include "msm_ispif.h"
#ifdef CONFIG_MSM_CAMERA_DEBUG
@@ -113,7 +114,7 @@
pcam_inst->plane_info.plane[0].offset;
}
buf_idx = vb->v4l2_buf.index;
- pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
for (i = 0; i < vb->num_planes; i++) {
mem = vb2_plane_cookie(vb, i);
if (buf_type == VIDEOBUF2_MULTIPLE_PLANES)
@@ -251,7 +252,7 @@
}
spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
}
- pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
for (i = 0; i < vb->num_planes; i++) {
mem = vb2_plane_cookie(vb, i);
videobuf2_pmem_contig_user_put(mem, pmctl->client);
@@ -472,7 +473,7 @@
int msm_mctl_buf_init(struct msm_cam_v4l2_device *pcam)
{
struct msm_cam_media_controller *pmctl;
- pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
pmctl->mctl_vbqueue_init = msm_vbqueue_init;
return 0;
}
diff --git a/drivers/media/video/msm/msm_vfe31_v4l2.c b/drivers/media/video/msm/msm_vfe31_v4l2.c
index 89615ec..d5f37dc 100644
--- a/drivers/media/video/msm/msm_vfe31_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe31_v4l2.c
@@ -367,7 +367,6 @@
static void vfe31_stop(void)
{
- uint8_t axiBusyFlag = true;
unsigned long flags;
atomic_set(&vfe31_ctrl->vstate, 0);
@@ -397,7 +396,52 @@
* at any time. stop camif immediately. */
msm_camera_io_w_mb(CAMIF_COMMAND_STOP_IMMEDIATELY,
vfe31_ctrl->vfebase + VFE_CAMIF_COMMAND);
+}
+void axi_start(void)
+{
+ 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_camera_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
+ msm_camera_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_camera_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
+ msm_camera_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
+ msm_camera_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_camera_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch0]);
+ msm_camera_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_camera_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch0]);
+ msm_camera_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch1]);
+ msm_camera_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch2]);
+ }
+ break;
+ }
+}
+
+void axi_stop(void)
+{
+ uint8_t axiBusyFlag = true;
/* axi halt command. */
msm_camera_io_w(AXI_HALT,
vfe31_ctrl->vfebase + VFE_AXI_CMD);
@@ -954,43 +998,6 @@
}
msm_camera_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_camera_io_w(1, vfe31_ctrl->vfebase +
- vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
- msm_camera_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_camera_io_w(1, vfe31_ctrl->vfebase +
- vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe31_ctrl->vfebase +
- vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
- msm_camera_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_camera_io_w(1, vfe31_ctrl->vfebase +
- vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch0]);
- msm_camera_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_camera_io_w(1, vfe31_ctrl->vfebase +
- vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(1, vfe31_ctrl->vfebase +
- vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch1]);
- msm_camera_io_w(1, vfe31_ctrl->vfebase +
- vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch2]);
- }
- break;
- }
msm_camio_bus_scale_cfg(
pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
vfe31_start_common();
@@ -3325,12 +3332,14 @@
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;
+ if (NULL != cmd->value) {
+ 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. */
@@ -3571,6 +3580,14 @@
}
break;
+ case CMD_AXI_START:
+ axi_start();
+ break;
+
+ case CMD_AXI_STOP:
+ axi_stop();
+ break;
+
default:
pr_err("%s Unsupported AXI configuration %x ", __func__,
cmd->cmd_type);
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index d50b778..220752a 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -358,7 +358,6 @@
static void vfe32_stop(void)
{
- uint8_t axiBusyFlag = true;
unsigned long flags;
atomic_set(&vfe32_ctrl->vstate, 0);
@@ -389,31 +388,6 @@
msm_camera_io_w(CAMIF_COMMAND_STOP_IMMEDIATELY,
vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
- /* axi halt command. */
- msm_camera_io_w(AXI_HALT,
- vfe32_ctrl->vfebase + VFE_AXI_CMD);
- wmb();
- while (axiBusyFlag) {
- if (msm_camera_io_r(vfe32_ctrl->vfebase + VFE_AXI_STATUS) & 0x1)
- axiBusyFlag = false;
- }
- /* Ensure the write order while writing
- to the command register using the barrier */
- msm_camera_io_w_mb(AXI_HALT_CLEAR,
- vfe32_ctrl->vfebase + VFE_AXI_CMD);
-
- /* after axi halt, then ok to apply global reset. */
- /* enable reset_ack and async timer interrupt only while
- stopping the pipeline.*/
- msm_camera_io_w(0xf0000000,
- vfe32_ctrl->vfebase + VFE_IRQ_MASK_0);
- msm_camera_io_w(VFE_IMASK_WHILE_STOPPING_1,
- vfe32_ctrl->vfebase + VFE_IRQ_MASK_1);
-
- /* Ensure the write order while writing
- to the command register using the barrier */
- msm_camera_io_w_mb(VFE_RESET_UPON_STOP_CMD,
- vfe32_ctrl->vfebase + VFE_GLOBAL_RESET);
}
static void vfe32_subdev_notify(int id, int path)
@@ -910,7 +884,6 @@
static int vfe32_start(struct msm_cam_media_controller *pmctl)
{
uint32_t irq_comp_mask = 0;
-
irq_comp_mask =
msm_camera_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
@@ -934,44 +907,6 @@
}
msm_camera_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
- switch (vfe32_ctrl->operation_mode) {
- case VFE_OUTPUTS_PREVIEW:
- case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
- if (vfe32_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY) {
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
- } else if (vfe32_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch2]);
- }
- break;
- default:
- if (vfe32_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_SECONDARY) {
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
- } else if (vfe32_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch2]);
- }
- break;
- }
-
msm_camio_bus_scale_cfg(
pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
vfe32_start_common();
@@ -3998,23 +3933,97 @@
vfe32_ctrl->vfebase = 0;
}
+void axi_start(void)
+{
+ switch (vfe32_ctrl->operation_mode) {
+ case VFE_OUTPUTS_PREVIEW:
+ case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
+ if (vfe32_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY) {
+ msm_camera_io_w(1, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
+ msm_camera_io_w(1, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
+ } else if (vfe32_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+ msm_camera_io_w(1, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
+ msm_camera_io_w(1, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
+ msm_camera_io_w(1, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch2]);
+ }
+ break;
+ default:
+ if (vfe32_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_SECONDARY) {
+ msm_camera_io_w(1, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
+ msm_camera_io_w(1, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
+ } else if (vfe32_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+ msm_camera_io_w(1, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
+ msm_camera_io_w(1, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
+ msm_camera_io_w(1, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch2]);
+ }
+ break;
+ }
+}
+
+void axi_stop(void)
+{
+ uint8_t axiBusyFlag = true;
+ /* axi halt command. */
+ msm_camera_io_w(AXI_HALT,
+ vfe32_ctrl->vfebase + VFE_AXI_CMD);
+ wmb();
+ while (axiBusyFlag) {
+ if (msm_camera_io_r(vfe32_ctrl->vfebase + VFE_AXI_STATUS) & 0x1)
+ axiBusyFlag = false;
+ }
+ /* Ensure the write order while writing
+ to the command register using the barrier */
+ msm_camera_io_w_mb(AXI_HALT_CLEAR,
+ vfe32_ctrl->vfebase + VFE_AXI_CMD);
+
+ /* after axi halt, then ok to apply global reset. */
+ /* enable reset_ack and async timer interrupt only while
+ stopping the pipeline.*/
+ msm_camera_io_w(0xf0000000,
+ vfe32_ctrl->vfebase + VFE_IRQ_MASK_0);
+ msm_camera_io_w(VFE_IMASK_WHILE_STOPPING_1,
+ vfe32_ctrl->vfebase + VFE_IRQ_MASK_1);
+
+ /* Ensure the write order while writing
+ to the command register using the barrier */
+ msm_camera_io_w_mb(VFE_RESET_UPON_STOP_CMD,
+ vfe32_ctrl->vfebase + VFE_GLOBAL_RESET);
+}
+
static int msm_axi_config(struct v4l2_subdev *sd, void __user *arg)
{
struct msm_vfe_cfg_cmd cfgcmd;
struct msm_isp_cmd vfecmd;
int rc = 0;
- if (copy_from_user(&cfgcmd, arg, sizeof(cfgcmd))) {
- ERR_COPY_FROM_USER();
- return -EFAULT;
+ if (NULL != arg) {
+ if (copy_from_user(&cfgcmd, arg, sizeof(cfgcmd))) {
+ ERR_COPY_FROM_USER();
+ return -EFAULT;
+ }
}
-
- if (copy_from_user(&vfecmd,
- (void __user *)(cfgcmd.value),
- sizeof(vfecmd))) {
- pr_err("%s %d: copy_from_user failed\n", __func__,
- __LINE__);
- return -EFAULT;
+ if (NULL != cfgcmd.value) {
+ if (copy_from_user(&vfecmd,
+ (void __user *)(cfgcmd.value),
+ sizeof(vfecmd))) {
+ pr_err("%s %d: copy_from_user failed\n", __func__,
+ __LINE__);
+ return -EFAULT;
+ }
}
switch (cfgcmd.cmd_type) {
@@ -4117,6 +4126,12 @@
pr_err("%s Invalid/Unsupported AXI configuration %x",
__func__, cfgcmd.cmd_type);
break;
+ case CMD_AXI_START:
+ axi_start();
+ break;
+ case CMD_AXI_STOP:
+ axi_stop();
+ break;
default:
pr_err("%s Unsupported AXI configuration %x ", __func__,
cfgcmd.cmd_type);
diff --git a/drivers/media/video/msm/server/Makefile b/drivers/media/video/msm/server/Makefile
new file mode 100644
index 0000000..55abeed
--- /dev/null
+++ b/drivers/media/video/msm/server/Makefile
@@ -0,0 +1,11 @@
+GCC_VERSION := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
+
+ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
+ EXTRA_CFLAGS += -Idrivers/media/video/msm
+ EXTRA_CFLAGS += -Idrivers/media/video/msm/io
+ EXTRA_CFLAGS += -Idrivers/media/video/msm/csi
+ EXTRA_CFLAGS += -Idrivers/media/video/msm/eeprom
+ EXTRA_CFLAGS += -Idrivers/media/video/msm/sensors
+ EXTRA_CFLAGS += -Idrivers/media/video/msm/actuators
+ obj-$(CONFIG_MSM_CAMERA) += msm_cam_server.o
+endif
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
new file mode 100644
index 0000000..7154797f
--- /dev/null
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -0,0 +1,2318 @@
+/* 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 "msm_cam_server.h"
+#include "msm_csid.h"
+#include "msm_csic.h"
+#include "msm_csiphy.h"
+#include "msm_ispif.h"
+#include "msm_sensor.h"
+#include "msm_actuator.h"
+#include "msm_vfe32.h"
+
+#ifdef CONFIG_MSM_CAMERA_DEBUG
+#define D(fmt, args...) pr_debug("msm: " fmt, ##args)
+#else
+#define D(fmt, args...) do {} while (0)
+#endif
+
+static struct msm_cam_server_dev g_server_dev;
+static struct class *msm_class;
+static dev_t msm_devno;
+
+static long msm_server_send_v4l2_evt(void *evt);
+static void msm_cam_server_subdev_notify(struct v4l2_subdev *sd,
+ unsigned int notification, void *arg);
+
+static void msm_queue_init(struct msm_device_queue *queue, const char *name)
+{
+ D("%s\n", __func__);
+ spin_lock_init(&queue->lock);
+ queue->len = 0;
+ queue->max = 0;
+ queue->name = name;
+ INIT_LIST_HEAD(&queue->list);
+ init_waitqueue_head(&queue->wait);
+}
+
+static void msm_enqueue(struct msm_device_queue *queue,
+ struct list_head *entry)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&queue->lock, flags);
+ queue->len++;
+ if (queue->len > queue->max) {
+ queue->max = queue->len;
+ pr_info("%s: queue %s new max is %d\n", __func__,
+ queue->name, queue->max);
+ }
+ list_add_tail(entry, &queue->list);
+ wake_up(&queue->wait);
+ D("%s: woke up %s\n", __func__, queue->name);
+ spin_unlock_irqrestore(&queue->lock, flags);
+}
+
+static void msm_drain_eventq(struct msm_device_queue *queue)
+{
+ unsigned long flags;
+ struct msm_queue_cmd *qcmd;
+ struct msm_isp_event_ctrl *isp_event;
+ spin_lock_irqsave(&queue->lock, flags);
+ while (!list_empty(&queue->list)) {
+ qcmd = list_first_entry(&queue->list,
+ struct msm_queue_cmd, list_eventdata);
+ list_del_init(&qcmd->list_eventdata);
+ isp_event =
+ (struct msm_isp_event_ctrl *)
+ qcmd->command;
+ if (isp_event->isp_data.ctrl.value != NULL)
+ kfree(isp_event->isp_data.ctrl.value);
+ kfree(qcmd->command);
+ free_qcmd(qcmd);
+ }
+ spin_unlock_irqrestore(&queue->lock, flags);
+}
+
+int32_t msm_find_free_queue(void)
+{
+ int i;
+ for (i = 0; i < MAX_NUM_ACTIVE_CAMERA; i++) {
+ struct msm_cam_server_queue *queue;
+ queue = &g_server_dev.server_queue[i];
+ if (!queue->queue_active)
+ return i;
+ }
+ return -EINVAL;
+}
+
+uint32_t msm_cam_server_get_mctl_handle(void)
+{
+ uint32_t i;
+ if ((g_server_dev.mctl_handle_cnt << 8) == 0)
+ g_server_dev.mctl_handle_cnt++;
+ for (i = 0; i < MAX_NUM_ACTIVE_CAMERA; i++) {
+ if (g_server_dev.mctl[i].handle == 0) {
+ g_server_dev.mctl[i].handle =
+ (++g_server_dev.mctl_handle_cnt) << 8 | i;
+ memset(&g_server_dev.mctl[i].mctl,
+ 0, sizeof(g_server_dev.mctl[i].mctl));
+ return g_server_dev.mctl[i].handle;
+ }
+ }
+ return 0;
+}
+
+void msm_cam_server_free_mctl(uint32_t handle)
+{
+ uint32_t mctl_index;
+ mctl_index = handle & 0xff;
+ if ((mctl_index < MAX_NUM_ACTIVE_CAMERA) &&
+ (g_server_dev.mctl[mctl_index].handle == handle))
+ g_server_dev.mctl[mctl_index].handle = 0;
+ else
+ pr_err("%s: invalid free handle\n", __func__);
+}
+
+struct msm_cam_media_controller *msm_cam_server_get_mctl(uint32_t handle)
+{
+ uint32_t mctl_index;
+ mctl_index = handle & 0xff;
+ if ((mctl_index < MAX_NUM_ACTIVE_CAMERA) &&
+ (g_server_dev.mctl[mctl_index].handle == handle))
+ return &g_server_dev.mctl[mctl_index].mctl;
+ return NULL;
+}
+
+static int msm_ctrl_cmd_done(void *arg)
+{
+ void __user *uptr;
+ struct msm_queue_cmd *qcmd;
+ struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg;
+ struct msm_ctrl_cmd *command;
+ D("%s\n", __func__);
+
+ command = kzalloc(sizeof(struct msm_ctrl_cmd), GFP_KERNEL);
+ if (!command) {
+ pr_err("%s Insufficient memory. return", __func__);
+ goto command_alloc_fail;
+ }
+
+ qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_KERNEL);
+ if (!qcmd) {
+ pr_err("%s Insufficient memory. return", __func__);
+ goto qcmd_alloc_fail;
+ }
+
+ mutex_lock(&g_server_dev.server_queue_lock);
+
+ if (copy_from_user(command, (void __user *)ioctl_ptr->ioctl_ptr,
+ sizeof(struct msm_ctrl_cmd))) {
+ pr_err("%s: copy_from_user failed, size=%d\n",
+ __func__, sizeof(struct msm_ctrl_cmd));
+ goto ctrl_cmd_done_error;
+ }
+
+ if (!g_server_dev.server_queue[command->queue_idx].queue_active) {
+ pr_err("%s: Invalid queue\n", __func__);
+ goto ctrl_cmd_done_error;
+ }
+
+ D("%s qid %d evtid %d %d\n", __func__, command->queue_idx,
+ command->evt_id,
+ g_server_dev.server_queue[command->queue_idx].evt_id);
+
+ if (command->evt_id !=
+ g_server_dev.server_queue[command->queue_idx].evt_id) {
+ pr_err("Invalid event id from userspace\n");
+ goto ctrl_cmd_done_error;
+ }
+
+ atomic_set(&qcmd->on_heap, 1);
+ uptr = command->value;
+ qcmd->command = command;
+
+ if (command->length > 0) {
+ command->value =
+ g_server_dev.server_queue[command->queue_idx].ctrl_data;
+ if (command->length > max_control_command_size) {
+ pr_err("%s: user data %d is too big (max %d)\n",
+ __func__, command->length,
+ max_control_command_size);
+ goto ctrl_cmd_done_error;
+ }
+ if (copy_from_user(command->value, uptr, command->length)) {
+ pr_err("%s: copy_from_user failed, size=%d\n",
+ __func__, sizeof(struct msm_ctrl_cmd));
+ goto ctrl_cmd_done_error;
+ }
+ }
+ msm_enqueue(&g_server_dev.server_queue
+ [command->queue_idx].ctrl_q, &qcmd->list_control);
+ mutex_unlock(&g_server_dev.server_queue_lock);
+ return 0;
+
+ctrl_cmd_done_error:
+ mutex_unlock(&g_server_dev.server_queue_lock);
+ free_qcmd(qcmd);
+qcmd_alloc_fail:
+ kfree(command);
+command_alloc_fail:
+ return -EINVAL;
+}
+
+/* send control command to config and wait for results*/
+static int msm_server_control(struct msm_cam_server_dev *server_dev,
+ struct msm_ctrl_cmd *out)
+{
+ int rc = 0;
+ void *value;
+ struct msm_queue_cmd *rcmd;
+ struct msm_queue_cmd *event_qcmd;
+ struct msm_ctrl_cmd *ctrlcmd;
+ struct msm_device_queue *queue =
+ &server_dev->server_queue[out->queue_idx].ctrl_q;
+
+ struct v4l2_event v4l2_evt;
+ struct msm_isp_event_ctrl *isp_event;
+ void *ctrlcmd_data;
+
+ event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_KERNEL);
+ if (!event_qcmd) {
+ pr_err("%s Insufficient memory. return", __func__);
+ rc = -ENOMEM;
+ goto event_qcmd_alloc_fail;
+ }
+
+ isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl), GFP_KERNEL);
+ if (!isp_event) {
+ pr_err("%s Insufficient memory. return", __func__);
+ rc = -ENOMEM;
+ goto isp_event_alloc_fail;
+ }
+
+ D("%s\n", __func__);
+ mutex_lock(&server_dev->server_queue_lock);
+ if (++server_dev->server_evt_id == 0)
+ server_dev->server_evt_id++;
+
+ D("%s qid %d evtid %d\n", __func__, out->queue_idx,
+ server_dev->server_evt_id);
+ server_dev->server_queue[out->queue_idx].evt_id =
+ server_dev->server_evt_id;
+ v4l2_evt.type = V4L2_EVENT_PRIVATE_START + MSM_CAM_RESP_V4L2;
+ v4l2_evt.u.data[0] = out->queue_idx;
+ /* setup event object to transfer the command; */
+ isp_event->resptype = MSM_CAM_RESP_V4L2;
+ isp_event->isp_data.ctrl = *out;
+ isp_event->isp_data.ctrl.evt_id = server_dev->server_evt_id;
+
+ if (out->value != NULL && out->length != 0) {
+ ctrlcmd_data = kzalloc(out->length, GFP_KERNEL);
+ if (!ctrlcmd_data) {
+ rc = -ENOMEM;
+ goto ctrlcmd_alloc_fail;
+ }
+ memcpy(ctrlcmd_data, out->value, out->length);
+ isp_event->isp_data.ctrl.value = ctrlcmd_data;
+ }
+
+ atomic_set(&event_qcmd->on_heap, 1);
+ event_qcmd->command = isp_event;
+
+ msm_enqueue(&server_dev->server_queue[out->queue_idx].eventData_q,
+ &event_qcmd->list_eventdata);
+
+ /* now send command to config thread in userspace,
+ * and wait for results */
+ v4l2_event_queue(server_dev->server_command_queue.pvdev,
+ &v4l2_evt);
+ D("%s v4l2_event_queue: type = 0x%x\n", __func__, v4l2_evt.type);
+ mutex_unlock(&server_dev->server_queue_lock);
+
+ /* wait for config return status */
+ D("Waiting for config status\n");
+ rc = wait_event_interruptible_timeout(queue->wait,
+ !list_empty_careful(&queue->list),
+ msecs_to_jiffies(out->timeout_ms));
+ D("Waiting is over for config status\n");
+ if (list_empty_careful(&queue->list)) {
+ if (!rc)
+ rc = -ETIMEDOUT;
+ if (rc < 0) {
+ if (++server_dev->server_evt_id == 0)
+ server_dev->server_evt_id++;
+ pr_err("%s: wait_event error %d\n", __func__, rc);
+ return rc;
+ }
+ }
+
+ rcmd = msm_dequeue(queue, list_control);
+ BUG_ON(!rcmd);
+ D("%s Finished servicing ioctl\n", __func__);
+
+ ctrlcmd = (struct msm_ctrl_cmd *)(rcmd->command);
+ value = out->value;
+ if (ctrlcmd->length > 0 && value != NULL &&
+ ctrlcmd->length <= out->length)
+ memcpy(value, ctrlcmd->value, ctrlcmd->length);
+
+ memcpy(out, ctrlcmd, sizeof(struct msm_ctrl_cmd));
+ out->value = value;
+
+ kfree(ctrlcmd);
+ free_qcmd(rcmd);
+ D("%s: rc %d\n", __func__, rc);
+ /* rc is the time elapsed. */
+ if (rc >= 0) {
+ /* TODO: Refactor msm_ctrl_cmd::status field */
+ if (out->status == 0)
+ rc = -1;
+ else if (out->status == 1 || out->status == 4)
+ rc = 0;
+ else
+ rc = -EINVAL;
+ }
+ return rc;
+
+ctrlcmd_alloc_fail:
+ kfree(isp_event);
+isp_event_alloc_fail:
+ kfree(event_qcmd);
+event_qcmd_alloc_fail:
+ return rc;
+}
+
+int msm_server_get_crop(struct msm_cam_v4l2_device *pcam,
+ int idx, struct v4l2_crop *crop)
+{
+ int rc = 0;
+ struct msm_ctrl_cmd ctrlcmd;
+
+ BUG_ON(crop == NULL);
+
+ ctrlcmd.type = MSM_V4L2_GET_CROP;
+ ctrlcmd.length = sizeof(struct v4l2_crop);
+ ctrlcmd.value = (void *)crop;
+ ctrlcmd.timeout_ms = 1000;
+ ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
+ ctrlcmd.stream_type = pcam->dev_inst[idx]->image_mode;
+ ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
+
+ /* send command to config thread in userspace, and get return value */
+ rc = msm_server_control(&g_server_dev, &ctrlcmd);
+ D("%s: rc = %d\n", __func__, rc);
+
+ return rc;
+}
+
+/*send open command to server*/
+int msm_send_open_server(struct msm_cam_v4l2_device *pcam)
+{
+ int rc = 0;
+ struct msm_ctrl_cmd ctrlcmd;
+ D("%s qid %d\n", __func__, pcam->server_queue_idx);
+ ctrlcmd.type = MSM_V4L2_OPEN;
+ ctrlcmd.timeout_ms = 10000;
+ ctrlcmd.length = strnlen(g_server_dev.config_info.config_dev_name[0],
+ MAX_DEV_NAME_LEN)+1;
+ ctrlcmd.value = (char *)g_server_dev.config_info.config_dev_name[0];
+ ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
+ ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
+
+ /* send command to config thread in usersspace, and get return value */
+ rc = msm_server_control(&g_server_dev, &ctrlcmd);
+
+ return rc;
+}
+
+int msm_send_close_server(struct msm_cam_v4l2_device *pcam)
+{
+ int rc = 0;
+ struct msm_ctrl_cmd ctrlcmd;
+ D("%s qid %d\n", __func__, pcam->server_queue_idx);
+ ctrlcmd.type = MSM_V4L2_CLOSE;
+ ctrlcmd.timeout_ms = 10000;
+ ctrlcmd.length = strnlen(g_server_dev.config_info.config_dev_name[0],
+ MAX_DEV_NAME_LEN)+1;
+ ctrlcmd.value = (char *)g_server_dev.config_info.config_dev_name[0];
+ ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
+ ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
+
+ /* send command to config thread in usersspace, and get return value */
+ rc = msm_server_control(&g_server_dev, &ctrlcmd);
+
+ return rc;
+}
+
+int msm_server_set_fmt(struct msm_cam_v4l2_device *pcam, int idx,
+ struct v4l2_format *pfmt)
+{
+ int rc = 0;
+ int i = 0;
+ struct v4l2_pix_format *pix = &pfmt->fmt.pix;
+ struct msm_ctrl_cmd ctrlcmd;
+ struct img_plane_info plane_info;
+
+ plane_info.width = pix->width;
+ plane_info.height = pix->height;
+ plane_info.pixelformat = pix->pixelformat;
+ plane_info.buffer_type = pfmt->type;
+ plane_info.ext_mode = pcam->dev_inst[idx]->image_mode;
+ plane_info.num_planes = 1;
+ D("%s: %d, %d, 0x%x\n", __func__,
+ pfmt->fmt.pix.width, pfmt->fmt.pix.height,
+ pfmt->fmt.pix.pixelformat);
+
+ if (pfmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ D("%s, Attention! Wrong buf-type %d\n", __func__, pfmt->type);
+
+ for (i = 0; i < pcam->num_fmts; i++)
+ if (pcam->usr_fmts[i].fourcc == pix->pixelformat)
+ break;
+ if (i == pcam->num_fmts) {
+ pr_err("%s: User requested pixelformat %x not supported\n",
+ __func__, pix->pixelformat);
+ return -EINVAL;
+ }
+
+ ctrlcmd.type = MSM_V4L2_VID_CAP_TYPE;
+ ctrlcmd.length = sizeof(struct img_plane_info);
+ ctrlcmd.value = (void *)&plane_info;
+ ctrlcmd.timeout_ms = 10000;
+ ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
+ ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
+
+ /* send command to config thread in usersspace, and get return value */
+ rc = msm_server_control(&g_server_dev, &ctrlcmd);
+
+ if (rc >= 0) {
+ pcam->dev_inst[idx]->vid_fmt = *pfmt;
+ pcam->dev_inst[idx]->sensor_pxlcode
+ = pcam->usr_fmts[i].pxlcode;
+ D("%s:inst=0x%x,idx=%d,width=%d,heigth=%d\n",
+ __func__, (u32)pcam->dev_inst[idx], idx,
+ pcam->dev_inst[idx]->vid_fmt.fmt.pix.width,
+ pcam->dev_inst[idx]->vid_fmt.fmt.pix.height);
+ pcam->dev_inst[idx]->plane_info = plane_info;
+ }
+
+ return rc;
+}
+
+int msm_server_set_fmt_mplane(struct msm_cam_v4l2_device *pcam, int idx,
+ struct v4l2_format *pfmt)
+{
+ int rc = 0;
+ int i = 0;
+ struct v4l2_pix_format_mplane *pix_mp = &pfmt->fmt.pix_mp;
+ struct msm_ctrl_cmd ctrlcmd;
+ struct img_plane_info plane_info;
+
+ plane_info.width = pix_mp->width;
+ plane_info.height = pix_mp->height;
+ plane_info.pixelformat = pix_mp->pixelformat;
+ plane_info.buffer_type = pfmt->type;
+ plane_info.ext_mode = pcam->dev_inst[idx]->image_mode;
+ plane_info.num_planes = pix_mp->num_planes;
+ if (plane_info.num_planes <= 0 ||
+ plane_info.num_planes > VIDEO_MAX_PLANES) {
+ pr_err("%s Invalid number of planes set %d", __func__,
+ plane_info.num_planes);
+ return -EINVAL;
+ }
+ D("%s: %d, %d, 0x%x\n", __func__,
+ pfmt->fmt.pix_mp.width, pfmt->fmt.pix_mp.height,
+ pfmt->fmt.pix_mp.pixelformat);
+
+ if (pfmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ pr_err("%s, Attention! Wrong buf-type %d\n",
+ __func__, pfmt->type);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < pcam->num_fmts; i++)
+ if (pcam->usr_fmts[i].fourcc == pix_mp->pixelformat)
+ break;
+ if (i == pcam->num_fmts) {
+ pr_err("%s: User requested pixelformat %x not supported\n",
+ __func__, pix_mp->pixelformat);
+ return -EINVAL;
+ }
+
+ ctrlcmd.type = MSM_V4L2_VID_CAP_TYPE;
+ ctrlcmd.length = sizeof(struct img_plane_info);
+ ctrlcmd.value = (void *)&plane_info;
+ ctrlcmd.timeout_ms = 10000;
+ ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
+
+ /* send command to config thread in usersspace, and get return value */
+ rc = msm_server_control(&g_server_dev, &ctrlcmd);
+ if (rc >= 0) {
+ pcam->dev_inst[idx]->vid_fmt = *pfmt;
+ pcam->dev_inst[idx]->sensor_pxlcode
+ = pcam->usr_fmts[i].pxlcode;
+ D("%s:inst=0x%x,idx=%d,width=%d,heigth=%d\n",
+ __func__, (u32)pcam->dev_inst[idx], idx,
+ pcam->dev_inst[idx]->vid_fmt.fmt.pix_mp.width,
+ pcam->dev_inst[idx]->vid_fmt.fmt.pix_mp.height);
+ pcam->dev_inst[idx]->plane_info = plane_info;
+ }
+
+ return rc;
+}
+
+int msm_server_streamon(struct msm_cam_v4l2_device *pcam, int idx)
+{
+ int rc = 0;
+ struct msm_ctrl_cmd ctrlcmd;
+ D("%s\n", __func__);
+ ctrlcmd.type = MSM_V4L2_STREAM_ON;
+ ctrlcmd.timeout_ms = 10000;
+ ctrlcmd.length = 0;
+ ctrlcmd.value = NULL;
+ ctrlcmd.stream_type = pcam->dev_inst[idx]->image_mode;
+ ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
+ ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
+
+
+ /* send command to config thread in usersspace, and get return value */
+ rc = msm_server_control(&g_server_dev, &ctrlcmd);
+
+ return rc;
+}
+
+int msm_server_streamoff(struct msm_cam_v4l2_device *pcam, int idx)
+{
+ int rc = 0;
+ struct msm_ctrl_cmd ctrlcmd;
+
+ D("%s, pcam = 0x%x\n", __func__, (u32)pcam);
+ ctrlcmd.type = MSM_V4L2_STREAM_OFF;
+ ctrlcmd.timeout_ms = 10000;
+ ctrlcmd.length = 0;
+ ctrlcmd.value = NULL;
+ ctrlcmd.stream_type = pcam->dev_inst[idx]->image_mode;
+ ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
+ ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
+
+ /* send command to config thread in usersspace, and get return value */
+ rc = msm_server_control(&g_server_dev, &ctrlcmd);
+
+ return rc;
+}
+
+int msm_server_proc_ctrl_cmd(struct msm_cam_v4l2_device *pcam,
+ struct v4l2_control *ctrl, int is_set_cmd)
+{
+ int rc = 0;
+ struct msm_ctrl_cmd ctrlcmd, *tmp_cmd;
+ uint8_t *ctrl_data = NULL;
+ void __user *uptr_cmd;
+ void __user *uptr_value;
+ uint32_t cmd_len = sizeof(struct msm_ctrl_cmd);
+ uint32_t value_len;
+
+ tmp_cmd = (struct msm_ctrl_cmd *)ctrl->value;
+ uptr_cmd = (void __user *)ctrl->value;
+ uptr_value = (void __user *)tmp_cmd->value;
+ value_len = tmp_cmd->length;
+
+ D("%s: cmd type = %d, up1=0x%x, ulen1=%d, up2=0x%x, ulen2=%d\n",
+ __func__, tmp_cmd->type, (uint32_t)uptr_cmd, cmd_len,
+ (uint32_t)uptr_value, tmp_cmd->length);
+
+ ctrl_data = kzalloc(value_len+cmd_len, GFP_KERNEL);
+ if (ctrl_data == 0) {
+ pr_err("%s could not allocate memory\n", __func__);
+ rc = -ENOMEM;
+ goto end;
+ }
+ tmp_cmd = (struct msm_ctrl_cmd *)ctrl_data;
+ if (copy_from_user((void *)ctrl_data, uptr_cmd,
+ cmd_len)) {
+ pr_err("%s: copy_from_user failed.\n", __func__);
+ rc = -EINVAL;
+ goto end;
+ }
+ tmp_cmd->value = (void *)(ctrl_data+cmd_len);
+ if (uptr_value && tmp_cmd->length > 0) {
+ if (copy_from_user((void *)tmp_cmd->value, uptr_value,
+ value_len)) {
+ pr_err("%s: copy_from_user failed, size=%d\n",
+ __func__, value_len);
+ rc = -EINVAL;
+ goto end;
+ }
+ } else
+ tmp_cmd->value = NULL;
+
+ ctrlcmd.type = MSM_V4L2_SET_CTRL_CMD;
+ ctrlcmd.length = cmd_len + value_len;
+ ctrlcmd.value = (void *)ctrl_data;
+ if (tmp_cmd->timeout_ms > 0)
+ ctrlcmd.timeout_ms = tmp_cmd->timeout_ms;
+ else
+ ctrlcmd.timeout_ms = 1000;
+ ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
+ ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
+ /* send command to config thread in usersspace, and get return value */
+ rc = msm_server_control(&g_server_dev, &ctrlcmd);
+ D("%s: msm_server_control rc=%d\n", __func__, rc);
+ if (rc == 0) {
+ if (uptr_value && tmp_cmd->length > 0 &&
+ copy_to_user((void __user *)uptr_value,
+ (void *)(ctrl_data+cmd_len), tmp_cmd->length)) {
+ pr_err("%s: copy_to_user failed, size=%d\n",
+ __func__, tmp_cmd->length);
+ rc = -EINVAL;
+ goto end;
+ }
+ tmp_cmd->value = uptr_value;
+ if (copy_to_user((void __user *)uptr_cmd,
+ (void *)tmp_cmd, cmd_len)) {
+ pr_err("%s: copy_to_user failed in cpy, size=%d\n",
+ __func__, cmd_len);
+ rc = -EINVAL;
+ goto end;
+ }
+ }
+end:
+ D("%s: END, type = %d, vaddr = 0x%x, vlen = %d, status = %d, rc = %d\n",
+ __func__, tmp_cmd->type, (uint32_t)tmp_cmd->value,
+ tmp_cmd->length, tmp_cmd->status, rc);
+ kfree(ctrl_data);
+ return rc;
+}
+
+int msm_server_s_ctrl(struct msm_cam_v4l2_device *pcam,
+ struct v4l2_control *ctrl)
+{
+ int rc = 0;
+ struct msm_ctrl_cmd ctrlcmd;
+ uint8_t ctrl_data[max_control_command_size];
+
+ WARN_ON(ctrl == NULL);
+ if (ctrl == NULL) {
+ pr_err("%s Invalid control\n", __func__);
+ return -EINVAL;
+ }
+ if (ctrl->id == MSM_V4L2_PID_CTRL_CMD)
+ return msm_server_proc_ctrl_cmd(pcam, ctrl, 1);
+
+ memset(ctrl_data, 0, sizeof(ctrl_data));
+
+ ctrlcmd.type = MSM_V4L2_SET_CTRL;
+ ctrlcmd.length = sizeof(struct v4l2_control);
+ ctrlcmd.value = (void *)ctrl_data;
+ memcpy(ctrlcmd.value, ctrl, ctrlcmd.length);
+ ctrlcmd.timeout_ms = 1000;
+ ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
+ ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
+
+ /* send command to config thread in usersspace, and get return value */
+ rc = msm_server_control(&g_server_dev, &ctrlcmd);
+
+ return rc;
+}
+
+int msm_server_g_ctrl(struct msm_cam_v4l2_device *pcam,
+ struct v4l2_control *ctrl)
+{
+ int rc = 0;
+ struct msm_ctrl_cmd ctrlcmd;
+ uint8_t ctrl_data[max_control_command_size];
+
+ WARN_ON(ctrl == NULL);
+ if (ctrl == NULL) {
+ pr_err("%s Invalid control\n", __func__);
+ return -EINVAL;
+ }
+ if (ctrl->id == MSM_V4L2_PID_CTRL_CMD)
+ return msm_server_proc_ctrl_cmd(pcam, ctrl, 0);
+
+ memset(ctrl_data, 0, sizeof(ctrl_data));
+
+ ctrlcmd.type = MSM_V4L2_GET_CTRL;
+ ctrlcmd.length = sizeof(struct v4l2_control);
+ ctrlcmd.value = (void *)ctrl_data;
+ memcpy(ctrlcmd.value, ctrl, ctrlcmd.length);
+ ctrlcmd.timeout_ms = 1000;
+ ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
+ ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
+
+ /* send command to config thread in usersspace, and get return value */
+ rc = msm_server_control(&g_server_dev, &ctrlcmd);
+
+ ctrl->value = ((struct v4l2_control *)ctrlcmd.value)->value;
+
+ return rc;
+}
+
+int msm_server_q_ctrl(struct msm_cam_v4l2_device *pcam,
+ struct v4l2_queryctrl *queryctrl)
+{
+ int rc = 0;
+ struct msm_ctrl_cmd ctrlcmd;
+ uint8_t ctrl_data[max_control_command_size];
+
+ WARN_ON(queryctrl == NULL);
+ memset(ctrl_data, 0, sizeof(ctrl_data));
+
+ ctrlcmd.type = MSM_V4L2_QUERY_CTRL;
+ ctrlcmd.length = sizeof(struct v4l2_queryctrl);
+ ctrlcmd.value = (void *)ctrl_data;
+ memcpy(ctrlcmd.value, queryctrl, ctrlcmd.length);
+ ctrlcmd.timeout_ms = 1000;
+ ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
+ ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
+
+ /* send command to config thread in userspace, and get return value */
+ rc = msm_server_control(&g_server_dev, &ctrlcmd);
+ D("%s: rc = %d\n", __func__, rc);
+
+ if (rc >= 0)
+ memcpy(queryctrl, ctrlcmd.value, sizeof(struct v4l2_queryctrl));
+
+ return rc;
+}
+
+int msm_server_get_fmt(struct msm_cam_v4l2_device *pcam,
+ int idx, struct v4l2_format *pfmt)
+{
+ struct v4l2_pix_format *pix = &pfmt->fmt.pix;
+
+ pix->width = pcam->dev_inst[idx]->vid_fmt.fmt.pix.width;
+ pix->height = pcam->dev_inst[idx]->vid_fmt.fmt.pix.height;
+ pix->field = pcam->dev_inst[idx]->vid_fmt.fmt.pix.field;
+ pix->pixelformat = pcam->dev_inst[idx]->vid_fmt.fmt.pix.pixelformat;
+ pix->bytesperline = pcam->dev_inst[idx]->vid_fmt.fmt.pix.bytesperline;
+ pix->colorspace = pcam->dev_inst[idx]->vid_fmt.fmt.pix.colorspace;
+ if (pix->bytesperline < 0)
+ return pix->bytesperline;
+
+ pix->sizeimage = pix->height * pix->bytesperline;
+
+ return 0;
+}
+
+int msm_server_get_fmt_mplane(struct msm_cam_v4l2_device *pcam,
+ int idx, struct v4l2_format *pfmt)
+{
+ *pfmt = pcam->dev_inst[idx]->vid_fmt;
+ return 0;
+}
+
+int msm_server_try_fmt(struct msm_cam_v4l2_device *pcam,
+ struct v4l2_format *pfmt)
+{
+ int rc = 0;
+ int i = 0;
+ struct v4l2_pix_format *pix = &pfmt->fmt.pix;
+
+ D("%s: 0x%x\n", __func__, pix->pixelformat);
+ if (pfmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ pr_err("%s: pfmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE!\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ /* check if the format is supported by this host-sensor combo */
+ for (i = 0; i < pcam->num_fmts; i++) {
+ D("%s: usr_fmts.fourcc: 0x%x\n", __func__,
+ pcam->usr_fmts[i].fourcc);
+ if (pcam->usr_fmts[i].fourcc == pix->pixelformat)
+ break;
+ }
+
+ if (i == pcam->num_fmts) {
+ pr_err("%s: Format %x not found\n", __func__, pix->pixelformat);
+ return -EINVAL;
+ }
+ return rc;
+}
+
+int msm_server_try_fmt_mplane(struct msm_cam_v4l2_device *pcam,
+ struct v4l2_format *pfmt)
+{
+ int rc = 0;
+ int i = 0;
+ struct v4l2_pix_format_mplane *pix_mp = &pfmt->fmt.pix_mp;
+
+ D("%s: 0x%x\n", __func__, pix_mp->pixelformat);
+ if (pfmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ pr_err("%s: Incorrect format type %d ",
+ __func__, pfmt->type);
+ return -EINVAL;
+ }
+
+ /* check if the format is supported by this host-sensor combo */
+ for (i = 0; i < pcam->num_fmts; i++) {
+ D("%s: usr_fmts.fourcc: 0x%x\n", __func__,
+ pcam->usr_fmts[i].fourcc);
+ if (pcam->usr_fmts[i].fourcc == pix_mp->pixelformat)
+ break;
+ }
+
+ if (i == pcam->num_fmts) {
+ pr_err("%s: Format %x not found\n",
+ __func__, pix_mp->pixelformat);
+ return -EINVAL;
+ }
+ return rc;
+}
+
+int msm_server_v4l2_subscribe_event(struct v4l2_fh *fh,
+ struct v4l2_event_subscription *sub)
+{
+ int rc = 0;
+
+ D("%s: fh = 0x%x, type = 0x%x", __func__, (u32)fh, sub->type);
+ if (sub->type == V4L2_EVENT_ALL) {
+ /*sub->type = MSM_ISP_EVENT_START;*/
+ sub->type = V4L2_EVENT_PRIVATE_START + MSM_CAM_RESP_CTRL;
+ D("sub->type start = 0x%x\n", sub->type);
+ do {
+ rc = v4l2_event_subscribe(fh, sub);
+ if (rc < 0) {
+ D("%s: failed for evtType = 0x%x, rc = %d\n",
+ __func__, sub->type, rc);
+ /* unsubscribe all events here and return */
+ sub->type = V4L2_EVENT_ALL;
+ v4l2_event_unsubscribe(fh, sub);
+ return rc;
+ } else
+ D("%s: subscribed evtType = 0x%x, rc = %d\n",
+ __func__, sub->type, rc);
+ sub->type++;
+ D("sub->type while = 0x%x\n", sub->type);
+ } while (sub->type !=
+ V4L2_EVENT_PRIVATE_START + MSM_SVR_RESP_MAX);
+ } else {
+ D("sub->type not V4L2_EVENT_ALL = 0x%x\n", sub->type);
+ rc = v4l2_event_subscribe(fh, sub);
+ if (rc < 0)
+ D("%s: failed for evtType = 0x%x, rc = %d\n",
+ __func__, sub->type, rc);
+ }
+
+ D("%s: rc = %d\n", __func__, rc);
+ return rc;
+}
+
+int msm_server_v4l2_unsubscribe_event(struct v4l2_fh *fh,
+ struct v4l2_event_subscription *sub)
+{
+ int rc = 0;
+
+ D("%s: fh = 0x%x\n", __func__, (u32)fh);
+ rc = v4l2_event_unsubscribe(fh, sub);
+ D("%s: rc = %d\n", __func__, rc);
+ return rc;
+}
+
+/* open an active camera session to manage the streaming logic */
+static int msm_cam_server_open_session(struct msm_cam_server_dev *ps,
+ struct msm_cam_v4l2_device *pcam)
+{
+ int rc = 0;
+ struct msm_cam_media_controller *pmctl;
+
+ D("%s\n", __func__);
+
+ if (!ps || !pcam) {
+ pr_err("%s NULL pointer passed in!\n", __func__);
+ return rc;
+ }
+
+ /* The number of camera instance should be controlled by the
+ resource manager. Currently supporting one active instance
+ until multiple instances are supported */
+ if (atomic_read(&ps->number_pcam_active) > 0) {
+ pr_err("%s Cannot have more than one active camera %d\n",
+ __func__, atomic_read(&ps->number_pcam_active));
+ return -EINVAL;
+ }
+ /* book keeping this camera session*/
+ ps->pcam_active = pcam;
+ atomic_inc(&ps->number_pcam_active);
+
+ D("config pcam = 0x%p\n", ps->pcam_active);
+
+ /* initialization the media controller module*/
+ msm_mctl_init(pcam);
+
+ /*for single VFE msms (8660, 8960v1), just populate the session
+ with our VFE devices that registered*/
+ pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
+ pmctl->axi_sdev = ps->axi_device[0];
+ pmctl->isp_sdev = ps->isp_subdev[0];
+ return rc;
+}
+
+/* close an active camera session to server */
+static int msm_cam_server_close_session(struct msm_cam_server_dev *ps,
+ struct msm_cam_v4l2_device *pcam)
+{
+ int rc = 0;
+ D("%s\n", __func__);
+
+ if (!ps || !pcam) {
+ D("%s NULL pointer passed in!\n", __func__);
+ return rc;
+ }
+
+
+ atomic_dec(&ps->number_pcam_active);
+ ps->pcam_active = NULL;
+
+ msm_mctl_free(pcam);
+ return rc;
+}
+
+static long msm_ioctl_server(struct file *file, void *fh,
+ bool valid_prio, int cmd, void *arg)
+{
+ int rc = -EINVAL;
+ struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg;
+ struct msm_camera_info temp_cam_info;
+ struct msm_cam_config_dev_info temp_config_info;
+ struct msm_mctl_node_info temp_mctl_info;
+ int i;
+
+ D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
+
+ switch (cmd) {
+ case MSM_CAM_V4L2_IOCTL_GET_CAMERA_INFO:
+ if (copy_from_user(&temp_cam_info,
+ (void __user *)ioctl_ptr->ioctl_ptr,
+ sizeof(struct msm_camera_info))) {
+ pr_err("%s Copy from user failed for cmd %d",
+ __func__, cmd);
+ rc = -EINVAL;
+ return rc;
+ }
+ for (i = 0; i < g_server_dev.camera_info.num_cameras; i++) {
+ if (copy_to_user((void __user *)
+ temp_cam_info.video_dev_name[i],
+ g_server_dev.camera_info.video_dev_name[i],
+ strnlen(g_server_dev.camera_info.video_dev_name[i],
+ MAX_DEV_NAME_LEN))) {
+ pr_err("%s Copy to user failed for cmd %d",
+ __func__, cmd);
+ rc = -EINVAL;
+ return rc;
+ }
+ temp_cam_info.has_3d_support[i] =
+ g_server_dev.camera_info.has_3d_support[i];
+ temp_cam_info.is_internal_cam[i] =
+ g_server_dev.camera_info.is_internal_cam[i];
+ temp_cam_info.s_mount_angle[i] =
+ g_server_dev.camera_info.s_mount_angle[i];
+ temp_cam_info.sensor_type[i] =
+ g_server_dev.camera_info.sensor_type[i];
+
+ }
+ temp_cam_info.num_cameras =
+ g_server_dev.camera_info.num_cameras;
+ if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
+ &temp_cam_info, sizeof(struct msm_camera_info))) {
+ pr_err("%s Copy to user failed for cmd %d",
+ __func__, cmd);
+ rc = -EINVAL;
+ return rc;
+ }
+ rc = 0;
+ break;
+
+ case MSM_CAM_V4L2_IOCTL_GET_CONFIG_INFO:
+ if (copy_from_user(&temp_config_info,
+ (void __user *)ioctl_ptr->ioctl_ptr,
+ sizeof(struct msm_cam_config_dev_info))) {
+ pr_err("%s Copy from user failed for cmd %d",
+ __func__, cmd);
+ rc = -EINVAL;
+ return rc;
+ }
+ for (i = 0;
+ i < g_server_dev.config_info.num_config_nodes; i++) {
+ if (copy_to_user(
+ (void __user *)temp_config_info.config_dev_name[i],
+ g_server_dev.config_info.config_dev_name[i],
+ strnlen(g_server_dev.config_info.config_dev_name[i],
+ MAX_DEV_NAME_LEN))) {
+ pr_err("%s Copy to user failed for cmd %d",
+ __func__, cmd);
+ rc = -EINVAL;
+ return rc;
+ }
+ }
+ temp_config_info.num_config_nodes =
+ g_server_dev.config_info.num_config_nodes;
+ if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
+ &temp_config_info,
+ sizeof(struct msm_cam_config_dev_info))) {
+ pr_err("%s Copy to user failed for cmd %d",
+ __func__, cmd);
+ rc = -EINVAL;
+ return rc;
+ }
+ rc = 0;
+ break;
+ case MSM_CAM_V4L2_IOCTL_GET_MCTL_INFO:
+ if (copy_from_user(&temp_mctl_info,
+ (void __user *)ioctl_ptr->ioctl_ptr,
+ sizeof(struct msm_mctl_node_info))) {
+ pr_err("%s Copy from user failed for cmd %d",
+ __func__, cmd);
+ rc = -EINVAL;
+ return rc;
+ }
+ for (i = 0; i < g_server_dev.mctl_node_info.num_mctl_nodes;
+ i++) {
+ if (copy_to_user((void __user *)
+ temp_mctl_info.mctl_node_name[i],
+ g_server_dev.mctl_node_info.mctl_node_name[i], strnlen(
+ g_server_dev.mctl_node_info.mctl_node_name[i],
+ MAX_DEV_NAME_LEN))) {
+ pr_err("%s Copy to user failed for cmd %d",
+ __func__, cmd);
+ rc = -EINVAL;
+ return rc;
+ }
+ }
+ temp_mctl_info.num_mctl_nodes =
+ g_server_dev.mctl_node_info.num_mctl_nodes;
+ if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
+ &temp_mctl_info, sizeof(struct msm_mctl_node_info))) {
+ pr_err("%s Copy to user failed for cmd %d",
+ __func__, cmd);
+ rc = -EINVAL;
+ return rc;
+ }
+ rc = 0;
+ break;
+
+ case MSM_CAM_V4L2_IOCTL_CTRL_CMD_DONE:
+ D("%s: MSM_CAM_IOCTL_CTRL_CMD_DONE\n", __func__);
+ rc = msm_ctrl_cmd_done(arg);
+ break;
+
+ case MSM_CAM_V4L2_IOCTL_GET_EVENT_PAYLOAD: {
+ struct msm_queue_cmd *event_cmd;
+ struct msm_isp_event_ctrl u_isp_event;
+ struct msm_isp_event_ctrl *k_isp_event;
+ struct msm_device_queue *queue;
+ void __user *u_ctrl_value = NULL;
+ if (copy_from_user(&u_isp_event,
+ (void __user *)ioctl_ptr->ioctl_ptr,
+ sizeof(struct msm_isp_event_ctrl))) {
+ pr_err("%s Copy from user failed for cmd %d",
+ __func__, cmd);
+ rc = -EINVAL;
+ return rc;
+ }
+
+ mutex_lock(&g_server_dev.server_queue_lock);
+ if (!g_server_dev.server_queue
+ [u_isp_event.isp_data.ctrl.queue_idx].queue_active) {
+ pr_err("%s: Invalid queue\n", __func__);
+ mutex_unlock(&g_server_dev.server_queue_lock);
+ rc = -EINVAL;
+ return rc;
+ }
+ queue = &g_server_dev.server_queue
+ [u_isp_event.isp_data.ctrl.queue_idx].eventData_q;
+ event_cmd = msm_dequeue(queue, list_eventdata);
+ if (!event_cmd) {
+ pr_err("%s: No event payload\n", __func__);
+ rc = -EINVAL;
+ mutex_unlock(&g_server_dev.server_queue_lock);
+ return rc;
+ }
+ k_isp_event = (struct msm_isp_event_ctrl *)
+ event_cmd->command;
+ free_qcmd(event_cmd);
+
+ /* Save the pointer of the user allocated command buffer*/
+ u_ctrl_value = u_isp_event.isp_data.ctrl.value;
+
+ /* Copy the event structure into user struct*/
+ u_isp_event = *k_isp_event;
+
+ /* Restore the saved pointer of the user
+ * allocated command buffer. */
+ u_isp_event.isp_data.ctrl.value = u_ctrl_value;
+
+ /* Copy the ctrl cmd, if present*/
+ if (k_isp_event->isp_data.ctrl.length > 0 &&
+ k_isp_event->isp_data.ctrl.value != NULL) {
+ void *k_ctrl_value =
+ k_isp_event->isp_data.ctrl.value;
+ if (copy_to_user(u_ctrl_value, k_ctrl_value,
+ k_isp_event->isp_data.ctrl.length)) {
+ pr_err("%s Copy to user failed for cmd %d",
+ __func__, cmd);
+ kfree(k_isp_event->isp_data.ctrl.value);
+ kfree(k_isp_event);
+ rc = -EINVAL;
+ mutex_unlock(&g_server_dev.server_queue_lock);
+ break;
+ }
+ kfree(k_isp_event->isp_data.ctrl.value);
+ }
+ if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
+ &u_isp_event, sizeof(struct msm_isp_event_ctrl))) {
+ pr_err("%s Copy to user failed for cmd %d",
+ __func__, cmd);
+ kfree(k_isp_event);
+ mutex_unlock(&g_server_dev.server_queue_lock);
+ rc = -EINVAL;
+ return rc;
+ }
+ kfree(k_isp_event);
+ mutex_unlock(&g_server_dev.server_queue_lock);
+ rc = 0;
+ break;
+ }
+
+ case MSM_CAM_IOCTL_SEND_EVENT:
+ rc = msm_server_send_v4l2_evt(arg);
+ break;
+
+ default:
+ pr_err("%s: Invalid IOCTL = %d", __func__, cmd);
+ break;
+ }
+ return rc;
+}
+
+static int msm_open_server(struct file *fp)
+{
+ int rc = 0;
+ D("%s: open %s\n", __func__, fp->f_path.dentry->d_name.name);
+ mutex_lock(&g_server_dev.server_lock);
+ g_server_dev.use_count++;
+ if (g_server_dev.use_count == 1)
+ fp->private_data =
+ &g_server_dev.server_command_queue.eventHandle;
+ mutex_unlock(&g_server_dev.server_lock);
+ return rc;
+}
+
+static int msm_close_server(struct file *fp)
+{
+ struct v4l2_event_subscription sub;
+ D("%s\n", __func__);
+ mutex_lock(&g_server_dev.server_lock);
+ if (g_server_dev.use_count > 0)
+ g_server_dev.use_count--;
+ mutex_unlock(&g_server_dev.server_lock);
+
+ if (g_server_dev.use_count == 0) {
+ mutex_lock(&g_server_dev.server_lock);
+ if (g_server_dev.pcam_active) {
+ struct v4l2_event v4l2_ev;
+ struct msm_cam_media_controller *pmctl = NULL;
+ int rc;
+
+ pmctl = msm_cam_server_get_mctl(
+ g_server_dev.pcam_active->mctl_handle);
+ if (pmctl && pmctl->mctl_release) {
+ rc = pmctl->mctl_release(pmctl);
+ if (rc < 0)
+ pr_err("mctl_release fails %d\n", rc);
+ /*so that it isn't closed again*/
+ pmctl->mctl_release = NULL;
+ }
+
+ v4l2_ev.type = V4L2_EVENT_PRIVATE_START
+ + MSM_CAM_APP_NOTIFY_ERROR_EVENT;
+ ktime_get_ts(&v4l2_ev.timestamp);
+ v4l2_event_queue(
+ g_server_dev.pcam_active->pvdev, &v4l2_ev);
+ }
+ sub.type = V4L2_EVENT_ALL;
+ msm_server_v4l2_unsubscribe_event(
+ &g_server_dev.server_command_queue.eventHandle, &sub);
+ mutex_unlock(&g_server_dev.server_lock);
+ }
+ return 0;
+}
+
+static unsigned int msm_poll_server(struct file *fp,
+ struct poll_table_struct *wait)
+{
+ int rc = 0;
+
+ D("%s\n", __func__);
+ poll_wait(fp,
+ &g_server_dev.server_command_queue.eventHandle.events->wait,
+ wait);
+ if (v4l2_event_pending(&g_server_dev.server_command_queue.eventHandle))
+ rc |= POLLPRI;
+
+ return rc;
+}
+
+int msm_server_get_usecount(void)
+{
+ return g_server_dev.use_count;
+}
+
+int msm_server_update_sensor_info(struct msm_cam_v4l2_device *pcam,
+ struct msm_camera_sensor_info *sdata)
+{
+ int rc = 0;
+
+ if (!pcam || !sdata) {
+ pr_err("%s Input data is null ", __func__);
+ return -EINVAL;
+ }
+
+ g_server_dev.camera_info.video_dev_name
+ [g_server_dev.camera_info.num_cameras]
+ = video_device_node_name(pcam->pvdev);
+ D("%s Connected video device %s\n", __func__,
+ g_server_dev.camera_info.video_dev_name
+ [g_server_dev.camera_info.num_cameras]);
+
+ g_server_dev.camera_info.s_mount_angle
+ [g_server_dev.camera_info.num_cameras]
+ = sdata->sensor_platform_info->mount_angle;
+
+ g_server_dev.camera_info.is_internal_cam
+ [g_server_dev.camera_info.num_cameras]
+ = sdata->camera_type;
+
+ g_server_dev.mctl_node_info.mctl_node_name
+ [g_server_dev.mctl_node_info.num_mctl_nodes]
+ = video_device_node_name(pcam->mctl_node.pvdev);
+
+ pr_info("%s mctl_node_name[%d] = %s\n", __func__,
+ g_server_dev.mctl_node_info.num_mctl_nodes,
+ g_server_dev.mctl_node_info.mctl_node_name
+ [g_server_dev.mctl_node_info.num_mctl_nodes]);
+
+ /*Temporary solution to store info in media device structure
+ until we can expand media device structure to support more
+ device info*/
+ snprintf(pcam->media_dev.serial,
+ sizeof(pcam->media_dev.serial),
+ "%s-%d-%d", QCAMERA_NAME,
+ sdata->sensor_platform_info->mount_angle,
+ sdata->camera_type);
+
+ g_server_dev.camera_info.num_cameras++;
+ g_server_dev.mctl_node_info.num_mctl_nodes++;
+
+ D("%s done, rc = %d\n", __func__, rc);
+ D("%s number of sensors connected is %d\n", __func__,
+ g_server_dev.camera_info.num_cameras);
+
+ return rc;
+}
+
+int msm_server_begin_session(struct msm_cam_v4l2_device *pcam,
+ int server_q_idx)
+{
+ int rc = -EINVAL, ges_evt;
+ struct msm_cam_server_queue *queue;
+
+ if (!pcam) {
+ pr_err("%s pcam passed is null ", __func__);
+ return rc;
+ }
+
+ ges_evt = MSM_V4L2_GES_CAM_OPEN;
+ D("%s send gesture evt\n", __func__);
+ msm_cam_server_subdev_notify(g_server_dev.gesture_device,
+ NOTIFY_GESTURE_CAM_EVT, &ges_evt);
+
+ pcam->server_queue_idx = server_q_idx;
+ queue = &g_server_dev.server_queue[server_q_idx];
+ queue->ctrl_data = kzalloc(sizeof(uint8_t) *
+ max_control_command_size, GFP_KERNEL);
+ msm_queue_init(&queue->ctrl_q, "control");
+ msm_queue_init(&queue->eventData_q, "eventdata");
+ queue->queue_active = 1;
+
+ rc = msm_cam_server_open_session(&g_server_dev, pcam);
+ if (rc < 0) {
+ pr_err("%s: cam_server_open_session failed %d\n",
+ __func__, rc);
+ goto error;
+ }
+
+ return rc;
+error:
+ ges_evt = MSM_V4L2_GES_CAM_CLOSE;
+ msm_cam_server_subdev_notify(g_server_dev.gesture_device,
+ NOTIFY_GESTURE_CAM_EVT, &ges_evt);
+
+ queue->queue_active = 0;
+ msm_drain_eventq(&queue->eventData_q);
+ msm_queue_drain(&queue->ctrl_q, list_control);
+ kfree(queue->ctrl_data);
+ queue->ctrl_data = NULL;
+ queue = NULL;
+ return rc;
+}
+
+int msm_server_end_session(struct msm_cam_v4l2_device *pcam)
+{
+ int rc = -EINVAL, ges_evt;
+ struct msm_cam_server_queue *queue;
+
+ mutex_lock(&g_server_dev.server_queue_lock);
+ queue = &g_server_dev.server_queue[pcam->server_queue_idx];
+ queue->queue_active = 0;
+ kfree(queue->ctrl_data);
+ queue->ctrl_data = NULL;
+ msm_queue_drain(&queue->ctrl_q, list_control);
+ msm_drain_eventq(&queue->eventData_q);
+ mutex_unlock(&g_server_dev.server_queue_lock);
+
+ rc = msm_cam_server_close_session(&g_server_dev, pcam);
+ if (rc < 0)
+ pr_err("msm_cam_server_close_session fails %d\n", rc);
+
+ ges_evt = MSM_V4L2_GES_CAM_CLOSE;
+ msm_cam_server_subdev_notify(g_server_dev.gesture_device,
+ NOTIFY_GESTURE_CAM_EVT, &ges_evt);
+
+ return rc;
+}
+
+/* Init a config node for ISP control,
+ * which will create a config device (/dev/config0/ and plug in
+ * ISP's operation "v4l2_ioctl_ops*"
+ */
+static const struct v4l2_file_operations msm_fops_server = {
+ .owner = THIS_MODULE,
+ .open = msm_open_server,
+ .poll = msm_poll_server,
+ .unlocked_ioctl = video_ioctl2,
+ .release = msm_close_server,
+};
+
+static const struct v4l2_ioctl_ops msm_ioctl_ops_server = {
+ .vidioc_subscribe_event = msm_server_v4l2_subscribe_event,
+ .vidioc_default = msm_ioctl_server,
+};
+
+static void msm_cam_server_subdev_notify(struct v4l2_subdev *sd,
+ unsigned int notification, void *arg)
+{
+ int rc = -EINVAL;
+ struct msm_sensor_ctrl_t *s_ctrl;
+ struct msm_camera_sensor_info *sinfo;
+ struct msm_camera_device_platform_data *camdev;
+ uint8_t csid_core = 0;
+
+ if (notification == NOTIFY_CID_CHANGE ||
+ notification == NOTIFY_ISPIF_STREAM ||
+ notification == NOTIFY_PCLK_CHANGE ||
+ notification == NOTIFY_CSIPHY_CFG ||
+ notification == NOTIFY_CSID_CFG ||
+ notification == NOTIFY_CSIC_CFG) {
+ s_ctrl = get_sctrl(sd);
+ sinfo = (struct msm_camera_sensor_info *) s_ctrl->sensordata;
+ camdev = sinfo->pdata;
+ csid_core = camdev->csid_core;
+ }
+
+ switch (notification) {
+ case NOTIFY_CID_CHANGE:
+ /* reconfig the ISPIF*/
+ if (g_server_dev.ispif_device) {
+ struct msm_ispif_params_list ispif_params;
+ ispif_params.len = 1;
+ ispif_params.params[0].intftype = PIX0;
+ ispif_params.params[0].cid_mask = 0x0001;
+ ispif_params.params[0].csid = csid_core;
+
+ rc = v4l2_subdev_call(
+ g_server_dev.ispif_device, core, ioctl,
+ VIDIOC_MSM_ISPIF_CFG, &ispif_params);
+ if (rc < 0)
+ return;
+ }
+ break;
+ case NOTIFY_ISPIF_STREAM:
+ /* call ISPIF stream on/off */
+ rc = v4l2_subdev_call(g_server_dev.ispif_device, video,
+ s_stream, (int)arg);
+ if (rc < 0)
+ return;
+
+ break;
+ case NOTIFY_ISP_MSG_EVT:
+ case NOTIFY_VFE_MSG_OUT:
+ case NOTIFY_VFE_MSG_STATS:
+ case NOTIFY_VFE_MSG_COMP_STATS:
+ case NOTIFY_VFE_BUF_EVT:
+ case NOTIFY_VFE_BUF_FREE_EVT:
+ if (g_server_dev.isp_subdev[0] &&
+ g_server_dev.isp_subdev[0]->isp_notify) {
+ rc = g_server_dev.isp_subdev[0]->isp_notify(
+ g_server_dev.vfe_device[0], notification, arg);
+ }
+ break;
+ case NOTIFY_VPE_MSG_EVT: {
+ struct msm_cam_media_controller *pmctl =
+ (struct msm_cam_media_controller *)
+ v4l2_get_subdev_hostdata(sd);
+ struct msm_vpe_resp *vdata = (struct msm_vpe_resp *)arg;
+ msm_mctl_pp_notify(pmctl,
+ (struct msm_mctl_pp_frame_info *)
+ vdata->extdata);
+ break;
+ }
+ case NOTIFY_VFE_IRQ:{
+ struct msm_vfe_cfg_cmd cfg_cmd;
+ struct msm_camvfe_params vfe_params;
+ cfg_cmd.cmd_type = CMD_VFE_PROCESS_IRQ;
+ vfe_params.vfe_cfg = &cfg_cmd;
+ vfe_params.data = arg;
+ rc = v4l2_subdev_call(g_server_dev.vfe_device[0],
+ core, ioctl, 0, &vfe_params);
+ }
+ break;
+ case NOTIFY_AXI_IRQ:
+ rc = v4l2_subdev_call(g_server_dev.axi_device[0],
+ core, ioctl, VIDIOC_MSM_AXI_IRQ, arg);
+ break;
+ case NOTIFY_PCLK_CHANGE:
+ if (g_server_dev.axi_device[0])
+ rc = v4l2_subdev_call(g_server_dev.axi_device[0], video,
+ s_crystal_freq, *(uint32_t *)arg, 0);
+ else
+ rc = v4l2_subdev_call(g_server_dev.vfe_device[0], video,
+ s_crystal_freq, *(uint32_t *)arg, 0);
+ break;
+ case NOTIFY_CSIPHY_CFG:
+ rc = v4l2_subdev_call(g_server_dev.csiphy_device[csid_core],
+ core, ioctl, VIDIOC_MSM_CSIPHY_CFG, arg);
+ break;
+ case NOTIFY_CSID_CFG:
+ rc = v4l2_subdev_call(g_server_dev.csid_device[csid_core],
+ core, ioctl, VIDIOC_MSM_CSID_CFG, arg);
+ break;
+ case NOTIFY_CSIC_CFG:
+ rc = v4l2_subdev_call(g_server_dev.csic_device[csid_core],
+ core, ioctl, VIDIOC_MSM_CSIC_CFG, arg);
+ break;
+ case NOTIFY_GESTURE_EVT:
+ rc = v4l2_subdev_call(g_server_dev.gesture_device,
+ core, ioctl, VIDIOC_MSM_GESTURE_EVT, arg);
+ break;
+ case NOTIFY_GESTURE_CAM_EVT:
+ rc = v4l2_subdev_call(g_server_dev.gesture_device,
+ core, ioctl, VIDIOC_MSM_GESTURE_CAM_EVT, arg);
+ break;
+ default:
+ break;
+ }
+
+ return;
+}
+
+int msm_cam_register_subdev_node(struct v4l2_subdev *sd,
+ enum msm_cam_subdev_type sdev_type, uint8_t index)
+{
+ struct video_device *vdev;
+ int err = 0;
+
+ switch (sdev_type) {
+ case CSIPHY_DEV:
+ if (index >= MAX_NUM_CSIPHY_DEV) {
+ pr_err("%s Invalid CSIPHY idx %d", __func__, index);
+ err = -EINVAL;
+ break;
+ }
+ g_server_dev.csiphy_device[index] = sd;
+ break;
+
+ case CSID_DEV:
+ if (index >= MAX_NUM_CSID_DEV) {
+ pr_err("%s Invalid CSID idx %d", __func__, index);
+ err = -EINVAL;
+ break;
+ }
+ g_server_dev.csid_device[index] = sd;
+ break;
+
+ case CSIC_DEV:
+ if (index >= MAX_NUM_CSIC_DEV) {
+ pr_err("%s Invalid CSIC idx %d", __func__, index);
+ err = -EINVAL;
+ break;
+ }
+ g_server_dev.csic_device[index] = sd;
+ break;
+
+ case ISPIF_DEV:
+ g_server_dev.ispif_device = sd;
+ break;
+
+ case VFE_DEV:
+ if (index >= MAX_NUM_VFE_DEV) {
+ pr_err("%s Invalid VFE idx %d", __func__, index);
+ err = -EINVAL;
+ break;
+ }
+ g_server_dev.vfe_device[index] = sd;
+ break;
+
+ case VPE_DEV:
+ if (index >= MAX_NUM_VPE_DEV) {
+ pr_err("%s Invalid VPE idx %d", __func__, index);
+ err = -EINVAL;
+ break;
+ }
+ g_server_dev.vpe_device[index] = sd;
+ break;
+
+ case AXI_DEV:
+ if (index >= MAX_NUM_VPE_DEV) {
+ pr_err("%s Invalid AXI idx %d", __func__, index);
+ err = -EINVAL;
+ break;
+ }
+ g_server_dev.axi_device[index] = sd;
+ break;
+
+ case GESTURE_DEV:
+ g_server_dev.gesture_device = sd;
+ break;
+ default:
+ break;
+ }
+
+ if (err < 0)
+ return err;
+
+ err = v4l2_device_register_subdev(&g_server_dev.v4l2_dev, sd);
+ if (err < 0) {
+ pr_err("%s v4l2 subdev register failed for %d ret = %d",
+ __func__, sdev_type, err);
+ return err;
+ }
+
+ /* Register a device node for every subdev marked with the
+ * V4L2_SUBDEV_FL_HAS_DEVNODE flag.
+ */
+ if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE))
+ return err;
+
+ vdev = &sd->devnode;
+ strlcpy(vdev->name, sd->name, sizeof(vdev->name));
+ vdev->v4l2_dev = &g_server_dev.v4l2_dev;
+ vdev->fops = &v4l2_subdev_fops;
+ vdev->release = video_device_release_empty;
+ err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
+ sd->owner);
+ if (err < 0)
+ return err;
+#if defined(CONFIG_MEDIA_CONTROLLER)
+ sd->entity.v4l.major = VIDEO_MAJOR;
+ sd->entity.v4l.minor = vdev->minor;
+#endif
+ return 0;
+}
+
+static int msm_setup_server_dev(struct platform_device *pdev)
+{
+ int rc = -ENODEV, i;
+
+ D("%s\n", __func__);
+ g_server_dev.server_pdev = pdev;
+ g_server_dev.v4l2_dev.dev = &pdev->dev;
+ g_server_dev.v4l2_dev.notify = msm_cam_server_subdev_notify;
+ rc = v4l2_device_register(g_server_dev.v4l2_dev.dev,
+ &g_server_dev.v4l2_dev);
+ if (rc < 0)
+ return -EINVAL;
+
+ g_server_dev.video_dev = video_device_alloc();
+ if (g_server_dev.video_dev == NULL) {
+ pr_err("%s: video_device_alloc failed\n", __func__);
+ return rc;
+ }
+
+ strlcpy(g_server_dev.video_dev->name, pdev->name,
+ sizeof(g_server_dev.video_dev->name));
+
+ g_server_dev.video_dev->v4l2_dev = &g_server_dev.v4l2_dev;
+ g_server_dev.video_dev->fops = &msm_fops_server;
+ g_server_dev.video_dev->ioctl_ops = &msm_ioctl_ops_server;
+ g_server_dev.video_dev->release = video_device_release;
+ g_server_dev.video_dev->minor = 100;
+ g_server_dev.video_dev->vfl_type = 1;
+
+ video_set_drvdata(g_server_dev.video_dev, &g_server_dev);
+
+ strlcpy(g_server_dev.media_dev.model, "qcamera",
+ sizeof(g_server_dev.media_dev.model));
+ g_server_dev.media_dev.dev = &pdev->dev;
+ rc = media_device_register(&g_server_dev.media_dev);
+ g_server_dev.v4l2_dev.mdev = &g_server_dev.media_dev;
+
+ rc = video_register_device(g_server_dev.video_dev,
+ VFL_TYPE_GRABBER, 100);
+
+ mutex_init(&g_server_dev.server_lock);
+ mutex_init(&g_server_dev.server_queue_lock);
+ g_server_dev.pcam_active = NULL;
+ g_server_dev.camera_info.num_cameras = 0;
+ atomic_set(&g_server_dev.number_pcam_active, 0);
+ g_server_dev.server_evt_id = 0;
+
+ /*initialize fake video device and event queue*/
+
+ g_server_dev.server_command_queue.pvdev = g_server_dev.video_dev;
+ rc = msm_setup_v4l2_event_queue(
+ &g_server_dev.server_command_queue.eventHandle,
+ g_server_dev.server_command_queue.pvdev);
+
+ if (rc < 0) {
+ pr_err("%s failed to initialize event queue\n", __func__);
+ video_device_release(g_server_dev.server_command_queue.pvdev);
+ return rc;
+ }
+
+ for (i = 0; i < MAX_NUM_ACTIVE_CAMERA; i++) {
+ struct msm_cam_server_queue *queue;
+ queue = &g_server_dev.server_queue[i];
+ queue->queue_active = 0;
+ msm_queue_init(&queue->ctrl_q, "control");
+ msm_queue_init(&queue->eventData_q, "eventdata");
+ }
+ return rc;
+}
+
+static long msm_server_send_v4l2_evt(void *evt)
+{
+ struct v4l2_event *v4l2_ev = (struct v4l2_event *)evt;
+ int rc = 0;
+
+ if (NULL == evt) {
+ pr_err("%s: evt is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ D("%s: evt type 0x%x\n", __func__, v4l2_ev->type);
+ if ((v4l2_ev->type >= MSM_GES_APP_EVT_MIN) &&
+ (v4l2_ev->type < MSM_GES_APP_EVT_MAX)) {
+ msm_cam_server_subdev_notify(g_server_dev.gesture_device,
+ NOTIFY_GESTURE_EVT, v4l2_ev);
+ } else {
+ pr_err("%s: Invalid evt %d\n", __func__, v4l2_ev->type);
+ rc = -EINVAL;
+ }
+ D("%s: end\n", __func__);
+
+ return rc;
+}
+
+int msm_cam_server_open_mctl_session(struct msm_cam_v4l2_device *pcam,
+ int *p_active)
+{
+ int rc = 0;
+ struct msm_cam_media_controller *pmctl = NULL;
+ D("%s: %p", __func__, g_server_dev.pcam_active);
+ *p_active = 0;
+ if (g_server_dev.pcam_active) {
+ D("%s: Active camera present return", __func__);
+ return 0;
+ }
+ rc = msm_cam_server_open_session(&g_server_dev, pcam);
+ if (rc < 0) {
+ pr_err("%s: cam_server_open_session failed %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
+ if (!pmctl->mctl_open) {
+ D("%s: media contoller is not inited\n",
+ __func__);
+ rc = -ENODEV;
+ return rc;
+ }
+
+ D("%s: call mctl_open\n", __func__);
+ rc = pmctl->mctl_open(pmctl, MSM_APPS_ID_V4L2);
+
+ if (rc < 0) {
+ pr_err("%s: HW open failed rc = 0x%x\n", __func__, rc);
+ return rc;
+ }
+ pmctl->pcam_ptr = pcam;
+ *p_active = 1;
+ return rc;
+}
+
+int msm_cam_server_close_mctl_session(struct msm_cam_v4l2_device *pcam)
+{
+ int rc = 0;
+ struct msm_cam_media_controller *pmctl = NULL;
+
+ pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
+ if (!pmctl) {
+ D("%s: invalid handle\n", __func__);
+ return -ENODEV;
+ }
+
+ if (pmctl->mctl_release) {
+ rc = pmctl->mctl_release(pmctl);
+ if (rc < 0)
+ pr_err("mctl_release fails %d\n", rc);
+ }
+
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ kref_put(&pmctl->refcount, msm_release_ion_client);
+#endif
+
+ rc = msm_cam_server_close_session(&g_server_dev, pcam);
+ if (rc < 0)
+ pr_err("msm_cam_server_close_session fails %d\n", rc);
+
+ return rc;
+}
+
+int msm_server_open_client(int *p_qidx)
+{
+ int rc = 0;
+ int server_q_idx = 0;
+ struct msm_cam_server_queue *queue = NULL;
+
+ mutex_lock(&g_server_dev.server_lock);
+ server_q_idx = msm_find_free_queue();
+ if (server_q_idx < 0) {
+ mutex_unlock(&g_server_dev.server_lock);
+ return server_q_idx;
+ }
+
+ *p_qidx = server_q_idx;
+ queue = &g_server_dev.server_queue[server_q_idx];
+ queue->ctrl_data = kzalloc(sizeof(uint8_t) *
+ max_control_command_size, GFP_KERNEL);
+ msm_queue_init(&queue->ctrl_q, "control");
+ msm_queue_init(&queue->eventData_q, "eventdata");
+ queue->queue_active = 1;
+ mutex_unlock(&g_server_dev.server_lock);
+ return rc;
+}
+
+int msm_server_send_ctrl(struct msm_ctrl_cmd *out,
+ int ctrl_id)
+{
+ int rc = 0;
+ void *value;
+ struct msm_queue_cmd *rcmd;
+ struct msm_queue_cmd *event_qcmd;
+ struct msm_ctrl_cmd *ctrlcmd;
+ struct msm_cam_server_dev *server_dev = &g_server_dev;
+ struct msm_device_queue *queue =
+ &server_dev->server_queue[out->queue_idx].ctrl_q;
+
+ struct v4l2_event v4l2_evt;
+ struct msm_isp_event_ctrl *isp_event;
+ isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl), GFP_KERNEL);
+ if (!isp_event) {
+ pr_err("%s Insufficient memory. return", __func__);
+ return -ENOMEM;
+ }
+ event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_KERNEL);
+ if (!event_qcmd) {
+ pr_err("%s Insufficient memory. return", __func__);
+ kfree(isp_event);
+ return -ENOMEM;
+ }
+
+ D("%s\n", __func__);
+ mutex_lock(&server_dev->server_queue_lock);
+ if (++server_dev->server_evt_id == 0)
+ server_dev->server_evt_id++;
+
+ D("%s qid %d evtid %d\n", __func__, out->queue_idx,
+ server_dev->server_evt_id);
+ server_dev->server_queue[out->queue_idx].evt_id =
+ server_dev->server_evt_id;
+ v4l2_evt.type = V4L2_EVENT_PRIVATE_START + ctrl_id;
+ v4l2_evt.u.data[0] = out->queue_idx;
+ /* setup event object to transfer the command; */
+ isp_event->resptype = MSM_CAM_RESP_V4L2;
+ isp_event->isp_data.ctrl = *out;
+ isp_event->isp_data.ctrl.evt_id = server_dev->server_evt_id;
+
+ atomic_set(&event_qcmd->on_heap, 1);
+ event_qcmd->command = isp_event;
+
+ msm_enqueue(&server_dev->server_queue[out->queue_idx].eventData_q,
+ &event_qcmd->list_eventdata);
+
+ /* now send command to config thread in userspace,
+ * and wait for results */
+ v4l2_event_queue(server_dev->server_command_queue.pvdev,
+ &v4l2_evt);
+ D("%s v4l2_event_queue: type = 0x%x\n", __func__, v4l2_evt.type);
+ mutex_unlock(&server_dev->server_queue_lock);
+
+ /* wait for config return status */
+ D("Waiting for config status\n");
+ rc = wait_event_interruptible_timeout(queue->wait,
+ !list_empty_careful(&queue->list),
+ msecs_to_jiffies(out->timeout_ms));
+ D("Waiting is over for config status\n");
+ if (list_empty_careful(&queue->list)) {
+ if (!rc)
+ rc = -ETIMEDOUT;
+ if (rc < 0) {
+ kfree(isp_event);
+ pr_err("%s: wait_event error %d\n", __func__, rc);
+ return rc;
+ }
+ }
+
+ rcmd = msm_dequeue(queue, list_control);
+ BUG_ON(!rcmd);
+ D("%s Finished servicing ioctl\n", __func__);
+
+ ctrlcmd = (struct msm_ctrl_cmd *)(rcmd->command);
+ value = out->value;
+ if (ctrlcmd->length > 0 && value != NULL &&
+ ctrlcmd->length <= out->length)
+ memcpy(value, ctrlcmd->value, ctrlcmd->length);
+
+ memcpy(out, ctrlcmd, sizeof(struct msm_ctrl_cmd));
+ out->value = value;
+
+ kfree(ctrlcmd);
+ free_qcmd(rcmd);
+ kfree(isp_event);
+ D("%s: rc %d\n", __func__, rc);
+ /* rc is the time elapsed. */
+ if (rc >= 0) {
+ /* TODO: Refactor msm_ctrl_cmd::status field */
+ if (out->status == 0)
+ rc = -1;
+ else if (out->status == 1 || out->status == 4)
+ rc = 0;
+ else
+ rc = -EINVAL;
+ }
+ return rc;
+}
+
+int msm_server_close_client(int idx)
+{
+ int rc = 0;
+ struct msm_cam_server_queue *queue = NULL;
+ mutex_lock(&g_server_dev.server_lock);
+ queue = &g_server_dev.server_queue[idx];
+ queue->queue_active = 0;
+ kfree(queue->ctrl_data);
+ queue->ctrl_data = NULL;
+ msm_queue_drain(&queue->ctrl_q, list_control);
+ msm_drain_eventq(&queue->eventData_q);
+ mutex_unlock(&g_server_dev.server_lock);
+ return rc;
+}
+
+static unsigned int msm_poll_config(struct file *fp,
+ struct poll_table_struct *wait)
+{
+ int rc = 0;
+ struct msm_cam_config_dev *config = fp->private_data;
+ if (config == NULL)
+ return -EINVAL;
+
+ D("%s\n", __func__);
+
+ poll_wait(fp,
+ &config->config_stat_event_queue.eventHandle.events->wait, wait);
+ if (v4l2_event_pending(&config->config_stat_event_queue.eventHandle))
+ rc |= POLLPRI;
+ return rc;
+}
+
+static int msm_mmap_config(struct file *fp, struct vm_area_struct *vma)
+{
+ struct msm_cam_config_dev *config_cam = fp->private_data;
+ int rc = 0;
+ int phyaddr;
+ int retval;
+ unsigned long size;
+
+ D("%s: phy_addr=0x%x", __func__, config_cam->mem_map.cookie);
+ phyaddr = (int)config_cam->mem_map.cookie;
+ if (!phyaddr) {
+ pr_err("%s: no physical memory to map", __func__);
+ return -EFAULT;
+ }
+ memset(&config_cam->mem_map, 0,
+ sizeof(struct msm_mem_map_info));
+ size = vma->vm_end - vma->vm_start;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ retval = remap_pfn_range(vma, vma->vm_start,
+ phyaddr >> PAGE_SHIFT,
+ size, vma->vm_page_prot);
+ if (retval) {
+ pr_err("%s: remap failed, rc = %d",
+ __func__, retval);
+ rc = -ENOMEM;
+ goto end;
+ }
+ D("%s: phy_addr=0x%x: %08lx-%08lx, pgoff %08lx\n",
+ __func__, (uint32_t)phyaddr,
+ vma->vm_start, vma->vm_end, vma->vm_pgoff);
+end:
+ return rc;
+}
+
+static int msm_open_config(struct inode *inode, struct file *fp)
+{
+ int rc;
+ struct msm_cam_config_dev *config_cam = container_of(inode->i_cdev,
+ struct msm_cam_config_dev, config_cdev);
+
+ D("%s: open %s\n", __func__, fp->f_path.dentry->d_name.name);
+
+ rc = nonseekable_open(inode, fp);
+ if (rc < 0) {
+ pr_err("%s: nonseekable_open error %d\n", __func__, rc);
+ return rc;
+ }
+ config_cam->use_count++;
+
+ /* assume there is only one active camera possible*/
+ config_cam->p_mctl =
+ msm_cam_server_get_mctl(g_server_dev.pcam_active->mctl_handle);
+
+ INIT_HLIST_HEAD(&config_cam->p_mctl->stats_info.pmem_stats_list);
+ spin_lock_init(&config_cam->p_mctl->stats_info.pmem_stats_spinlock);
+
+ config_cam->p_mctl->config_device = config_cam;
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ kref_get(&config_cam->p_mctl->refcount);
+#endif
+ fp->private_data = config_cam;
+ return rc;
+}
+
+static long msm_ioctl_config(struct file *fp, unsigned int cmd,
+ unsigned long arg)
+{
+
+ int rc = 0;
+ struct v4l2_event ev;
+ struct msm_cam_config_dev *config_cam = fp->private_data;
+ struct v4l2_event_subscription temp_sub;
+
+ D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
+
+ switch (cmd) {
+ /* memory management shall be handeld here*/
+ case MSM_CAM_IOCTL_REGISTER_PMEM:
+ return msm_register_pmem(
+ &config_cam->p_mctl->stats_info.pmem_stats_list,
+ (void __user *)arg, config_cam->p_mctl->client);
+ break;
+
+ case MSM_CAM_IOCTL_UNREGISTER_PMEM:
+ return msm_pmem_table_del(
+ &config_cam->p_mctl->stats_info.pmem_stats_list,
+ (void __user *)arg, config_cam->p_mctl->client);
+ break;
+
+ case VIDIOC_SUBSCRIBE_EVENT:
+ if (copy_from_user(&temp_sub,
+ (void __user *)arg,
+ sizeof(struct v4l2_event_subscription))) {
+ pr_err("%s copy_from_user failed for cmd %d ",
+ __func__, cmd);
+ rc = -EINVAL;
+ return rc;
+ }
+ rc = msm_server_v4l2_subscribe_event
+ (&config_cam->config_stat_event_queue.eventHandle,
+ &temp_sub);
+ if (rc < 0) {
+ pr_err("%s: cam_v4l2_subscribe_event failed rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+ break;
+
+ case VIDIOC_UNSUBSCRIBE_EVENT:
+ if (copy_from_user(&temp_sub, (void __user *)arg,
+ sizeof(struct v4l2_event_subscription))) {
+ rc = -EINVAL;
+ return rc;
+ }
+ rc = msm_server_v4l2_unsubscribe_event
+ (&config_cam->config_stat_event_queue.eventHandle,
+ &temp_sub);
+ if (rc < 0) {
+ pr_err("%s: cam_v4l2_unsubscribe_event failed rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+ break;
+
+ case VIDIOC_DQEVENT: {
+ void __user *u_msg_value = NULL, *user_ptr = NULL;
+ struct msm_isp_event_ctrl u_isp_event;
+ struct msm_isp_event_ctrl *k_isp_event;
+
+ /* First, copy the v4l2 event structure from userspace */
+ D("%s: VIDIOC_DQEVENT\n", __func__);
+ if (copy_from_user(&ev, (void __user *)arg,
+ sizeof(struct v4l2_event)))
+ break;
+ /* Next, get the pointer to event_ctrl structure
+ * embedded inside the v4l2_event.u.data array. */
+ user_ptr = (void __user *)(*((uint32_t *)ev.u.data));
+
+ /* Next, copy the userspace event ctrl structure */
+ if (copy_from_user((void *)&u_isp_event, user_ptr,
+ sizeof(struct msm_isp_event_ctrl))) {
+ break;
+ }
+ /* Save the pointer of the user allocated command buffer*/
+ u_msg_value = u_isp_event.isp_data.isp_msg.data;
+
+ /* Dequeue the event queued into the v4l2 queue*/
+ rc = v4l2_event_dequeue(
+ &config_cam->config_stat_event_queue.eventHandle,
+ &ev, fp->f_flags & O_NONBLOCK);
+ if (rc < 0) {
+ pr_err("no pending events?");
+ break;
+ }
+ /* Use k_isp_event to point to the event_ctrl structure
+ * embedded inside v4l2_event.u.data */
+ k_isp_event = (struct msm_isp_event_ctrl *)
+ (*((uint32_t *)ev.u.data));
+ /* Copy the event structure into user struct. */
+ u_isp_event = *k_isp_event;
+ if (ev.type != (V4L2_EVENT_PRIVATE_START +
+ MSM_CAM_RESP_DIV_FRAME_EVT_MSG) &&
+ ev.type != (V4L2_EVENT_PRIVATE_START +
+ MSM_CAM_RESP_MCTL_PP_EVENT)) {
+
+ /* Restore the saved pointer of the
+ * user allocated command buffer. */
+ u_isp_event.isp_data.isp_msg.data = u_msg_value;
+
+ if (ev.type == (V4L2_EVENT_PRIVATE_START +
+ MSM_CAM_RESP_STAT_EVT_MSG)) {
+ if (k_isp_event->isp_data.isp_msg.len > 0) {
+ void *k_msg_value =
+ k_isp_event->isp_data.isp_msg.data;
+ if (copy_to_user(u_msg_value,
+ k_msg_value,
+ k_isp_event->isp_data.isp_msg.len)) {
+ rc = -EINVAL;
+ break;
+ }
+ kfree(k_msg_value);
+ }
+ }
+ }
+ /* Copy the event ctrl structure back
+ * into user's structure. */
+ if (copy_to_user(user_ptr,
+ (void *)&u_isp_event, sizeof(
+ struct msm_isp_event_ctrl))) {
+ rc = -EINVAL;
+ break;
+ }
+ kfree(k_isp_event);
+
+ /* Copy the v4l2_event structure back to the user*/
+ if (copy_to_user((void __user *)arg, &ev,
+ sizeof(struct v4l2_event))) {
+ rc = -EINVAL;
+ break;
+ }
+ }
+
+ break;
+
+ case MSM_CAM_IOCTL_V4L2_EVT_NOTIFY:
+ rc = msm_v4l2_evt_notify(config_cam->p_mctl, cmd, arg);
+ break;
+
+ case MSM_CAM_IOCTL_SET_MEM_MAP_INFO:
+ if (copy_from_user(&config_cam->mem_map, (void __user *)arg,
+ sizeof(struct msm_mem_map_info)))
+ rc = -EINVAL;
+ break;
+
+ default:{
+ /* For the rest of config command, forward to media controller*/
+ struct msm_cam_media_controller *p_mctl = config_cam->p_mctl;
+ if (p_mctl && p_mctl->mctl_cmd) {
+ rc = config_cam->p_mctl->mctl_cmd(p_mctl, cmd, arg);
+ } else {
+ rc = -EINVAL;
+ pr_err("%s: media controller is null\n", __func__);
+ }
+
+ break;
+ } /* end of default*/
+ } /* end of switch*/
+ return rc;
+}
+
+static int msm_close_config(struct inode *node, struct file *f)
+{
+ struct v4l2_event ev;
+ struct v4l2_event_subscription sub;
+ struct msm_isp_event_ctrl *isp_event;
+ struct msm_cam_config_dev *config_cam = f->private_data;
+
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ D("%s Decrementing ref count of config node ", __func__);
+ kref_put(&config_cam->p_mctl->refcount, msm_release_ion_client);
+#endif
+ sub.type = V4L2_EVENT_ALL;
+ msm_server_v4l2_unsubscribe_event(
+ &config_cam->config_stat_event_queue.eventHandle,
+ &sub);
+ while (v4l2_event_pending(
+ &config_cam->config_stat_event_queue.eventHandle)) {
+ v4l2_event_dequeue(
+ &config_cam->config_stat_event_queue.eventHandle,
+ &ev, O_NONBLOCK);
+ isp_event = (struct msm_isp_event_ctrl *)
+ (*((uint32_t *)ev.u.data));
+ if (isp_event) {
+ if (isp_event->isp_data.isp_msg.len != 0 &&
+ isp_event->isp_data.isp_msg.data != NULL)
+ kfree(isp_event->isp_data.isp_msg.data);
+ kfree(isp_event);
+ }
+ }
+ return 0;
+}
+
+static const struct file_operations msm_fops_config = {
+ .owner = THIS_MODULE,
+ .open = msm_open_config,
+ .poll = msm_poll_config,
+ .unlocked_ioctl = msm_ioctl_config,
+ .mmap = msm_mmap_config,
+ .release = msm_close_config,
+};
+
+static int msm_setup_config_dev(int node, char *device_name)
+{
+ int rc = -ENODEV;
+ struct device *device_config;
+ int dev_num = node;
+ dev_t devno;
+ struct msm_cam_config_dev *config_cam;
+
+ config_cam = kzalloc(sizeof(*config_cam), GFP_KERNEL);
+ if (!config_cam) {
+ pr_err("%s: could not allocate memory for config_device\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ D("%s\n", __func__);
+
+ devno = MKDEV(MAJOR(msm_devno), dev_num+1);
+ device_config = device_create(msm_class, NULL, devno, NULL, "%s%d",
+ device_name, dev_num);
+
+ if (IS_ERR(device_config)) {
+ rc = PTR_ERR(device_config);
+ pr_err("%s: error creating device: %d\n", __func__, rc);
+ goto config_setup_fail;
+ }
+
+ cdev_init(&config_cam->config_cdev, &msm_fops_config);
+ config_cam->config_cdev.owner = THIS_MODULE;
+
+ rc = cdev_add(&config_cam->config_cdev, devno, 1);
+ if (rc < 0) {
+ pr_err("%s: error adding cdev: %d\n", __func__, rc);
+ device_destroy(msm_class, devno);
+ goto config_setup_fail;
+ }
+ g_server_dev.config_info.config_dev_name[dev_num] =
+ dev_name(device_config);
+ D("%s Connected config device %s\n", __func__,
+ g_server_dev.config_info.config_dev_name[dev_num]);
+ g_server_dev.config_info.config_dev_id[dev_num] =
+ dev_num;
+
+ config_cam->config_stat_event_queue.pvdev = video_device_alloc();
+ if (config_cam->config_stat_event_queue.pvdev == NULL) {
+ pr_err("%s: video_device_alloc failed\n", __func__);
+ goto config_setup_fail;
+ }
+
+ rc = msm_setup_v4l2_event_queue(
+ &config_cam->config_stat_event_queue.eventHandle,
+ config_cam->config_stat_event_queue.pvdev);
+ if (rc < 0) {
+ pr_err("%s failed to initialize event queue\n", __func__);
+ video_device_release(config_cam->config_stat_event_queue.pvdev);
+ goto config_setup_fail;
+ }
+
+ return rc;
+
+config_setup_fail:
+ kfree(config_cam);
+ return rc;
+}
+
+static int __devinit msm_camera_probe(struct platform_device *pdev)
+{
+ int rc = 0, i;
+ /*for now just create a config 0 node
+ put logic here later to know how many configs to create*/
+ g_server_dev.config_info.num_config_nodes = 1;
+
+ rc = msm_isp_init_module(g_server_dev.config_info.num_config_nodes);
+ if (rc < 0) {
+ pr_err("Failed to initialize isp\n");
+ return rc;
+ }
+
+ if (!msm_class) {
+ rc = alloc_chrdev_region(&msm_devno, 0,
+ g_server_dev.config_info.num_config_nodes+1, "msm_camera");
+ if (rc < 0) {
+ pr_err("%s: failed to allocate chrdev: %d\n", __func__,
+ rc);
+ return rc;
+ }
+
+ msm_class = class_create(THIS_MODULE, "msm_camera");
+ if (IS_ERR(msm_class)) {
+ rc = PTR_ERR(msm_class);
+ pr_err("%s: create device class failed: %d\n",
+ __func__, rc);
+ return rc;
+ }
+ }
+
+ D("creating server and config nodes\n");
+ rc = msm_setup_server_dev(pdev);
+ if (rc < 0) {
+ pr_err("%s: failed to create server dev: %d\n", __func__,
+ rc);
+ return rc;
+ }
+
+ for (i = 0; i < g_server_dev.config_info.num_config_nodes; i++) {
+ rc = msm_setup_config_dev(i, "config");
+ if (rc < 0) {
+ pr_err("%s:failed to create config dev: %d\n",
+ __func__, rc);
+ return rc;
+ }
+ }
+
+ msm_isp_register(&g_server_dev);
+ return rc;
+}
+
+static int __exit msm_camera_exit(struct platform_device *pdev)
+{
+ msm_isp_unregister(&g_server_dev);
+ return 0;
+}
+
+static struct platform_driver msm_cam_server_driver = {
+ .probe = msm_camera_probe,
+ .remove = msm_camera_exit,
+ .driver = {
+ .name = "msm_cam_server",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_cam_server_init(void)
+{
+ return platform_driver_register(&msm_cam_server_driver);
+}
+
+static void __exit msm_cam_server_exit(void)
+{
+ platform_driver_unregister(&msm_cam_server_driver);
+}
+
+module_init(msm_cam_server_init);
+module_exit(msm_cam_server_exit);
+MODULE_DESCRIPTION("msm camera server");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/server/msm_cam_server.h b/drivers/media/video/msm/server/msm_cam_server.h
new file mode 100644
index 0000000..2fe4c2b
--- /dev/null
+++ b/drivers/media/video/msm/server/msm_cam_server.h
@@ -0,0 +1,65 @@
+/* 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_CAM_SERVER_H
+#define _MSM_CAM_SERVER_H
+
+#include <linux/proc_fs.h>
+#include <linux/ioctl.h>
+#include <mach/camera.h>
+#include "msm.h"
+
+uint32_t msm_cam_server_get_mctl_handle(void);
+struct msm_cam_media_controller *msm_cam_server_get_mctl(uint32_t handle);
+void msm_cam_server_free_mctl(uint32_t handle);
+/* Server session control APIs */
+int msm_server_begin_session(struct msm_cam_v4l2_device *pcam,
+ int server_q_idx);
+int msm_server_end_session(struct msm_cam_v4l2_device *pcam);
+int msm_send_open_server(struct msm_cam_v4l2_device *pcam);
+int msm_send_close_server(struct msm_cam_v4l2_device *pcam);
+int msm_server_update_sensor_info(struct msm_cam_v4l2_device *pcam,
+ struct msm_camera_sensor_info *sdata);
+/* Server camera control APIs */
+int msm_server_streamon(struct msm_cam_v4l2_device *pcam, int idx);
+int msm_server_streamoff(struct msm_cam_v4l2_device *pcam, int idx);
+int msm_server_get_usecount(void);
+int32_t msm_find_free_queue(void);
+int msm_server_proc_ctrl_cmd(struct msm_cam_v4l2_device *pcam,
+ struct v4l2_control *ctrl, int is_set_cmd);
+int msm_server_s_ctrl(struct msm_cam_v4l2_device *pcam,
+ struct v4l2_control *ctrl);
+int msm_server_g_ctrl(struct msm_cam_v4l2_device *pcam,
+ struct v4l2_control *ctrl);
+int msm_server_q_ctrl(struct msm_cam_v4l2_device *pcam,
+ struct v4l2_queryctrl *queryctrl);
+int msm_server_set_fmt(struct msm_cam_v4l2_device *pcam, int idx,
+ struct v4l2_format *pfmt);
+int msm_server_set_fmt_mplane(struct msm_cam_v4l2_device *pcam, int idx,
+ struct v4l2_format *pfmt);
+int msm_server_get_fmt(struct msm_cam_v4l2_device *pcam,
+ int idx, struct v4l2_format *pfmt);
+int msm_server_get_fmt_mplane(struct msm_cam_v4l2_device *pcam,
+ int idx, struct v4l2_format *pfmt);
+int msm_server_try_fmt(struct msm_cam_v4l2_device *pcam,
+ struct v4l2_format *pfmt);
+int msm_server_try_fmt_mplane(struct msm_cam_v4l2_device *pcam,
+ struct v4l2_format *pfmt);
+int msm_server_v4l2_subscribe_event(struct v4l2_fh *fh,
+ struct v4l2_event_subscription *sub);
+int msm_server_v4l2_unsubscribe_event(struct v4l2_fh *fh,
+ struct v4l2_event_subscription *sub);
+int msm_server_get_crop(struct msm_cam_v4l2_device *pcam,
+ int idx, struct v4l2_crop *crop);
+
+#endif /* _MSM_CAM_SERVER_H */
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 1d26d45..37f0799 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1588,6 +1588,9 @@
usbmon_urb_complete(&hcd->self, urb, status);
usb_unanchor_urb(urb);
+ if (hcd->driver->log_urb_complete)
+ hcd->driver->log_urb_complete(urb, "C", status);
+
/* pass ownership to the completion handler */
urb->status = status;
urb->complete (urb);
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 822abdcf..6bd0577 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -39,6 +39,7 @@
#include <mach/msm_iomap.h>
#include <mach/msm_xo.h>
#include <linux/spinlock.h>
+#include <linux/cpu.h>
#define MSM_USB_BASE (hcd->regs)
@@ -64,6 +65,183 @@
};
static bool debug_bus_voting_enabled = true;
+
+static unsigned int enable_dbg_log = 1;
+module_param(enable_dbg_log, uint, S_IRUGO | S_IWUSR);
+/*by default log ep0 and efs sync ep*/
+static unsigned int ep_addr_rxdbg_mask = 9;
+module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
+static unsigned int ep_addr_txdbg_mask = 9;
+module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
+
+/* Maximum debug message length */
+#define DBG_MSG_LEN 100UL
+
+/* Maximum number of messages */
+#define DBG_MAX_MSG 256UL
+
+#define TIME_BUF_LEN 20
+
+enum event_type {
+ EVENT_UNDEF = -1,
+ URB_SUBMIT,
+ URB_COMPLETE,
+ EVENT_NONE,
+};
+
+#define EVENT_STR_LEN 5
+
+static char *event_to_str(enum event_type e)
+{
+ switch (e) {
+ case URB_SUBMIT:
+ return "S";
+ case URB_COMPLETE:
+ return "C";
+ case EVENT_NONE:
+ return "NONE";
+ default:
+ return "UNDEF";
+ }
+}
+
+static enum event_type str_to_event(const char *name)
+{
+ if (!strncasecmp("S", name, EVENT_STR_LEN))
+ return URB_SUBMIT;
+ if (!strncasecmp("C", name, EVENT_STR_LEN))
+ return URB_COMPLETE;
+ if (!strncasecmp("", name, EVENT_STR_LEN))
+ return EVENT_NONE;
+
+ return EVENT_UNDEF;
+}
+
+/*log ep0 activity*/
+static struct {
+ char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
+ unsigned idx; /* index */
+ rwlock_t lck; /* lock */
+} dbg_hsic_ctrl = {
+ .idx = 0,
+ .lck = __RW_LOCK_UNLOCKED(lck)
+};
+
+static struct {
+ char (buf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
+ unsigned idx; /* index */
+ rwlock_t lck; /* lock */
+} dbg_hsic_data = {
+ .idx = 0,
+ .lck = __RW_LOCK_UNLOCKED(lck)
+};
+
+/**
+ * dbg_inc: increments debug event index
+ * @idx: buffer index
+ */
+static void dbg_inc(unsigned *idx)
+{
+ *idx = (*idx + 1) & (DBG_MAX_MSG-1);
+}
+
+/*get_timestamp - returns time of day in us */
+static char *get_timestamp(char *tbuf)
+{
+ unsigned long long t;
+ unsigned long nanosec_rem;
+
+ t = cpu_clock(smp_processor_id());
+ nanosec_rem = do_div(t, 1000000000)/1000;
+ scnprintf(tbuf, TIME_BUF_LEN, "[%5lu.%06lu] ", (unsigned long)t,
+ nanosec_rem);
+ return tbuf;
+}
+
+static int allow_dbg_log(int ep_addr)
+{
+ int dir, num;
+
+ dir = ep_addr & USB_DIR_IN ? USB_DIR_IN : USB_DIR_OUT;
+ num = ep_addr & ~USB_DIR_IN;
+ num = 1 << num;
+
+ if ((dir == USB_DIR_IN) && (num & ep_addr_rxdbg_mask))
+ return 1;
+ if ((dir == USB_DIR_OUT) && (num & ep_addr_txdbg_mask))
+ return 1;
+
+ return 0;
+}
+
+static void dbg_log_event(struct urb *urb, char * event, unsigned extra)
+{
+ unsigned long flags;
+ int ep_addr;
+ char tbuf[TIME_BUF_LEN];
+
+ if (!enable_dbg_log)
+ return;
+
+ if (!urb) {
+ write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
+ scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx], DBG_MSG_LEN,
+ "%s: %s : %u\n", get_timestamp(tbuf), event, extra);
+ dbg_inc(&dbg_hsic_ctrl.idx);
+ write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
+ return;
+ }
+
+ ep_addr = urb->ep->desc.bEndpointAddress;
+ if (!allow_dbg_log(ep_addr))
+ return;
+
+ if ((ep_addr & 0x0f) == 0x0) {
+ /*submit event*/
+ if (!str_to_event(event)) {
+ write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
+ scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
+ DBG_MSG_LEN, "%s: [%s : %p]:[%s] "
+ "%02x %02x %04x %04x %04x %u %d\n",
+ get_timestamp(tbuf), event, urb,
+ (ep_addr & USB_DIR_IN) ? "in" : "out",
+ urb->setup_packet[0], urb->setup_packet[1],
+ (urb->setup_packet[3] << 8) |
+ urb->setup_packet[2],
+ (urb->setup_packet[5] << 8) |
+ urb->setup_packet[4],
+ (urb->setup_packet[7] << 8) |
+ urb->setup_packet[6],
+ urb->transfer_buffer_length, urb->status);
+
+ dbg_inc(&dbg_hsic_ctrl.idx);
+ write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
+ } else {
+ write_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
+ scnprintf(dbg_hsic_ctrl.buf[dbg_hsic_ctrl.idx],
+ DBG_MSG_LEN, "%s: [%s : %p]:[%s] %u %d\n",
+ get_timestamp(tbuf), event, urb,
+ (ep_addr & USB_DIR_IN) ? "in" : "out",
+ urb->actual_length, extra);
+
+ dbg_inc(&dbg_hsic_ctrl.idx);
+ write_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
+ }
+ } else {
+ write_lock_irqsave(&dbg_hsic_data.lck, flags);
+ scnprintf(dbg_hsic_data.buf[dbg_hsic_data.idx], DBG_MSG_LEN,
+ "%s: [%s : %p]:ep%d[%s] %u %d\n",
+ get_timestamp(tbuf), event, urb, ep_addr & 0x0f,
+ (ep_addr & USB_DIR_IN) ? "in" : "out",
+ str_to_event(event) ? urb->actual_length :
+ urb->transfer_buffer_length,
+ str_to_event(event) ? extra : urb->status);
+
+ dbg_inc(&dbg_hsic_data.idx);
+ write_unlock_irqrestore(&dbg_hsic_data.lck, flags);
+ }
+}
+
static inline struct msm_hsic_hcd *hcd_to_hsic(struct usb_hcd *hcd)
{
return (struct msm_hsic_hcd *) (hcd->hcd_priv);
@@ -589,6 +767,25 @@
return 0;
}
+static int ehci_hsic_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+ gfp_t mem_flags)
+{
+ dbg_log_event(urb, event_to_str(URB_SUBMIT), 0);
+ return ehci_urb_enqueue(hcd, urb, mem_flags);
+}
+
+static int ehci_hsic_bus_suspend(struct usb_hcd *hcd)
+{
+ dbg_log_event(NULL, "Suspend RH", 0);
+ return ehci_bus_suspend(hcd);
+}
+
+static int ehci_hsic_bus_resume(struct usb_hcd *hcd)
+{
+ dbg_log_event(NULL, "Resume RH", 0);
+ return ehci_bus_resume(hcd);
+}
+
static struct hc_driver msm_hsic_driver = {
.description = hcd_name,
.product_desc = "Qualcomm EHCI Host Controller using HSIC",
@@ -609,7 +806,7 @@
/*
* managing i/o requests and associated device resources
*/
- .urb_enqueue = ehci_urb_enqueue,
+ .urb_enqueue = ehci_hsic_urb_enqueue,
.urb_dequeue = ehci_urb_dequeue,
.endpoint_disable = ehci_endpoint_disable,
.endpoint_reset = ehci_endpoint_reset,
@@ -631,8 +828,10 @@
/*
* PM support
*/
- .bus_suspend = ehci_bus_suspend,
- .bus_resume = ehci_bus_resume,
+ .bus_suspend = ehci_hsic_bus_suspend,
+ .bus_resume = ehci_hsic_bus_resume,
+
+ .log_urb_complete = dbg_log_event,
};
static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
@@ -729,6 +928,7 @@
struct msm_hsic_hcd *mehci = data;
mehci->wakeup_int_cnt++;
+ dbg_log_event(NULL, "Remote Wakeup IRQ", mehci->wakeup_int_cnt);
dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt cnt: %u\n",
__func__, mehci->wakeup_int_cnt);
@@ -822,6 +1022,68 @@
.release = single_release,
};
+static int ehci_hsic_msm_data_events_show(struct seq_file *s, void *unused)
+{
+ unsigned long flags;
+ unsigned i;
+
+ read_lock_irqsave(&dbg_hsic_data.lck, flags);
+
+ i = dbg_hsic_data.idx;
+ for (dbg_inc(&i); i != dbg_hsic_data.idx; dbg_inc(&i)) {
+ if (!strnlen(dbg_hsic_data.buf[i], DBG_MSG_LEN))
+ continue;
+ seq_printf(s, "%s\n", dbg_hsic_data.buf[i]);
+ }
+
+ read_unlock_irqrestore(&dbg_hsic_data.lck, flags);
+
+ return 0;
+}
+
+static int ehci_hsic_msm_data_events_open(struct inode *inode, struct file *f)
+{
+ return single_open(f, ehci_hsic_msm_data_events_show, inode->i_private);
+}
+
+const struct file_operations ehci_hsic_msm_dbg_data_fops = {
+ .open = ehci_hsic_msm_data_events_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int ehci_hsic_msm_ctrl_events_show(struct seq_file *s, void *unused)
+{
+ unsigned long flags;
+ unsigned i;
+
+ read_lock_irqsave(&dbg_hsic_ctrl.lck, flags);
+
+ i = dbg_hsic_ctrl.idx;
+ for (dbg_inc(&i); i != dbg_hsic_ctrl.idx; dbg_inc(&i)) {
+ if (!strnlen(dbg_hsic_ctrl.buf[i], DBG_MSG_LEN))
+ continue;
+ seq_printf(s, "%s\n", dbg_hsic_ctrl.buf[i]);
+ }
+
+ read_unlock_irqrestore(&dbg_hsic_ctrl.lck, flags);
+
+ return 0;
+}
+
+static int ehci_hsic_msm_ctrl_events_open(struct inode *inode, struct file *f)
+{
+ return single_open(f, ehci_hsic_msm_ctrl_events_show, inode->i_private);
+}
+
+const struct file_operations ehci_hsic_msm_dbg_ctrl_fops = {
+ .open = ehci_hsic_msm_ctrl_events_open,
+ .read = seq_read,
+ .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)
{
@@ -852,6 +1114,26 @@
return -ENODEV;
}
+ ehci_hsic_msm_dentry = debugfs_create_file("show_ctrl_events",
+ S_IRUGO,
+ ehci_hsic_msm_dbg_root, mehci,
+ &ehci_hsic_msm_dbg_ctrl_fops);
+
+ if (!ehci_hsic_msm_dentry) {
+ debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
+ return -ENODEV;
+ }
+
+ ehci_hsic_msm_dentry = debugfs_create_file("show_data_events",
+ S_IRUGO,
+ ehci_hsic_msm_dbg_root, mehci,
+ &ehci_hsic_msm_dbg_data_fops);
+
+ if (!ehci_hsic_msm_dentry) {
+ debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
+ return -ENODEV;
+ }
+
return 0;
}
@@ -1077,6 +1359,8 @@
dev_dbg(dev, "ehci-msm-hsic PM suspend\n");
+ dbg_log_event(NULL, "PM Suspend", 0);
+
if (device_may_wakeup(dev))
enable_irq_wake(hcd->irq);
@@ -1094,6 +1378,8 @@
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
+ dbg_log_event(NULL, "PM Resume", 0);
+
if (device_may_wakeup(dev))
disable_irq_wake(hcd->irq);
@@ -1123,6 +1409,9 @@
struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
dev_dbg(dev, "EHCI runtime suspend\n");
+
+ dbg_log_event(NULL, "Run Time PM Suspend", 0);
+
return msm_hsic_suspend(mehci);
}
@@ -1132,6 +1421,9 @@
struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
dev_dbg(dev, "EHCI runtime resume\n");
+
+ dbg_log_event(NULL, "Run Time PM Resume", 0);
+
return msm_hsic_resume(mehci);
}
#endif
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index 6d93360..a1d192d 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -56,7 +56,11 @@
va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
- printk("%sFAT-fs (%s): %pV\n", level, sb->s_id, &vaf);
+ if (!strncmp(level, KERN_ERR, sizeof(KERN_ERR)))
+ printk_ratelimited("%sFAT-fs (%s): %pV\n", level,
+ sb->s_id, &vaf);
+ else
+ printk("%sFAT-fs (%s): %pV\n", level, sb->s_id, &vaf);
va_end(args);
}
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 5762463..a255388 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -343,6 +343,10 @@
* address is set
*/
int (*update_device)(struct usb_hcd *, struct usb_device *);
+
+ /* to log completion events*/
+ void (*log_urb_complete)(struct urb *urb, char * event,
+ unsigned extra);
};
extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index d4cf1d2..8222b67 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -448,6 +448,9 @@
#define CMD_AXI_CFG_SEC 0xF4
#define CMD_AXI_CFG_SEC_ALL_CHNLS 0xF8
+#define CMD_AXI_START 0xE1
+#define CMD_AXI_STOP 0xE2
+
/* vfe config command: config command(from config thread)*/
struct msm_vfe_cfg_cmd {
int cmd_type;
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index 72bb9b5..a15928f 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -45,6 +45,11 @@
#define SITAR_MBHC_DEF_BUTTONS 8
#define SITAR_MBHC_DEF_RLOADS 5
+#define GPIO_AUX_PCM_DOUT 63
+#define GPIO_AUX_PCM_DIN 64
+#define GPIO_AUX_PCM_SYNC 65
+#define GPIO_AUX_PCM_CLK 66
+
static int msm8930_spk_control;
static int msm8930_slim_0_rx_ch = 1;
static int msm8930_slim_0_tx_ch = 1;
@@ -812,6 +817,80 @@
return 0;
}
+static int msm8930_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ /* PCM only supports mono output with 8khz sample rate */
+ rate->min = rate->max = 8000;
+ channels->min = channels->max = 1;
+
+ return 0;
+}
+
+static int msm8930_aux_pcm_get_gpios(void)
+{
+ int ret = 0;
+
+ pr_debug("%s\n", __func__);
+
+ ret = gpio_request(GPIO_AUX_PCM_DOUT, "AUX PCM DOUT");
+ if (ret < 0) {
+ pr_err("%s: Failed to request gpio(%d): AUX PCM DOUT",
+ __func__, GPIO_AUX_PCM_DOUT);
+
+ goto fail_dout;
+ }
+
+ ret = gpio_request(GPIO_AUX_PCM_DIN, "AUX PCM DIN");
+ if (ret < 0) {
+ pr_err("%s: Failed to request gpio(%d): AUX PCM DIN",
+ __func__, GPIO_AUX_PCM_DIN);
+ goto fail_din;
+ }
+
+ ret = gpio_request(GPIO_AUX_PCM_SYNC, "AUX PCM SYNC");
+ if (ret < 0) {
+ pr_err("%s: Failed to request gpio(%d): AUX PCM SYNC",
+ __func__, GPIO_AUX_PCM_SYNC);
+ goto fail_sync;
+ }
+
+ ret = gpio_request(GPIO_AUX_PCM_CLK, "AUX PCM CLK");
+ if (ret < 0) {
+ pr_err("%s: Failed to request gpio(%d): AUX PCM CLK",
+ __func__, GPIO_AUX_PCM_CLK);
+ goto fail_clk;
+ }
+
+ return 0;
+
+fail_clk:
+ gpio_free(GPIO_AUX_PCM_SYNC);
+fail_sync:
+ gpio_free(GPIO_AUX_PCM_DIN);
+fail_din:
+ gpio_free(GPIO_AUX_PCM_DOUT);
+fail_dout:
+
+ return ret;
+}
+
+static int msm8930_aux_pcm_free_gpios(void)
+{
+ gpio_free(GPIO_AUX_PCM_DIN);
+ gpio_free(GPIO_AUX_PCM_DOUT);
+ gpio_free(GPIO_AUX_PCM_SYNC);
+ gpio_free(GPIO_AUX_PCM_CLK);
+
+ return 0;
+}
+
static int msm8930_startup(struct snd_pcm_substream *substream)
{
pr_debug("%s(): substream = %s stream = %d\n", __func__,
@@ -819,6 +898,26 @@
return 0;
}
+static int msm8930_auxpcm_startup(struct snd_pcm_substream *substream)
+{
+ int ret = 0;
+
+ pr_debug("%s(): substream = %s\n", __func__, substream->name);
+ ret = msm8930_aux_pcm_get_gpios();
+ if (ret < 0) {
+ pr_err("%s: Aux PCM GPIO request failed\n", __func__);
+ return -EINVAL;
+ }
+ return 0;
+
+}
+
+static void msm8930_auxpcm_shutdown(struct snd_pcm_substream *substream)
+{
+ pr_debug("%s(): substream = %s\n", __func__, substream->name);
+ msm8930_aux_pcm_free_gpios();
+}
+
static void msm8930_shutdown(struct snd_pcm_substream *substream)
{
pr_debug("%s(): substream = %s stream = %d\n", __func__,
@@ -831,6 +930,11 @@
.shutdown = msm8930_shutdown,
};
+static struct snd_soc_ops msm8930_auxpcm_be_ops = {
+ .startup = msm8930_auxpcm_startup,
+ .shutdown = msm8930_auxpcm_shutdown,
+};
+
/* Digital audio interface glue - connects codec <---> CPU */
static struct snd_soc_dai_link msm8930_dai[] = {
/* FrontEnd DAI Links */
@@ -1061,6 +1165,30 @@
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
},
+ /* AUX PCM Backend DAI Links */
+ {
+ .name = LPASS_BE_AUXPCM_RX,
+ .stream_name = "AUX PCM Playback",
+ .cpu_dai_name = "msm-dai-q6.2",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_AUXPCM_RX,
+ .be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
+ .ops = &msm8930_auxpcm_be_ops,
+ },
+ {
+ .name = LPASS_BE_AUXPCM_TX,
+ .stream_name = "AUX PCM Capture",
+ .cpu_dai_name = "msm-dai-q6.3",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_AUXPCM_TX,
+ .be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
+ },
/* Incall Music BACK END DAI Link */
{
.name = LPASS_BE_VOICE_PLAYBACK_TX,