Merge "ASoC: msm: Fix SRS key not being sent to DSP sometimes problem" into msm-3.4
diff --git a/arch/arm/mach-msm/acpuclock-7627.c b/arch/arm/mach-msm/acpuclock-7627.c
index 7c2c556..f9ff226 100644
--- a/arch/arm/mach-msm/acpuclock-7627.c
+++ b/arch/arm/mach-msm/acpuclock-7627.c
@@ -18,6 +18,7 @@
#include <linux/version.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/string.h>
@@ -27,6 +28,8 @@
#include <linux/mutex.h>
#include <linux/io.h>
#include <linux/sort.h>
+#include <linux/platform_device.h>
+
#include <mach/board.h>
#include <mach/msm_iomap.h>
#include <mach/socinfo.h>
@@ -402,7 +405,7 @@
#ifdef CONFIG_CPU_FREQ_MSM
static struct cpufreq_frequency_table freq_table[NR_CPUS][20];
-static void __init cpufreq_table_init(void)
+static void __devinit cpufreq_table_init(void)
{
int cpu;
for_each_possible_cpu(cpu) {
@@ -693,7 +696,7 @@
return rc;
}
-static void __init acpuclk_hw_init(void)
+static void __devinit acpuclk_hw_init(void)
{
struct clkctl_acpu_speed *speed;
uint32_t div, sel, reg_clksel;
@@ -775,7 +778,7 @@
* Clock driver initialization
*---------------------------------------------------------------------------*/
#define MHZ 1000000
-static void __init select_freq_plan(void)
+static void __devinit select_freq_plan(void)
{
unsigned long pll_mhz[ACPU_PLL_END];
struct pll_freq_tbl_map *t;
@@ -835,7 +838,7 @@
* Hardware requires the CPU to be dropped to less than MAX_WAIT_FOR_IRQ_KHZ
* before entering a wait for irq low-power mode. Find a suitable rate.
*/
-static unsigned long __init find_wait_for_irq_khz(void)
+static unsigned long __devinit find_wait_for_irq_khz(void)
{
unsigned long found_khz = 0;
int i;
@@ -847,7 +850,7 @@
return found_khz;
}
-static void __init lpj_init(void)
+static void __devinit lpj_init(void)
{
int i = 0, cpu;
const struct clkctl_acpu_speed *base_clk = drv_state.current_speed;
@@ -868,7 +871,7 @@
}
}
-static void __init precompute_stepping(void)
+static void __devinit precompute_stepping(void)
{
int i, step_idx;
@@ -909,7 +912,7 @@
}
}
-static void __init print_acpu_freq_tbl(void)
+static void __devinit print_acpu_freq_tbl(void)
{
struct clkctl_acpu_speed *t;
short down_idx[ACPU_PLL_END];
@@ -947,15 +950,17 @@
.switch_time_us = 50,
};
-static int __init acpuclk_7627_init(struct acpuclk_soc_data *soc_data)
+static int __devinit acpuclk_7627_probe(struct platform_device *pdev)
{
+ const struct acpuclk_pdata *pdata = pdev->dev.platform_data;
+
pr_info("%s()\n", __func__);
drv_state.ebi1_clk = clk_get(NULL, "ebi1_acpu_clk");
BUG_ON(IS_ERR(drv_state.ebi1_clk));
mutex_init(&drv_state.lock);
- drv_state.max_speed_delta_khz = soc_data->max_speed_delta_khz;
+ drv_state.max_speed_delta_khz = pdata->max_speed_delta_khz;
select_freq_plan();
acpuclk_7627_data.wait_for_irq_khz = find_wait_for_irq_khz();
precompute_stepping();
@@ -970,23 +975,16 @@
return 0;
}
-struct acpuclk_soc_data acpuclk_7x27_soc_data __initdata = {
- .max_speed_delta_khz = 400000,
- .init = acpuclk_7627_init,
+static struct platform_driver acpuclk_7627_driver = {
+ .probe = acpuclk_7627_probe,
+ .driver = {
+ .name = "acpuclk-7627",
+ .owner = THIS_MODULE,
+ },
};
-struct acpuclk_soc_data acpuclk_7x27a_soc_data __initdata = {
- .max_speed_delta_khz = 400000,
- .init = acpuclk_7627_init,
-};
-
-struct acpuclk_soc_data acpuclk_7x27aa_soc_data __initdata = {
- .max_speed_delta_khz = 504000,
- .init = acpuclk_7627_init,
-};
-
-struct acpuclk_soc_data acpuclk_8625_soc_data __initdata = {
- /* TODO: Need to update speed delta from H/w Team */
- .max_speed_delta_khz = 604800,
- .init = acpuclk_7627_init,
-};
+static int __init acpuclk_7627_init(void)
+{
+ return platform_driver_register(&acpuclk_7627_driver);
+}
+postcore_initcall(acpuclk_7627_init);
diff --git a/arch/arm/mach-msm/acpuclock-7x30.c b/arch/arm/mach-msm/acpuclock-7x30.c
index 29b0065..b49613e 100644
--- a/arch/arm/mach-msm/acpuclock-7x30.c
+++ b/arch/arm/mach-msm/acpuclock-7x30.c
@@ -16,6 +16,7 @@
#include <linux/version.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/string.h>
@@ -25,6 +26,7 @@
#include <linux/mutex.h>
#include <linux/io.h>
#include <linux/sort.h>
+#include <linux/platform_device.h>
#include <mach/board.h>
#include <mach/msm_iomap.h>
#include <asm/mach-types.h>
@@ -315,7 +317,7 @@
* Clock driver initialization
*---------------------------------------------------------------------------*/
-static void __init acpuclk_hw_init(void)
+static void __devinit acpuclk_hw_init(void)
{
struct clkctl_acpu_speed *s;
uint32_t div, sel, src_num;
@@ -393,7 +395,7 @@
}
/* Initalize the lpj field in the acpu_freq_tbl. */
-static void __init lpj_init(void)
+static void __devinit lpj_init(void)
{
int i;
const struct clkctl_acpu_speed *base_clk = drv_state.current_speed;
@@ -431,7 +433,7 @@
* Truncate the frequency table at the current PLL2 rate and determine the
* backup PLL to use when scaling PLL2.
*/
-void __init pll2_fixup(void)
+void __devinit pll2_fixup(void)
{
struct clkctl_acpu_speed *speed = acpu_freq_tbl;
u8 pll2_l = readl_relaxed(PLL2_L_VAL_ADDR) & 0xFF;
@@ -453,7 +455,7 @@
#define RPM_BYPASS_MASK (1 << 3)
#define PMIC_MODE_MASK (1 << 4)
-static void __init populate_plls(void)
+static void __devinit populate_plls(void)
{
acpuclk_sources[PLL_1] = clk_get_sys("acpu", "pll1_clk");
BUG_ON(IS_ERR(acpuclk_sources[PLL_1]));
@@ -479,7 +481,7 @@
.switch_time_us = 50,
};
-static int __init acpuclk_7x30_init(struct acpuclk_soc_data *soc_data)
+static int __devinit acpuclk_7x30_probe(struct platform_device *pdev)
{
pr_info("%s()\n", __func__);
@@ -494,6 +496,16 @@
return 0;
}
-struct acpuclk_soc_data acpuclk_7x30_soc_data __initdata = {
- .init = acpuclk_7x30_init,
+static struct platform_driver acpuclk_7x30_driver = {
+ .probe = acpuclk_7x30_probe,
+ .driver = {
+ .name = "acpuclk-7x30",
+ .owner = THIS_MODULE,
+ },
};
+
+static int __init acpuclk_7x30_init(void)
+{
+ return platform_driver_register(&acpuclk_7x30_driver);
+}
+postcore_initcall(acpuclk_7x30_init);
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index afa98c1..d29fee6 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -13,6 +13,7 @@
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/delay.h>
@@ -22,6 +23,7 @@
#include <linux/cpufreq.h>
#include <linux/cpu.h>
#include <linux/regulator/consumer.h>
+#include <linux/platform_device.h>
#include <asm/mach-types.h>
#include <asm/cpu.h>
@@ -1649,7 +1651,7 @@
.wait_for_irq_khz = STBY_KHZ,
};
-static int __init acpuclk_8960_init(struct acpuclk_soc_data *soc_data)
+static int __init acpuclk_8960_probe(struct platform_device *pdev)
{
struct acpu_level *max_acpu_level = select_freq_plan();
@@ -1667,14 +1669,15 @@
return 0;
}
-struct acpuclk_soc_data acpuclk_8960_soc_data __initdata = {
- .init = acpuclk_8960_init,
+static struct platform_driver acpuclk_8960_driver = {
+ .driver = {
+ .name = "acpuclk-8960",
+ .owner = THIS_MODULE,
+ },
};
-struct acpuclk_soc_data acpuclk_8930_soc_data __initdata = {
- .init = acpuclk_8960_init,
-};
-
-struct acpuclk_soc_data acpuclk_8064_soc_data __initdata = {
- .init = acpuclk_8960_init,
-};
+static int __init acpuclk_8960_init(void)
+{
+ return platform_driver_probe(&acpuclk_8960_driver, acpuclk_8960_probe);
+}
+device_initcall(acpuclk_8960_init);
diff --git a/arch/arm/mach-msm/acpuclock-8x50.c b/arch/arm/mach-msm/acpuclock-8x50.c
index cde5a14..996f883 100644
--- a/arch/arm/mach-msm/acpuclock-8x50.c
+++ b/arch/arm/mach-msm/acpuclock-8x50.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-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
@@ -12,6 +12,7 @@
*/
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/delay.h>
@@ -20,6 +21,7 @@
#include <linux/cpufreq.h>
#include <linux/clk.h>
#include <linux/mfd/tps65023.h>
+#include <linux/platform_device.h>
#include <mach/board.h>
#include <mach/msm_iomap.h>
@@ -130,7 +132,7 @@
#ifdef CONFIG_CPU_FREQ_MSM
static struct cpufreq_frequency_table freq_table[20];
-static void __init cpufreq_table_init(void)
+static void __devinit cpufreq_table_init(void)
{
unsigned int i;
unsigned int freq_cnt = 0;
@@ -504,7 +506,7 @@
return rc;
}
-static void __init acpuclk_hw_init(void)
+static void __devinit acpuclk_hw_init(void)
{
struct clkctl_acpu_speed *speed;
uint32_t div, sel, regval;
@@ -582,7 +584,7 @@
#define PLL0_M_VAL_ADDR (MSM_CLK_CTL_BASE + 0x308)
-static void __init acpu_freq_tbl_fixup(void)
+static void __devinit acpu_freq_tbl_fixup(void)
{
void __iomem *ct_csr_base;
uint32_t tcsr_spare2, pll0_m_val;
@@ -645,7 +647,7 @@
}
/* Initalize the lpj field in the acpu_freq_tbl. */
-static void __init lpj_init(void)
+static void __devinit lpj_init(void)
{
int i;
const struct clkctl_acpu_speed *base_clk = drv_state.current_speed;
@@ -657,7 +659,7 @@
}
#ifdef CONFIG_MSM_CPU_AVS
-static int __init acpu_avs_init(int (*set_vdd) (int), int khz)
+static int __devinit acpu_avs_init(int (*set_vdd) (int), int khz)
{
int i;
int freq_count = 0;
@@ -704,7 +706,7 @@
.switch_time_us = 20,
};
-static int __init acpuclk_8x50_init(struct acpuclk_soc_data *soc_data)
+static int __devinit acpuclk_8x50_probe(struct platform_device *pdev)
{
mutex_init(&drv_state.lock);
drv_state.acpu_set_vdd = qsd8x50_tps65023_set_dcdc1;
@@ -736,6 +738,16 @@
return 0;
}
-struct acpuclk_soc_data acpuclk_8x50_soc_data __initdata = {
- .init = acpuclk_8x50_init,
+static struct platform_driver acpuclk_8x50_driver = {
+ .probe = acpuclk_8x50_probe,
+ .driver = {
+ .name = "acpuclk-8x50",
+ .owner = THIS_MODULE,
+ },
};
+
+static int __init acpuclk_8x50_init(void)
+{
+ return platform_driver_register(&acpuclk_8x50_driver);
+}
+postcore_initcall(acpuclk_8x50_init);
diff --git a/arch/arm/mach-msm/acpuclock-8x60.c b/arch/arm/mach-msm/acpuclock-8x60.c
index 48efa18..ef34b3c 100644
--- a/arch/arm/mach-msm/acpuclock-8x60.c
+++ b/arch/arm/mach-msm/acpuclock-8x60.c
@@ -11,6 +11,7 @@
*/
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/delay.h>
@@ -20,6 +21,7 @@
#include <linux/cpufreq.h>
#include <linux/cpu.h>
#include <linux/regulator/consumer.h>
+#include <linux/platform_device.h>
#include <asm/cpu.h>
@@ -734,7 +736,7 @@
}
/* AVS needs SAW_VCTL to be intitialized correctly, before enable,
- * and is not initialized at acpuclk_init().
+ * and is not initialized during probe.
*/
if (reason == SETRATE_CPUFREQ)
AVS_DISABLE(cpu);
@@ -1062,7 +1064,7 @@
.wait_for_irq_khz = MAX_AXI,
};
-static int __init acpuclk_8x60_init(struct acpuclk_soc_data *soc_data)
+static int __init acpuclk_8x60_probe(struct platform_device *pdev)
{
struct clkctl_acpu_speed *max_freq;
int cpu;
@@ -1091,6 +1093,15 @@
return 0;
}
-struct acpuclk_soc_data acpuclk_8x60_soc_data __initdata = {
- .init = acpuclk_8x60_init,
+static struct platform_driver acpuclk_8x60_driver = {
+ .driver = {
+ .name = "acpuclk-8x60",
+ .owner = THIS_MODULE,
+ },
};
+
+static int __init acpuclk_8x60_init(void)
+{
+ return platform_driver_probe(&acpuclk_8x60_driver, acpuclk_8x60_probe);
+}
+device_initcall(acpuclk_8x60_init);
diff --git a/arch/arm/mach-msm/acpuclock-9615.c b/arch/arm/mach-msm/acpuclock-9615.c
index 24b81b9..db7bab3 100644
--- a/arch/arm/mach-msm/acpuclock-9615.c
+++ b/arch/arm/mach-msm/acpuclock-9615.c
@@ -14,6 +14,7 @@
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/delay.h>
@@ -22,6 +23,7 @@
#include <linux/errno.h>
#include <linux/cpufreq.h>
#include <linux/clk.h>
+#include <linux/platform_device.h>
#include <asm/cpu.h>
@@ -306,7 +308,7 @@
.wait_for_irq_khz = 19200,
};
-static int __init acpuclk_9615_init(struct acpuclk_soc_data *soc_data)
+static int __init acpuclk_9615_probe(struct platform_device *pdev)
{
unsigned long max_cpu_khz = 0;
int i;
@@ -351,6 +353,15 @@
return 0;
}
-struct acpuclk_soc_data acpuclk_9615_soc_data __initdata = {
- .init = acpuclk_9615_init,
+static struct platform_driver acpuclk_9615_driver = {
+ .driver = {
+ .name = "acpuclk-9615",
+ .owner = THIS_MODULE,
+ },
};
+
+static int __init acpuclk_9615_init(void)
+{
+ return platform_driver_probe(&acpuclk_9615_driver, acpuclk_9615_probe);
+}
+device_initcall(acpuclk_9615_init);
diff --git a/arch/arm/mach-msm/acpuclock-fsm9xxx.c b/arch/arm/mach-msm/acpuclock-fsm9xxx.c
index 3cdc58d..af1c0eb 100644
--- a/arch/arm/mach-msm/acpuclock-fsm9xxx.c
+++ b/arch/arm/mach-msm/acpuclock-fsm9xxx.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,8 +11,10 @@
*
*/
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/platform_device.h>
#include <mach/board.h>
#include "acpuclock.h"
@@ -40,13 +42,22 @@
.get_rate = acpuclk_9xxx_get_rate,
};
-static int __init acpuclk_9xxx_init(struct acpuclk_soc_data *soc_data)
+static int __init acpuclk_9xxx_probe(struct platform_device *pdev)
{
acpuclk_register(&acpuclk_9xxx_data);
pr_info("ACPU running at %lu KHz\n", acpuclk_get_rate(0));
return 0;
}
-struct acpuclk_soc_data acpuclk_9xxx_soc_data __initdata = {
- .init = acpuclk_9xxx_init,
+static struct platform_driver acpuclk_9xxx_driver = {
+ .driver = {
+ .name = "acpuclk-9xxx",
+ .owner = THIS_MODULE,
+ },
};
+
+static int __init acpuclk_9xxx_init(void)
+{
+ return platform_driver_probe(&acpuclk_9xxx_driver, acpuclk_9xxx_probe);
+}
+device_initcall(acpuclk_9xxx_init);
diff --git a/arch/arm/mach-msm/acpuclock.c b/arch/arm/mach-msm/acpuclock.c
index 91071c4..be056e6 100644
--- a/arch/arm/mach-msm/acpuclock.c
+++ b/arch/arm/mach-msm/acpuclock.c
@@ -53,24 +53,7 @@
return rate;
}
-void __init acpuclk_register(struct acpuclk_data *data)
+void __devinit acpuclk_register(struct acpuclk_data *data)
{
acpuclk_data = data;
}
-
-int __init acpuclk_init(struct acpuclk_soc_data *soc_data)
-{
- int rc;
-
- if (!soc_data->init)
- return -EINVAL;
-
- rc = soc_data->init(soc_data);
- if (rc)
- return rc;
-
- if (!acpuclk_data)
- return -ENODEV;
-
- return 0;
-}
diff --git a/arch/arm/mach-msm/acpuclock.h b/arch/arm/mach-msm/acpuclock.h
index c5f0ee3..e73a2af 100644
--- a/arch/arm/mach-msm/acpuclock.h
+++ b/arch/arm/mach-msm/acpuclock.h
@@ -31,12 +31,11 @@
};
/**
- * struct acpuclk_soc_data - SoC data for acpuclk_init()
+ * struct acpuclk_pdata - Platform data for acpuclk
*/
-struct acpuclk_soc_data {
+struct acpuclk_pdata {
unsigned long max_speed_delta_khz;
unsigned int max_axi_khz;
- int (*init)(struct acpuclk_soc_data *);
};
/**
@@ -91,25 +90,4 @@
*/
void acpuclk_register(struct acpuclk_data *data);
-/**
- * acpuclk_init() - acpuclock driver initialization function
- *
- * Return 0 for success.
- */
-int acpuclk_init(struct acpuclk_soc_data *);
-
-/* SoC-specific acpuclock initialization functions. */
-extern struct acpuclk_soc_data acpuclk_7x27_soc_data;
-extern struct acpuclk_soc_data acpuclk_7x27a_soc_data;
-extern struct acpuclk_soc_data acpuclk_7x27aa_soc_data;
-extern struct acpuclk_soc_data acpuclk_7x30_soc_data;
-extern struct acpuclk_soc_data acpuclk_8x50_soc_data;
-extern struct acpuclk_soc_data acpuclk_8x60_soc_data;
-extern struct acpuclk_soc_data acpuclk_8960_soc_data;
-extern struct acpuclk_soc_data acpuclk_9xxx_soc_data;
-extern struct acpuclk_soc_data acpuclk_9615_soc_data;
-extern struct acpuclk_soc_data acpuclk_8930_soc_data;
-extern struct acpuclk_soc_data acpuclk_8064_soc_data;
-extern struct acpuclk_soc_data acpuclk_8625_soc_data;
-
#endif
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 40b87fc..1d231ef 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -74,7 +74,6 @@
#include "msm_watchdog.h"
#include "board-8064.h"
-#include "acpuclock.h"
#include "spm.h"
#include <mach/mpm.h>
#include "rpm_resources.h"
@@ -2110,6 +2109,7 @@
};
static struct platform_device *common_devices[] __initdata = {
+ &msm8960_device_acpuclk,
&apq8064_device_dmov,
&apq8064_device_qup_spi_gsbi5,
&apq8064_device_ext_5v_vreg,
@@ -2911,7 +2911,6 @@
ARRAY_SIZE(apq8064_slim_devices));
apq8064_init_dsps();
msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
- acpuclk_init(&acpuclk_8064_soc_data);
msm_spm_l2_init(msm_spm_l2_data);
BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 6c4cbd3..e075630 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -86,7 +86,6 @@
#include <mach/cpuidle.h>
#include "rpm_resources.h"
#include <mach/mpm.h>
-#include "acpuclock.h"
#include "smd_private.h"
#include "pm-boot.h"
#include "msm_watchdog.h"
@@ -2035,6 +2034,7 @@
};
static struct platform_device *common_devices[] __initdata = {
+ &msm8960_device_acpuclk,
&msm8960_device_dmov,
&msm_device_smd,
&msm8960_device_uart_gsbi5,
@@ -2433,7 +2433,6 @@
msm8930_init_cam();
#endif
msm8930_init_mmc();
- acpuclk_init(&acpuclk_8930_soc_data);
mxt_init_vkeys_8930();
register_i2c_devices();
msm8930_init_fb();
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 8f49afd..22ef940 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -97,7 +97,6 @@
#include <mach/cpuidle.h>
#include "rpm_resources.h"
#include <mach/mpm.h>
-#include "acpuclock.h"
#include "smd_private.h"
#include "pm-boot.h"
#include "msm_watchdog.h"
@@ -2508,6 +2507,7 @@
#endif
static struct platform_device *common_devices[] __initdata = {
+ &msm8960_device_acpuclk,
&msm8960_device_dmov,
&msm_device_smd,
&msm_device_uart_dm6,
@@ -3060,7 +3060,6 @@
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
msm8960_pm8921_gpio_mpp_init();
platform_add_devices(sim_devices, ARRAY_SIZE(sim_devices));
- acpuclk_init(&acpuclk_8960_soc_data);
msm8960_device_qup_spi_gsbi1.dev.platform_data =
&msm8960_qup_spi_gsbi1_pdata;
@@ -3173,7 +3172,6 @@
msm8960_init_cam();
#endif
msm8960_init_mmc();
- acpuclk_init(&acpuclk_8960_soc_data);
if (machine_is_msm8960_liquid())
mxt_init_hw_liquid();
register_i2c_devices();
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index dc376b5..1089d61 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -50,7 +50,6 @@
#include "devices.h"
#include "board-9615.h"
#include "pm.h"
-#include "acpuclock.h"
#include "pm-boot.h"
#include <mach/gpiomux.h>
@@ -850,6 +849,7 @@
};
static struct platform_device *common_devices[] = {
+ &msm9615_device_acpuclk,
&msm9615_device_dmov,
&msm_device_smd,
#ifdef CONFIG_LTC4088_CHARGER
@@ -979,7 +979,6 @@
msm_device_usb_bam.dev.platform_data = &msm_usb_bam_pdata;
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
msm9615_pm8xxx_gpio_mpp_init();
- acpuclk_init(&acpuclk_9615_soc_data);
/* Ensure ar6000pm device is registered before MMC/SDC */
msm9615_init_ar6000pm();
diff --git a/arch/arm/mach-msm/board-fsm9xxx.c b/arch/arm/mach-msm/board-fsm9xxx.c
index 6ad3cef..b071353 100644
--- a/arch/arm/mach-msm/board-fsm9xxx.c
+++ b/arch/arm/mach-msm/board-fsm9xxx.c
@@ -38,7 +38,6 @@
#include <mach/socinfo.h>
#include "devices.h"
#include "timer.h"
-#include "acpuclock.h"
#include "pm.h"
#include "spm.h"
#include <linux/regulator/consumer.h>
@@ -804,11 +803,17 @@
},
};
+static struct platform_device fsm9xxx_device_acpuclk = {
+ .name = "acpuclk-9xxx",
+ .id = -1,
+};
+
/*
* Devices
*/
static struct platform_device *devices[] __initdata = {
+ &fsm9xxx_device_acpuclk,
&msm_device_smd,
&msm_device_dmov,
&msm_device_nand,
@@ -873,8 +878,6 @@
static void __init fsm9xxx_init(void)
{
- acpuclk_init(&acpuclk_9xxx_soc_data);
-
regulator_has_full_constraints();
#if defined(CONFIG_I2C_SSBI) || defined(CONFIG_MSM_SSBI)
diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c
index d42458f..a7fed3e 100644
--- a/arch/arm/mach-msm/board-msm7x27.c
+++ b/arch/arm/mach-msm/board-msm7x27.c
@@ -65,7 +65,6 @@
#include "board-msm7627-regulator.h"
#include "devices.h"
#include "clock.h"
-#include "acpuclock.h"
#include "msm-keypad-devices.h"
#include "pm.h"
#include "pm-boot.h"
@@ -1775,7 +1774,7 @@
}
}
#endif
- acpuclk_init(&acpuclk_7x27_soc_data);
+ platform_device_register(&msm7x27_device_acpuclk);
usb_mpp_init();
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 96d8b17..2834f24 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -6956,7 +6956,7 @@
msm7x30_init_uart2();
#endif
msm_spm_init(&msm_spm_data, 1);
- acpuclk_init(&acpuclk_7x30_soc_data);
+ platform_device_register(&msm7x30_device_acpuclk);
if (machine_is_msm7x30_surf() || machine_is_msm7x30_fluid())
msm7x30_cfg_smsc911x();
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 54c8fbd..098ad6e 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -100,7 +100,6 @@
#include "peripheral-loader.h"
#include <linux/platform_data/qcom_crypto_device.h>
#include "rpm_resources.h"
-#include "acpuclock.h"
#include "pm-boot.h"
#include "board-storage-common-a.h"
@@ -5135,6 +5134,7 @@
};
static struct platform_device *surf_devices[] __initdata = {
+ &msm8x60_device_acpuclk,
&msm_device_smd,
&msm_device_uart_dm12,
&msm_pil_q6v3,
@@ -10339,9 +10339,6 @@
*/
msm8x60_init_buses();
platform_add_devices(early_devices, ARRAY_SIZE(early_devices));
- /* CPU frequency control is not supported on simulated targets. */
- if (!machine_is_msm8x60_rumi3() && !machine_is_msm8x60_sim())
- acpuclk_init(&acpuclk_8x60_soc_data);
/*
* Enable EBI2 only for boards which make use of it. Leave
diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c
index 6a39316..4df4266 100644
--- a/arch/arm/mach-msm/board-qsd8x50.c
+++ b/arch/arm/mach-msm/board-qsd8x50.c
@@ -2409,7 +2409,7 @@
{
msm_clock_init(&qds8x50_clock_init_data);
qsd8x50_cfg_smc91x();
- acpuclk_init(&acpuclk_8x50_soc_data);
+ platform_device_register(&msm8x50_device_acpuclk);
msm_hsusb_pdata.swfi_latency =
msm_pm_data
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 6a9f7f0..550a283 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -202,6 +202,11 @@
},
};
+struct platform_device msm8960_device_acpuclk = {
+ .name = "acpuclk-8960",
+ .id = -1,
+};
+
#define SHARED_IMEM_TZ_BASE 0x2a03f720
static struct resource tzlog_resources[] = {
{
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index f13c266..06d8653 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -107,6 +107,11 @@
},
};
+struct platform_device msm9615_device_acpuclk = {
+ .name = "acpuclk-9615",
+ .id = -1,
+};
+
#define MSM_USB_BAM_BASE 0x12502000
#define MSM_USB_BAM_SIZE SZ_16K
#define MSM_HSIC_BAM_BASE 0x12542000
diff --git a/arch/arm/mach-msm/devices-msm7x27.c b/arch/arm/mach-msm/devices-msm7x27.c
index ffd10fa..4619cca 100644
--- a/arch/arm/mach-msm/devices-msm7x27.c
+++ b/arch/arm/mach-msm/devices-msm7x27.c
@@ -27,6 +27,7 @@
#include "devices.h"
#include "footswitch.h"
+#include "acpuclock.h"
#include <asm/mach/flash.h>
@@ -431,6 +432,16 @@
msm_pm_set_irq_extns(&msm7x27_pm_irq_calls);
}
+static struct acpuclk_pdata msm7x27_acpuclk_pdata = {
+ .max_speed_delta_khz = 400000,
+};
+
+struct platform_device msm7x27_device_acpuclk = {
+ .name = "acpuclk-7627",
+ .id = -1,
+ .dev.platform_data = &msm7x27_acpuclk_pdata,
+};
+
#define MSM_SDC1_BASE 0xA0400000
#define MSM_SDC2_BASE 0xA0500000
#define MSM_SDC3_BASE 0xA0600000
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index adc9169..b3454cd 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -211,6 +211,37 @@
},
};
+static struct acpuclk_pdata msm7x27a_acpuclk_pdata = {
+ .max_speed_delta_khz = 400000,
+};
+
+struct platform_device msm7x27a_device_acpuclk = {
+ .name = "acpuclk-7627",
+ .id = -1,
+ .dev.platform_data = &msm7x27a_acpuclk_pdata,
+};
+
+static struct acpuclk_pdata msm7x27aa_acpuclk_pdata = {
+ .max_speed_delta_khz = 504000,
+};
+
+struct platform_device msm7x27aa_device_acpuclk = {
+ .name = "acpuclk-7627",
+ .id = -1,
+ .dev.platform_data = &msm7x27aa_acpuclk_pdata,
+};
+
+static struct acpuclk_pdata msm8625_acpuclk_pdata = {
+ /* TODO: Need to update speed delta from H/w Team */
+ .max_speed_delta_khz = 604800,
+};
+
+struct platform_device msm8625_device_acpuclk = {
+ .name = "acpuclk-7627",
+ .id = -1,
+ .dev.platform_data = &msm8625_acpuclk_pdata,
+};
+
struct platform_device msm_device_smd = {
.name = "msm_smd",
.id = -1,
@@ -1623,16 +1654,15 @@
msm_clock_init(&msm7x27a_clock_init_data);
if (cpu_is_msm7x27aa() || cpu_is_msm7x25ab())
- acpuclk_init(&acpuclk_7x27aa_soc_data);
+ platform_device_register(&msm7x27aa_device_acpuclk);
else if (cpu_is_msm8625()) {
if (msm8625_cpu_id() == MSM8625)
- acpuclk_init(&acpuclk_7x27aa_soc_data);
+ platform_device_register(&msm7x27aa_device_acpuclk);
else if (msm8625_cpu_id() == MSM8625A)
- acpuclk_init(&acpuclk_8625_soc_data);
- } else {
- acpuclk_init(&acpuclk_7x27a_soc_data);
- }
-
+ platform_device_register(&msm8625_device_acpuclk);
+ } else {
+ platform_device_register(&msm7x27a_device_acpuclk);
+ }
return 0;
}
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index de70429..ff747e2 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -42,6 +42,11 @@
#include "pm.h"
#include "irq.h"
+struct platform_device msm7x30_device_acpuclk = {
+ .name = "acpuclk-7x30",
+ .id = -1,
+};
+
/* EBI THERMAL DRIVER */
static struct resource msm_ebi0_thermal_resources[] = {
{
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 37844c1..d8bf054 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -163,6 +163,11 @@
},
};
+struct platform_device msm8x60_device_acpuclk = {
+ .name = "acpuclk-8x60",
+ .id = -1,
+};
+
#ifdef CONFIG_MSM_DSPS
#define GSBI12_DEV (&msm_dsps_device.dev)
#else
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
index ee8a2cf..2ecc852 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -34,6 +34,11 @@
#include <mach/rpc_hsusb.h>
#include "pm.h"
+struct platform_device msm8x50_device_acpuclk = {
+ .name = "acpuclk-8x50",
+ .id = -1,
+};
+
static struct resource resources_uart1[] = {
{
.start = INT_UART1,
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 17cce7b..ea47727 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -412,3 +412,13 @@
extern struct platform_device mdm_sglte_device;
extern struct platform_device apq_device_tz_log;
+
+extern struct platform_device msm7x27_device_acpuclk;
+extern struct platform_device msm7x27a_device_acpuclk;
+extern struct platform_device msm7x27aa_device_acpuclk;
+extern struct platform_device msm7x30_device_acpuclk;
+extern struct platform_device msm8625_device_acpuclk;
+extern struct platform_device msm8x50_device_acpuclk;
+extern struct platform_device msm8x60_device_acpuclk;
+extern struct platform_device msm8960_device_acpuclk;
+extern struct platform_device msm9615_device_acpuclk;
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 83d65b1..69aa411 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1016,7 +1016,7 @@
ENCODE_RSP_AND_SEND(8+rt_mask_size-1);
return 0;
}
- ptr += MAX_SSID_PER_RANGE*4;
+ rt_mask_ptr += MAX_SSID_PER_RANGE*4;
}
} else
buf = temp;
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index 964218f..5ffc133 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -261,6 +261,16 @@
---help---
Enable support for Video Pre-processing Engine
+config MSM_CAM_IRQ_ROUTER
+ bool "Enable MSM CAM IRQ Router"
+ depends on MSM_CAMERA
+ ---help---
+ Enable IRQ Router for Camera. Depending on the
+ configuration, this module can handle the
+ interrupts from multiple camera hardware
+ cores and composite them into a single
+ interrupt to the MSM.
+
config QUP_EXCLUSIVE_TO_CAMERA
bool "QUP exclusive to camera"
depends on MSM_CAMERA
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index 9ed6cca..431da2e 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -14,6 +14,7 @@
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) += server/ eeprom/ sensors/ actuators/ csi/
obj-$(CONFIG_MSM_CAMERA) += msm_gesture.o
+ obj-$(CONFIG_MSM_CAM_IRQ_ROUTER) += msm_camirq_router.o
else
obj-$(CONFIG_MSM_CAMERA) += msm_camera.o
endif
diff --git a/drivers/media/video/msm/csi/msm_csic.c b/drivers/media/video/msm/csi/msm_csic.c
index a217f9d..dbb4f32 100644
--- a/drivers/media/video/msm/csi/msm_csic.c
+++ b/drivers/media/video/msm/csi/msm_csic.c
@@ -388,6 +388,8 @@
{
struct csic_device *new_csic_dev;
int rc = 0;
+ struct msm_cam_subdev_info sd_info;
+
CDBG("%s: device id = %d\n", __func__, pdev->id);
new_csic_dev = kzalloc(sizeof(struct csic_device), GFP_KERNEL);
if (!new_csic_dev) {
@@ -455,8 +457,11 @@
iounmap(new_csic_dev->base);
new_csic_dev->base = NULL;
+ sd_info.sdev_type = CSIC_DEV;
+ sd_info.sd_index = pdev->id;
+ sd_info.irq_num = new_csic_dev->irq->start;
msm_cam_register_subdev_node(
- &new_csic_dev->subdev, CSIC_DEV, pdev->id);
+ &new_csic_dev->subdev, &sd_info);
return 0;
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
index bb2a1d4..1ab4e66 100644
--- a/drivers/media/video/msm/csi/msm_csid.c
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -298,6 +298,8 @@
static int __devinit csid_probe(struct platform_device *pdev)
{
struct csid_device *new_csid_dev;
+ struct msm_cam_subdev_info sd_info;
+
int rc = 0;
CDBG("%s: device id = %d\n", __func__, pdev->id);
new_csid_dev = kzalloc(sizeof(struct csid_device), GFP_KERNEL);
@@ -338,7 +340,10 @@
}
new_csid_dev->pdev = pdev;
- msm_cam_register_subdev_node(&new_csid_dev->subdev, CSID_DEV, pdev->id);
+ sd_info.sdev_type = CSID_DEV;
+ sd_info.sd_index = pdev->id;
+ sd_info.irq_num = new_csid_dev->irq->start;
+ msm_cam_register_subdev_node(&new_csid_dev->subdev, &sd_info);
return 0;
csid_no_resource:
diff --git a/drivers/media/video/msm/csi/msm_csiphy.c b/drivers/media/video/msm/csi/msm_csiphy.c
index e25660b..4693a8a 100644
--- a/drivers/media/video/msm/csi/msm_csiphy.c
+++ b/drivers/media/video/msm/csi/msm_csiphy.c
@@ -282,6 +282,8 @@
{
struct csiphy_device *new_csiphy_dev;
int rc = 0;
+ struct msm_cam_subdev_info sd_info;
+
CDBG("%s: device id = %d\n", __func__, pdev->id);
new_csiphy_dev = kzalloc(sizeof(struct csiphy_device), GFP_KERNEL);
if (!new_csiphy_dev) {
@@ -333,8 +335,11 @@
disable_irq(new_csiphy_dev->irq->start);
new_csiphy_dev->pdev = pdev;
+ sd_info.sdev_type = CSIPHY_DEV;
+ sd_info.sd_index = pdev->id;
+ sd_info.irq_num = new_csiphy_dev->irq->start;
msm_cam_register_subdev_node(
- &new_csiphy_dev->subdev, CSIPHY_DEV, pdev->id);
+ &new_csiphy_dev->subdev, &sd_info);
return 0;
csiphy_no_resource:
diff --git a/drivers/media/video/msm/csi/msm_ispif.c b/drivers/media/video/msm/csi/msm_ispif.c
index be97091..0f16bbf 100644
--- a/drivers/media/video/msm/csi/msm_ispif.c
+++ b/drivers/media/video/msm/csi/msm_ispif.c
@@ -640,6 +640,8 @@
static int __devinit ispif_probe(struct platform_device *pdev)
{
int rc = 0;
+ struct msm_cam_subdev_info sd_info;
+
CDBG("%s\n", __func__);
ispif = kzalloc(sizeof(struct ispif_device), GFP_KERNEL);
if (!ispif) {
@@ -687,7 +689,10 @@
}
ispif->pdev = pdev;
- msm_cam_register_subdev_node(&ispif->subdev, ISPIF_DEV, pdev->id);
+ sd_info.sdev_type = ISPIF_DEV;
+ sd_info.sd_index = pdev->id;
+ sd_info.irq_num = ispif->irq->start;
+ msm_cam_register_subdev_node(&ispif->subdev, &sd_info);
return 0;
ispif_no_mem:
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index c3c09d4..d34b8e1 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -1277,6 +1277,7 @@
struct msm_camera_sensor_info *sdata;
struct msm_cam_v4l2_device *pcam;
struct msm_sensor_ctrl_t *s_ctrl;
+ struct msm_cam_subdev_info sd_info;
D("%s for %s\n", __func__, sensor_sd->name);
@@ -1321,8 +1322,11 @@
}
msm_server_update_sensor_info(pcam, sdata);
+ sd_info.sdev_type = SENSOR_DEV;
+ sd_info.sd_index = vnode_count;
+ sd_info.irq_num = 0;
/* register the subdevice, must be done for callbacks */
- rc = msm_cam_register_subdev_node(sensor_sd, SENSOR_DEV, vnode_count);
+ rc = msm_cam_register_subdev_node(sensor_sd, &sd_info);
if (rc < 0) {
D("%s sensor sub device register failed\n",
__func__);
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 1f1f329..d0322d1 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -58,14 +58,16 @@
#define MSM_GEMINI_DRV_NAME "msm_gemini"
#define MSM_MERCURY_DRV_NAME "msm_mercury"
#define MSM_I2C_MUX_DRV_NAME "msm_cam_i2c_mux"
+#define MSM_IRQ_ROUTER_DRV_NAME "msm_cam_irq_router"
#define MAX_NUM_CSIPHY_DEV 3
-#define MAX_NUM_CSID_DEV 3
+#define MAX_NUM_CSID_DEV 4
#define MAX_NUM_CSIC_DEV 3
#define MAX_NUM_ISPIF_DEV 1
#define MAX_NUM_VFE_DEV 2
#define MAX_NUM_AXI_DEV 2
#define MAX_NUM_VPE_DEV 1
+#define MAX_NUM_JPEG_DEV 3
enum msm_cam_subdev_type {
CSIPHY_DEV,
@@ -79,6 +81,7 @@
ACTUATOR_DEV,
EEPROM_DEV,
GESTURE_DEV,
+ IRQ_ROUTER_DEV,
};
/* msm queue management APIs*/
@@ -405,6 +408,15 @@
struct msm_mem_map_info mem_map;
};
+struct msm_cam_subdev_info {
+ uint8_t sdev_type;
+ /* Subdev index. For eg: CSIPHY0, CSIPHY1 etc */
+ uint8_t sd_index;
+ /* This device/subdev's interrupt number, assigned
+ * from the hardware document. */
+ uint8_t irq_num;
+};
+
/* 2 for camera, 1 for gesture */
#define MAX_NUM_ACTIVE_CAMERA 3
@@ -421,6 +433,68 @@
uint32_t handle;
};
+struct msm_cam_server_irqmap_entry {
+ int irq_num;
+ int irq_idx;
+ uint8_t cam_hw_idx;
+ uint8_t is_composite;
+};
+
+struct intr_table_entry {
+ /* irq_num as understood by msm.
+ * Unique for every camera hw core & target. Use a mapping function
+ * to map this irq number to its equivalent index in camera side. */
+ int irq_num;
+ /* Camera hw core idx, in case of non-composite IRQs*/
+ uint8_t cam_hw_idx;
+ /* Camera hw core mask, in case of composite IRQs. */
+ uint32_t cam_hw_mask;
+ /* Each interrupt is mapped to an index, which is used
+ * to add/delete entries into the lookup table. Both the information
+ * are needed in the lookup table to avoid another subdev call into
+ * the IRQ Router subdev to get the irq_idx in the interrupt context */
+ int irq_idx;
+ /* Is this irq composite? */
+ uint8_t is_composite;
+ /* IRQ Trigger type: TRIGGER_RAISING, TRIGGER_HIGH, etc. */
+ uint32_t irq_trigger_type;
+ /* If IRQ Router hw is present,
+ * this field holds the number of camera hw core
+ * which are bundled together in the above
+ * interrupt. > 1 in case of composite irqs.
+ * If IRQ Router hw is not present, this field should be set to 1. */
+ int num_hwcore;
+ /* Pointers to the subdevs composited in this
+ * irq. If not composite, the 0th index stores the subdev to which
+ * this irq needs to be dispatched to. */
+ struct v4l2_subdev *subdev_list[CAMERA_SS_IRQ_MAX];
+ /* Device requesting the irq. */
+ const char *dev_name;
+ /* subdev private data, if any */
+ void *data;
+};
+
+struct irqmgr_intr_lkup_table {
+ /* Individual(hw) interrupt lookup table:
+ * This table is populated during initialization and doesnt
+ * change, unless the IRQ Router has been configured
+ * for composite IRQs. If the IRQ Router has been configured
+ * for composite IRQs, the is_composite field of that IRQ will
+ * be set to 1(default 0). And when there is an interrupt on
+ * that line, the composite interrupt lookup table is used
+ * for handling the interrupt. */
+ struct intr_table_entry ind_intr_tbl[CAMERA_SS_IRQ_MAX];
+
+ /* Composite interrupt lookup table:
+ * This table can be dynamically modified based on the usecase.
+ * If the usecase requires two or more HW core IRQs to be bundled
+ * into a single composite IRQ, then this table is populated
+ * accordingly. Also when this is done, the composite field
+ * in the intr_lookup_table has to be updated to reflect that
+ * the irq 'irq_num' will now be triggered in composite mode. */
+ struct intr_table_entry comp_intr_tbl[CAMERA_SS_IRQ_MAX];
+};
+
/* abstract camera server device for all sensor successfully probed*/
struct msm_cam_server_dev {
@@ -466,9 +540,18 @@
struct v4l2_subdev *axi_device[MAX_NUM_AXI_DEV];
struct v4l2_subdev *vpe_device[MAX_NUM_VPE_DEV];
struct v4l2_subdev *gesture_device;
-};
+ struct v4l2_subdev *irqr_device;
-/* camera server related functions */
+ spinlock_t intr_table_lock;
+ struct irqmgr_intr_lkup_table irq_lkup_table;
+ /* Stores the pointer to the subdev when the individual
+ * subdevices register themselves with the server. This
+ * will be used while dispatching composite irqs. The
+ * cam_hw_idx will serve as the index into this array to
+ * dispatch the irq to the corresponding subdev. */
+ struct v4l2_subdev *subdev_table[MSM_CAM_HW_MAX];
+ struct msm_cam_server_irqmap_entry hw_irqmap[CAMERA_SS_IRQ_MAX];
+};
/* ISP related functions */
void msm_isp_vfe_dev_init(struct v4l2_subdev *vd);
@@ -583,7 +666,7 @@
void __user *arg);
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);
+ struct msm_cam_subdev_info *sd_info);
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);
diff --git a/drivers/media/video/msm/msm_camirq_router.c b/drivers/media/video/msm/msm_camirq_router.c
new file mode 100644
index 0000000..52dd175
--- /dev/null
+++ b/drivers/media/video/msm/msm_camirq_router.c
@@ -0,0 +1,266 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <mach/irqs.h>
+#include <media/msm_isp.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include "msm.h"
+#include "server/msm_cam_server.h"
+#include "msm_camirq_router.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 void msm_irqrouter_update_irqmap_entry(
+ struct msm_cam_server_irqmap_entry *entry,
+ int is_composite, int irq_idx, int cam_hw_idx)
+{
+ int rc = 0;
+ entry->irq_idx = irq_idx;
+ entry->is_composite = is_composite;
+ entry->cam_hw_idx = cam_hw_idx;
+ rc = msm_cam_server_update_irqmap(entry);
+ if (rc < 0)
+ pr_err("%s Error updating irq %d information ",
+ __func__, irq_idx);
+}
+
+static void msm_irqrouter_send_default_irqmap(
+ struct irqrouter_ctrl_type *irqrouter_ctrl)
+{
+ struct msm_cam_server_irqmap_entry *irqmap =
+ &irqrouter_ctrl->def_hw_irqmap[0];
+
+ msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_0],
+ 0, CAMERA_SS_IRQ_0, MSM_CAM_HW_MICRO);
+
+ msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_1],
+ 0, CAMERA_SS_IRQ_1, MSM_CAM_HW_CCI);
+
+ msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_2],
+ 0, CAMERA_SS_IRQ_2, MSM_CAM_HW_CSI0);
+
+ msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_3],
+ 0, CAMERA_SS_IRQ_3, MSM_CAM_HW_CSI1);
+
+ msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_4],
+ 0, CAMERA_SS_IRQ_4, MSM_CAM_HW_CSI2);
+
+ msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_5],
+ 0, CAMERA_SS_IRQ_5, MSM_CAM_HW_CSI3);
+
+ msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_6],
+ 0, CAMERA_SS_IRQ_6, MSM_CAM_HW_ISPIF);
+
+ msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_7],
+ 0, CAMERA_SS_IRQ_7, MSM_CAM_HW_CPP);
+
+ msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_8],
+ 0, CAMERA_SS_IRQ_8, MSM_CAM_HW_VFE0);
+
+ msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_9],
+ 0, CAMERA_SS_IRQ_9, MSM_CAM_HW_VFE1);
+
+ msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_10],
+ 0, CAMERA_SS_IRQ_10, MSM_CAM_HW_JPEG0);
+
+ msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_11],
+ 0, CAMERA_SS_IRQ_11, MSM_CAM_HW_JPEG1);
+
+ msm_irqrouter_update_irqmap_entry(&irqmap[CAMERA_SS_IRQ_12],
+ 0, CAMERA_SS_IRQ_12, MSM_CAM_HW_JPEG2);
+}
+
+static int msm_irqrouter_open(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh)
+{
+ struct irqrouter_ctrl_type *irqrouter_ctrl = v4l2_get_subdevdata(sd);
+ /* Only one object of IRQ Router allowed. */
+ if (atomic_read(&irqrouter_ctrl->active) != 0) {
+ pr_err("%s IRQ router is already opened\n", __func__);
+ return -EINVAL;
+ }
+
+ D("%s E ", __func__);
+ atomic_inc(&irqrouter_ctrl->active);
+
+ return 0;
+}
+
+static int msm_irqrouter_close(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh)
+{
+ struct irqrouter_ctrl_type *irqrouter_ctrl = v4l2_get_subdevdata(sd);
+ if (atomic_read(&irqrouter_ctrl->active) == 0) {
+ pr_err("%s IRQ router is already closed\n", __func__);
+ return -EINVAL;
+ }
+ D("%s E ", __func__);
+ atomic_dec(&irqrouter_ctrl->active);
+ return 0;
+}
+
+static const struct v4l2_subdev_internal_ops msm_irqrouter_internal_ops = {
+ .open = msm_irqrouter_open,
+ .close = msm_irqrouter_close,
+};
+
+long msm_irqrouter_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg)
+{
+ struct irqrouter_ctrl_type *irqrouter_ctrl = v4l2_get_subdevdata(sd);
+ struct msm_camera_irq_cfg *irq_cfg;
+ struct intr_table_entry irq_req;
+ int rc = 0;
+
+ /* Handle all IRQ Router Subdev IOCTLs here.
+ * Userspace sends the composite irq configuration.
+ * IRQ Router subdev then configures the registers to group
+ * together individual core hw irqs into a composite IRQ
+ * to the MSM IRQ controller. It also registers them with
+ * the irq manager in the camera server. */
+ switch (cmd) {
+ case MSM_IRQROUTER_CFG_COMPIRQ:
+ COPY_FROM_USER(rc, &irq_cfg, (void __user *)arg,
+ sizeof(struct msm_camera_irq_cfg));
+ if (rc) {
+ ERR_COPY_FROM_USER();
+ break;
+ }
+
+ if (!irq_cfg ||
+ (irq_cfg->irq_idx < CAMERA_SS_IRQ_0) ||
+ (irq_cfg->irq_idx >= CAMERA_SS_IRQ_MAX)) {
+ pr_err("%s Invalid input", __func__);
+ return -EINVAL;
+ } else {
+ irq_req.cam_hw_mask = irq_cfg->cam_hw_mask;
+ irq_req.irq_idx = irq_cfg->irq_idx;
+ irq_req.irq_num =
+ irqrouter_ctrl->def_hw_irqmap[irq_cfg->irq_idx].irq_num;
+ irq_req.is_composite = 1;
+ irq_req.irq_trigger_type = IRQF_TRIGGER_RISING;
+ irq_req.num_hwcore = irq_cfg->num_hwcore;
+ irq_req.data = NULL;
+ rc = msm_cam_server_request_irq(&irq_req);
+ if (rc < 0) {
+ pr_err("%s Error requesting comp irq %d ",
+ __func__, irq_req.irq_idx);
+ return rc;
+ }
+ irqrouter_ctrl->def_hw_irqmap
+ [irq_cfg->irq_idx].is_composite = 1;
+ }
+ break;
+ default:
+ pr_err("%s Invalid cmd %d ", __func__, cmd);
+ break;
+ }
+
+ return rc;
+}
+
+static const struct v4l2_subdev_core_ops msm_irqrouter_subdev_core_ops = {
+ .ioctl = msm_irqrouter_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_irqrouter_subdev_ops = {
+ .core = &msm_irqrouter_subdev_core_ops,
+};
+
+static int __devinit irqrouter_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+ struct irqrouter_ctrl_type *irqrouter_ctrl;
+ struct msm_cam_subdev_info sd_info;
+
+ D("%s: device id = %d\n", __func__, pdev->id);
+
+ irqrouter_ctrl = kzalloc(sizeof(struct irqrouter_ctrl_type),
+ GFP_KERNEL);
+ if (!irqrouter_ctrl) {
+ pr_err("%s: not enough memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ v4l2_subdev_init(&irqrouter_ctrl->subdev, &msm_irqrouter_subdev_ops);
+ irqrouter_ctrl->subdev.internal_ops = &msm_irqrouter_internal_ops;
+ irqrouter_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ snprintf(irqrouter_ctrl->subdev.name,
+ sizeof(irqrouter_ctrl->subdev.name), "msm_irqrouter");
+ v4l2_set_subdevdata(&irqrouter_ctrl->subdev, irqrouter_ctrl);
+ irqrouter_ctrl->pdev = pdev;
+
+ msm_irqrouter_send_default_irqmap(irqrouter_ctrl);
+
+ media_entity_init(&irqrouter_ctrl->subdev.entity, 0, NULL, 0);
+ irqrouter_ctrl->subdev.entity.type = MEDIA_ENT_T_DEVNODE_V4L;
+ irqrouter_ctrl->subdev.entity.group_id = IRQ_ROUTER_DEV;
+ irqrouter_ctrl->subdev.entity.name = pdev->name;
+
+ sd_info.sdev_type = IRQ_ROUTER_DEV;
+ sd_info.sd_index = 0;
+ sd_info.irq_num = 0;
+ /* Now register this subdev with the camera server. */
+ rc = msm_cam_register_subdev_node(&irqrouter_ctrl->subdev, &sd_info);
+ if (rc < 0) {
+ pr_err("%s Error registering irqr subdev %d", __func__, rc);
+ goto error;
+ }
+ irqrouter_ctrl->subdev.entity.revision =
+ irqrouter_ctrl->subdev.devnode->num;
+ atomic_set(&irqrouter_ctrl->active, 0);
+
+ platform_set_drvdata(pdev, &irqrouter_ctrl->subdev);
+
+ return rc;
+error:
+ kfree(irqrouter_ctrl);
+ return rc;
+}
+
+static int __exit irqrouter_exit(struct platform_device *pdev)
+{
+ kfree(irqrouter_ctrl);
+ return 0;
+}
+
+static struct platform_driver msm_irqrouter_driver = {
+ .probe = irqrouter_probe,
+ .remove = irqrouter_exit,
+ .driver = {
+ .name = MSM_IRQ_ROUTER_DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_irqrouter_init_module(void)
+{
+ return platform_driver_register(&msm_irqrouter_driver);
+}
+
+static void __exit msm_irqrouter_exit_module(void)
+{
+ platform_driver_unregister(&msm_irqrouter_driver);
+}
+
+module_init(msm_irqrouter_init_module);
+module_exit(msm_irqrouter_exit_module);
+MODULE_DESCRIPTION("msm camera irq router");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm_camirq_router.h b/drivers/media/video/msm/msm_camirq_router.h
new file mode 100644
index 0000000..2c9cb73
--- /dev/null
+++ b/drivers/media/video/msm/msm_camirq_router.h
@@ -0,0 +1,206 @@
+/* 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_IRQROUTER_H__
+#define __MSM_CAM_IRQROUTER_H__
+
+#include <linux/bitops.h>
+
+/* Camera SS common registers defines - Start */
+/* These registers are not directly related to
+ * IRQ Router, but are common to the Camera SS.
+ * IRQ Router registers dont have a unique base address
+ * in the memory mapped address space. It is offset from
+ * the Camera SS base address. So keep the common Camera
+ * SS registers also in the IRQ Router subdev for now. */
+
+/* READ ONLY: Camera Subsystem HW version */
+#define CAMSS_HW_VERSION 0x00000000
+
+/* Bits 4:0 of this register can be used to select a desired
+ * camera core test bus to drive the Camera_SS test bus output */
+#define CAMSS_TESTBUS_SEL 0x00000004
+
+/* Bits 4:0 of this register is used to allow either Microcontroller
+ * or the CCI drive the corresponding GPIO output.
+ * For eg: Setting bit 0 of this register allows Microcontroller to
+ * drive GPIO #0. Clearing the bit allows CCI to drive GPIO #0. */
+#define CAMSS_GPIO_MUX_SEL 0x00000008
+
+/* Bit 0 of this register is used to set the default AHB master
+ * for the AHB Arbiter. 0 - AHB Master 0, 1 - AHB Master 1*/
+#define CAMSS_AHB_ARB_CTL 0x0000000C
+
+/* READ ONLY */
+#define CAMSS_XPU2_STATUS 0x00000010
+
+/* Select the appropriate CSI clock for CSID Pixel pipes */
+#define CAMSS_CSI_PIX_CLK_MUX_SEL 0x00000020
+#define CAMSS_CSI_PIX_CLK_CGC_EN 0x00000024
+
+/* Select the appropriate CSI clock for CSID RDI pipes */
+#define CAMSS_CSI_RDI_CLK_MUX_SEL 0x00000028
+#define CAMSS_CSI_RDI_CLK_CGC_EN 0x0000002C
+
+/* Select the appropriate CSI clock for CSI Phy0 */
+#define CAMSS_CSI_PHY_0_CLK_MUX_SEL 0x00000030
+#define CAMSS_CSI_PHY_0_CLK_CGC_EN 0x00000034
+
+/* Select the appropriate CSI clock for CSI Phy1 */
+#define CAMSS_CSI_PHY_1_CLK_MUX_SEL 0x00000038
+#define CAMSS_CSI_PHY_1_CLK_CGC_EN 0x0000003C
+
+/* Select the appropriate CSI clock for CSI Phy2 */
+#define CAMSS_CSI_PHY_2_CLK_MUX_SEL 0x00000040
+#define CAMSS_CSI_PHY_2_CLK_CGC_EN 0x00000044
+/* Camera SS common registers defines - End */
+
+/* IRQ Router registers defines - Start */
+/* This register is used to reset the composite
+ * IRQ outputs of the Camera_SS IRQ Router */
+#define CAMSS_IRQ_COMPOSITE_RESET_CTRL 0x00000060
+
+/* By default, this 'allows' the interrupts from
+ * Micro to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_0 0x00000064
+
+/* By default, this 'allows' the interrupts from
+ * CCI to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_1 0x00000068
+
+/* By default, this 'allows' the interrupts from
+ * CSI_0 to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_2 0x0000006C
+
+/* By default, this 'allows' the interrupts from
+ * CSI_1 to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_3 0x00000070
+
+/* By default, this 'allows' the interrupts from
+ * CSI_2 to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_4 0x00000074
+
+/* By default, this 'allows' the interrupts from
+ * CSI_3 to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_5 0x00000078
+
+/* By default, this 'allows' the interrupts from
+ * ISPIF to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_6 0x0000007C
+
+/* By default, this 'allows' the interrupts from
+ * CPP to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_7 0x00000080
+
+/* By default, this 'allows' the interrupts from
+ * VFE_0 to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_8 0x00000084
+
+/* By default, this 'allows' the interrupts from
+ * VFE_1 to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_9 0x00000088
+
+/* By default, this 'allows' the interrupts from
+ * JPEG_0 to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_10 0x0000008C
+
+/* By default, this 'allows' the interrupts from
+ * JPEG_1 to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_11 0x00000090
+
+/* By default, this 'allows' the interrupts from
+ * JPEG_2 to pass through, unless configured in
+ * composite mode. */
+#define CAMSS_IRQ_COMPOSITE_MASK_12 0x00000094
+
+/* The following IRQ_COMPOSITE_MICRO_MASK registers
+ * allow the interrupts from the individual hw
+ * cores to be composited into an IRQ for Micro. */
+#define CAMSS_IRQ_COMPOSITE_MICRO_MASK_0 0x000000A4
+#define CAMSS_IRQ_COMPOSITE_MICRO_MASK_1 0x000000A8
+#define CAMSS_IRQ_COMPOSITE_MICRO_MASK_2 0x000000AC
+#define CAMSS_IRQ_COMPOSITE_MICRO_MASK_3 0x000000B0
+#define CAMSS_IRQ_COMPOSITE_MICRO_MASK_4 0x000000B4
+#define CAMSS_IRQ_COMPOSITE_MICRO_MASK_5 0x000000B8
+/* IRQ Router register defines - End */
+
+/* Writing this mask will reset all the composite
+ * IRQs of the Camera_SS IRQ Router */
+#define CAMSS_IRQ_COMPOSITE_RESET_MASK 0x003F1FFF
+
+/* Use this to enable Micro IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_MICRO_IRQ_IN_COMPOSITE BIT(0)
+/* Use this to enable CCI IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_CCI_IRQ_IN_COMPOSITE BIT(1)
+/* Use this to enable CSI0 IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_CSI0_IRQ_IN_COMPOSITE BIT(2)
+/* Use this to enable CSI1 IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_CSI1_IRQ_IN_COMPOSITE BIT(3)
+/* Use this to enable CSI2 IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_CSI2_IRQ_IN_COMPOSITE BIT(4)
+/* Use this to enable CSI3 IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_CSI3_IRQ_IN_COMPOSITE BIT(5)
+/* Use this to enable ISPIF IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_ISPIF_IRQ_IN_COMPOSITE BIT(6)
+/* Use this to enable CPP IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_CPP_IRQ_IN_COMPOSITE BIT(7)
+/* Use this to enable VFE0 IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_VFE0_IRQ_IN_COMPOSITE BIT(8)
+/* Use this to enable VFE1 IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_VFE1_IRQ_IN_COMPOSITE BIT(9)
+/* Use this to enable JPEG0 IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_JPEG0_IRQ_IN_COMPOSITE BIT(10)
+/* Use this to enable JPEG1 IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_JPEG1_IRQ_IN_COMPOSITE BIT(11)
+/* Use this to enable JPEG2 IRQ from IRQ Router
+ * composite interrupt */
+#define ENABLE_JPEG2_IRQ_IN_COMPOSITE BIT(12)
+
+struct irqrouter_ctrl_type {
+ /* v4l2 subdev */
+ struct v4l2_subdev subdev;
+ struct platform_device *pdev;
+
+ void __iomem *irqr_dev_base;
+
+ struct resource *irqr_dev_mem;
+ struct resource *irqr_dev_io;
+ atomic_t active;
+ struct msm_cam_server_irqmap_entry def_hw_irqmap[CAMERA_SS_IRQ_MAX];
+};
+
+#endif /* __MSM_CAM_IRQROUTER_H__ */
diff --git a/drivers/media/video/msm/msm_gesture.c b/drivers/media/video/msm/msm_gesture.c
index 6b81d15..5777cb5 100644
--- a/drivers/media/video/msm/msm_gesture.c
+++ b/drivers/media/video/msm/msm_gesture.c
@@ -455,6 +455,8 @@
struct msm_gesture_ctrl *p_gesture_ctrl = &g_gesture_ctrl;
struct v4l2_subdev *gesture_subdev =
kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+ struct msm_cam_subdev_info sd_info;
+
D("%s\n", __func__);
if (!gesture_subdev) {
pr_err("%s: no enough memory\n", __func__);
@@ -475,7 +477,10 @@
/* events */
gesture_subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
- msm_cam_register_subdev_node(gesture_subdev, GESTURE_DEV, 0);
+ sd_info.sdev_type = GESTURE_DEV;
+ sd_info.sd_index = 0;
+ sd_info.irq_num = 0;
+ msm_cam_register_subdev_node(gesture_subdev, &sd_info);
gesture_subdev->entity.revision = gesture_subdev->devnode->num;
diff --git a/drivers/media/video/msm/msm_vfe31_v4l2.c b/drivers/media/video/msm/msm_vfe31_v4l2.c
index a6cc06e..885cd90 100644
--- a/drivers/media/video/msm/msm_vfe31_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe31_v4l2.c
@@ -3844,7 +3844,10 @@
static int __devinit vfe31_probe(struct platform_device *pdev)
{
int rc = 0;
+ struct msm_cam_subdev_info sd_info;
+
CDBG("%s: device id = %d\n", __func__, pdev->id);
+
vfe31_ctrl = kzalloc(sizeof(struct vfe31_ctrl_type), GFP_KERNEL);
if (!vfe31_ctrl) {
pr_err("%s: no enough memory\n", __func__);
@@ -3916,7 +3919,10 @@
disable_irq(vfe31_ctrl->vfeirq->start);
vfe31_ctrl->pdev = pdev;
- msm_cam_register_subdev_node(&vfe31_ctrl->subdev, VFE_DEV, 0);
+ sd_info.sdev_type = VFE_DEV;
+ sd_info.sd_index = 0;
+ sd_info.irq_num = vfe31_ctrl->vfeirq->start;
+ msm_cam_register_subdev_node(&vfe31_ctrl->subdev, &sd_info);
return 0;
vfe31_no_resource:
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 9544ce5..9382292 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -25,6 +25,7 @@
#include <media/msm_isp.h>
#include "msm.h"
+#include "msm_cam_server.h"
#include "msm_vfe32.h"
atomic_t irq_cnt;
@@ -3979,6 +3980,17 @@
return IRQ_HANDLED;
}
+int msm_axi_subdev_isr_routine(struct v4l2_subdev *sd,
+ u32 status, bool *handled)
+{
+ struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+ irqreturn_t ret;
+ pr_info("%s E ", __func__);
+ ret = vfe32_parse_irq(axi_ctrl->vfeirq->start, axi_ctrl);
+ *handled = TRUE;
+ return 0;
+}
+
static long msm_vfe_subdev_ioctl(struct v4l2_subdev *sd,
unsigned int subdev_cmd, void *arg)
{
@@ -4678,6 +4690,7 @@
static const struct v4l2_subdev_core_ops msm_axi_subdev_core_ops = {
.ioctl = msm_axi_subdev_ioctl,
+ .interrupt_service_routine = msm_axi_subdev_isr_routine,
};
static const struct v4l2_subdev_video_ops msm_axi_subdev_video_ops = {
@@ -4697,6 +4710,9 @@
struct axi_ctrl_t *axi_ctrl;
struct vfe32_ctrl_type *vfe32_ctrl;
struct vfe_share_ctrl_t *share_ctrl;
+ struct intr_table_entry irq_req;
+ struct msm_cam_subdev_info sd_info;
+
CDBG("%s: device id = %d\n", __func__, pdev->id);
share_ctrl = kzalloc(sizeof(struct vfe_share_ctrl_t), GFP_KERNEL);
@@ -4732,7 +4748,11 @@
sizeof(axi_ctrl->subdev.name), "axi");
v4l2_set_subdevdata(&axi_ctrl->subdev, axi_ctrl);
axi_ctrl->pdev = pdev;
- msm_cam_register_subdev_node(&axi_ctrl->subdev, AXI_DEV, 0);
+
+ sd_info.sdev_type = AXI_DEV;
+ sd_info.sd_index = 0;
+ sd_info.irq_num = 0;
+ msm_cam_register_subdev_node(&axi_ctrl->subdev, &sd_info);
v4l2_subdev_init(&vfe32_ctrl->subdev, &msm_vfe_subdev_ops);
vfe32_ctrl->subdev.internal_ops = &msm_vfe_internal_ops;
@@ -4765,23 +4785,49 @@
goto vfe32_no_resource;
}
- rc = request_irq(axi_ctrl->vfeirq->start, vfe32_parse_irq,
- IRQF_TRIGGER_RISING, "vfe", axi_ctrl);
- if (rc < 0) {
- release_mem_region(axi_ctrl->vfemem->start,
- resource_size(axi_ctrl->vfemem));
- pr_err("%s: irq request fail\n", __func__);
- rc = -EBUSY;
+ /* Request for this device irq from the camera server. If the
+ * IRQ Router is present on this target, the interrupt will be
+ * handled by the camera server and the interrupt service
+ * routine called. If the request_irq call returns ENXIO, then
+ * the IRQ Router hardware is not present on this target. We
+ * have to request for the irq ourselves and register the
+ * appropriate interrupt handler. */
+ irq_req.cam_hw_idx = MSM_CAM_HW_VFE0;
+ irq_req.dev_name = "vfe";
+ irq_req.irq_idx = CAMERA_SS_IRQ_8;
+ irq_req.irq_num = axi_ctrl->vfeirq->start;
+ irq_req.is_composite = 0;
+ irq_req.irq_trigger_type = IRQF_TRIGGER_RISING;
+ irq_req.num_hwcore = 1;
+ irq_req.subdev_list[0] = &axi_ctrl->subdev;
+ irq_req.data = (void *)axi_ctrl;
+ rc = msm_cam_server_request_irq(&irq_req);
+ if (rc == -ENXIO) {
+ /* IRQ Router hardware is not present on this hardware.
+ * Request for the IRQ and register the interrupt handler. */
+ rc = request_irq(axi_ctrl->vfeirq->start, vfe32_parse_irq,
+ IRQF_TRIGGER_RISING, "vfe", axi_ctrl);
+ if (rc < 0) {
+ release_mem_region(axi_ctrl->vfemem->start,
+ resource_size(axi_ctrl->vfemem));
+ pr_err("%s: irq request fail\n", __func__);
+ rc = -EBUSY;
+ goto vfe32_no_resource;
+ }
+ disable_irq(axi_ctrl->vfeirq->start);
+ } else if (rc < 0) {
+ pr_err("%s Error registering irq ", __func__);
goto vfe32_no_resource;
}
- disable_irq(axi_ctrl->vfeirq->start);
-
tasklet_init(&axi_ctrl->vfe32_tasklet,
axi32_do_tasklet, (unsigned long)axi_ctrl);
vfe32_ctrl->pdev = pdev;
- msm_cam_register_subdev_node(&vfe32_ctrl->subdev, VFE_DEV, 0);
+ sd_info.sdev_type = VFE_DEV;
+ sd_info.sd_index = 0;
+ sd_info.irq_num = axi_ctrl->vfeirq->start;
+ msm_cam_register_subdev_node(&vfe32_ctrl->subdev, &sd_info);
return 0;
vfe32_no_resource:
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
index 7369f6f..398621f 100644
--- a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
@@ -1795,6 +1795,8 @@
static int __devinit vfe2x_probe(struct platform_device *pdev)
{
+ struct msm_cam_subdev_info sd_info;
+
CDBG("%s: device id = %d\n", __func__, pdev->id);
vfe2x_ctrl = kzalloc(sizeof(struct vfe2x_ctrl_type), GFP_KERNEL);
if (!vfe2x_ctrl) {
@@ -1811,7 +1813,10 @@
platform_set_drvdata(pdev, &vfe2x_ctrl->subdev);
vfe2x_ctrl->pdev = pdev;
- msm_cam_register_subdev_node(&vfe2x_ctrl->subdev, VFE_DEV, 0);
+ sd_info.sdev_type = VFE_DEV;
+ sd_info.sd_index = 0;
+ sd_info.irq_num = 0;
+ msm_cam_register_subdev_node(&vfe2x_ctrl->subdev, &sd_info);
return 0;
}
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index 54e9582..fb22cf9 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -970,6 +970,8 @@
static int __devinit msm_vpe_probe(struct platform_device *pdev)
{
int rc = 0;
+ struct msm_cam_subdev_info sd_info;
+
D("%s: device id = %d\n", __func__, pdev->id);
vpe_ctrl = kzalloc(sizeof(struct vpe_ctrl_type), GFP_KERNEL);
if (!vpe_ctrl) {
@@ -1028,7 +1030,10 @@
atomic_set(&vpe_ctrl->active, 0);
vpe_ctrl->pdev = pdev;
- msm_cam_register_subdev_node(&vpe_ctrl->subdev, VPE_DEV, pdev->id);
+ sd_info.sdev_type = VPE_DEV;
+ sd_info.sd_index = pdev->id;
+ sd_info.irq_num = vpe_ctrl->vpeirq->start;
+ msm_cam_register_subdev_node(&vpe_ctrl->subdev, &sd_info);
vpe_ctrl->subdev.entity.revision = vpe_ctrl->subdev.devnode->num;
msm_queue_init(&vpe_ctrl->eventData_q, "ackevents");
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index 65893c1..dfa7fbe 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -1435,20 +1435,379 @@
}
return;
-}
-
-void msm_cam_release_subdev_node(struct video_device *vdev)
-{
- struct v4l2_subdev *sd = video_get_drvdata(vdev);
- sd->devnode = NULL;
- kfree(vdev);
+}
+
+void msm_cam_release_subdev_node(struct video_device *vdev)
+{
+ struct v4l2_subdev *sd = video_get_drvdata(vdev);
+ sd->devnode = NULL;
+ kfree(vdev);
+}
+
+/* Helper function to get the irq_idx corresponding
+ * to the irq_num. */
+int get_irq_idx_from_irq_num(int irq_num)
+{
+ int i;
+ for (i = 0; i < CAMERA_SS_IRQ_MAX; i++)
+ if (irq_num == g_server_dev.hw_irqmap[i].irq_num)
+ return g_server_dev.hw_irqmap[i].irq_idx;
+
+ return -EINVAL;
+}
+
+static irqreturn_t msm_camera_server_parse_irq(int irq_num, void *data)
+{
+ unsigned long flags;
+ int irq_idx, i, rc;
+ u32 status = 0;
+ struct intr_table_entry *ind_irq_tbl;
+ struct intr_table_entry *comp_irq_tbl;
+ bool subdev_handled = 0;
+
+ irq_idx = get_irq_idx_from_irq_num(irq_num);
+ if (irq_idx < 0) {
+ pr_err("server_parse_irq: no clients for irq #%d. returning ",
+ irq_num);
+ return IRQ_HANDLED;
+ }
+
+ spin_lock_irqsave(&g_server_dev.intr_table_lock, flags);
+ ind_irq_tbl = &g_server_dev.irq_lkup_table.ind_intr_tbl[0];
+ comp_irq_tbl = &g_server_dev.irq_lkup_table.comp_intr_tbl[0];
+ if (ind_irq_tbl[irq_idx].is_composite) {
+ for (i = 0; i < comp_irq_tbl[irq_idx].num_hwcore; i++) {
+ if (comp_irq_tbl[irq_idx].subdev_list[i]) {
+ rc = v4l2_subdev_call(
+ comp_irq_tbl[irq_idx].subdev_list[i],
+ core, interrupt_service_routine,
+ status, &subdev_handled);
+ if ((rc < 0) || !subdev_handled) {
+ pr_err("server_parse_irq:Error\n"
+ "handling irq %d rc = %d",
+ irq_num, rc);
+ /* Dispatch the irq to the remaining
+ * subdevs in the list. */
+ continue;
+ }
+ }
+ }
+ } else {
+ rc = v4l2_subdev_call(ind_irq_tbl[irq_idx].subdev_list[0],
+ core, interrupt_service_routine,
+ status, &subdev_handled);
+ if ((rc < 0) || !subdev_handled) {
+ pr_err("server_parse_irq: Error handling irq %d rc = %d",
+ irq_num, rc);
+ spin_unlock_irqrestore(&g_server_dev.intr_table_lock,
+ flags);
+ return IRQ_HANDLED;
+ }
+ }
+ spin_unlock_irqrestore(&g_server_dev.intr_table_lock, flags);
+ return IRQ_HANDLED;
+}
+
+/* Helper function to get the irq_idx corresponding
+ * to the camera hwcore. This function should _only_
+ * be invoked when the IRQ Router is configured
+ * non-composite mode. */
+int get_irq_idx_from_camhw_idx(int cam_hw_idx)
+{
+ int i;
+ for (i = 0; i < MSM_CAM_HW_MAX; i++)
+ if (cam_hw_idx == g_server_dev.hw_irqmap[i].cam_hw_idx)
+ return g_server_dev.hw_irqmap[i].irq_idx;
+
+ return -EINVAL;
+}
+
+static inline void update_compirq_subdev_info(
+ struct intr_table_entry *irq_entry,
+ uint32_t cam_hw_mask, uint8_t cam_hw_id,
+ int *num_hwcore)
+{
+ if (cam_hw_mask & (0x1 << cam_hw_id)) {
+ /* If the mask has been set for this cam hwcore
+ * update the subdev ptr......*/
+ irq_entry->subdev_list[cam_hw_id] =
+ g_server_dev.subdev_table[cam_hw_id];
+ (*num_hwcore)++;
+ } else {
+ /*....else, just clear it, so that the irq will
+ * not be dispatched to this hw. */
+ irq_entry->subdev_list[cam_hw_id] = NULL;
+ }
+}
+
+static int msm_server_update_composite_irq_info(
+ struct intr_table_entry *irq_req)
+{
+ int num_hwcore = 0, rc = 0;
+ struct intr_table_entry *comp_irq_tbl =
+ &g_server_dev.irq_lkup_table.comp_intr_tbl[0];
+
+ comp_irq_tbl[irq_req->irq_idx].is_composite = 1;
+ comp_irq_tbl[irq_req->irq_idx].irq_trigger_type =
+ irq_req->irq_trigger_type;
+ comp_irq_tbl[irq_req->irq_idx].num_hwcore = irq_req->num_hwcore;
+
+ update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+ irq_req->cam_hw_mask, MSM_CAM_HW_MICRO, &num_hwcore);
+
+ update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+ irq_req->cam_hw_mask, MSM_CAM_HW_CCI, &num_hwcore);
+
+ update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+ irq_req->cam_hw_mask, MSM_CAM_HW_CSI0, &num_hwcore);
+
+ update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+ irq_req->cam_hw_mask, MSM_CAM_HW_CSI1, &num_hwcore);
+
+ update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+ irq_req->cam_hw_mask, MSM_CAM_HW_CSI2, &num_hwcore);
+
+ update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+ irq_req->cam_hw_mask, MSM_CAM_HW_CSI3, &num_hwcore);
+
+ update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+ irq_req->cam_hw_mask, MSM_CAM_HW_ISPIF, &num_hwcore);
+
+ update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+ irq_req->cam_hw_mask, MSM_CAM_HW_CPP, &num_hwcore);
+
+ update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+ irq_req->cam_hw_mask, MSM_CAM_HW_VFE0, &num_hwcore);
+
+ update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+ irq_req->cam_hw_mask, MSM_CAM_HW_VFE1, &num_hwcore);
+
+ update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+ irq_req->cam_hw_mask, MSM_CAM_HW_JPEG0, &num_hwcore);
+
+ update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+ irq_req->cam_hw_mask, MSM_CAM_HW_JPEG1, &num_hwcore);
+
+ update_compirq_subdev_info(&comp_irq_tbl[irq_req->irq_idx],
+ irq_req->cam_hw_mask, MSM_CAM_HW_JPEG2, &num_hwcore);
+
+ if (num_hwcore != irq_req->num_hwcore) {
+ pr_warn("%s Mismatch!! requested cam hwcores: %d, Mask set %d",
+ __func__, irq_req->num_hwcore, num_hwcore);
+ rc = -EINVAL;
+ }
+ return rc;
+}
+
+int msm_cam_server_request_irq(void *arg)
+{
+ unsigned long flags;
+ int rc = 0;
+ struct intr_table_entry *irq_req = (struct intr_table_entry *)arg;
+ struct intr_table_entry *ind_irq_tbl =
+ &g_server_dev.irq_lkup_table.ind_intr_tbl[0];
+ struct intr_table_entry *comp_irq_tbl =
+ &g_server_dev.irq_lkup_table.comp_intr_tbl[0];
+
+ if (!irq_req || !irq_req->irq_num || !irq_req->num_hwcore) {
+ pr_err("%s Invalid input ", __func__);
+ return -EINVAL;
+ }
+
+ if (!g_server_dev.irqr_device) {
+ /* This either means, the current target does not
+ * have a IRQ Router hw or the IRQ Router device is
+ * not probed yet. The latter should not happen.
+ * In any case, just return back without updating
+ * the interrupt lookup table. */
+ pr_info("%s IRQ Router hw is not present. ", __func__);
+ return -ENXIO;
+ }
+
+ if (irq_req->is_composite) {
+ if (irq_req->irq_idx >= CAMERA_SS_IRQ_0 &&
+ irq_req->irq_idx < CAMERA_SS_IRQ_MAX) {
+ spin_lock_irqsave(&g_server_dev.intr_table_lock, flags);
+ /* Update the composite irq information into
+ * the composite irq lookup table.... */
+ if (msm_server_update_composite_irq_info(irq_req)) {
+ pr_err("%s Invalid configuration", __func__);
+ spin_unlock_irqrestore(
+ &g_server_dev.intr_table_lock, flags);
+ return -EINVAL;
+ }
+ spin_unlock_irqrestore(&g_server_dev.intr_table_lock,
+ flags);
+ /*...and then update the corresponding entry
+ * in the individual irq lookup table to indicate
+ * that this IRQ is a composite irq and needs to be
+ * sent to multiple subdevs. */
+ ind_irq_tbl[irq_req->irq_idx].is_composite = 1;
+ rc = request_irq(comp_irq_tbl[irq_req->irq_idx].irq_num,
+ msm_camera_server_parse_irq,
+ irq_req->irq_trigger_type,
+ ind_irq_tbl[irq_req->irq_idx].dev_name,
+ ind_irq_tbl[irq_req->irq_idx].data);
+ if (rc < 0) {
+ pr_err("%s: request_irq failed for %s\n",
+ __func__, irq_req->dev_name);
+ return -EBUSY;
+ }
+ } else {
+ pr_err("%s Invalid irq_idx %d ",
+ __func__, irq_req->irq_idx);
+ return -EINVAL;
+ }
+ } else {
+ if (irq_req->cam_hw_idx >= MSM_CAM_HW_MICRO &&
+ irq_req->cam_hw_idx < MSM_CAM_HW_MAX) {
+ /* Update the irq information into
+ * the individual irq lookup table.... */
+ irq_req->irq_idx =
+ get_irq_idx_from_camhw_idx(irq_req->cam_hw_idx);
+ if (irq_req->cam_hw_idx < 0) {
+ pr_err("%s Invalid hw index %d ", __func__,
+ irq_req->cam_hw_idx);
+ return -EINVAL;
+ }
+ spin_lock_irqsave(&g_server_dev.intr_table_lock, flags);
+ /* Make sure the composite irq is not configured for
+ * this IRQ already. */
+ BUG_ON(ind_irq_tbl[irq_req->irq_idx].is_composite);
+
+ ind_irq_tbl[irq_req->irq_idx] = *irq_req;
+ /* irq_num is stored inside the server's hw_irqmap
+ * during the device subdevice registration. */
+ ind_irq_tbl[irq_req->irq_idx].irq_num =
+ g_server_dev.hw_irqmap[irq_req->irq_idx].irq_num;
+
+ /*...and clear the corresponding entry in the
+ * compsoite irq lookup table to indicate that this
+ * IRQ will only be dispatched to single subdev. */
+ memset(&comp_irq_tbl[irq_req->irq_idx], 0,
+ sizeof(struct intr_table_entry));
+ D("%s Saving Entry %d %d %d %p",
+ __func__,
+ ind_irq_tbl[irq_req->cam_hw_idx].irq_num,
+ ind_irq_tbl[irq_req->cam_hw_idx].cam_hw_idx,
+ ind_irq_tbl[irq_req->cam_hw_idx].is_composite,
+ ind_irq_tbl[irq_req->cam_hw_idx].subdev_list[0]);
+
+ spin_unlock_irqrestore(&g_server_dev.intr_table_lock,
+ flags);
+
+ rc = request_irq(ind_irq_tbl[irq_req->irq_idx].irq_num,
+ msm_camera_server_parse_irq,
+ irq_req->irq_trigger_type,
+ ind_irq_tbl[irq_req->irq_idx].dev_name,
+ ind_irq_tbl[irq_req->irq_idx].data);
+ if (rc < 0) {
+ pr_err("%s: request_irq failed for %s\n",
+ __func__, irq_req->dev_name);
+ return -EBUSY;
+ }
+ } else {
+ pr_err("%s Invalid hw index %d ", __func__,
+ irq_req->cam_hw_idx);
+ return -EINVAL;
+ }
+ }
+ D("%s Successfully requested for IRQ for device %s ", __func__,
+ irq_req->dev_name);
+ return rc;
+}
+
+int msm_cam_server_update_irqmap(
+ struct msm_cam_server_irqmap_entry *irqmap_entry)
+{
+ if (!irqmap_entry || (irqmap_entry->irq_idx < CAMERA_SS_IRQ_0 ||
+ irqmap_entry->irq_idx >= CAMERA_SS_IRQ_MAX)) {
+ pr_err("%s Invalid irqmap entry ", __func__);
+ return -EINVAL;
+ }
+ g_server_dev.hw_irqmap[irqmap_entry->irq_idx] = *irqmap_entry;
+ return 0;
+}
+
+static int msm_cam_server_register_subdev(struct v4l2_device *v4l2_dev,
+ struct v4l2_subdev *sd)
+{
+ int rc = 0;
+ struct video_device *vdev;
+
+ if (v4l2_dev == NULL || sd == NULL || !sd->name[0]) {
+ pr_err("%s Invalid input ", __func__);
+ return -EINVAL;
+ }
+
+ rc = v4l2_device_register_subdev(v4l2_dev, sd);
+ if (rc < 0) {
+ pr_err("%s v4l2 subdev register failed for %s ret = %d",
+ __func__, sd->name, rc);
+ return rc;
+ }
+
+ /* 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 rc;
+
+ vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+ if (!vdev) {
+ pr_err("%s Not enough memory ", __func__);
+ rc = -ENOMEM;
+ goto clean_up;
+ }
+
+ video_set_drvdata(vdev, sd);
+ strlcpy(vdev->name, sd->name, sizeof(vdev->name));
+ vdev->v4l2_dev = v4l2_dev;
+ vdev->fops = &v4l2_subdev_fops;
+ vdev->release = msm_cam_release_subdev_node;
+ rc = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
+ sd->owner);
+ if (rc < 0) {
+ pr_err("%s Error registering video device %s", __func__,
+ sd->name);
+ kfree(vdev);
+ goto clean_up;
+ }
+#if defined(CONFIG_MEDIA_CONTROLLER)
+ sd->entity.info.v4l.major = VIDEO_MAJOR;
+ sd->entity.info.v4l.minor = vdev->minor;
+#endif
+ sd->devnode = vdev;
+ return 0;
+
+clean_up:
+ if (sd->devnode)
+ video_unregister_device(sd->devnode);
+ return rc;
+}
+
+static int msm_cam_server_fill_sdev_irqnum(int cam_hw_idx,
+ int irq_num)
+{
+ int rc = 0, irq_idx;
+ irq_idx = get_irq_idx_from_camhw_idx(cam_hw_idx);
+ if (irq_idx < 0) {
+ pr_err("%s Invalid cam_hw_idx %d ", __func__, cam_hw_idx);
+ rc = -EINVAL;
+ } else {
+ g_server_dev.hw_irqmap[irq_idx].irq_num = irq_num;
+ }
+ return rc;
}
int msm_cam_register_subdev_node(struct v4l2_subdev *sd,
- enum msm_cam_subdev_type sdev_type, uint8_t index)
+ struct msm_cam_subdev_info *sd_info)
{
- struct video_device *vdev;
- int err = 0;
+ int err = 0, cam_hw_idx;
+ uint8_t sdev_type, index;
+
+ sdev_type = sd_info->sdev_type;
+ index = sd_info->sd_index;
switch (sdev_type) {
case CSIPHY_DEV:
@@ -1466,7 +1825,13 @@
err = -EINVAL;
break;
}
+ cam_hw_idx = MSM_CAM_HW_CSI0 + index;
g_server_dev.csid_device[index] = sd;
+ if (g_server_dev.irqr_device) {
+ g_server_dev.subdev_table[cam_hw_idx] = sd;
+ err = msm_cam_server_fill_sdev_irqnum(cam_hw_idx,
+ sd_info->irq_num);
+ }
break;
case CSIC_DEV:
@@ -1480,6 +1845,11 @@
case ISPIF_DEV:
g_server_dev.ispif_device = sd;
+ if (g_server_dev.irqr_device) {
+ g_server_dev.subdev_table[cam_hw_idx] = sd;
+ err = msm_cam_server_fill_sdev_irqnum(MSM_CAM_HW_ISPIF,
+ sd_info->irq_num);
+ }
break;
case VFE_DEV:
@@ -1488,7 +1858,13 @@
err = -EINVAL;
break;
}
+ cam_hw_idx = MSM_CAM_HW_VFE0 + index;
g_server_dev.vfe_device[index] = sd;
+ if (g_server_dev.irqr_device) {
+ g_server_dev.subdev_table[cam_hw_idx] = sd;
+ err = msm_cam_server_fill_sdev_irqnum(cam_hw_idx,
+ sd_info->irq_num);
+ }
break;
case VPE_DEV:
@@ -1512,6 +1888,9 @@
case GESTURE_DEV:
g_server_dev.gesture_device = sd;
break;
+ case IRQ_ROUTER_DEV:
+ g_server_dev.irqr_device = sd;
+ break;
default:
break;
}
@@ -1519,49 +1898,11 @@
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 = kzalloc(sizeof(*vdev), GFP_KERNEL);
- if (!vdev) {
- err = -ENOMEM;
- goto clean_up;
- }
-
- video_set_drvdata(vdev, sd);
- strlcpy(vdev->name, sd->name, sizeof(vdev->name));
- vdev->v4l2_dev = &g_server_dev.v4l2_dev;
- vdev->fops = &v4l2_subdev_fops;
- vdev->release = msm_cam_release_subdev_node;
- err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
- sd->owner);
- if (err < 0) {
- kfree(vdev);
- goto clean_up;
- }
-#if defined(CONFIG_MEDIA_CONTROLLER)
- sd->entity.info.v4l.major = VIDEO_MAJOR;
- sd->entity.info.v4l.minor = vdev->minor;
-#endif
- sd->devnode = vdev;
- return 0;
-
-clean_up:
- if (sd->devnode)
- video_unregister_device(sd->devnode);
- return err;
+ err = msm_cam_server_register_subdev(&g_server_dev.v4l2_dev, sd);
+ return err;
}
+
static int msm_setup_server_dev(struct platform_device *pdev)
{
int rc = -ENODEV, i;
@@ -1604,6 +1945,9 @@
mutex_init(&g_server_dev.server_lock);
mutex_init(&g_server_dev.server_queue_lock);
+ spin_lock_init(&g_server_dev.intr_table_lock);
+ memset(&g_server_dev.irq_lkup_table, 0,
+ sizeof(struct irqmgr_intr_lkup_table));
g_server_dev.pcam_active = NULL;
g_server_dev.camera_info.num_cameras = 0;
atomic_set(&g_server_dev.number_pcam_active, 0);
diff --git a/drivers/media/video/msm/server/msm_cam_server.h b/drivers/media/video/msm/server/msm_cam_server.h
index 677feaa..8a02d32 100644
--- a/drivers/media/video/msm/server/msm_cam_server.h
+++ b/drivers/media/video/msm/server/msm_cam_server.h
@@ -61,5 +61,7 @@
struct v4l2_event_subscription *sub);
int msm_server_get_crop(struct msm_cam_v4l2_device *pcam,
int idx, struct v4l2_crop *crop);
-
+int msm_cam_server_request_irq(void *arg);
+int msm_cam_server_update_irqmap(
+ struct msm_cam_server_irqmap_entry *entry);
#endif /* _MSM_CAM_SERVER_H */
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
index 1c646dd..6cd9e6b 100644
--- a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
@@ -28,6 +28,7 @@
#include "msm_smem.h"
#define BASE_DEVICE_NUMBER 32
+#define MAX_EVENTS 30
struct msm_vidc_drv *vidc_driver;
@@ -215,21 +216,20 @@
int rc;
struct buffer_info *bi;
struct v4l2_buffer buffer_info;
+ struct v4l2_plane plane;
v4l2_inst = get_v4l2_inst(file, NULL);
if (b->count == 0) {
list_for_each_safe(ptr, next, &v4l2_inst->registered_bufs) {
bi = list_entry(ptr, struct buffer_info, list);
if (bi->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
buffer_info.type = bi->type;
- buffer_info.m.planes[0].reserved[0] =
- bi->fd;
- buffer_info.m.planes[0].reserved[1] =
- bi->buff_off;
- buffer_info.m.planes[0].length = bi->size;
- buffer_info.m.planes[0].m.userptr =
- bi->uvaddr;
+ plane.reserved[0] = bi->fd;
+ plane.reserved[1] = bi->buff_off;
+ plane.length = bi->size;
+ plane.m.userptr = bi->uvaddr;
+ buffer_info.m.planes = &plane;
buffer_info.length = 1;
- pr_err("Releasing buffer: %d, %d, %d\n",
+ pr_info("Releasing buffer: %d, %d, %d\n",
buffer_info.m.planes[0].reserved[0],
buffer_info.m.planes[0].reserved[1],
buffer_info.m.planes[0].length);
@@ -359,9 +359,7 @@
struct v4l2_event_subscription *sub)
{
int rc = 0;
- if (sub->type == V4L2_EVENT_ALL)
- sub->type = V4L2_EVENT_PRIVATE_START + V4L2_EVENT_VIDC_BASE;
- rc = v4l2_event_subscribe(fh, sub, 0);
+ rc = v4l2_event_subscribe(fh, sub, MAX_EVENTS);
return rc;
}
@@ -445,7 +443,7 @@
INIT_LIST_HEAD(&core->instances);
mutex_init(&core->sync_lock);
spin_lock_init(&core->lock);
- core->base_addr = 0x34f00000;
+ core->base_addr = 0x14f00000;
core->state = VIDC_CORE_UNINIT;
for (i = SYS_MSG_INDEX(SYS_MSG_START);
i <= SYS_MSG_INDEX(SYS_MSG_END); i++) {
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index ed99d35..ec93628 100644
--- a/drivers/media/video/msm_vidc/msm_venc.c
+++ b/drivers/media/video/msm_vidc/msm_venc.c
@@ -348,7 +348,7 @@
{
.id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
.name = "H.264 Loop Filter Mode",
- .type = V4L2_CTRL_TYPE_INTEGER,
+ .type = V4L2_CTRL_TYPE_MENU,
.minimum = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
.maximum = L_MODE,
.default_value = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
@@ -375,7 +375,9 @@
static u32 get_frame_size_compressed(int plane, u32 height, u32 width)
{
- return ((height + 31) & (~31)) * ((width + 31) & (~31)) * 3/2;
+ int sz = ((height + 31) & (~31)) * ((width + 31) & (~31)) * 3/2;
+ sz = (sz + 4095) & (~4095);
+ return sz;
}
static struct hal_quantization
diff --git a/drivers/media/video/msm_vidc/msm_vidc.c b/drivers/media/video/msm_vidc/msm_vidc.c
index a11f817..11fbcf4 100644
--- a/drivers/media/video/msm_vidc/msm_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_vidc.c
@@ -186,7 +186,7 @@
void *vidc_get_userptr(void *alloc_ctx, unsigned long vaddr,
unsigned long size, int write)
{
- return NULL;
+ return (void *)0xdeadbeef;
}
void vidc_put_userptr(void *buf_priv)
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index 52f1dca..9b617aa 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -183,21 +183,9 @@
{
struct msm_vidc_cb_cmd_done *response = data;
struct msm_vidc_inst *inst;
- struct video_device *vdev;
- struct v4l2_event dqevent;
- struct msm_vidc_core *core;
if (response) {
inst = (struct msm_vidc_inst *)response->session_id;
signal_session_msg_receipt(cmd, inst);
- core = inst->core;
- if (inst->session_type == MSM_VIDC_ENCODER)
- vdev = &core->vdev[MSM_VIDC_ENCODER].vdev;
- else
- vdev = &core->vdev[MSM_VIDC_DECODER].vdev;
- dqevent.type = V4L2_EVENT_PRIVATE_START + V4L2_EVENT_VIDC_BASE;
- dqevent.u.data[0] = (uint8_t)MSM_VIDC_OPEN_DONE;
- v4l2_event_queue(vdev, &dqevent);
- return;
} else {
pr_err("Failed to get valid response for session init\n");
}
@@ -207,24 +195,17 @@
{
struct msm_vidc_cb_cmd_done *response = data;
struct msm_vidc_inst *inst;
- struct video_device *vdev;
struct v4l2_event dqevent;
struct msm_vidc_cb_event *event_notify;
- struct msm_vidc_core *core;
if (response) {
inst = (struct msm_vidc_inst *)response->session_id;
- core = inst->core;
- if (inst->session_type == MSM_VIDC_ENCODER)
- vdev = &core->vdev[MSM_VIDC_ENCODER].vdev;
- else
- vdev = &core->vdev[MSM_VIDC_DECODER].vdev;
- dqevent.type = V4L2_EVENT_PRIVATE_START + V4L2_EVENT_VIDC_BASE;
- dqevent.u.data[0] = (uint8_t)MSM_VIDC_DECODER_EVENT_CHANGE;
+ dqevent.type = V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED;
+ dqevent.id = 0;
event_notify = (struct msm_vidc_cb_event *) response->data;
inst->reconfig_height = event_notify->height;
inst->reconfig_width = event_notify->width;
inst->in_reconfig = true;
- v4l2_event_queue(vdev, &dqevent);
+ v4l2_event_queue_fh(&inst->event_handler, &dqevent);
return;
} else {
pr_err("Failed to get valid response for event_change\n");
@@ -262,20 +243,9 @@
{
struct msm_vidc_cb_cmd_done *response = data;
struct msm_vidc_inst *inst;
- struct video_device *vdev;
- struct v4l2_event dqevent;
- struct msm_vidc_core *core;
if (response) {
inst = (struct msm_vidc_inst *)response->session_id;
signal_session_msg_receipt(cmd, inst);
- core = inst->core;
- if (inst->session_type == MSM_VIDC_ENCODER)
- vdev = &core->vdev[MSM_VIDC_ENCODER].vdev;
- else
- vdev = &core->vdev[MSM_VIDC_DECODER].vdev;
- dqevent.type = V4L2_EVENT_PRIVATE_START + V4L2_EVENT_VIDC_BASE;
- dqevent.u.data[0] = (uint8_t)MSM_VIDC_START_DONE;
- v4l2_event_queue(vdev, &dqevent);
} else {
pr_err("Failed to get valid response for start\n");
}
@@ -285,20 +255,9 @@
{
struct msm_vidc_cb_cmd_done *response = data;
struct msm_vidc_inst *inst;
- struct video_device *vdev;
- struct v4l2_event dqevent;
- struct msm_vidc_core *core;
if (response) {
inst = (struct msm_vidc_inst *)response->session_id;
signal_session_msg_receipt(cmd, inst);
- core = inst->core;
- if (inst->session_type == MSM_VIDC_ENCODER)
- vdev = &core->vdev[MSM_VIDC_ENCODER].vdev;
- else
- vdev = &core->vdev[MSM_VIDC_DECODER].vdev;
- dqevent.type = V4L2_EVENT_PRIVATE_START + V4L2_EVENT_VIDC_BASE;
- dqevent.u.data[0] = (uint8_t)MSM_VIDC_STOP_DONE;
- v4l2_event_queue(vdev, &dqevent);
} else {
pr_err("Failed to get valid response for stop\n");
}
@@ -320,19 +279,12 @@
{
struct msm_vidc_cb_cmd_done *response = data;
struct msm_vidc_inst *inst;
- struct video_device *vdev;
struct v4l2_event dqevent;
- struct msm_vidc_core *core;
if (response) {
inst = (struct msm_vidc_inst *)response->session_id;
- core = inst->core;
- if (inst->session_type == MSM_VIDC_ENCODER)
- vdev = &core->vdev[MSM_VIDC_ENCODER].vdev;
- else
- vdev = &core->vdev[MSM_VIDC_DECODER].vdev;
- dqevent.type = V4L2_EVENT_PRIVATE_START + V4L2_EVENT_VIDC_BASE;
- dqevent.u.data[0] = (uint8_t)MSM_VIDC_DECODER_FLUSH_DONE;
- v4l2_event_queue(vdev, &dqevent);
+ dqevent.type = V4L2_EVENT_MSM_VIDC_FLUSH_DONE;
+ dqevent.id = 0;
+ v4l2_event_queue_fh(&inst->event_handler, &dqevent);
} else {
pr_err("Failed to get valid response for flush\n");
}
@@ -343,20 +295,13 @@
{
struct msm_vidc_cb_cmd_done *response = data;
struct msm_vidc_inst *inst;
- struct video_device *vdev;
struct v4l2_event dqevent;
- struct msm_vidc_core *core;
if (response) {
inst = (struct msm_vidc_inst *)response->session_id;
signal_session_msg_receipt(cmd, inst);
- core = inst->core;
- if (inst->session_type == MSM_VIDC_ENCODER)
- vdev = &core->vdev[MSM_VIDC_ENCODER].vdev;
- else
- vdev = &core->vdev[MSM_VIDC_DECODER].vdev;
- dqevent.type = V4L2_EVENT_PRIVATE_START + V4L2_EVENT_VIDC_BASE;
- dqevent.u.data[0] = (uint8_t)MSM_VIDC_CLOSE_DONE;
- v4l2_event_queue(vdev, &dqevent);
+ dqevent.type = V4L2_EVENT_MSM_VIDC_CLOSE_DONE;
+ dqevent.id = 0;
+ v4l2_event_queue_fh(&inst->event_handler, &dqevent);
} else {
pr_err("Failed to get valid response for session close\n");
}
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/video/msm_vidc/msm_vidc_internal.h
index fb1ab58..fb8fbc4 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_internal.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_internal.h
@@ -75,11 +75,6 @@
MSM_VIDC_CORE_UNINIT,
};
-enum vidc_resposes_id {
- MSM_VIDC_DECODER_FLUSH_DONE = 0x11,
- MSM_VIDC_DECODER_EVENT_CHANGE,
-};
-
struct buf_info {
struct list_head list;
struct vb2_buffer *buf;
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index c983389..a1561f0 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -3308,6 +3308,9 @@
int rc;
int vdd_safe;
+ /* forcing 19p2mhz before accessing any charger registers */
+ pm8921_chg_force_19p2mhz_clk(chip);
+
rc = pm_chg_masked_write(chip, SYS_CONFIG_2,
BOOT_DONE_BIT, BOOT_DONE_BIT);
if (rc) {
@@ -3501,8 +3504,6 @@
/* Disable EOC FSM processing */
pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0x91);
- pm8921_chg_force_19p2mhz_clk(chip);
-
rc = pm_chg_masked_write(chip, CHG_CNTRL, VREF_BATT_THERM_FORCE_ON,
VREF_BATT_THERM_FORCE_ON);
if (rc)
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 90a3b1e..be8e6aa 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -1546,7 +1546,8 @@
{ \
if (size >= sizeof(buffer)) \
return -EINVAL; \
- strlcpy(buffer, strim((char *) buf), sizeof(buffer)); \
+ strlcpy(buffer, buf, sizeof(buffer)); \
+ strim(buffer); \
return size; \
} \
static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, field ## _show, field ## _store);
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 55d2b3e..cad6e02 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -914,6 +914,7 @@
goto error;
}
+ mutex_lock(&mgmt->mdp_do_hist_mutex);
mutex_lock(&mgmt->mdp_hist_mutex);
if (mgmt->mdp_is_hist_start == TRUE) {
pr_err("%s histogram already started\n", __func__);
@@ -933,6 +934,7 @@
error_lock:
mutex_unlock(&mgmt->mdp_hist_mutex);
+ mutex_unlock(&mgmt->mdp_do_hist_mutex);
error:
return ret;
}
@@ -949,6 +951,7 @@
goto error;
}
+ mutex_lock(&mgmt->mdp_do_hist_mutex);
mutex_lock(&mgmt->mdp_hist_mutex);
if (mgmt->mdp_is_hist_start == FALSE) {
pr_err("%s histogram already stopped\n", __func__);
@@ -969,10 +972,12 @@
mutex_unlock(&mgmt->mdp_hist_mutex);
cancel_work_sync(&mgmt->mdp_histogram_worker);
+ mutex_unlock(&mgmt->mdp_do_hist_mutex);
return ret;
error_lock:
mutex_unlock(&mgmt->mdp_hist_mutex);
+ mutex_unlock(&mgmt->mdp_do_hist_mutex);
error:
return ret;
}
@@ -1178,11 +1183,13 @@
return ret;
}
+#define MDP_HISTOGRAM_TIMEOUT_MS 84 /*5 Frames*/
static int mdp_do_histogram(struct fb_info *info,
struct mdp_histogram_data *hist)
{
struct mdp_hist_mgmt *mgmt = NULL;
int ret = 0;
+ unsigned long timeout = (MDP_HISTOGRAM_TIMEOUT_MS * HZ) / 1000;
ret = mdp_histogram_block2mgmt(hist->block, &mgmt);
if (ret) {
@@ -1227,9 +1234,17 @@
mgmt->hist = hist;
mutex_unlock(&mgmt->mdp_hist_mutex);
- if (wait_for_completion_killable(&mgmt->mdp_hist_comp)) {
- pr_err("%s(): histogram bin collection killed", __func__);
- ret = -EINVAL;
+ ret = wait_for_completion_killable_timeout(&mgmt->mdp_hist_comp,
+ timeout);
+ if (ret <= 0) {
+ if (!ret) {
+ mgmt->hist = NULL;
+ ret = -ETIMEDOUT;
+ pr_debug("%s: bin collection timedout", __func__);
+ } else {
+ mgmt->hist = NULL;
+ pr_debug("%s: bin collection interrupted", __func__);
+ }
goto error;
}
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
index 45430e8..a5171f0 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -590,6 +590,12 @@
__func__, dev_ctxt);
return false;
}
+ if (dev_ctxt->turbo_mode_set &&
+ (req_perf_lvl < RESTRK_1080P_TURBO_PERF_LEVEL)) {
+ VCDRES_MSG_MED("%s(): TURBO MODE!!\n", __func__);
+ return true;
+ }
+
VCDRES_MSG_LOW("%s(), req_perf_lvl = %d", __func__, req_perf_lvl);
if (resource_context.vidc_platform_data->disable_turbo
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
index 2b534f1..96e729d 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
@@ -759,6 +759,7 @@
client = dev_ctxt->cctxt_list_head;
dev_ctxt->cctxt_list_head = cctxt;
cctxt->next = client;
+ dev_ctxt->turbo_mode_set = 0;
*clnt_cctxt = cctxt;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
index 80e03ba..33b2300 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c
@@ -312,6 +312,7 @@
return false;
}
dev_ctxt->curr_perf_lvl = RESTRK_1080P_TURBO_PERF_LEVEL;
+ vcd_update_decoder_perf_level(dev_ctxt, RESTRK_1080P_TURBO_PERF_LEVEL);
#endif
return rc;
}
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index f18fafd..63ebdea 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -2295,11 +2295,11 @@
#define V4L2_EVENT_FRAME_SYNC 4
#define V4L2_EVENT_PRIVATE_START 0x08000000
-#define V4L2_EVENT_MSM_VIDC_START { V4L2_EVENT_PRIVATE_START + 0x00001000}
-#define V4L2_EVENT_MSM_VIDC_FLUSH_DONE {V4L2_EVENT_PRIVATE_START + 1}
+#define V4L2_EVENT_MSM_VIDC_START (V4L2_EVENT_PRIVATE_START + 0x00001000)
+#define V4L2_EVENT_MSM_VIDC_FLUSH_DONE (V4L2_EVENT_PRIVATE_START + 1)
#define V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED \
- {V4L2_EVENT_PRIVATE_START + 2}
-#define V4L2_EVENT_MSM_VIDC_CLOSE_DONE {V4L2_EVENT_PRIVATE_START + 3}
+ (V4L2_EVENT_PRIVATE_START + 2)
+#define V4L2_EVENT_MSM_VIDC_CLOSE_DONE (V4L2_EVENT_PRIVATE_START + 3)
/* Payload for V4L2_EVENT_VSYNC */
struct v4l2_event_vsync {
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 0c9b274..320ac8b 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -1594,4 +1594,66 @@
uint32_t len;
};
+enum msm_camss_irq_idx {
+ CAMERA_SS_IRQ_0,
+ CAMERA_SS_IRQ_1,
+ CAMERA_SS_IRQ_2,
+ CAMERA_SS_IRQ_3,
+ CAMERA_SS_IRQ_4,
+ CAMERA_SS_IRQ_5,
+ CAMERA_SS_IRQ_6,
+ CAMERA_SS_IRQ_7,
+ CAMERA_SS_IRQ_8,
+ CAMERA_SS_IRQ_9,
+ CAMERA_SS_IRQ_10,
+ CAMERA_SS_IRQ_11,
+ CAMERA_SS_IRQ_12,
+ CAMERA_SS_IRQ_MAX
+};
+
+enum msm_cam_hw_idx {
+ MSM_CAM_HW_MICRO,
+ MSM_CAM_HW_CCI,
+ MSM_CAM_HW_CSI0,
+ MSM_CAM_HW_CSI1,
+ MSM_CAM_HW_CSI2,
+ MSM_CAM_HW_CSI3,
+ MSM_CAM_HW_ISPIF,
+ MSM_CAM_HW_CPP,
+ MSM_CAM_HW_VFE0,
+ MSM_CAM_HW_VFE1,
+ MSM_CAM_HW_JPEG0,
+ MSM_CAM_HW_JPEG1,
+ MSM_CAM_HW_JPEG2,
+ MSM_CAM_HW_MAX
+};
+
+struct msm_camera_irq_cfg {
+ /* Bit mask of all the camera hardwares that needs to
+ * be composited into a single IRQ to the MSM.
+ * Current usage: (may be updated based on hw changes)
+ * Bits 31:13 - Reserved.
+ * Bits 12:0
+ * 12 - MSM_CAM_HW_JPEG2
+ * 11 - MSM_CAM_HW_JPEG1
+ * 10 - MSM_CAM_HW_JPEG0
+ * 9 - MSM_CAM_HW_VFE1
+ * 8 - MSM_CAM_HW_VFE0
+ * 7 - MSM_CAM_HW_CPP
+ * 6 - MSM_CAM_HW_ISPIF
+ * 5 - MSM_CAM_HW_CSI3
+ * 4 - MSM_CAM_HW_CSI2
+ * 3 - MSM_CAM_HW_CSI1
+ * 2 - MSM_CAM_HW_CSI0
+ * 1 - MSM_CAM_HW_CCI
+ * 0 - MSM_CAM_HW_MICRO
+ */
+ uint32_t cam_hw_mask;
+ uint8_t irq_idx;
+ uint8_t num_hwcore;
+};
+
+#define MSM_IRQROUTER_CFG_COMPIRQ \
+ _IOWR('V', BASE_VIDIOC_PRIVATE, void __user *)
+
#endif /* __LINUX_MSM_CAMERA_H */
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index a7fd38b..2da5c6a 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -18,6 +18,8 @@
#include <linux/gpio.h>
#include <linux/mfd/pm8xxx/pm8921.h>
#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/slimbus/slimbus.h>
#include <sound/core.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
@@ -1417,6 +1419,19 @@
return 0;
}
+static int msm_slimbus_1_startup(struct snd_pcm_substream *substream)
+{
+ struct slim_controller *slim = slim_busnum_to_ctrl(1);
+
+ pr_debug("%s(): substream = %s stream = %d\n", __func__,
+ substream->name, substream->stream);
+
+ if (slim != NULL)
+ pm_runtime_get_sync(slim->dev.parent);
+
+ return 0;
+}
+
static void msm_auxpcm_shutdown(struct snd_pcm_substream *substream)
{
@@ -1433,6 +1448,19 @@
rtd->dai_link->cpu_dai_name, rtd->dai_link->codec_dai_name);
}
+static void msm_slimbus_1_shutdown(struct snd_pcm_substream *substream)
+{
+ struct slim_controller *slim = slim_busnum_to_ctrl(1);
+
+ pr_debug("%s(): substream = %s stream = %d\n", __func__,
+ substream->name, substream->stream);
+
+ if (slim != NULL) {
+ pm_runtime_mark_last_busy(slim->dev.parent);
+ pm_runtime_put(slim->dev.parent);
+ }
+}
+
static struct snd_soc_ops msm_be_ops = {
.startup = msm_startup,
.hw_params = msm_hw_params,
@@ -1445,9 +1473,9 @@
};
static struct snd_soc_ops msm_slimbus_1_be_ops = {
- .startup = msm_startup,
+ .startup = msm_slimbus_1_startup,
.hw_params = msm_slimbus_1_hw_params,
- .shutdown = msm_shutdown,
+ .shutdown = msm_slimbus_1_shutdown,
};
static struct snd_soc_ops msm_slimbus_3_be_ops = {